Merge pull request #15128 from rudkx/handle-relational-constraints-in-bindings
Begin refactoring type variable binding code.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ab911cf..390d338 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,19 @@
Swift 4.2
---------
+* [SE-0196][]
+
+ Custom compile-time warnings or error messages can be emitted using the
+ `#warning(_:)` and `#error(_:)` directives.
+
+ ```swift
+ #warning("this is incomplete")
+
+ #if MY_BUILD_CONFIG && MY_OTHER_BUILD_CONFIG
+ #error("MY_BUILD_CONFIG and MY_OTHER_BUILD_CONFIG cannot both be set")
+ #endif
+ ```
+
* Public classes may now have internal `required` initializers. The rule for
`required` initializers is that they must be available everywhere the class
can be subclassed, but previously we said that `required` initializers on
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0050546..bc10278 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -822,20 +822,23 @@
endif()
message(STATUS "Building host Swift tools for ${SWIFT_HOST_VARIANT_SDK} ${SWIFT_HOST_VARIANT_ARCH}")
-message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
-message(STATUS " Assertions: ${LLVM_ENABLE_ASSERTIONS}")
-message(STATUS " LTO: ${SWIFT_TOOLS_ENABLE_LTO}")
+message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
+message(STATUS " Assertions: ${LLVM_ENABLE_ASSERTIONS}")
+message(STATUS " LTO: ${SWIFT_TOOLS_ENABLE_LTO}")
+message(STATUS " +0 Normal Args: ${SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS}")
message(STATUS "")
-if (SWIFT_BULID_STDLIB OR SWIFT_BUILD_SDK_OVERLAY)
+if (SWIFT_BUILD_STDLIB OR SWIFT_BUILD_SDK_OVERLAY)
message(STATUS "Building Swift standard library and overlays for SDKs: ${SWIFT_SDKS}")
- message(STATUS " Build type: ${SWIFT_STDLIB_BUILD_TYPE}")
- message(STATUS " Assertions: ${SWIFT_STDLIB_ASSERTIONS}")
+ message(STATUS " Build type: ${SWIFT_STDLIB_BUILD_TYPE}")
+ message(STATUS " Assertions: ${SWIFT_STDLIB_ASSERTIONS}")
+ message(STATUS " +0 Normal Args: ${SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS}")
message(STATUS "")
message(STATUS "Building Swift runtime with:")
message(STATUS " Leak Detection Checker Entrypoints: ${SWIFT_RUNTIME_ENABLE_LEAK_CHECKER}")
+ message(STATUS " +0 Normal Args: ${SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS}")
message(STATUS "")
else()
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index e837cf6..a251222 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -100,26 +100,8 @@
set(result ${${CFLAGS_RESULT_VAR_NAME}})
- # MSVC and clang-cl don't understand -target.
- if (NOT SWIFT_COMPILER_IS_MSVC_LIKE)
- list(APPEND result "-target" "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_TRIPLE}")
- endif()
-
is_darwin_based_sdk("${CFLAGS_SDK}" IS_DARWIN)
if(IS_DARWIN)
- list(APPEND result "-isysroot" "${SWIFT_SDK_${CFLAGS_SDK}_PATH}")
- elseif(NOT SWIFT_COMPILER_IS_MSVC_LIKE AND NOT "${SWIFT_SDK_${CFLAGS_SDK}_PATH}" STREQUAL "/")
- list(APPEND result "--sysroot=${SWIFT_SDK_${CFLAGS_SDK}_PATH}")
- endif()
-
- if("${CFLAGS_SDK}" STREQUAL "ANDROID")
- list(APPEND result
- "--sysroot=${SWIFT_ANDROID_SDK_PATH}"
- # Use the linker included in the Android NDK.
- "-B" "${SWIFT_ANDROID_PREBUILT_PATH}/arm-linux-androideabi/bin/")
- endif()
-
- if(IS_DARWIN)
# Check if there's a specific OS deployment version needed for this invocation
if("${CFLAGS_SDK}" STREQUAL "OSX")
set(DEPLOYMENT_VERSION ${CFLAGS_DEPLOYMENT_VERSION_OSX})
@@ -134,7 +116,27 @@
if("${DEPLOYMENT_VERSION}" STREQUAL "")
set(DEPLOYMENT_VERSION "${SWIFT_SDK_${CFLAGS_SDK}_DEPLOYMENT_VERSION}")
endif()
+ endif()
+ # MSVC and clang-cl don't understand -target.
+ if (NOT SWIFT_COMPILER_IS_MSVC_LIKE)
+ list(APPEND result "-target" "${SWIFT_SDK_${CFLAGS_SDK}_ARCH_${CFLAGS_ARCH}_TRIPLE}${DEPLOYMENT_VERSION}")
+ endif()
+
+ if(IS_DARWIN)
+ list(APPEND result "-isysroot" "${SWIFT_SDK_${CFLAGS_SDK}_PATH}")
+ elseif(NOT SWIFT_COMPILER_IS_MSVC_LIKE AND NOT "${SWIFT_SDK_${CFLAGS_SDK}_PATH}" STREQUAL "/")
+ list(APPEND result "--sysroot=${SWIFT_SDK_${CFLAGS_SDK}_PATH}")
+ endif()
+
+ if("${CFLAGS_SDK}" STREQUAL "ANDROID")
+ list(APPEND result
+ "--sysroot=${SWIFT_ANDROID_SDK_PATH}"
+ # Use the linker included in the Android NDK.
+ "-B" "${SWIFT_ANDROID_PREBUILT_PATH}/arm-linux-androideabi/bin/")
+ endif()
+
+ if(IS_DARWIN)
list(APPEND result
"-arch" "${CFLAGS_ARCH}"
"-F" "${SWIFT_SDK_${CFLAGS_SDK}_PATH}/../../../Developer/Library/Frameworks"
@@ -297,16 +299,19 @@
list(APPEND result "-sdk" "${SWIFT_SDK_${sdk}_PATH}")
endif()
- if(BUILD_STANDALONE)
+ is_darwin_based_sdk("${sdk}" IS_DARWIN)
+ if(IS_DARWIN)
list(APPEND result
- "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}")
+ "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}${SWIFT_SDK_${sdk}_DEPLOYMENT_VERSION}")
else()
list(APPEND result
- "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}"
- "-resource-dir" "${SWIFTLIB_DIR}")
+ "-target" "${SWIFT_SDK_${sdk}_ARCH_${arch}_TRIPLE}")
endif()
- is_darwin_based_sdk("${sdk}" IS_DARWIN)
+ if(NOT BUILD_STANDALONE)
+ list(APPEND result "-resource-dir" "${SWIFTLIB_DIR}")
+ endif()
+
if(IS_DARWIN)
list(APPEND result
"-F" "${SWIFT_SDK_${sdk}_PATH}/../../../Developer/Library/Frameworks")
@@ -2002,7 +2007,7 @@
BINARY_DIR ${SWIFT_RUNTIME_OUTPUT_INTDIR}
LIBRARY_DIR ${SWIFT_LIBRARY_OUTPUT_INTDIR})
- target_link_libraries("${name}" ${SWIFTEXE_SINGLE_LINK_LIBRARIES} ${SWIFTEXE_SINGLE_LINK_FAT_LIBRARIES})
+ target_link_libraries("${name}" PRIVATE ${SWIFTEXE_SINGLE_LINK_LIBRARIES} ${SWIFTEXE_SINGLE_LINK_FAT_LIBRARIES})
swift_common_llvm_config("${name}" ${SWIFTEXE_SINGLE_LLVM_COMPONENT_DEPENDS})
set_target_properties(${name}
diff --git a/cmake/modules/SwiftConfigureSDK.cmake b/cmake/modules/SwiftConfigureSDK.cmake
index 75682c1..ab3c7fb 100644
--- a/cmake/modules/SwiftConfigureSDK.cmake
+++ b/cmake/modules/SwiftConfigureSDK.cmake
@@ -123,7 +123,7 @@
foreach(arch ${architectures})
set(SWIFT_SDK_${prefix}_ARCH_${arch}_TRIPLE
- "${arch}-apple-${SWIFT_SDK_${prefix}_TRIPLE_NAME}${SWIFT_SDK_${prefix}_DEPLOYMENT_VERSION}")
+ "${arch}-apple-${SWIFT_SDK_${prefix}_TRIPLE_NAME}")
endforeach()
# Add this to the list of known SDKs.
@@ -141,7 +141,7 @@
set(SWIFT_SDK_${prefix}_PATH "${sdkpath}")
set(SWIFT_SDK_${prefix}_VERSION "don't use")
set(SWIFT_SDK_${prefix}_BUILD_NUMBER "don't use")
- set(SWIFT_SDK_${prefix}_DEPLOYMENT_VERSION "don't use")
+ set(SWIFT_SDK_${prefix}_DEPLOYMENT_VERSION "")
set(SWIFT_SDK_${prefix}_LIB_SUBDIR "${lib_subdir}")
set(SWIFT_SDK_${prefix}_VERSION_MIN_NAME "")
set(SWIFT_SDK_${prefix}_TRIPLE_NAME "${triple_name}")
@@ -171,7 +171,7 @@
set(SWIFT_SDK_${prefix}_PATH "/")
set(SWIFT_SDK_${prefix}_VERSION "NOTFOUND")
set(SWIFT_SDK_${prefix}_BUILD_NUMBER "NOTFOUND")
- set(SWIFT_SDK_${prefix}_DEPLOYMENT_VERSION "NOTFOUND")
+ set(SWIFT_SDK_${prefix}_DEPLOYMENT_VERSION "")
set(SWIFT_SDK_${prefix}_LIB_SUBDIR "windows")
set(SWIFT_SDK_${prefix}_VERSION_MIN_NAME "NOTFOUND")
set(SWIFT_SDK_${prefix}_TRIPLE_NAME "Win32")
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index a832224..8edeed4 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -309,7 +309,7 @@
else()
# HACK: Otherwise (for example, for executables), use a plain signature,
# because LLVM CMake does that already.
- target_link_libraries("${target}" ${libnames})
+ target_link_libraries("${target}" PRIVATE ${libnames})
endif()
else()
# If Swift was not built standalone, dispatch to 'llvm_config()'.
diff --git a/docs/OptimizationTips.rst b/docs/OptimizationTips.rst
index f428915..8661d07 100644
--- a/docs/OptimizationTips.rst
+++ b/docs/OptimizationTips.rst
@@ -21,7 +21,7 @@
======================
The first thing one should always do is to enable optimization. Swift provides
-three different optimization levels:
+four different optimization levels:
- ``-Onone``: This is meant for normal development. It performs minimal
optimizations and preserves all debug info.
@@ -35,6 +35,8 @@
result in undetected memory safety issues and integer overflows. Only use this
if you have carefully reviewed that your code is safe with respect to integer
overflow and type casts.
+- ``-Osize``: This is a special optimization mode where the compiler prioritizes
+ code size over performance.
In the Xcode UI, one can modify the current optimization level as follows:
diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md
index 734729b..7bf7324 100644
--- a/docs/WindowsBuild.md
+++ b/docs/WindowsBuild.md
@@ -121,8 +121,6 @@
two hours depending on your system.
- You may need to adjust the `SWIFT_WINDOWS_LIB_DIRECTORY` parameter depending on
your target platform or Windows SDK version.
-- While the commands here use MSVC to build, using `clang-cl` is recommended (see
- the **Clang-cl** section below).
```cmd
mkdir "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
pushd "%swift_source_dir%/build/Ninja-DebugAssert/swift-windows-amd64/ninja"
diff --git a/include/swift/AST/ConcreteDeclRef.h b/include/swift/AST/ConcreteDeclRef.h
index 6dc3159..d9c378e 100644
--- a/include/swift/AST/ConcreteDeclRef.h
+++ b/include/swift/AST/ConcreteDeclRef.h
@@ -71,7 +71,7 @@
llvm::PointerUnion<ValueDecl *, SpecializedDeclRef *> Data;
- friend class llvm::PointerLikeTypeTraits<ConcreteDeclRef>;
+ friend struct llvm::PointerLikeTypeTraits<ConcreteDeclRef>;
public:
/// Create an empty declaration reference.
@@ -140,7 +140,7 @@
} // end namespace swift
namespace llvm {
- template<> class PointerLikeTypeTraits<swift::ConcreteDeclRef> {
+ template<> struct PointerLikeTypeTraits<swift::ConcreteDeclRef> {
typedef llvm::PointerUnion<swift::ValueDecl *,
swift::ConcreteDeclRef::SpecializedDeclRef *>
DataPointer;
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index ba7931f..ca901bf 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -447,7 +447,9 @@
/// Add a rewrite rule that makes \c otherPA a part of the given equivalence
/// class.
- void addSameTypeRewriteRule(EquivalenceClass *equivClass,
+ ///
+ /// \returns true if a new rewrite rule was added, and false otherwise.
+ bool addSameTypeRewriteRule(EquivalenceClass *equivClass,
PotentialArchetype *otherPA);
/// \brief Add a new conformance requirement specifying that the given
diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h
index 784ed2a..957632e 100644
--- a/include/swift/AST/Identifier.h
+++ b/include/swift/AST/Identifier.h
@@ -191,9 +191,9 @@
};
// An Identifier is "pointer like".
- template<typename T> class PointerLikeTypeTraits;
+ template<typename T> struct PointerLikeTypeTraits;
template<>
- class PointerLikeTypeTraits<swift::Identifier> {
+ struct PointerLikeTypeTraits<swift::Identifier> {
public:
static inline void *getAsVoidPointer(swift::Identifier I) {
return const_cast<void *>(I.getAsOpaquePointer());
@@ -333,8 +333,8 @@
};
// A DeclBaseName is "pointer like".
-template <typename T> class PointerLikeTypeTraits;
-template <> class PointerLikeTypeTraits<swift::DeclBaseName> {
+template <typename T> struct PointerLikeTypeTraits;
+template <> struct PointerLikeTypeTraits<swift::DeclBaseName> {
public:
static inline void *getAsVoidPointer(swift::DeclBaseName D) {
return const_cast<void *>(D.getAsOpaquePointer());
@@ -687,9 +687,9 @@
namespace llvm {
// A DeclName is "pointer like".
- template<typename T> class PointerLikeTypeTraits;
+ template<typename T> struct PointerLikeTypeTraits;
template<>
- class PointerLikeTypeTraits<swift::DeclName> {
+ struct PointerLikeTypeTraits<swift::DeclName> {
public:
static inline void *getAsVoidPointer(swift::DeclName name) {
return name.getOpaqueValue();
@@ -717,9 +717,9 @@
};
// An ObjCSelector is "pointer like".
- template<typename T> class PointerLikeTypeTraits;
+ template<typename T> struct PointerLikeTypeTraits;
template<>
- class PointerLikeTypeTraits<swift::ObjCSelector> {
+ struct PointerLikeTypeTraits<swift::ObjCSelector> {
public:
static inline void *getAsVoidPointer(swift::ObjCSelector name) {
return name.getOpaqueValue();
diff --git a/include/swift/AST/LayoutConstraint.h b/include/swift/AST/LayoutConstraint.h
index ef0561c..961fa8a 100644
--- a/include/swift/AST/LayoutConstraint.h
+++ b/include/swift/AST/LayoutConstraint.h
@@ -395,7 +395,7 @@
};
// A LayoutConstraint is "pointer like".
-template <> class PointerLikeTypeTraits<swift::LayoutConstraint> {
+template <> struct PointerLikeTypeTraits<swift::LayoutConstraint> {
public:
static inline void *getAsVoidPointer(swift::LayoutConstraint I) {
return (void *)I.getPointer();
diff --git a/include/swift/AST/Type.h b/include/swift/AST/Type.h
index 2619c78..fd1e1ca 100644
--- a/include/swift/AST/Type.h
+++ b/include/swift/AST/Type.h
@@ -674,7 +674,7 @@
// A Type is "pointer like".
template<>
- class PointerLikeTypeTraits<swift::Type> {
+ struct PointerLikeTypeTraits<swift::Type> {
public:
static inline void *getAsVoidPointer(swift::Type I) {
return (void*)I.getPointer();
@@ -686,7 +686,7 @@
};
template<>
- class PointerLikeTypeTraits<swift::CanType> :
+ struct PointerLikeTypeTraits<swift::CanType> :
public PointerLikeTypeTraits<swift::Type> {
public:
static inline swift::CanType getFromVoidPointer(void *P) {
@@ -695,7 +695,7 @@
};
template<>
- class PointerLikeTypeTraits<swift::CanGenericSignature> {
+ struct PointerLikeTypeTraits<swift::CanGenericSignature> {
public:
static inline swift::CanGenericSignature getFromVoidPointer(void *P) {
return swift::CanGenericSignature((swift::GenericSignature*)P);
diff --git a/include/swift/AST/TypeAlignments.h b/include/swift/AST/TypeAlignments.h
index 3c68c5a..f4c4b78 100644
--- a/include/swift/AST/TypeAlignments.h
+++ b/include/swift/AST/TypeAlignments.h
@@ -72,14 +72,14 @@
}
};
- template <class T> class PointerLikeTypeTraits;
+ template <class T> struct PointerLikeTypeTraits;
}
/// Declare the expected alignment of pointers to the given type.
/// This macro should be invoked from a top-level file context.
#define LLVM_DECLARE_TYPE_ALIGNMENT(CLASS, ALIGNMENT) \
namespace llvm { \
-template <> class PointerLikeTypeTraits<CLASS*> \
+template <> struct PointerLikeTypeTraits<CLASS*> \
: public MoreAlignedPointerTraits<CLASS, ALIGNMENT> {}; \
}
diff --git a/include/swift/Basic/DiverseStack.h b/include/swift/Basic/DiverseStack.h
index 9403912..7445512 100644
--- a/include/swift/Basic/DiverseStack.h
+++ b/include/swift/Basic/DiverseStack.h
@@ -378,7 +378,7 @@
/// Allow stable_iterators to be put in things like TinyPtrVectors.
namespace llvm {
template <>
- class PointerLikeTypeTraits<
+ struct PointerLikeTypeTraits<
swift::DiverseStackBase::stable_iterator::AsPointer> {
using AsPointer = swift::DiverseStackBase::stable_iterator::AsPointer;
public:
diff --git a/include/swift/Basic/FlaggedPointer.h b/include/swift/Basic/FlaggedPointer.h
index b409f47..5b5743d 100644
--- a/include/swift/Basic/FlaggedPointer.h
+++ b/include/swift/Basic/FlaggedPointer.h
@@ -152,7 +152,7 @@
// Teach SmallPtrSet that FlaggedPointer is "basically a pointer".
template <typename PointerTy, unsigned BitPosition, typename PtrTraits>
-class llvm::PointerLikeTypeTraits<
+struct llvm::PointerLikeTypeTraits<
swift::FlaggedPointer<PointerTy, BitPosition, PtrTraits>> {
public:
static inline void *
diff --git a/include/swift/Basic/SupplementaryOutputPaths.h b/include/swift/Basic/SupplementaryOutputPaths.h
index 95098da..6653c7e 100644
--- a/include/swift/Basic/SupplementaryOutputPaths.h
+++ b/include/swift/Basic/SupplementaryOutputPaths.h
@@ -49,6 +49,9 @@
/// frontend invocation.
std::string SerializedDiagnosticsPath;
+ /// The path to which we should output fix-its as source edits.
+ std::string FixItsOutputPath;
+
/// The path to which we should output a loaded module trace file.
/// It is currently only used with WMO, but could be generalized.
std::string LoadedModuleTracePath;
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 0e8146d..62e4829 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -55,9 +55,6 @@
/// The name of the library to link against when using this module.
std::string ModuleLinkName;
- /// The path to which we should output fixits as source edits.
- std::string FixitsOutputPath;
-
/// Arguments which should be passed in immediate mode.
std::vector<std::string> ImmediateArgv;
diff --git a/include/swift/Frontend/InputFile.h b/include/swift/Frontend/InputFile.h
index caed06f..6965501 100644
--- a/include/swift/Frontend/InputFile.h
+++ b/include/swift/Frontend/InputFile.h
@@ -95,6 +95,9 @@
return getPrimarySpecificPaths().SupplementaryOutputs
.SerializedDiagnosticsPath;
}
+ std::string fixItsOutputPath() const {
+ return getPrimarySpecificPaths().SupplementaryOutputs.FixItsOutputPath;
+ }
};
} // namespace swift
diff --git a/include/swift/Parse/Lexer.h b/include/swift/Parse/Lexer.h
index 90b544c..9440aa6 100644
--- a/include/swift/Parse/Lexer.h
+++ b/include/swift/Parse/Lexer.h
@@ -195,8 +195,10 @@
void lex(Token &Result, syntax::Trivia &LeadingTriviaResult,
syntax::Trivia &TrailingTriviaResult) {
Result = NextToken;
- LeadingTriviaResult = {LeadingTrivia};
- TrailingTriviaResult = {TrailingTrivia};
+ if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
+ LeadingTriviaResult = {LeadingTrivia};
+ TrailingTriviaResult = {TrailingTrivia};
+ }
if (Result.isNot(tok::eof))
lexImpl();
}
diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h
index f2fa9a2..c495998 100644
--- a/include/swift/Runtime/Debug.h
+++ b/include/swift/Runtime/Debug.h
@@ -224,6 +224,10 @@
SWIFT_RUNTIME_STDLIB_SPI
bool _swift_reportFatalErrorsToDebugger;
+SWIFT_RUNTIME_STDLIB_SPI
+bool _swift_shouldReportFatalErrorsToDebugger();
+
+
LLVM_ATTRIBUTE_ALWAYS_INLINE
inline static int swift_asprintf(char **strp, const char *fmt, ...) {
va_list args;
diff --git a/include/swift/SIL/Dominance.h b/include/swift/SIL/Dominance.h
index 539c580..091a9a6 100644
--- a/include/swift/SIL/Dominance.h
+++ b/include/swift/SIL/Dominance.h
@@ -30,10 +30,8 @@
using SILDomTree = llvm::DomTreeBase<swift::SILBasicBlock>;
using SILPostDomTree = llvm::PostDomTreeBase<swift::SILBasicBlock>;
-extern template void Calculate<SILDomTree, swift::SILFunction>(
- SILDomTree &DT, swift::SILFunction &F);
-extern template void Calculate<SILPostDomTree, swift::SILFunction>(
- SILPostDomTree &DT, swift::SILFunction &F);
+extern template void Calculate<SILDomTree>(SILDomTree &DT);
+extern template void Calculate<SILPostDomTree>(SILPostDomTree &DT);
} // namespace DomTreeBuilder
} // namespace llvm
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index d3ac08b..29b5d64 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -166,7 +166,7 @@
reverse_range getReversedValues() const;
using type_range = llvm::iterator_range<
- llvm::mapped_iterator<iterator, std::function<SILType(SILValue)>>>;
+ llvm::mapped_iterator<iterator, std::function<SILType(SILValue)>, SILType>>;
type_range getTypes() const;
bool operator==(const SILInstructionResultArray &rhs);
diff --git a/include/swift/SIL/SILNode.h b/include/swift/SIL/SILNode.h
index b6e0b84..106365a 100644
--- a/include/swift/SIL/SILNode.h
+++ b/include/swift/SIL/SILNode.h
@@ -544,7 +544,7 @@
/// ValueBase * is always at least eight-byte aligned; make the three tag bits
/// available through PointerLikeTypeTraits.
template<>
-class PointerLikeTypeTraits<swift::SILNode *> {
+struct PointerLikeTypeTraits<swift::SILNode *> {
public:
static inline void *getAsVoidPointer(swift::SILNode *I) {
return (void*)I;
diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h
index 9a65ee9..05883c7 100644
--- a/include/swift/SIL/SILType.h
+++ b/include/swift/SIL/SILType.h
@@ -615,7 +615,7 @@
// Allow the low bit of SILType to be used for nefarious purposes, e.g. putting
// a SILType into a PointerUnion.
template<>
-class PointerLikeTypeTraits<swift::SILType> {
+struct PointerLikeTypeTraits<swift::SILType> {
public:
static inline void *getAsVoidPointer(swift::SILType T) {
return T.getOpaqueValue();
diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h
index bfc202c..dedf753 100644
--- a/include/swift/SIL/SILValue.h
+++ b/include/swift/SIL/SILValue.h
@@ -272,7 +272,7 @@
/// ValueBase * is always at least eight-byte aligned; make the three tag bits
/// available through PointerLikeTypeTraits.
template<>
-class PointerLikeTypeTraits<swift::ValueBase *> {
+struct PointerLikeTypeTraits<swift::ValueBase *> {
public:
static inline void *getAsVoidPointer(swift::ValueBase *I) {
return (void*)I;
@@ -627,7 +627,7 @@
};
/// SILValue is a PointerLikeType.
- template<> class PointerLikeTypeTraits<::swift::SILValue> {
+ template<> struct PointerLikeTypeTraits<::swift::SILValue> {
using SILValue = ::swift::SILValue;
public:
static void *getAsVoidPointer(SILValue v) {
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index cd0c9a1..e8e86f8 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -2143,7 +2143,7 @@
if (ASD->getSetter() &&
ASD->getSetter()->getFormalAccess() != setterAccess) {
Out << "AbstractStorageDecl's setter access is out of sync"
- " with the access actually on the setter";
+ " with the access actually on the setter\n";
abort();
}
}
@@ -2151,21 +2151,22 @@
if (auto getter = ASD->getGetter()) {
if (getter->isMutating() != ASD->isGetterMutating()) {
Out << "AbstractStorageDecl::isGetterMutating is out of sync"
- " with whether the getter is actually mutating";
+ " with whether the getter is actually mutating\n";
abort();
}
}
if (auto setter = ASD->getSetter()) {
if (setter->isMutating() != ASD->isSetterMutating()) {
Out << "AbstractStorageDecl::isSetterMutating is out of sync"
- " with whether the setter is actually mutating";
+ " with whether the setter is actually mutating\n";
abort();
}
}
if (auto materializeForSet = ASD->getMaterializeForSetFunc()) {
- if (materializeForSet->isMutating() != ASD->isSetterMutating()) {
- Out << "AbstractStorageDecl::isSetterMutating is out of sync"
- " with whether materializeForSet is mutating";
+ if (materializeForSet->isMutating() !=
+ (ASD->isSetterMutating() || ASD->isGetterMutating())) {
+ Out << "AbstractStorageDecl::is{Getter,Setter}Mutating is out of sync"
+ " with whether materializeForSet is mutating\n";
abort();
}
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index a63cf56..0d96054 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -107,6 +107,14 @@
"Delayed requirements left unresolved");
STATISTIC(NumConditionalRequirementsAdded,
"# of conditional requirements added");
+STATISTIC(NumRewriteMinimizations,
+ "# of rewrite system minimizations performed");
+STATISTIC(NumRewriteRhsSimplified,
+ "# of rewrite rule right-hand sides simplified");
+STATISTIC(NumRewriteRhsSimplifiedToLhs,
+ "# of rewrite rule right-hand sides simplified to lhs (and removed)");
+STATISTIC(NumRewriteRulesRedundant,
+ "# of rewrite rules that are redundant (and removed)");
namespace {
@@ -114,6 +122,8 @@
/// sequence of associated type references.
using RelativeRewritePath = ArrayRef<AssociatedTypeDecl *>;
+class AnchorPathCache;
+
/// Describes a rewrite path, which contains an optional base (generic
/// parameter) followed by a sequence of associated type references.
class RewritePath {
@@ -158,13 +168,25 @@
/// types.
Optional<RewritePath> static createPath(Type type);
+ /// Decompose a type into a path.
+ ///
+ /// \param path Will be filled in with the components of the path, in
+ /// reverse order.
+ ///
+ /// \returns the generic parameter at the start of the path, or \c None if
+ ///
+ Optional<GenericParamKey>
+ static createPath(Type type, SmallVectorImpl<AssociatedTypeDecl *> &path);
+
/// Compute the longer common prefix between this path and \c other.
RewritePath commonPath(const RewritePath &other) const;
/// Form a canonical, dependent type.
///
- /// This requires that the rewrite path have a base.
- CanType formDependentType(ASTContext &ctx) const;
+ /// This requires that either the rewrite path have a base, or the
+ /// \c baseEquivClass to be non-null (which substitutes in a base).
+ CanType formDependentType(ASTContext &ctx,
+ AnchorPathCache *anchorPathCache = nullptr) const;
/// Compare the given rewrite paths.
int compare(const RewritePath &other) const;
@@ -182,6 +204,26 @@
}
};
+/// A cache that lazily computes the anchor path for the given equivalence
+/// class.
+class AnchorPathCache {
+ GenericSignatureBuilder &builder;
+ EquivalenceClass &equivClass;
+ Optional<RewritePath> anchorPath;
+
+public:
+ AnchorPathCache(GenericSignatureBuilder &builder,
+ EquivalenceClass &equivClass)
+ : builder(builder), equivClass(equivClass) { }
+
+ Optional<RewritePath> getAnchorPath() {
+ if (anchorPath) return anchorPath;
+
+ anchorPath = RewritePath::createPath(equivClass.getAnchor(builder, { }));
+ return anchorPath;
+ }
+};
+
/// A node within the prefix tree that is used to match associated type
/// references.
class RewriteTreeNode {
@@ -239,12 +281,24 @@
rewrite = replacementPath;
}
+ /// Remove the rewrite rule.
+ void removeRewriteRule() {
+ assert(hasRewriteRule());
+ assocTypeAndHasRewrite.setInt(false);
+ }
+
/// Retrieve the path to which this node will be rewritten.
- const RewritePath &getRewriteRule() const {
+ const RewritePath &getRewriteRule() const & {
assert(hasRewriteRule());
return rewrite;
}
+ /// Retrieve the path to which this node will be rewritten.
+ RewritePath &&getRewriteRule() && {
+ assert(hasRewriteRule());
+ return std::move(rewrite);
+ }
+
/// Add a new rewrite rule to this tree node.
///
/// \param matchPath The path of associated type declarations that must
@@ -252,7 +306,10 @@
///
/// \param replacementPath The sequence of associated type declarations
/// with which a match will be replaced.
- void addRewriteRule(RelativeRewritePath matchPath,
+ ///
+ /// \returns true if a rewrite rule was added, and false if it already
+ /// existed.
+ bool addRewriteRule(RelativeRewritePath matchPath,
RewritePath replacementPath);
/// Enumerate all of the paths to which the given matched path can be
@@ -283,11 +340,62 @@
/// \param path The path to match.
/// \param prefixLength The length of the prefix leading up to \c path.
Optional<std::pair<unsigned, RewritePath>>
- bestMatch(GenericParamKey base, RelativeRewritePath path,
+ bestRewritePath(GenericParamKey base, RelativeRewritePath path,
unsigned prefixLength);
/// Merge the given rewrite tree into \c other.
- void mergeInto(RewriteTreeNode *other);
+ ///
+ /// \returns true if any rules were created by this merge.
+ bool mergeInto(RewriteTreeNode *other);
+
+ /// An action to perform for the given rule
+ class RuleAction {
+ enum Kind {
+ /// No action; continue traversal.
+ None,
+
+ /// Stop traversal.
+ Stop,
+
+ /// Remove the given rule completely.
+ Remove,
+
+ /// Replace the right-hand side of the rule with the given new path.
+ Replace,
+ } kind;
+
+ RewritePath path;
+
+ RuleAction(Kind kind, RewritePath path = {})
+ : kind(kind), path(path) { }
+
+ friend class RewriteTreeNode;
+
+ public:
+ static RuleAction none() { return RuleAction(None); }
+ static RuleAction stop() { return RuleAction(Stop); }
+ static RuleAction remove() { return RuleAction(Remove); }
+
+ static RuleAction replace(RewritePath path) {
+ return RuleAction(Replace, std::move(path));
+ }
+
+ operator Kind() const { return kind; }
+ };
+
+ /// Callback function for enumerating rules in a tree.
+ using EnumerateCallback =
+ RuleAction(RelativeRewritePath lhs, const RewritePath &rhs);
+
+ /// Enumerate all of the rewrite rules, calling \c fn with the left and
+ /// right-hand sides of each rule.
+ ///
+ /// \returns true if the action function returned \c Stop at any point.
+ bool enumerateRules(llvm::function_ref<EnumerateCallback> fn,
+ bool temporarilyDisableVisitedRule = false) {
+ SmallVector<AssociatedTypeDecl *, 4> lhs;
+ return enumerateRulesRec(fn, temporarilyDisableVisitedRule, lhs);
+ }
LLVM_ATTRIBUTE_DEPRECATED(void dump() const LLVM_ATTRIBUTE_USED,
"only for use within the debugger");
@@ -296,9 +404,13 @@
void dump(llvm::raw_ostream &out, bool lastChild = true) const;
private:
- /// Merge the given rewrite tree into \c other.
- void mergeIntoRec(RewriteTreeNode *other,
- llvm::SmallVectorImpl<AssociatedTypeDecl *> &matchPath);
+ /// Enumerate all of the rewrite rules, calling \c fn with the left and
+ /// right-hand sides of each rule.
+ ///
+ /// \returns true if the action function returned \c Stop at any point.
+ bool enumerateRulesRec(llvm::function_ref<EnumerateCallback> &fn,
+ bool temporarilyDisableVisitedRule,
+ llvm::SmallVectorImpl<AssociatedTypeDecl *> &lhs);
};
}
@@ -329,6 +441,13 @@
DenseMap<const EquivalenceClass *, std::unique_ptr<RewriteTreeNode>>
RewriteTreeRoots;
+ /// The generation number for the term-rewriting system, which is
+ /// increased every time a new rule gets added.
+ unsigned RewriteGeneration = 0;
+
+ /// The generation at which the term-rewriting system was last minimized.
+ unsigned LastRewriteMinimizedGeneration = 0;
+
/// The generation number, which is incremented whenever we successfully
/// introduce a new constraint.
unsigned Generation = 0;
@@ -339,6 +458,9 @@
/// Whether we are currently processing delayed requirements.
bool ProcessingDelayedRequirements = false;
+ /// Whether we are currently minimizing the term-rewriting system.
+ bool MinimizingRewriteSystem = false;
+
/// Whether there were any errors.
bool HadAnyError = false;
@@ -369,6 +491,21 @@
/// creating it if needed.
RewriteTreeNode *getOrCreateRewriteTreeRoot(
const EquivalenceClass *equivClass);
+
+ /// Minimize the rewrite tree by minimizing the right-hand sides and
+ /// removing redundant rules.
+ void minimizeRewriteTree(GenericSignatureBuilder &builder);
+
+private:
+ /// Minimize the right-hand sides of the rewrite tree, simplifying them
+ /// as far as possible and removing any changes that result in trivial
+ /// rules.
+ void minimizeRewriteTreeRhs(GenericSignatureBuilder &builder);
+
+ /// Minimize the right-hand sides of the rewrite tree, simplifying them
+ /// as far as possible and removing any changes that result in trivial
+ /// rules.
+ void removeRewriteTreeRedundancies(GenericSignatureBuilder &builder);
};
#pragma mark Memory management
@@ -3038,6 +3175,16 @@
Optional<RewritePath> RewritePath::createPath(Type type) {
SmallVector<AssociatedTypeDecl *, 4> path;
+ if (auto genericParam = createPath(type, path)) {
+ return RewritePath(*genericParam, path, Reverse);
+ }
+
+ return None;
+}
+
+Optional<GenericParamKey>
+RewritePath::createPath(Type type,
+ SmallVectorImpl<AssociatedTypeDecl *> &path) {
while (auto depMemTy = type->getAs<DependentMemberType>()) {
auto assocType = depMemTy->getAssocType();
if (!assocType) return None;
@@ -3049,7 +3196,7 @@
auto genericParam = type->getAs<GenericTypeParamType>();
if (!genericParam) return None;
- return RewritePath(GenericParamKey(genericParam), path, Reverse);
+ return GenericParamKey(genericParam);
}
RewritePath RewritePath::commonPath(const RewritePath &other) const {
@@ -3090,9 +3237,24 @@
path);
}
-CanType RewritePath::formDependentType(ASTContext &ctx) const {
- assert(getBase());
- return CanType(::formDependentType(ctx, *getBase(), getPath()));
+CanType RewritePath::formDependentType(
+ ASTContext &ctx,
+ AnchorPathCache *anchorPathCache) const {
+ if (auto base = getBase())
+ return CanType(::formDependentType(ctx, *base, getPath()));
+
+ assert(anchorPathCache && "Need an anchor path cache");
+ Optional<RewritePath> anchorPath = anchorPathCache->getAnchorPath();
+ if (!anchorPath) return CanType();
+
+ // Add the relative path to the anchor path.
+ SmallVector<AssociatedTypeDecl *, 4> absolutePath;
+ absolutePath.append(anchorPath->getPath().begin(),
+ anchorPath->getPath().end());
+ absolutePath.append(getPath().begin(), getPath().end());
+ return CanType(::formDependentType(ctx, *anchorPath->getBase(),
+ absolutePath));
+
}
int RewritePath::compare(const RewritePath &other) const {
@@ -3162,25 +3324,25 @@
};
}
-void RewriteTreeNode::addRewriteRule(RelativeRewritePath matchPath,
+bool RewriteTreeNode::addRewriteRule(RelativeRewritePath matchPath,
RewritePath replacementPath) {
// If the match path is empty, we're adding the rewrite rule to this node.
if (matchPath.empty()) {
// If we don't already have a rewrite rule, add it.
if (!hasRewriteRule()) {
setRewriteRule(replacementPath);
- return;
+ return true;
}
// If we already have this rewrite rule, we're done.
- if (getRewriteRule() == replacementPath) return;
+ if (getRewriteRule() == replacementPath) return false;
// Check whether any of the continuation children matches.
auto insertPos = children.begin();
while (insertPos != children.end() && !(*insertPos)->getMatch()) {
if ((*insertPos)->hasRewriteRule() &&
(*insertPos)->getRewriteRule() == replacementPath)
- return;
+ return false;
++insertPos;
}
@@ -3190,7 +3352,7 @@
auto newChild = new RewriteTreeNode(nullptr);
newChild->setRewriteRule(replacementPath);
children.insert(insertPos, newChild);
- return;
+ return true;
}
// Find (or create) a child node describing the next step in the match.
@@ -3203,7 +3365,7 @@
}
// Add the rewrite rule to the child.
- (*childPos)->addRewriteRule(matchPath.slice(1), replacementPath);
+ return (*childPos)->addRewriteRule(matchPath.slice(1), replacementPath);
}
void RewriteTreeNode::enumerateRewritePathsImpl(
@@ -3236,7 +3398,7 @@
}
Optional<std::pair<unsigned, RewritePath>>
-RewriteTreeNode::bestMatch(GenericParamKey base, RelativeRewritePath path,
+RewriteTreeNode::bestRewritePath(GenericParamKey base, RelativeRewritePath path,
unsigned prefixLength) {
Optional<std::pair<unsigned, RewritePath>> best;
unsigned bestAdjustedLength = 0;
@@ -3267,29 +3429,82 @@
return best;
}
-void RewriteTreeNode::mergeInto(RewriteTreeNode *other) {
- SmallVector<AssociatedTypeDecl *, 4> matchPath;
- mergeIntoRec(other, matchPath);
-}
-
-void RewriteTreeNode::mergeIntoRec(
- RewriteTreeNode *other,
- llvm::SmallVectorImpl<AssociatedTypeDecl *> &matchPath) {
+bool RewriteTreeNode::mergeInto(RewriteTreeNode *other) {
// FIXME: A destructive version of this operation would be more efficient,
// since we generally don't care about \c other after doing this.
- if (auto assocType = getMatch())
- matchPath.push_back(assocType);
+ bool anyAdded = false;
+ (void)enumerateRules([other, &anyAdded](RelativeRewritePath lhs,
+ const RewritePath &rhs) {
+ if (other->addRewriteRule(lhs, rhs))
+ anyAdded = true;
+ return RuleAction::none();
+ });
- // Add this rewrite rule, if there is one.
- if (hasRewriteRule())
- other->addRewriteRule(matchPath, rewrite);
+ return anyAdded;
+}
+
+bool RewriteTreeNode::enumerateRulesRec(
+ llvm::function_ref<EnumerateCallback> &fn,
+ bool temporarilyDisableVisitedRule,
+ llvm::SmallVectorImpl<AssociatedTypeDecl *> &lhs) {
+ if (auto assocType = getMatch())
+ lhs.push_back(assocType);
+
+ SWIFT_DEFER {
+ if (auto assocType = getMatch())
+ lhs.pop_back();
+ };
+
+ // If there is a rewrite rule, invoke the callback.
+ if (hasRewriteRule()) {
+ // If we're supposed to temporarily disabled the visited rule, do so
+ // now.
+ Optional<RewritePath> rewriteRule;
+ if (temporarilyDisableVisitedRule) {
+ rewriteRule = std::move(*this).getRewriteRule();
+ removeRewriteRule();
+ }
+
+ // Make sure that we put the rewrite rule back in place if we moved it
+ // aside.
+ SWIFT_DEFER {
+ if (temporarilyDisableVisitedRule && rewriteRule)
+ setRewriteRule(*std::move(rewriteRule));
+ };
+
+ switch (auto action =
+ fn(lhs, rewriteRule ? *rewriteRule : getRewriteRule())) {
+ case RuleAction::None:
+ break;
+
+ case RuleAction::Stop:
+ return true;
+
+ case RuleAction::Remove:
+ if (temporarilyDisableVisitedRule)
+ rewriteRule = None;
+ else
+ removeRewriteRule();
+ break;
+
+ case RuleAction::Replace:
+ if (temporarilyDisableVisitedRule) {
+ rewriteRule = std::move(action.path);
+ } else {
+ removeRewriteRule();
+ setRewriteRule(action.path);
+ }
+ break;
+ }
+ }
// Recurse into the child nodes.
- for (auto child : children)
- child->mergeIntoRec(other, matchPath);
+ for (auto child : children) {
+ if (child->enumerateRulesRec(fn, temporarilyDisableVisitedRule, lhs))
+ return true;
+ }
- if (getMatch())
- matchPath.pop_back();
+ return false;
}
void RewriteTreeNode::dump() const {
@@ -3354,22 +3569,133 @@
return root.get();
}
-void GenericSignatureBuilder::addSameTypeRewriteRule(
+void GenericSignatureBuilder::Implementation::minimizeRewriteTree(
+ GenericSignatureBuilder &builder) {
+ // Only perform minimization if the term-rewriting tree has changed.
+ if (LastRewriteMinimizedGeneration == RewriteGeneration
+ || MinimizingRewriteSystem)
+ return;
+
+ ++NumRewriteMinimizations;
+ llvm::SaveAndRestore<bool> minimizingRewriteSystem(MinimizingRewriteSystem,
+ true);
+ SWIFT_DEFER {
+ LastRewriteMinimizedGeneration = RewriteGeneration;
+ };
+
+ minimizeRewriteTreeRhs(builder);
+ removeRewriteTreeRedundancies(builder);
+}
+
+void GenericSignatureBuilder::Implementation::minimizeRewriteTreeRhs(
+ GenericSignatureBuilder &builder) {
+ assert(MinimizingRewriteSystem);
+
+ // Minimize the right-hand sides of each rule in the tree.
+ for (auto &equivClass : EquivalenceClasses) {
+ auto root = RewriteTreeRoots.find(&equivClass);
+ if (root == RewriteTreeRoots.end()) continue;
+
+ AnchorPathCache anchorPathCache(builder, equivClass);
+
+ ASTContext &ctx = builder.getASTContext();
+ root->second->enumerateRules([&](RelativeRewritePath lhs,
+ const RewritePath &rhs) {
+ // Compute the type of the right-hand side.
+ Type rhsType = rhs.formDependentType(ctx, &anchorPathCache);
+ if (!rhsType) return RewriteTreeNode::RuleAction::none();
+
+ // Compute the canonical type for the right-hand side.
+ Type canonicalRhsType = builder.getCanonicalTypeParameter(rhsType);
+
+ // If the canonicalized result is equivalent to the right-hand side we
+ // had, there's nothing to do.
+ if (rhsType->isEqual(canonicalRhsType))
+ return RewriteTreeNode::RuleAction::none();
+
+ // We have a canonical replacement path. Determine its encoding and
+ // perform the replacement.
+ ++NumRewriteRhsSimplified;
+
+ // Determine replacement path, which might be relative to the anchor.
+ auto canonicalRhsPath = *RewritePath::createPath(canonicalRhsType);
+ auto anchorPath = anchorPathCache.getAnchorPath();
+ if (auto prefix = anchorPath->commonPath(canonicalRhsPath)) {
+ unsigned prefixLength = prefix.getPath().size();
+ RelativeRewritePath replacementRhsPath =
+ canonicalRhsPath.getPath().slice(prefixLength);
+
+ // If the left and right-hand sides are equivalent, just remove the
+ // rule.
+ if (lhs == replacementRhsPath) {
+ ++NumRewriteRhsSimplifiedToLhs;
+ return RewriteTreeNode::RuleAction::remove();
+ }
+
+ RewritePath replacementRhs(None, replacementRhsPath,
+ RewritePath::Forward);
+ return RewriteTreeNode::RuleAction::replace(std::move(replacementRhs));
+ }
+
+ return RewriteTreeNode::RuleAction::replace(canonicalRhsPath);
+ });
+ }
+}
+
+void GenericSignatureBuilder::Implementation::removeRewriteTreeRedundancies(
+ GenericSignatureBuilder &builder) {
+ assert(MinimizingRewriteSystem);
+
+ // Minimize the right-hand sides of each rule in the tree.
+ for (auto &equivClass : EquivalenceClasses) {
+ auto root = RewriteTreeRoots.find(&equivClass);
+ if (root == RewriteTreeRoots.end()) continue;
+
+ AnchorPathCache anchorPathCache(builder, equivClass);
+
+ ASTContext &ctx = builder.getASTContext();
+ root->second->enumerateRules([&](RelativeRewritePath lhs,
+ const RewritePath &rhs) {
+ /// Left-hand side type.
+ Type lhsType = RewritePath(None, lhs, RewritePath::Forward)
+ .formDependentType(ctx, &anchorPathCache);
+ if (!lhsType) return RewriteTreeNode::RuleAction::none();
+
+ // Simplify the left-hand type.
+ Type simplifiedLhsType = builder.getCanonicalTypeParameter(lhsType);
+ if (!simplifiedLhsType) return RewriteTreeNode::RuleAction::none();
+
+ // Compute the type of the right-hand side.
+ Type rhsType = rhs.formDependentType(ctx, &anchorPathCache);
+ if (!rhsType) return RewriteTreeNode::RuleAction::none();
+
+ if (simplifiedLhsType->isEqual(rhsType)) {
+ ++NumRewriteRulesRedundant;
+ return RewriteTreeNode::RuleAction::remove();
+ }
+
+ return RewriteTreeNode::RuleAction::none();
+ },
+ /*temporarilyDisableVisitedRule=*/true);
+ }
+}
+
+bool GenericSignatureBuilder::addSameTypeRewriteRule(
EquivalenceClass *equivClass,
PotentialArchetype *otherPA){
// Simplify both sides in the hope of uncovering a common path.
Type simplifiedType1 = equivClass->getAnchor(*this, { });
- if (!simplifiedType1) return;
+ if (!simplifiedType1) return false;
Type simplifiedType2;
if (auto otherEquivClass = otherPA->getEquivalenceClassIfPresent())
simplifiedType2 = otherEquivClass->getAnchor(*this, { });
else
simplifiedType2 = getCanonicalTypeParameter(otherPA->getDependentType({ }));
- if (!simplifiedType2) return;
+ if (!simplifiedType2) return false;
// We already effectively have this rewrite rule.
- if (simplifiedType1->isEqual(simplifiedType2)) return;
+ if (simplifiedType1->isEqual(simplifiedType2)) return false;
auto path1 = *RewritePath::createPath(simplifiedType1);
auto path2 = *RewritePath::createPath(simplifiedType2);
@@ -3394,10 +3720,9 @@
// Add the rewrite rule.
auto root = Impl->getOrCreateRewriteTreeRoot(equivClass);
- root->addRewriteRule(relPath1,
- RewritePath(None, relPath2, RewritePath::Forward));
-
- return;
+ return root->addRewriteRule(
+ relPath1,
+ RewritePath(None, relPath2, RewritePath::Forward));
}
// Otherwise, form a rewrite rule with absolute paths.
@@ -3417,7 +3742,7 @@
assert(baseEquivClass && "Base cannot be resolved?");
auto root = Impl->getOrCreateRewriteTreeRoot(baseEquivClass);
- root->addRewriteRule(path1.getPath(), path2);
+ return root->addRewriteRule(path1.getPath(), path2);
}
Type GenericSignatureBuilder::getCanonicalTypeParameter(Type type) {
@@ -3443,7 +3768,7 @@
if (auto rootNode = Impl->getRewriteTreeRootIfPresent(equivClass)) {
// Find the best rewrite rule for the path starting at startIndex.
auto match =
- rootNode->bestMatch(genericParamType,
+ rootNode->bestRewritePath(genericParamType,
llvm::makeArrayRef(path).slice(startIndex),
startIndex);
@@ -4143,7 +4468,9 @@
// ... from the same module as the protocol.
if (type->getModuleContext() != proto->getModuleContext()) continue;
- // Or is constrained.
+ // Ignore types defined in constrained extensions; their equivalence
+ // to the associated type would have to be conditional, which we cannot
+ // model.
if (auto ext = dyn_cast<ExtensionDecl>(type->getDeclContext())) {
if (ext->isConstrainedExtension()) continue;
}
@@ -4564,7 +4891,8 @@
// Add a rewrite rule to map T2 down to the anchor.
auto equivClass = T1->getOrCreateEquivalenceClass(*this);
- addSameTypeRewriteRule(equivClass, T2);
+ if (addSameTypeRewriteRule(equivClass, T2))
+ ++Impl->RewriteGeneration;
// Merge the equivalence classes.
equivClass->modified(*this);
@@ -4595,7 +4923,8 @@
if (auto rewriteRoot2 = Impl->getOrCreateRewriteTreeRoot(equivClass2)) {
if (auto rewriteRoot1 = Impl->getOrCreateRewriteTreeRoot(equivClass)) {
// Merge the second rewrite tree into the first.
- rewriteRoot2->mergeInto(rewriteRoot1);
+ if (rewriteRoot2->mergeInto(rewriteRoot1))
+ ++Impl->RewriteGeneration;
Impl->RewriteTreeRoots.erase(equivClass2);
} else {
// Take the second rewrite tree and make it the first.
diff --git a/lib/Basic/CMakeLists.txt b/lib/Basic/CMakeLists.txt
index 5510318..debe5ce 100644
--- a/lib/Basic/CMakeLists.txt
+++ b/lib/Basic/CMakeLists.txt
@@ -5,7 +5,7 @@
set(UUID_LIBRARIES "")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(UUID_INCLUDE "")
- set(UUID_LIBRARIES "ole32.lib")
+ set(UUID_LIBRARIES "rpcrt4.lib")
else()
find_package(UUID REQUIRED)
set(UUID_INCLUDE "-I${UUID_INCLUDE_DIRS}")
diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp
index 206aaca..2c90231 100644
--- a/lib/Basic/Platform.cpp
+++ b/lib/Basic/Platform.cpp
@@ -113,7 +113,6 @@
case llvm::Triple::RTEMS:
case llvm::Triple::NaCl:
case llvm::Triple::CNK:
- case llvm::Triple::Bitrig:
case llvm::Triple::AIX:
case llvm::Triple::CUDA:
case llvm::Triple::NVCL:
@@ -121,6 +120,7 @@
case llvm::Triple::ELFIAMCU:
case llvm::Triple::Mesa3D:
case llvm::Triple::Contiki:
+ case llvm::Triple::AMDPAL:
return "";
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
diff --git a/lib/Basic/UUID.cpp b/lib/Basic/UUID.cpp
index a8099ba..f17aab4 100644
--- a/lib/Basic/UUID.cpp
+++ b/lib/Basic/UUID.cpp
@@ -42,7 +42,7 @@
swift::UUID::UUID(FromTime_t) {
#if defined(_WIN32)
- ::GUID uuid;
+ ::UUID uuid;
::CoCreateGuid(&uuid);
memcpy(Value, &uuid, Size);
@@ -53,7 +53,8 @@
swift::UUID::UUID() {
#if defined(_WIN32)
- ::GUID uuid = GUID();
+ ::UUID uuid = *((::UUID *)&Value);
+ UuidCreateNil(&uuid);
memcpy(Value, &uuid, Size);
#else
@@ -63,18 +64,11 @@
Optional<swift::UUID> swift::UUID::fromString(const char *s) {
#if defined(_WIN32)
- int length = strlen(s) + 1;
- wchar_t *unicodeString = new wchar_t[length];
+ RPC_CSTR t = const_cast<RPC_CSTR>(reinterpret_cast<const unsigned char*>(s));
- size_t convertedChars = 0;
- errno_t conversionResult =
- mbstowcs_s(&convertedChars, unicodeString, length, s, length);
- assert(conversionResult == 0 &&
- "expected successful conversion of char* to wchar_t*");
-
- ::GUID uuid;
- HRESULT parseResult = CLSIDFromString(unicodeString, &uuid);
- if (parseResult != 0) {
+ ::UUID uuid;
+ RPC_STATUS status = UuidFromStringA(t, &uuid);
+ if (status == RPC_S_INVALID_STRING_UUID) {
return None;
}
@@ -92,19 +86,14 @@
void swift::UUID::toString(llvm::SmallVectorImpl<char> &out) const {
out.resize(UUID::StringBufferSize);
#if defined(_WIN32)
- ::GUID uuid;
+ ::UUID uuid;
memcpy(&uuid, Value, Size);
- LPOLESTR unicodeStr;
- StringFromCLSID(uuid, &unicodeStr);
+ RPC_CSTR str;
+ UuidToStringA(&uuid, &str);
- char str[StringBufferSize];
- int strLen = wcstombs(str, unicodeStr, sizeof(str));
-
- assert(strLen == 37 && "expected ascii convertible output from StringFromCLSID.");
- (void)strLen;
-
- memcpy(out.data(), str, StringBufferSize);
+ char* signedStr = reinterpret_cast<char*>(str);
+ memcpy(out.data(), signedStr, StringBufferSize);
#else
uuid_unparse_upper(Value, out.data());
#endif
@@ -115,13 +104,14 @@
int swift::UUID::compare(UUID y) const {
#if defined(_WIN32)
- ::GUID uuid1;
+ RPC_STATUS s;
+ ::UUID uuid1;
memcpy(&uuid1, Value, Size);
- ::GUID uuid2;
+ ::UUID uuid2;
memcpy(&uuid2, y.Value, Size);
- return memcmp(Value, y.Value, Size);
+ return UuidCompare(&uuid1, &uuid2, &s);
#else
return uuid_compare(Value, y.Value);
#endif
diff --git a/lib/ClangImporter/ClangAdapter.cpp b/lib/ClangImporter/ClangAdapter.cpp
index 04daaf81..6ed0bf4 100644
--- a/lib/ClangImporter/ClangAdapter.cpp
+++ b/lib/ClangImporter/ClangAdapter.cpp
@@ -337,6 +337,7 @@
// FIXME: Types that can be mapped, but aren't yet.
case clang::BuiltinType::Half:
case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::Float16:
case clang::BuiltinType::Float128:
case clang::BuiltinType::NullPtr:
return OmissionTypeName();
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index b43cc42..d8cc57d 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -406,27 +406,6 @@
#define SHIMS_INCLUDE_FLAG "-isystem"
-static StringRef
-getMinVersionOptNameForDarwinTriple(const llvm::Triple &triple) {
- switch(getDarwinPlatformKind(triple)) {
- case DarwinPlatformKind::MacOS:
- return "-mmacosx-version-min=";
- case DarwinPlatformKind::IPhoneOS:
- return "-mios-version-min=";
- case DarwinPlatformKind::IPhoneOSSimulator:
- return "-mios-simulator-version-min=";
- case DarwinPlatformKind::TvOS:
- return "-mtvos-version-min=";
- case DarwinPlatformKind::TvOSSimulator:
- return "-mtvos-simulator-version-min=";
- case DarwinPlatformKind::WatchOS:
- return "-mwatchos-version-min=";
- case DarwinPlatformKind::WatchOSSimulator:
- return "-mwatchos-simulator-version-min=";
- }
- llvm_unreachable("Unsupported Darwin platform");
-}
-
static void
getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
ASTContext &ctx,
@@ -659,24 +638,6 @@
invocationArgStrs.push_back("-target");
invocationArgStrs.push_back(triple.str());
- if (triple.isOSDarwin()) {
- std::string minVersionBuf;
- llvm::raw_string_ostream minVersionOpt{minVersionBuf};
- minVersionOpt << getMinVersionOptNameForDarwinTriple(triple);
-
- unsigned major, minor, micro;
- if (triple.isiOS()) {
- triple.getiOSVersion(major, minor, micro);
- } else if (triple.isWatchOS()) {
- triple.getWatchOSVersion(major, minor, micro);
- } else {
- assert(triple.isMacOSX());
- triple.getMacOSXVersion(major, minor, micro);
- }
- minVersionOpt << clang::VersionTuple(major, minor, micro);
- invocationArgStrs.push_back(std::move(minVersionOpt.str()));
- }
-
invocationArgStrs.push_back(ImporterImpl::moduleImportBufferName);
if (ctx.LangOpts.EnableAppExtensionRestrictions) {
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index c1b09ad..d2c6249 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -224,6 +224,7 @@
// FIXME: Types that can be mapped, but aren't yet.
case clang::BuiltinType::Half:
+ case clang::BuiltinType::Float16:
case clang::BuiltinType::Float128:
case clang::BuiltinType::NullPtr:
return Type();
diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp
index 68c583a..697f015 100644
--- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp
+++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp
@@ -117,9 +117,6 @@
if (checkUnusedSupplementaryOutputPaths())
return true;
- if (const Arg *A = Args.getLastArg(OPT_emit_fixits_path))
- Opts.FixitsOutputPath = A->getValue();
-
if (const Arg *A = Args.getLastArg(OPT_module_link_name))
Opts.ModuleLinkName = A->getValue();
diff --git a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp
index 5698a56..f9616c2 100644
--- a/lib/Frontend/ArgsToFrontendOutputsConverter.cpp
+++ b/lib/Frontend/ArgsToFrontendOutputsConverter.cpp
@@ -283,13 +283,15 @@
options::OPT_emit_reference_dependencies_path);
auto serializedDiagnostics = getSupplementaryFilenamesFromArguments(
options::OPT_serialize_diagnostics_path);
+ auto fixItsOutput = getSupplementaryFilenamesFromArguments(
+ options::OPT_emit_fixits_path);
auto loadedModuleTrace = getSupplementaryFilenamesFromArguments(
options::OPT_emit_loaded_module_trace_path);
auto TBD = getSupplementaryFilenamesFromArguments(options::OPT_emit_tbd_path);
if (!objCHeaderOutput || !moduleOutput || !moduleDocOutput ||
!dependenciesFile || !referenceDependenciesFile ||
- !serializedDiagnostics || !loadedModuleTrace || !TBD) {
+ !serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD) {
return None;
}
std::vector<SupplementaryOutputPaths> result;
@@ -304,6 +306,7 @@
sop.DependenciesFilePath = (*dependenciesFile)[i];
sop.ReferenceDependenciesFilePath = (*referenceDependenciesFile)[i];
sop.SerializedDiagnosticsPath = (*serializedDiagnostics)[i];
+ sop.FixItsOutputPath = (*fixItsOutput)[i];
sop.LoadedModuleTracePath = (*loadedModuleTrace)[i];
sop.TBDPath = (*TBD)[i];
@@ -356,6 +359,9 @@
OPT_serialize_diagnostics, pathsFromArguments.SerializedDiagnosticsPath,
"dia", "", defaultSupplementaryOutputPathExcludingExtension);
+ // There is no non-path form of -emit-fixits-path
+ auto fixItsOutputPath = pathsFromArguments.FixItsOutputPath;
+
auto objcHeaderOutputPath = determineSupplementaryOutputFilename(
OPT_emit_objc_header, pathsFromArguments.ObjCHeaderOutputPath, "h", "",
defaultSupplementaryOutputPathExcludingExtension);
@@ -391,6 +397,7 @@
sop.DependenciesFilePath = dependenciesFilePath;
sop.ReferenceDependenciesFilePath = referenceDependenciesFilePath;
sop.SerializedDiagnosticsPath = serializedDiagnosticsPath;
+ sop.FixItsOutputPath = fixItsOutputPath;
sop.LoadedModuleTracePath = loadedModuleTracePath;
sop.TBDPath = tbdPath;
return sop;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6eb05c3..b522760 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -908,8 +908,10 @@
return false;
}
-bool ParseMigratorArgs(MigratorOptions &Opts, llvm::Triple &Triple,
- StringRef ResourcePath, ArgList &Args,
+bool ParseMigratorArgs(MigratorOptions &Opts,
+ const FrontendOptions &FrontendOpts,
+ const llvm::Triple &Triple,
+ StringRef ResourcePath, const ArgList &Args,
DiagnosticEngine &Diags) {
using namespace options;
@@ -958,6 +960,21 @@
}
}
+ if (Opts.shouldRunMigrator()) {
+ assert(!FrontendOpts.InputsAndOutputs.isWholeModule());
+ // FIXME: In order to support batch mode properly, the migrator would have
+ // to support having one remap file path and one migrated file path per
+ // primary input. The easiest way to do this would be to move processing of
+ // these paths into FrontendOptions, like other supplementary outputs, and
+ // to call migrator::updateCodeAndEmitRemapIfNeeded once for each primary
+ // file.
+ //
+ // Supporting WMO would be similar, but WMO is set up to only produce one
+ // supplementary output for the whole compilation instead of one per input,
+ // so it's probably not worth it.
+ FrontendOpts.InputsAndOutputs.assertMustNotBeMoreThanOnePrimaryInput();
+ }
+
return false;
}
@@ -1022,7 +1039,7 @@
return true;
}
- if (ParseMigratorArgs(MigratorOpts, LangOpts.Target,
+ if (ParseMigratorArgs(MigratorOpts, FrontendOpts, LangOpts.Target,
SearchPathOpts.RuntimeResourcePath, ParsedArgs, Diags)) {
return true;
}
diff --git a/lib/Frontend/DiagnosticVerifier.cpp b/lib/Frontend/DiagnosticVerifier.cpp
index 604bb78..e43fc97 100644
--- a/lib/Frontend/DiagnosticVerifier.cpp
+++ b/lib/Frontend/DiagnosticVerifier.cpp
@@ -17,9 +17,10 @@
#include "swift/Frontend/DiagnosticVerifier.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Parse/Lexer.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include <fstream>
+
using namespace swift;
namespace {
@@ -688,9 +689,12 @@
// Retain the end of the file.
Result.append(LastPos, bufferRange.end());
-
- std::ofstream outs(memBuffer->getBufferIdentifier());
- outs << Result;
+
+ std::error_code error;
+ llvm::raw_fd_ostream outs(memBuffer->getBufferIdentifier(), error,
+ llvm::sys::fs::OpenFlags::F_None);
+ if (!error)
+ outs << Result;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 041886c..743c1d7 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -1509,6 +1509,41 @@
ProfileEvents, ProfileEntities);
}
+/// Creates a diagnostic consumer that handles dispatching diagnostics to
+/// multiple output files, based on the supplementary output paths specified by
+/// \p inputsAndOutputs.
+///
+/// If no output files are needed, returns null.
+static std::unique_ptr<DiagnosticConsumer>
+createDispatchingDiagnosticConsumerIfNeeded(
+ const FrontendInputsAndOutputs &inputsAndOutputs,
+ llvm::function_ref<std::unique_ptr<DiagnosticConsumer>(const InputFile &)>
+ maybeCreateSingleConsumer) {
+
+ // The "4" here is somewhat arbitrary. In practice we're going to have one
+ // sub-consumer for each diagnostic file we're trying to output, which (again
+ // in practice) is going to be 1 in WMO mode and equal to the number of
+ // primary inputs in batch mode. That in turn is going to be "the number of
+ // files we need to recompile in this build, divided by the number of jobs".
+ // So a value of "4" here means that there would be no heap allocation on a
+ // clean build of a module with up to 32 files on an 8-core machine, if the
+ // user doesn't customize anything.
+ SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 4> subConsumers;
+
+ inputsAndOutputs.forEachInputProducingSupplementaryOutput(
+ [&](const InputFile &input) -> bool {
+ if (auto subConsumer = maybeCreateSingleConsumer(input))
+ subConsumers.emplace_back(input.file(), std::move(subConsumer));
+ return false;
+ });
+
+ if (subConsumers.empty())
+ return nullptr;
+ if (subConsumers.size() == 1)
+ return std::move(subConsumers.front()).second;
+ return llvm::make_unique<FileSpecificDiagnosticConsumer>(subConsumers);
+}
+
/// Creates a diagnostic consumer that handles serializing diagnostics, based on
/// the supplementary output paths specified by \p inputsAndOutputs.
///
@@ -1520,39 +1555,39 @@
static std::unique_ptr<DiagnosticConsumer>
createSerializedDiagnosticConsumerIfNeeded(
const FrontendInputsAndOutputs &inputsAndOutputs) {
-
- // The "4" here is somewhat arbitrary. In practice we're going to have one
- // sub-consumer for each .dia file we're trying to output, which (again in
- // practice) is going to be 1 in WMO mode and equal to the number of primary
- // inputs in batch mode. That in turn is going to be "the number of files we
- // need to recompile in this build, divided by the number of jobs". So a
- // value of "4" here means that there would be no heap allocation on a clean
- // build of a module with up to 32 files on an 8-core machine, if the user
- // doesn't customize anything.
- SmallVector<FileSpecificDiagnosticConsumer::ConsumerPair, 4>
- serializedConsumers;
-
- inputsAndOutputs.forEachInputProducingSupplementaryOutput(
- [&](const InputFile &Input) -> bool {
- std::string serializedDiagnosticsPath = Input.serializedDiagnosticsPath();
+ return createDispatchingDiagnosticConsumerIfNeeded(
+ inputsAndOutputs,
+ [](const InputFile &input) -> std::unique_ptr<DiagnosticConsumer> {
+ std::string serializedDiagnosticsPath = input.serializedDiagnosticsPath();
if (serializedDiagnosticsPath.empty())
- return false;
-
- serializedConsumers.emplace_back(
- Input.file(),
- serialized_diagnostics::createConsumer(serializedDiagnosticsPath));
-
- // Continue for other inputs.
- return false;
+ return nullptr;
+ return serialized_diagnostics::createConsumer(serializedDiagnosticsPath);
});
-
- if (serializedConsumers.empty())
- return nullptr;
- if (serializedConsumers.size() == 1)
- return std::move(serializedConsumers.front()).second;
- return llvm::make_unique<FileSpecificDiagnosticConsumer>(serializedConsumers);
}
+/// Creates a diagnostic consumer that handles serializing diagnostics, based on
+/// the supplementary output paths specified in \p options.
+///
+/// The returned consumer will handle producing multiple serialized diagnostics
+/// files if necessary, by using sub-consumers for each file and dispatching to
+/// the right one.
+///
+/// If no serialized diagnostics are being produced, returns null.
+static std::unique_ptr<DiagnosticConsumer>
+createJSONFixItDiagnosticConsumerIfNeeded(
+ const CompilerInvocation &invocation) {
+ return createDispatchingDiagnosticConsumerIfNeeded(
+ invocation.getFrontendOptions().InputsAndOutputs,
+ [&](const InputFile &input) -> std::unique_ptr<DiagnosticConsumer> {
+ std::string fixItsOutputPath = input.fixItsOutputPath();
+ if (fixItsOutputPath.empty())
+ return nullptr;
+ return llvm::make_unique<JSONFixitWriter>(
+ fixItsOutputPath, invocation.getDiagnosticOptions());
+ });
+}
+
+
int swift::performFrontend(ArrayRef<const char *> Args,
const char *Argv0, void *MainAddr,
FrontendObserver *observer) {
@@ -1671,17 +1706,10 @@
if (SerializedConsumerDispatcher)
Instance->addDiagnosticConsumer(SerializedConsumerDispatcher.get());
- // FIXME: The fix-its need to be multiplexed like the serialized diagnostics.
- std::unique_ptr<DiagnosticConsumer> FixitsConsumer;
- {
- const std::string &FixitsOutputPath =
- Invocation.getFrontendOptions().FixitsOutputPath;
- if (!FixitsOutputPath.empty()) {
- FixitsConsumer.reset(new JSONFixitWriter(FixitsOutputPath,
- Invocation.getDiagnosticOptions()));
- Instance->addDiagnosticConsumer(FixitsConsumer.get());
- }
- }
+ std::unique_ptr<DiagnosticConsumer> FixItsConsumer =
+ createJSONFixItDiagnosticConsumerIfNeeded(Invocation);
+ if (FixItsConsumer)
+ Instance->addDiagnosticConsumer(FixItsConsumer.get());
if (Invocation.getDiagnosticOptions().UseColor)
PDC.forceColors();
diff --git a/lib/IDE/APIDigesterData.cpp b/lib/IDE/APIDigesterData.cpp
index 8e7450d..cc6d032 100644
--- a/lib/IDE/APIDigesterData.cpp
+++ b/lib/IDE/APIDigesterData.cpp
@@ -309,7 +309,7 @@
#define DIFF_ITEM_KEY_KIND_STRING(NAME) StringRef NAME;
#define DIFF_ITEM_KEY_KIND_INT(NAME) Optional<int> NAME;
#include "swift/IDE/DigesterEnums.def"
- for (auto Pair : *Node) {
+ for (auto &Pair : *Node) {
switch(parseKeyKind(getScalarString(Pair.getKey()))) {
#define DIFF_ITEM_KEY_KIND_STRING(NAME) \
case DiffItemKeyKind::KK_##NAME: \
diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp
index a90895f..b2157ce 100644
--- a/lib/IRGen/GenCall.cpp
+++ b/lib/IRGen/GenCall.cpp
@@ -870,6 +870,9 @@
return convertFloatingType(Ctx.getTargetInfo().getDoubleFormat());
case clang::BuiltinType::LongDouble:
return convertFloatingType(Ctx.getTargetInfo().getLongDoubleFormat());
+ case clang::BuiltinType::Float16:
+ llvm_unreachable("When upstream support is added for Float16 in "
+ "clang::TargetInfo, use the implementation here");
case clang::BuiltinType::Float128:
return convertFloatingType(Ctx.getTargetInfo().getFloat128Format());
diff --git a/lib/IRGen/IRBuilder.h b/lib/IRGen/IRBuilder.h
index ac59edc..8c2d1d2 100644
--- a/lib/IRGen/IRBuilder.h
+++ b/lib/IRGen/IRBuilder.h
@@ -376,7 +376,7 @@
} // end namespace swift
namespace llvm {
- template <> class PointerLikeTypeTraits<swift::irgen::IRBuilder::StableIP> {
+ template <> struct PointerLikeTypeTraits<swift::irgen::IRBuilder::StableIP> {
typedef swift::irgen::IRBuilder::StableIP type;
public:
static void *getAsVoidPointer(type IP) {
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 353faeb..40d3a5f 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -41,6 +41,7 @@
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
#include "llvm/CodeGen/BasicTTIImpl.h"
+#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/IRPrintingPasses.h"
@@ -62,7 +63,6 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/Coroutines.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
@@ -556,7 +556,7 @@
// Create a target machine.
llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
EffectiveTriple.str(), CPU, targetFeatures, TargetOpts, Reloc::PIC_,
- CodeModel::Default, OptLevel);
+ None, OptLevel);
if (!TargetMachine) {
Ctx.Diags.diagnose(SourceLoc(), diag::no_llvm_target,
EffectiveTriple.str(), "no LLVM target machine");
diff --git a/lib/IRGen/SwiftTargetInfo.cpp b/lib/IRGen/SwiftTargetInfo.cpp
index 3a5b504..c8a5a1c 100644
--- a/lib/IRGen/SwiftTargetInfo.cpp
+++ b/lib/IRGen/SwiftTargetInfo.cpp
@@ -51,7 +51,7 @@
// arm64 requires marker assembly for objc_retainAutoreleasedReturnValue.
target.ObjCRetainAutoreleasedReturnValueMarker =
- "mov\tfp, fp\t\t# marker for objc_retainAutoreleaseReturnValue";
+ "mov\tfp, fp\t\t// marker for objc_retainAutoreleaseReturnValue";
// arm64 requires ISA-masking.
target.ObjCUseISAMask = true;
@@ -100,7 +100,7 @@
SwiftTargetInfo &target) {
// ARM requires marker assembly for objc_retainAutoreleasedReturnValue.
target.ObjCRetainAutoreleasedReturnValueMarker =
- "mov\tr7, r7\t\t@ marker for objc_retainAutoreleaseReturnValue";
+ "mov\tr7, r7\t\t// marker for objc_retainAutoreleaseReturnValue";
// armv7k has opaque ISAs which must go through the ObjC runtime.
if (triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v7k)
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 06b2c47..44b2391 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -1209,7 +1209,7 @@
IndexSymbol Info;
Info.decl = nullptr;
Info.symInfo = SymbolInfo{ SymbolKind::CommentTag, SymbolSubKind::None,
- SymbolPropertySet(), SymbolLanguage::Swift };
+ SymbolLanguage::Swift, SymbolPropertySet() };
Info.roles |= (unsigned)SymbolRole::Definition;
Info.name = StringRef();
SmallString<128> storage;
diff --git a/lib/Index/IndexSymbol.cpp b/lib/Index/IndexSymbol.cpp
index acfd1f1..afcc92d 100644
--- a/lib/Index/IndexSymbol.cpp
+++ b/lib/Index/IndexSymbol.cpp
@@ -138,7 +138,7 @@
SymbolInfo index::getSymbolInfoForDecl(const Decl *D) {
SymbolInfo info{ SymbolKind::Unknown, SymbolSubKind::None,
- SymbolPropertySet(), SymbolLanguage::Swift };
+ SymbolLanguage::Swift, SymbolPropertySet() };
switch (D->getKind()) {
case DeclKind::Enum: info.Kind = SymbolKind::Enum; break;
case DeclKind::Struct: info.Kind = SymbolKind::Struct; break;
diff --git a/lib/LLVMPasses/LLVMSwiftAA.cpp b/lib/LLVMPasses/LLVMSwiftAA.cpp
index 4b349b4..97e3350 100644
--- a/lib/LLVMPasses/LLVMSwiftAA.cpp
+++ b/lib/LLVMPasses/LLVMSwiftAA.cpp
@@ -25,7 +25,7 @@
static ModRefInfo getConservativeModRefForKind(const llvm::Instruction &I) {
switch (classifyInstruction(I)) {
-#define KIND(Name, MemBehavior) case RT_ ## Name: return MRI_ ## MemBehavior;
+#define KIND(Name, MemBehavior) case RT_ ## Name: return ModRefInfo:: MemBehavior;
#include "LLVMSwift.def"
}
@@ -37,8 +37,9 @@
// We know at compile time that certain entry points do not modify any
// compiler-visible state ever. Quickly check if we have one of those
// instructions and return if so.
- if (MRI_NoModRef == getConservativeModRefForKind(*CS.getInstruction()))
- return MRI_NoModRef;
+ if (ModRefInfo::NoModRef ==
+ getConservativeModRefForKind(*CS.getInstruction()))
+ return ModRefInfo::NoModRef;
// Otherwise, delegate to the rest of the AA ModRefInfo machinery.
return AAResultBase::getModRefInfo(CS, Loc);
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 66829cd..047e880 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -283,7 +283,9 @@
StringRef TokenText { TokStart, static_cast<size_t>(CurPtr - TokStart) };
- lexTrivia(TrailingTrivia, /* IsForTrailingTrivia */ true);
+ if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
+ lexTrivia(TrailingTrivia, /* IsForTrailingTrivia */ true);
+ }
NextToken.setToken(Kind, TokenText, CommentLength, MultilineString);
}
@@ -292,11 +294,11 @@
assert(CurPtr - TokStart >= 3 && "escaped identifier must be longer than or equal 3 bytes");
assert(TokStart[0] == '`' && "escaped identifier starts with backtick");
assert(CurPtr[-1] == '`' && "escaped identifier ends with backtick");
- if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
- LeadingTrivia.push_back(TriviaPiece::backtick());
- assert(TrailingTrivia.empty() && "TrailingTrivia is empty here");
- TrailingTrivia.push_back(TriviaPiece::backtick());
- }
+
+ LeadingTrivia.push_back(TriviaPiece::backtick());
+ assert(TrailingTrivia.empty() && "TrailingTrivia is empty here");
+ TrailingTrivia.push_back(TriviaPiece::backtick());
+
formToken(tok::identifier, TokStart);
// If this token is at ArtificialEOF, it's forced to be tok::eof. Don't mark
// this as escaped-identifier in this case.
@@ -2159,18 +2161,15 @@
assert(CurPtr >= BufferStart &&
CurPtr <= BufferEnd && "Current pointer out of range!");
- if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
- LeadingTrivia.clear();
- TrailingTrivia.clear();
- }
+ LeadingTrivia.clear();
+ TrailingTrivia.clear();
+
if (CurPtr == BufferStart) {
if (BufferStart < ContentStart) {
size_t BOMLen = ContentStart - BufferStart;
assert(BOMLen == 3 && "UTF-8 BOM is 3 bytes");
- if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
- // Add UTF-8 BOM to LeadingTrivia.
- LeadingTrivia.push_back(TriviaPiece::garbageText({CurPtr, BOMLen}));
- }
+ // Add UTF-8 BOM to LeadingTrivia.
+ LeadingTrivia.push_back(TriviaPiece::garbageText({CurPtr, BOMLen}));
CurPtr += BOMLen;
}
NextToken.setAtStartOfLine(true);
@@ -2182,7 +2181,6 @@
LastCommentBlockStart = CurPtr;
SeenComment = false;
-Restart:
lexTrivia(LeadingTrivia, /* IsForTrailingTrivia */ false);
// Remember the start of the token so we can form the text range.
@@ -2198,24 +2196,23 @@
return lexOperatorIdentifier();
bool ShouldTokenize = lexUnknown(/*EmitDiagnosticsIfToken=*/true);
- if (ShouldTokenize) {
- return formToken(tok::unknown, TokStart);
- }
- goto Restart; // Skip presumed whitespace.
+ assert(
+ ShouldTokenize &&
+ "Invalid UTF-8 sequence should be eaten by lexTrivia as LeadingTrivia");
+ (void)ShouldTokenize;
+ return formToken(tok::unknown, TokStart);
}
case '\n':
case '\r':
- assert(TriviaRetention != TriviaRetentionMode::WithTrivia &&
- "newlines should be eaten by lexTrivia as LeadingTrivia");
- NextToken.setAtStartOfLine(true);
- goto Restart; // Skip whitespace.
+ llvm_unreachable("Newlines should be eaten by lexTrivia as LeadingTrivia");
case ' ':
case '\t':
case '\f':
case '\v':
- goto Restart; // Skip whitespace.
+ llvm_unreachable(
+ "Whitespaces should be eaten by lexTrivia as LeadingTrivia");
case -1:
case -2:
@@ -2228,17 +2225,16 @@
case NulCharacterKind::CodeCompletion:
return formToken(tok::code_complete, TokStart);
- case NulCharacterKind::Embedded:
- // If this is a random nul character in the middle of a buffer, skip it as
- // whitespace.
- diagnoseEmbeddedNul(Diags, CurPtr-1);
- goto Restart;
case NulCharacterKind::BufferEnd:
- // Otherwise, this is the real end of the buffer. Put CurPtr back into
- // buffer bounds.
+ // This is the real end of the buffer.
+ // Put CurPtr back into buffer bounds.
--CurPtr;
// Return EOF.
return formToken(tok::eof, TokStart);
+
+ case NulCharacterKind::Embedded:
+ llvm_unreachable(
+ "Embedded nul should be eaten by lexTrivia as LeadingTrivia");
}
case '@': return formToken(tok::at_sign, TokStart);
@@ -2275,16 +2271,16 @@
if (CurPtr[0] == '/') { // "//"
skipSlashSlashComment(/*EatNewline=*/true);
SeenComment = true;
- if (isKeepingComments())
- return formToken(tok::comment, TokStart);
- goto Restart;
+ assert(isKeepingComments() &&
+ "Non token comment should be eaten by lexTrivia as LeadingTrivia");
+ return formToken(tok::comment, TokStart);
}
if (CurPtr[0] == '*') { // "/*"
skipSlashStarComment();
SeenComment = true;
- if (isKeepingComments())
- return formToken(tok::comment, TokStart);
- goto Restart;
+ assert(isKeepingComments() &&
+ "Non token comment should be eaten by lexTrivia as LeadingTrivia");
+ return formToken(tok::comment, TokStart);
}
return lexOperatorIdentifier();
case '%':
@@ -2313,13 +2309,9 @@
case '<':
if (CurPtr[0] == '#')
return tryLexEditorPlaceholder();
- else if (CurPtr[0] == '<' && tryLexConflictMarker(/*EatNewline=*/true))
- goto Restart;
- return lexOperatorIdentifier();
+ return lexOperatorIdentifier();
case '>':
- if (CurPtr[0] == '>' && tryLexConflictMarker(/*EatNewline=*/true))
- goto Restart;
return lexOperatorIdentifier();
case '=': case '-': case '+': case '*':
@@ -2378,9 +2370,6 @@
}
void Lexer::lexTrivia(syntax::Trivia &Pieces, bool IsForTrailingTrivia) {
- if (TriviaRetention == TriviaRetentionMode::WithoutTrivia)
- return;
-
Restart:
const char *TriviaStart = CurPtr;
diff --git a/lib/SIL/Dominance.cpp b/lib/SIL/Dominance.cpp
index eb27420..88e034c 100644
--- a/lib/SIL/Dominance.cpp
+++ b/lib/SIL/Dominance.cpp
@@ -24,10 +24,8 @@
namespace llvm {
namespace DomTreeBuilder {
-template void Calculate<SILDomTree, swift::SILFunction>(
- SILDomTree &DT, swift::SILFunction &F);
-template void Calculate<SILPostDomTree, swift::SILFunction>(
- SILPostDomTree &DT, swift::SILFunction &F);
+template void Calculate<SILDomTree>(SILDomTree &DT);
+template void Calculate<SILPostDomTree>(SILPostDomTree &DT);
} // namespace DomTreeBuilder
} // namespace llvm
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 67c1107..70d3889 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -150,7 +150,7 @@
namespace llvm {
-template <> class PointerLikeTypeTraits<GeneralizedUser> {
+template <> struct PointerLikeTypeTraits<GeneralizedUser> {
public:
static void *getAsVoidPointer(GeneralizedUser v) {
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index cf92a42..2ac2bff 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -2342,14 +2342,6 @@
case SILInstructionKind::ApplyInst:
case SILInstructionKind::TryApplyInst:
case SILInstructionKind::PartialApplyInst:
- // Non-Mutating set pattern that allows a inout (that can't really
- // write back. Only SILGen generates PointerToThinkFunction
- // instructions in the writeback code.
- if (auto *AI = dyn_cast<ApplyInst>(inst)) {
- if (isa<PointerToThinFunctionInst>(AI->getCallee())) {
- break;
- }
- }
if (isConsumingOrMutatingApplyUse(use))
return true;
else
@@ -3849,7 +3841,13 @@
case KeyPathPatternComponent::Kind::SettableProperty: {
bool hasIndices = !component.getSubscriptIndices().empty();
- // Getter should be <Sig...> @convention(thin) (@in Base) -> @out Result
+ ParameterConvention normalArgConvention;
+ if (F.getModule().getOptions().EnableGuaranteedNormalArguments)
+ normalArgConvention = ParameterConvention::Indirect_In_Guaranteed;
+ else
+ normalArgConvention = ParameterConvention::Indirect_In;
+
+ // Getter should be <Sig...> @convention(thin) (@in_guaranteed Base) -> @out Result
{
auto getter = component.getComputedPropertyGetter();
auto substGetterType = getter->getLoweredFunctionType()
@@ -3861,9 +3859,8 @@
require(substGetterType->getNumParameters() == 1 + hasIndices,
"getter should have one parameter");
auto baseParam = substGetterType->getParameters()[0];
- require(baseParam.getConvention() ==
- ParameterConvention::Indirect_In,
- "getter base parameter should be @in");
+ require(baseParam.getConvention() == normalArgConvention,
+ "getter base parameter should have normal arg convention");
require(baseParam.getType() == loweredBaseTy.getSwiftRValueType(),
"getter base parameter should match base of component");
@@ -3889,7 +3886,7 @@
if (kind == KeyPathPatternComponent::Kind::SettableProperty) {
// Setter should be
- // <Sig...> @convention(thin) (@in Result, @in Base) -> ()
+ // <Sig...> @convention(thin) (@in_guaranteed Result, @in Base) -> ()
auto setter = component.getComputedPropertySetter();
auto substSetterType = setter->getLoweredFunctionType()
@@ -3903,16 +3900,17 @@
"setter should have two parameters");
auto newValueParam = substSetterType->getParameters()[0];
- require(newValueParam.getConvention() ==
- ParameterConvention::Indirect_In,
- "setter value parameter should be @in");
+ // TODO: This should probably be unconditionally +1 when we
+ // can represent that.
+ require(newValueParam.getConvention() == normalArgConvention,
+ "setter value parameter should havee normal arg convention");
auto baseParam = substSetterType->getParameters()[1];
- require(baseParam.getConvention() ==
- ParameterConvention::Indirect_In
+ require(baseParam.getConvention() == normalArgConvention
|| baseParam.getConvention() ==
ParameterConvention::Indirect_Inout,
- "setter base parameter should be @in or @inout");
+ "setter base parameter should be normal arg convention "
+ "or @inout");
if (hasIndices) {
auto indicesParam = substSetterType->getParameters()[2];
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index 37a0957..c54f546 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -2071,25 +2071,28 @@
auto selfMetatypeType = MetatypeType::get(selfType,
MetatypeRepresentation::Thick);
+ auto canSelfType = selfType->getCanonicalType(genericSig);
+ auto canSelfMetatypeType = selfMetatypeType->getCanonicalType(genericSig);
+ auto selfConvention = (storage->isSetterMutating()
+ ? ParameterConvention::Indirect_Inout
+ : ParameterConvention::Indirect_In_Guaranteed);
+
{
GenericContextScope scope(*this, genericSig);
// If 'self' is a metatype, make it @thin or @thick as needed, but not inside
// selfMetatypeType.
- if (auto metatype = selfType->getAs<MetatypeType>()) {
+ if (auto metatype = canSelfType->getAs<MetatypeType>()) {
if (!metatype->hasRepresentation())
- selfType = getLoweredType(metatype).getSwiftRValueType();
+ canSelfType = getLoweredType(metatype).getSwiftRValueType();
}
}
- auto canSelfType = selfType->getCanonicalType(genericSig);
- auto canSelfMetatypeType = selfMetatypeType->getCanonicalType(genericSig);
-
// Create the SILFunctionType for the callback.
SILParameterInfo params[] = {
{ ctx.TheRawPointerType, ParameterConvention::Direct_Unowned },
{ ctx.TheUnsafeValueBufferType, ParameterConvention::Indirect_Inout },
- { canSelfType, ParameterConvention::Indirect_Inout },
+ { canSelfType, selfConvention },
{ canSelfMetatypeType, ParameterConvention::Direct_Unowned },
};
ArrayRef<SILResultInfo> results = {};
diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp
index 9f5ce5e..765a145 100644
--- a/lib/SILGen/ArgumentSource.cpp
+++ b/lib/SILGen/ArgumentSource.cpp
@@ -174,7 +174,9 @@
case Kind::RValue: {
auto loc = getKnownRValueLocation();
if (auto init = C.getEmitInto()) {
- std::move(*this).asKnownRValue(SGF).forwardInto(SGF, loc, init);
+ std::move(*this).asKnownRValue(SGF)
+ .ensurePlusOne(SGF, loc)
+ .forwardInto(SGF, loc, init);
return ManagedValue::forInContext();
} else {
return std::move(*this).asKnownRValue(SGF).getAsSingleValue(SGF, loc);
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 53ead97..3149b26 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -3008,7 +3008,14 @@
if (!storage->getDeclContext()->isTypeContext())
return ManagedValue();
- auto paramOrigValue = subSGF.emitManagedRValueWithCleanup(paramArg);
+ ManagedValue paramOrigValue;
+
+ if (subSGF.SGM.M.getOptions().EnableGuaranteedNormalArguments) {
+ paramOrigValue =
+ ManagedValue::forBorrowedRValue(paramArg).copy(subSGF, loc);
+ } else {
+ paramOrigValue = subSGF.emitManagedRValueWithCleanup(paramArg);
+ }
auto paramSubstValue = subSGF.emitOrigToSubstValue(loc, paramOrigValue,
AbstractionPattern::getOpaque(),
baseType);
@@ -3107,9 +3114,15 @@
propertyType);
}
+ ParameterConvention paramConvention;
+ if (SGM.M.getOptions().EnableGuaranteedNormalArguments)
+ paramConvention = ParameterConvention::Indirect_In_Guaranteed;
+ else
+ paramConvention = ParameterConvention::Indirect_In;
+
SmallVector<SILParameterInfo, 2> params;
params.push_back({loweredBaseTy.getSwiftRValueType(),
- ParameterConvention::Indirect_In});
+ paramConvention});
auto &C = SGM.getASTContext();
if (!indexes.empty())
params.push_back({C.getUnsafeRawPointerDecl()->getDeclaredType()
@@ -3224,15 +3237,21 @@
auto &C = SGM.getASTContext();
+ ParameterConvention paramConvention;
+ if (SGM.M.getOptions().EnableGuaranteedNormalArguments)
+ paramConvention = ParameterConvention::Indirect_In_Guaranteed;
+ else
+ paramConvention = ParameterConvention::Indirect_In;
+
SmallVector<SILParameterInfo, 3> params;
// property value
params.push_back({loweredPropTy.getSwiftRValueType(),
- ParameterConvention::Indirect_In});
+ paramConvention});
// base
params.push_back({loweredBaseTy.getSwiftRValueType(),
property->isSetterMutating()
? ParameterConvention::Indirect_Inout
- : ParameterConvention::Indirect_In});
+ : paramConvention});
// indexes
if (!indexes.empty())
params.push_back({C.getUnsafeRawPointerDecl()->getDeclaredType()
@@ -3298,7 +3317,12 @@
indexes,
indexPtrArg);
- auto valueOrig = subSGF.emitManagedRValueWithCleanup(valueArg);
+ ManagedValue valueOrig;
+ if (SGM.M.getOptions().EnableGuaranteedNormalArguments)
+ valueOrig = ManagedValue::forBorrowedRValue(valueArg)
+ .copy(subSGF, loc);
+ else
+ valueOrig = subSGF.emitManagedRValueWithCleanup(valueArg);
auto valueSubst = subSGF.emitOrigToSubstValue(loc, valueOrig,
AbstractionPattern::getOpaque(),
propertyType);
@@ -3613,8 +3637,7 @@
SILValue hashCode;
- // TODO: Combine hashes of the indexes. There isn't a great hash combining
- // interface in the standard library to do this yet.
+ // TODO: Combine hashes of the indexes using an inout _Hasher
{
auto &index = indexes[0];
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index 046948d..b3c4cb5 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -964,7 +964,7 @@
}
// The callback gets the address of 'self' at +0.
- ManagedValue mSelf = ManagedValue::forLValue(self);
+ ManagedValue mSelf = ManagedValue::forUnmanaged(self);
// That's enough to build the l-value.
LValue lvalue = buildLValue(SGF, loc, mSelf, std::move(indices),
diff --git a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp
index 7b846a8..ee77a47 100644
--- a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp
+++ b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp
@@ -286,20 +286,25 @@
ArrayRef<Operand> TailCounts = ARI->getTailAllocatedCounts();
SILType TailType;
unsigned NumTailElems = 0;
- if (!TailCounts.empty()) {
- // We only support a single tail allocated array.
- if (TailCounts.size() > 1)
+
+ // We only support a single tail allocated arrays.
+ // Stdlib's tail allocated arrays don't have any side-effects in the
+ // constructor if the element type is trivial.
+ // TODO: also exclude custom tail allocated arrays which might have
+ // side-effects in the destructor.
+ if (TailCounts.size() != 1)
return false;
- // The number of tail allocated elements must be constant.
- if (auto *ILI = dyn_cast<IntegerLiteralInst>(TailCounts[0].get())) {
- if (ILI->getValue().getActiveBits() > 20)
- return false;
- NumTailElems = ILI->getValue().getZExtValue();
- TailType = ARI->getTailAllocatedTypes()[0];
- } else {
+
+ // The number of tail allocated elements must be constant.
+ if (auto *ILI = dyn_cast<IntegerLiteralInst>(TailCounts[0].get())) {
+ if (ILI->getValue().getActiveBits() > 20)
return false;
- }
+ NumTailElems = ILI->getValue().getZExtValue();
+ TailType = ARI->getTailAllocatedTypes()[0];
+ } else {
+ return false;
}
+
SILType Ty = ARI->getType();
ClassDecl *Cl = Ty.getClassOrBoundGenericClass();
if (!Cl)
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 2dcc3fb..1e93ffc 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -296,7 +296,9 @@
static AccessorDecl *
createMaterializeForSetPrototype(AbstractStorageDecl *storage,
- FuncDecl *setter, TypeChecker &TC) {
+ FuncDecl *getter,
+ FuncDecl *setter,
+ TypeChecker &TC) {
auto &ctx = storage->getASTContext();
SourceLoc loc = storage->getLoc();
@@ -319,7 +321,7 @@
params.push_back(buildIndexForwardingParamList(storage, bufferElements));
// The accessor returns (temporary: Builtin.RawPointer,
- // callback: Builtin.RawPointer),
+ // callback: Optional<Builtin.RawPointer>),
// where the first pointer is the materialized address and the
// second is the address of an optional callback.
TupleTypeElt retElts[] = {
@@ -349,10 +351,15 @@
// Open-code the setMutating() calculation since we might run before
// the setter has been type checked.
Type contextTy = DC->getDeclaredInterfaceType();
- if (contextTy && !contextTy->hasReferenceSemantics() &&
+ if (contextTy && !contextTy->hasReferenceSemantics()) {
+ bool hasMutatingSetter =
!setter->getAttrs().hasAttribute<NonMutatingAttr>() &&
- storage->isSetterMutating())
- materializeForSet->setSelfAccessKind(SelfAccessKind::Mutating);
+ storage->isSetterMutating();
+ bool hasMutatingGetter =
+ getter->getAttrs().hasAttribute<MutatingAttr>();
+ if (hasMutatingSetter || hasMutatingGetter)
+ materializeForSet->setSelfAccessKind(SelfAccessKind::Mutating);
+ }
materializeForSet->setStatic(storage->isStatic());
@@ -847,7 +854,7 @@
}
auto materializeForSet = createMaterializeForSetPrototype(
- storage, storage->getSetter(), TC);
+ storage, storage->getGetter(), storage->getSetter(), TC);
addMemberToContextIfNeeded(materializeForSet, storage->getDeclContext(),
storage->getSetter());
storage->setMaterializeForSetFunc(materializeForSet);
@@ -1815,7 +1822,9 @@
AccessorDecl *materializeForSet = nullptr;
if (dc->getAsNominalTypeOrNominalTypeExtensionContext())
- materializeForSet = createMaterializeForSetPrototype(var, setter, TC);
+ materializeForSet = createMaterializeForSetPrototype(var,
+ getter, setter,
+ TC);
var->makeComputed(SourceLoc(), getter, setter, materializeForSet, SourceLoc());
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 7833007..e6b40b8 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -4347,7 +4347,7 @@
if (!MapNode) {
return true;
}
- for (auto Pair : *MapNode) {
+ for (auto &Pair : *MapNode) {
auto *Key = dyn_cast_or_null<llvm::yaml::ScalarNode>(Pair.getKey());
auto *Value = dyn_cast_or_null<llvm::yaml::SequenceNode>(Pair.getValue());
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
index 6be54c0..9f626c4 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
@@ -1089,6 +1089,15 @@
static var runNoTestsWasCalled: Bool = false
static var ranSomething: Bool = false
static var complaintInstalled = false
+ static var hashingKeyOverridden = false
+
+ static func overrideHashingKey() {
+ if !hashingKeyOverridden {
+ // FIXME(hasher): This has to run before creating the first Set/Dictionary
+ _Hasher._secretKey = (0, 0)
+ hashingKeyOverridden = true
+ }
+ }
static func complainIfNothingRuns() {
if !complaintInstalled {
@@ -1200,6 +1209,7 @@
public final class TestSuite {
public init(_ name: String) {
+ PersistentState.overrideHashingKey()
self.name = name
_precondition(
_testNameToIndex[name] == nil,
diff --git a/stdlib/public/core/AnyHashable.swift b/stdlib/public/core/AnyHashable.swift
index ef3087b..3e8b243 100644
--- a/stdlib/public/core/AnyHashable.swift
+++ b/stdlib/public/core/AnyHashable.swift
@@ -48,6 +48,7 @@
/// no comparison is possible. Otherwise, contains the result of `==`.
func _isEqual(to: _AnyHashableBox) -> Bool?
var _hashValue: Int { get }
+ func _hash(_into hasher: inout _Hasher)
var _base: Any { get }
func _downCastConditional<T>(into result: UnsafeMutablePointer<T>) -> Bool
@@ -95,6 +96,12 @@
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
+ func _hash(_into hasher: inout _Hasher) {
+ _baseHashable._hash(into: &hasher)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ @_versioned // FIXME(sil-serialize-all)
internal var _base: Any {
return _baseHashable
}
@@ -295,6 +302,11 @@
public var hashValue: Int {
return _box._hashValue
}
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ _box._hash(_into: &hasher)
+ }
}
extension AnyHashable : CustomStringConvertible {
diff --git a/stdlib/public/core/Bool.swift b/stdlib/public/core/Bool.swift
index 6ab1c17..c4b22c6 100644
--- a/stdlib/public/core/Bool.swift
+++ b/stdlib/public/core/Bool.swift
@@ -154,9 +154,13 @@
/// invocations of the same program. Do not persist the hash value across
/// program runs.
@_inlineable // FIXME(sil-serialize-all)
- @_transparent
public var hashValue: Int {
- return self ? 1 : 0
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append((self ? 1 : 0) as UInt8)
}
@_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift
index e35d1d7..628903b 100644
--- a/stdlib/public/core/CTypes.swift
+++ b/stdlib/public/core/CTypes.swift
@@ -182,7 +182,12 @@
/// program runs.
@_inlineable // FIXME(sil-serialize-all)
public var hashValue: Int {
- return Int(Builtin.ptrtoint_Word(_rawValue))
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(Int(Builtin.ptrtoint_Word(_rawValue)))
}
}
diff --git a/stdlib/public/core/DoubleWidth.swift.gyb b/stdlib/public/core/DoubleWidth.swift.gyb
index b7474bb..fe6f93c 100644
--- a/stdlib/public/core/DoubleWidth.swift.gyb
+++ b/stdlib/public/core/DoubleWidth.swift.gyb
@@ -151,10 +151,13 @@
extension DoubleWidth : Hashable {
@_inlineable // FIXME(sil-serialize-all)
public var hashValue: Int {
- var result = 0
- result = _combineHashValues(result, _storage.high.hashValue)
- result = _combineHashValues(result, _storage.low.hashValue)
- return result
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(low)
+ hasher.append(high)
}
}
diff --git a/stdlib/public/core/DropWhile.swift b/stdlib/public/core/DropWhile.swift
index 741808d..08e8ed8 100644
--- a/stdlib/public/core/DropWhile.swift
+++ b/stdlib/public/core/DropWhile.swift
@@ -190,6 +190,10 @@
public var hashValue: Int {
return base.hashValue
}
+
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(base)
+ }
}
extension LazyDropWhileCollection: Collection {
diff --git a/stdlib/public/core/Flatten.swift b/stdlib/public/core/Flatten.swift
index ea8bade..f94f0af 100644
--- a/stdlib/public/core/Flatten.swift
+++ b/stdlib/public/core/Flatten.swift
@@ -233,7 +233,14 @@
extension FlattenCollection.Index : Hashable
where Base.Index : Hashable, Base.Element.Index : Hashable {
public var hashValue: Int {
- return _combineHashValues(_inner?.hashValue ?? 0, _outer.hashValue)
+ return _hashValue(for: self)
+ }
+
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(_outer)
+ if let inner = _inner {
+ hasher.append(inner)
+ }
}
}
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 39cdc31..ff9a700 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -1524,26 +1524,25 @@
/// your program. Do not save hash values to use during a future execution.
@_inlineable // FIXME(sil-serialize-all)
public var hashValue: Int {
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ var v = self
if isZero {
// To satisfy the axiom that equality implies hash equality, we need to
// finesse the hash value of -0.0 to match +0.0.
- return 0
- } else {
- %if bits <= word_bits:
- return Int(bitPattern: UInt(bitPattern))
- %elif bits == 64: # Double -> 32-bit Int
- return Int(truncatingIfNeeded: bitPattern &>> 32) ^
- Int(truncatingIfNeeded: bitPattern)
- %elif word_bits == 32: # Float80 -> 32-bit Int
- return Int(truncatingIfNeeded: significandBitPattern &>> 32) ^
- Int(truncatingIfNeeded: significandBitPattern) ^
- Int(_representation.signAndExponent)
- %else: # Float80 -> 64-bit Int
- return Int(bitPattern: UInt(significandBitPattern)) ^
- Int(_representation.signAndExponent)
- %end
+ v = 0
}
+ %if bits == 80:
+ hasher.append(v._representation.signAndExponent)
+ hasher.append(v.significandBitPattern)
+ %else:
+ hasher.append(v.bitPattern)
+ %end
}
+
}
extension ${Self} {
diff --git a/stdlib/public/core/Hashable.swift b/stdlib/public/core/Hashable.swift
index 98fd5ff..d92cad5 100644
--- a/stdlib/public/core/Hashable.swift
+++ b/stdlib/public/core/Hashable.swift
@@ -108,6 +108,24 @@
/// Hash values are not guaranteed to be equal across different executions of
/// your program. Do not save hash values to use during a future execution.
var hashValue: Int { get }
+
+ /// Feed bits to be hashed into the hash function represented by `hasher`.
+ func _hash(into hasher: inout _Hasher)
+}
+
+extension Hashable {
+ @inline(__always)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(self.hashValue)
+ }
+}
+
+// Called by synthesized `hashValue` implementations.
+@inline(__always)
+public func _hashValue<H: Hashable>(for value: H) -> Int {
+ var hasher = _Hasher()
+ hasher.append(value)
+ return hasher.finalize()
}
// Called by the SwiftValue implementation.
@@ -126,4 +144,3 @@
) -> Int {
return value.pointee.hashValue
}
-
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/HashedCollections.swift.gyb
index b91923f..e755ee2 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/HashedCollections.swift.gyb
@@ -792,11 +792,16 @@
@_inlineable // FIXME(sil-serialize-all)
public var hashValue: Int {
// FIXME(ABI)#177: <rdar://problem/18915294> Cache Set<T> hashValue
- var result: Int = _mixInt(0)
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ var hash = 0
for member in self {
- result ^= _mixInt(member.hashValue)
+ hash ^= _hashValue(for: member)
}
- return result
+ hasher.append(hash)
}
}
@@ -3985,7 +3990,7 @@
@_versioned
@inline(__always) // For performance reasons.
internal func _bucket(_ k: Key) -> Int {
- return _squeezeHashValue(k.hashValue, bucketCount)
+ return _hashValue(for: k) & _bucketMask
}
@_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/Hashing.swift b/stdlib/public/core/Hashing.swift
index f6fef16..97ff40b 100644
--- a/stdlib/public/core/Hashing.swift
+++ b/stdlib/public/core/Hashing.swift
@@ -25,31 +25,9 @@
@_fixed_layout // FIXME(sil-serialize-all)
public // @testable
-enum _Hashing {
- // FIXME(ABI)#41 : make this an actual public API.
- @_inlineable // FIXME(sil-serialize-all)
- public // SPI
- static var secretKey: (UInt64, UInt64) {
- get {
- // The variable itself is defined in C++ code so that it is initialized
- // during static construction. Almost every Swift program uses hash
- // tables, so initializing the secret key during the startup seems to be
- // the right trade-off.
- return (
- _swift_stdlib_Hashing_secretKey.key0,
- _swift_stdlib_Hashing_secretKey.key1)
- }
- set {
- (_swift_stdlib_Hashing_secretKey.key0,
- _swift_stdlib_Hashing_secretKey.key1) = newValue
- }
- }
-}
-
-@_fixed_layout // FIXME(sil-serialize-all)
-public // @testable
enum _HashingDetail {
+ // FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
public // @testable
static var fixedSeedOverride: UInt64 {
@@ -64,6 +42,7 @@
}
}
+ // FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_versioned
@_transparent
@@ -74,6 +53,7 @@
return _HashingDetail.fixedSeedOverride == 0 ? seed : fixedSeedOverride
}
+ // FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_versioned
@_transparent
@@ -98,6 +78,7 @@
// their inputs and just exhibit avalanche effect.
//
+// FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public // @testable
@@ -112,6 +93,7 @@
return UInt32((extendedResult >> 3) & 0xffff_ffff)
}
+// FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public // @testable
@@ -119,6 +101,7 @@
return Int32(bitPattern: _mixUInt32(UInt32(bitPattern: value)))
}
+// FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public // @testable
@@ -130,6 +113,7 @@
return _HashingDetail.hash16Bytes(seed &+ (low << 3), high)
}
+// FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public // @testable
@@ -137,6 +121,7 @@
return Int64(bitPattern: _mixUInt64(UInt64(bitPattern: value)))
}
+// FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public // @testable
@@ -148,6 +133,7 @@
#endif
}
+// FIXME(hasher): Remove
@_inlineable // FIXME(sil-serialize-all)
@_transparent
public // @testable
@@ -159,35 +145,6 @@
#endif
}
-/// Given a hash value, returns an integer value in the range of
-/// 0..<`upperBound` that corresponds to a hash value.
-///
-/// The `upperBound` must be positive and a power of 2.
-///
-/// This function is superior to computing the remainder of `hashValue` by
-/// the range length. Some types have bad hash functions; sometimes simple
-/// patterns in data sets create patterns in hash values and applying the
-/// remainder operation just throws away even more information and invites
-/// even more hash collisions. This effect is especially bad because the
-/// range is a power of two, which means to throws away high bits of the hash
-/// (which would not be a problem if the hash was known to be good). This
-/// function mixes the bits in the hash value to compensate for such cases.
-///
-/// Of course, this function is a compressing function, and applying it to a
-/// hash value does not change anything fundamentally: collisions are still
-/// possible, and it does not prevent malicious users from constructing data
-/// sets that will exhibit pathological collisions.
-@_inlineable // FIXME(sil-serialize-all)
-public // @testable
-func _squeezeHashValue(_ hashValue: Int, _ upperBound: Int) -> Int {
- _sanityCheck(_isPowerOf2(upperBound))
- let mixedHashValue = _mixInt(hashValue)
-
- // As `upperBound` is a power of two we can do a bitwise-and to calculate
- // mixedHashValue % upperBound.
- return mixedHashValue & (upperBound &- 1)
-}
-
/// Returns a new value that combines the two given hash values.
///
/// Combining is performed using [a hash function][ref] described by T.C. Hoad
@@ -214,3 +171,130 @@
x ^= UInt(bitPattern: secondValue) &+ magic &+ (x &<< 6) &+ (x &>> 2)
return Int(bitPattern: x)
}
+
+// FIXME(hasher): This hasher emulates Swift 4.1 hashValues. It is purely for
+// benchmarking; to be removed.
+internal struct _LegacyHasher {
+ internal var _hash: Int
+
+ @inline(__always)
+ internal init(key: (UInt64, UInt64) = (0, 0)) { // key is ignored
+ _hash = 0
+ }
+
+ @inline(__always)
+ internal mutating func append(_ value: Int) {
+ _hash = (_hash == 0 ? value : _combineHashValues(_hash, value))
+ }
+
+ @inline(__always)
+ internal mutating func append(_ value: UInt) {
+ append(Int(bitPattern: value))
+ }
+
+ @inline(__always)
+ internal mutating func append(_ value: UInt32) {
+ append(Int(truncatingIfNeeded: value))
+ }
+
+ @inline(__always)
+ internal mutating func append(_ value: UInt64) {
+ if UInt64.bitWidth > Int.bitWidth {
+ append(Int(truncatingIfNeeded: value ^ (value &>> 32)))
+ } else {
+ append(Int(truncatingIfNeeded: value))
+ }
+ }
+
+ @inline(__always)
+ internal mutating func finalize() -> UInt64 {
+ return UInt64(
+ _truncatingBits: UInt(bitPattern: _mixInt(_hash))._lowWord)
+ }
+}
+
+
+// NOT @_fixed_layout
+public struct _Hasher {
+ internal typealias Core = _SipHash13
+
+ // NOT @_versioned
+ internal var _core: Core
+
+ // NOT @_inlineable
+ @effects(releasenone)
+ public init() {
+ self._core = Core(key: _Hasher._secretKey)
+ }
+
+ // NOT @_inlineable
+ @effects(releasenone)
+ public init(key: (UInt64, UInt64)) {
+ self._core = Core(key: key)
+ }
+
+ // FIXME(ABI)#41 : make this an actual public API.
+ @_inlineable // FIXME(sil-serialize-all)
+ public // SPI
+ static var _secretKey: (UInt64, UInt64) {
+ get {
+ // The variable itself is defined in C++ code so that it is initialized
+ // during static construction. Almost every Swift program uses hash
+ // tables, so initializing the secret key during the startup seems to be
+ // the right trade-off.
+ return (
+ _swift_stdlib_Hashing_secretKey.key0,
+ _swift_stdlib_Hashing_secretKey.key1)
+ }
+ set {
+ // FIXME(hasher) Replace setter with some override mechanism inside
+ // the runtime
+ (_swift_stdlib_Hashing_secretKey.key0,
+ _swift_stdlib_Hashing_secretKey.key1) = newValue
+ }
+ }
+
+ @_inlineable
+ @inline(__always)
+ public mutating func append<H: Hashable>(_ value: H) {
+ value._hash(into: &self)
+ }
+
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func append(bits: UInt) {
+ _core.append(bits)
+ }
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func append(bits: UInt32) {
+ _core.append(bits)
+ }
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func append(bits: UInt64) {
+ _core.append(bits)
+ }
+
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func append(bits: Int) {
+ _core.append(UInt(bitPattern: bits))
+ }
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func append(bits: Int32) {
+ _core.append(UInt32(bitPattern: bits))
+ }
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func append(bits: Int64) {
+ _core.append(UInt64(bitPattern: bits))
+ }
+
+ // NOT @_inlineable
+ @effects(releasenone)
+ public mutating func finalize() -> Int {
+ return Int(truncatingIfNeeded: _core.finalize())
+ }
+}
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index 76bc9ca..a2a02b8 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -3610,22 +3610,29 @@
public var hashValue: Int {
@inline(__always)
get {
-% if bits <= word_bits and signed:
- // Sign extend the value.
- return Int(self)
-% elif bits <= word_bits and not signed:
- // Sign extend the value.
- return Int(${OtherSelf}(bitPattern: self))
-% elif bits == word_bits * 2:
- // We have twice as many bits as we need to return.
- return
- Int(truncatingIfNeeded: self) ^
- Int(truncatingIfNeeded: self &>> 32)
-% else:
- _Unimplemented()
-% end
+ return _hashValue(for: self)
}
}
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ // FIXME(hasher): To correctly bridge `Set`s/`Dictionary`s containing
+ // `AnyHashable`-boxed integers, all integer values are currently required
+ // to hash exactly the same way as the corresponding (U)Int64 value. To fix
+ // this, we should introduce a custom AnyHashable box for integer values
+ // that sign-extends values to 64 bits.
+ % if bits <= word_bits:
+ hasher.append(bits: _lowWord)
+ % elif bits == 2 * word_bits:
+ if let word = ${"" if signed else "U"}Int(exactly: self) {
+ hasher.append(bits: word._lowWord)
+ } else {
+ hasher.append(bits: UInt64(_value))
+ }
+ % else:
+ fatalError("Unsupported integer width")
+ % end
+ }
}
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 70dace6..28e9cb7 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -49,21 +49,25 @@
@_inlineable // FIXME(sil-serialize-all)
final public var hashValue: Int {
- var hash = 0
- withBuffer {
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ return withBuffer {
var buffer = $0
while true {
let (component, type) = buffer.next()
- hash ^= _mixInt(component.value.hashValue)
+ hasher.append(component.value)
if let type = type {
- hash ^= _mixInt(unsafeBitCast(type, to: Int.self))
+ hasher.append(unsafeBitCast(type, to: Int.self))
} else {
break
}
}
}
- return hash
}
+
@_inlineable // FIXME(sil-serialize-all)
public static func ==(a: AnyKeyPath, b: AnyKeyPath) -> Bool {
// Fast-path identical objects
@@ -452,11 +456,14 @@
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var hashValue: Int {
- var hash = 0
- hash ^= _mixInt(value)
- hash ^= _mixInt(isStoredProperty ? 13 : 17)
- hash ^= _mixInt(isTableOffset ? 19 : 23)
- return hash
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(value)
+ hasher.append(isStoredProperty)
+ hasher.append(isTableOffset)
}
}
@@ -473,6 +480,7 @@
(_ xInstanceArguments: UnsafeRawPointer,
_ yInstanceArguments: UnsafeRawPointer,
_ size: Int) -> Bool
+ // FIXME(hasher) Append to an inout _Hasher instead
internal typealias Hash = @convention(thin)
(_ instanceArguments: UnsafeRawPointer,
_ size: Int) -> Int
@@ -584,46 +592,54 @@
@_inlineable // FIXME(sil-serialize-all)
@_versioned // FIXME(sil-serialize-all)
internal var hashValue: Int {
- var hash: Int = 0
- func mixHashFromArgument(_ argument: KeyPathComponent.ArgumentRef?) {
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ @_versioned // FIXME(sil-serialize-all)
+ internal func _hash(into hasher: inout _Hasher) {
+ var hasher = hasher
+ func appendHashFromArgument(
+ _ argument: KeyPathComponent.ArgumentRef?
+ ) {
if let argument = argument {
- let addedHash = argument.witnesses.pointee.hash(
+ let hash = argument.witnesses.pointee.hash(
argument.data.baseAddress.unsafelyUnwrapped,
argument.data.count)
// Returning 0 indicates that the arguments should not impact the
// hash value of the overall key path.
- if addedHash != 0 {
- hash ^= _mixInt(addedHash)
+ // FIXME(hasher): hash witness should just mutate hasher directly
+ if hash != 0 {
+ hasher.append(hash)
}
}
}
switch self {
case .struct(offset: let a):
- hash ^= _mixInt(0)
- hash ^= _mixInt(a)
+ hasher.append(0)
+ hasher.append(a)
case .class(offset: let b):
- hash ^= _mixInt(1)
- hash ^= _mixInt(b)
+ hasher.append(1)
+ hasher.append(b)
case .optionalChain:
- hash ^= _mixInt(2)
+ hasher.append(2)
case .optionalForce:
- hash ^= _mixInt(3)
+ hasher.append(3)
case .optionalWrap:
- hash ^= _mixInt(4)
+ hasher.append(4)
case .get(id: let id, get: _, argument: let argument):
- hash ^= _mixInt(5)
- hash ^= _mixInt(id.hashValue)
- mixHashFromArgument(argument)
+ hasher.append(5)
+ hasher.append(id)
+ appendHashFromArgument(argument)
case .mutatingGetSet(id: let id, get: _, set: _, argument: let argument):
- hash ^= _mixInt(6)
- hash ^= _mixInt(id.hashValue)
- mixHashFromArgument(argument)
+ hasher.append(6)
+ hasher.append(id)
+ appendHashFromArgument(argument)
case .nonmutatingGetSet(id: let id, get: _, set: _, argument: let argument):
- hash ^= _mixInt(7)
- hash ^= _mixInt(id.hashValue)
- mixHashFromArgument(argument)
+ hasher.append(7)
+ hasher.append(id)
+ appendHashFromArgument(argument)
}
- return hash
}
}
diff --git a/stdlib/public/core/PrefixWhile.swift b/stdlib/public/core/PrefixWhile.swift
index 92a627d..b5e7b1e 100644
--- a/stdlib/public/core/PrefixWhile.swift
+++ b/stdlib/public/core/PrefixWhile.swift
@@ -208,11 +208,15 @@
extension LazyPrefixWhileCollection.Index: Hashable where Base.Index: Hashable {
public var hashValue: Int {
+ return _hashValue(for: self)
+ }
+
+ public func _hash(into hasher: inout _Hasher) {
switch _value {
case .index(let value):
- return value.hashValue
+ hasher.append(value)
case .pastEnd:
- return .max
+ hasher.append(Int.max)
}
}
}
diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift
index ad08943..01585dd 100644
--- a/stdlib/public/core/Reverse.swift
+++ b/stdlib/public/core/Reverse.swift
@@ -197,6 +197,10 @@
public var hashValue: Int {
return base.hashValue
}
+
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(base)
+ }
}
extension ReversedCollection: BidirectionalCollection {
diff --git a/stdlib/public/core/SipHash.swift.gyb b/stdlib/public/core/SipHash.swift.gyb
index 558cca3..54f4d0d 100644
--- a/stdlib/public/core/SipHash.swift.gyb
+++ b/stdlib/public/core/SipHash.swift.gyb
@@ -19,63 +19,20 @@
/// * Daniel J. Bernstein <djb@cr.yp.to>
//===----------------------------------------------------------------------===//
+%{
+# Number of bits in the Builtin.Word type
+word_bits = int(CMAKE_SIZEOF_VOID_P) * 8
+}%
+
@_fixed_layout // FIXME(sil-serialize-all)
@_versioned
internal enum _SipHashDetail {
- @_inlineable // FIXME(sil-serialize-all)
@_versioned
@inline(__always)
- internal static func _rotate(_ x: UInt64, leftBy amount: Int) -> UInt64 {
- return (x &<< UInt64(amount)) | (x &>> UInt64(64 - amount))
+ internal static func _rotate(_ x: UInt64, leftBy amount: UInt64) -> UInt64 {
+ return (x &<< amount) | (x &>> (64 - amount))
}
- @_inlineable // FIXME(sil-serialize-all)
- @_versioned
- @inline(__always)
- internal static func _loadUnalignedUInt64LE(
- from p: UnsafeRawPointer
- ) -> UInt64 {
- // FIXME(integers): split into multiple expressions to speed up the
- // typechecking
- var result =
- UInt64(p.load(fromByteOffset: 0, as: UInt8.self))
- result |=
- (UInt64(p.load(fromByteOffset: 1, as: UInt8.self)) &<< (8 as UInt64))
- result |=
- (UInt64(p.load(fromByteOffset: 2, as: UInt8.self)) &<< (16 as UInt64))
- result |=
- (UInt64(p.load(fromByteOffset: 3, as: UInt8.self)) &<< (24 as UInt64))
- result |=
- (UInt64(p.load(fromByteOffset: 4, as: UInt8.self)) &<< (32 as UInt64))
- result |=
- (UInt64(p.load(fromByteOffset: 5, as: UInt8.self)) &<< (40 as UInt64))
- result |=
- (UInt64(p.load(fromByteOffset: 6, as: UInt8.self)) &<< (48 as UInt64))
- result |=
- (UInt64(p.load(fromByteOffset: 7, as: UInt8.self)) &<< (56 as UInt64))
- return result
- }
-
- @_inlineable // FIXME(sil-serialize-all)
- @_versioned
- @inline(__always)
- internal static func _loadPartialUnalignedUInt64LE(
- from p: UnsafeRawPointer,
- byteCount: Int
- ) -> UInt64 {
- _sanityCheck((0..<8).contains(byteCount))
- var result: UInt64 = 0
- if byteCount >= 1 { result |= UInt64(p.load(fromByteOffset: 0, as: UInt8.self)) }
- if byteCount >= 2 { result |= UInt64(p.load(fromByteOffset: 1, as: UInt8.self)) &<< (8 as UInt64) }
- if byteCount >= 3 { result |= UInt64(p.load(fromByteOffset: 2, as: UInt8.self)) &<< (16 as UInt64) }
- if byteCount >= 4 { result |= UInt64(p.load(fromByteOffset: 3, as: UInt8.self)) &<< (24 as UInt64) }
- if byteCount >= 5 { result |= UInt64(p.load(fromByteOffset: 4, as: UInt8.self)) &<< (32 as UInt64) }
- if byteCount >= 6 { result |= UInt64(p.load(fromByteOffset: 5, as: UInt8.self)) &<< (40 as UInt64) }
- if byteCount >= 7 { result |= UInt64(p.load(fromByteOffset: 6, as: UInt8.self)) &<< (48 as UInt64) }
- return result
- }
-
- @_inlineable // FIXME(sil-serialize-all)
@_versioned
@inline(__always)
internal static func _sipRound(
@@ -102,7 +59,7 @@
}
% for (c_rounds, d_rounds) in [(2, 4), (1, 3)]:
-% Self = '_SipHash{}{}Context'.format(c_rounds, d_rounds)
+% Self = '_SipHash{}{}'.format(c_rounds, d_rounds)
@_fixed_layout // FIXME(sil-serialize-all)
public // @testable
@@ -120,19 +77,14 @@
@_versioned
internal var v3: UInt64 = 0x7465646279746573
+ /// This value holds the byte count and the pending bytes that haven't been
+ /// compressed yet, in the format that the finalization step needs. (The least
+ /// significant 56 bits hold the trailing bytes, while the most significant 8
+ /// bits hold the count of bytes appended so far, mod 256.)
@_versioned
- internal var hashedByteCount: UInt64 = 0
+ internal var tailAndByteCount: UInt64 = 0
- @_versioned
- internal var dataTail: UInt64 = 0
-
- @_versioned
- internal var dataTailByteCount: Int = 0
-
- @_versioned
- internal var finalizedHash: UInt64?
-
- @_inlineable // FIXME(sil-serialize-all)
+ @inline(__always)
public init(key: (UInt64, UInt64)) {
v3 ^= key.1
v2 ^= key.0
@@ -140,113 +92,102 @@
v0 ^= key.0
}
- // FIXME(ABI)#62 (UnsafeRawBufferPointer): Use UnsafeRawBufferPointer.
- @_inlineable // FIXME(sil-serialize-all)
- public // @testable
- mutating func append(_ data: UnsafeRawPointer, byteCount: Int) {
- _append_alwaysInline(data, byteCount: byteCount)
- }
-
- // FIXME(ABI)#63 (UnsafeRawBufferPointer): Use UnsafeRawBufferPointer.
- @_inlineable // FIXME(sil-serialize-all)
@_versioned
- @inline(__always)
- internal mutating func _append_alwaysInline(
- _ data: UnsafeRawPointer,
- byteCount: Int
- ) {
- precondition(finalizedHash == nil)
- _sanityCheck((0..<8).contains(dataTailByteCount))
-
- let dataEnd = data + byteCount
-
- var data = data
- var byteCount = byteCount
- if dataTailByteCount != 0 {
- let restByteCount = min(
- MemoryLayout<UInt64>.size - dataTailByteCount,
- byteCount)
- let rest = _SipHashDetail._loadPartialUnalignedUInt64LE(
- from: data,
- byteCount: restByteCount)
- dataTail |= rest &<< UInt64(dataTailByteCount * 8)
- dataTailByteCount += restByteCount
- data += restByteCount
- byteCount -= restByteCount
- }
-
- if dataTailByteCount == MemoryLayout<UInt64>.size {
- _appendDirectly(dataTail)
- dataTail = 0
- dataTailByteCount = 0
- } else if dataTailByteCount != 0 {
- _sanityCheck(data == dataEnd)
- return
- }
-
- let endOfWords =
- data + byteCount - (byteCount % MemoryLayout<UInt64>.size)
- while data != endOfWords {
- _appendDirectly(_SipHashDetail._loadUnalignedUInt64LE(from: data))
- data += 8
- // No need to update `byteCount`, it is not used beyond this point.
- }
-
- if data != dataEnd {
- dataTailByteCount = dataEnd - data
- dataTail = _SipHashDetail._loadPartialUnalignedUInt64LE(
- from: data,
- byteCount: dataTailByteCount)
+ internal var byteCount: UInt64 {
+ @inline(__always)
+ get {
+ return tailAndByteCount &>> 56
}
}
- /// This function mixes in the given word directly into the state,
- /// ignoring `dataTail`.
- @_inlineable // FIXME(sil-serialize-all)
@_versioned
+ internal var tail: UInt64 {
+ @inline(__always)
+ get {
+ return tailAndByteCount & ~(0xFF &<< 56)
+ }
+ }
+
@inline(__always)
- internal mutating func _appendDirectly(_ m: UInt64) {
+ @_versioned
+ internal mutating func _compress(_ m: UInt64) {
v3 ^= m
for _ in 0..<${c_rounds} {
_SipHashDetail._sipRound(v0: &v0, v1: &v1, v2: &v2, v3: &v3)
}
v0 ^= m
- hashedByteCount += 8
}
-% for data_type in ['UInt', 'Int', 'UInt64', 'Int64', 'UInt32', 'Int32']:
- @_inlineable // FIXME(sil-serialize-all)
- public // @testable
- mutating func append(_ data: ${data_type}) {
- var data = data
- _append_alwaysInline(&data, byteCount: MemoryLayout.size(ofValue: data))
- }
-% end
-
- @_inlineable // FIXME(sil-serialize-all)
- public // @testable
- mutating func finalizeAndReturnHash() -> UInt64 {
- return _finalizeAndReturnHash_alwaysInline()
- }
-
- @_inlineable // FIXME(sil-serialize-all)
- @_versioned
@inline(__always)
- internal mutating func _finalizeAndReturnHash_alwaysInline() -> UInt64 {
- if let finalizedHash = finalizedHash {
- return finalizedHash
+ public mutating func append(_ value: Int) {
+ append(UInt(bitPattern: value))
+ }
+
+ @inline(__always)
+ public mutating func append(_ value: UInt) {
+ % if word_bits == 64:
+ append(UInt64(_truncatingBits: value._lowWord))
+ % elif word_bits == 32:
+ append(UInt32(_truncatingBits: value._lowWord))
+ % else:
+ fatalError("Unsupported word width")
+ % end
+ }
+
+ @inline(__always)
+ public mutating func append(_ value: Int32) {
+ append(UInt32(bitPattern: value))
+ }
+
+ @inline(__always)
+ public mutating func append(_ value: UInt32) {
+ let m = UInt64(_truncatingBits: value._lowWord)
+ if byteCount & 4 == 0 {
+ _sanityCheck(byteCount & 7 == 0 && tail == 0)
+ tailAndByteCount = (tailAndByteCount | m) &+ (4 &<< 56)
+ } else {
+ _sanityCheck(byteCount & 3 == 0)
+ _compress((m &<< 32) | tail)
+ tailAndByteCount = (byteCount &+ 4) &<< 56
}
+ }
- _sanityCheck((0..<8).contains(dataTailByteCount))
+ @inline(__always)
+ public mutating func append(_ value: Int64) {
+ append(UInt64(bitPattern: value))
+ }
- hashedByteCount += UInt64(dataTailByteCount)
- let b: UInt64 = (hashedByteCount << 56) | dataTail
-
- v3 ^= b
- for _ in 0..<${c_rounds} {
- _SipHashDetail._sipRound(v0: &v0, v1: &v1, v2: &v2, v3: &v3)
+ @inline(__always)
+ public mutating func append(_ m: UInt64) {
+ if byteCount & 4 == 0 {
+ _sanityCheck(byteCount & 7 == 0 && tail == 0)
+ _compress(m)
+ tailAndByteCount = tailAndByteCount &+ (8 &<< 56)
+ } else {
+ _sanityCheck(byteCount & 3 == 0)
+ _compress((m &<< 32) | tail)
+ tailAndByteCount = ((byteCount &+ 8) &<< 56) | (m &>> 32)
}
- v0 ^= b
+ }
+
+ @inline(__always)
+ public mutating func finalize(
+ tailBytes: UInt64,
+ tailByteCount: Int
+ ) -> UInt64 {
+ _sanityCheck(tailByteCount >= 0)
+ _sanityCheck(tailByteCount < 8 - (byteCount & 7))
+ _sanityCheck(tailBytes >> (tailByteCount << 3) == 0)
+ let count = UInt64(_truncatingBits: tailByteCount._lowWord)
+ let currentByteCount = byteCount & 7
+ tailAndByteCount |= (tailBytes &<< (currentByteCount &<< 3))
+ tailAndByteCount = tailAndByteCount &+ (count &<< 56)
+ return finalize()
+ }
+
+ @inline(__always)
+ public mutating func finalize() -> UInt64 {
+ _compress(tailAndByteCount)
v2 ^= 0xff
@@ -254,47 +195,7 @@
_SipHashDetail._sipRound(v0: &v0, v1: &v1, v2: &v2, v3: &v3)
}
- finalizedHash = v0 ^ v1 ^ v2 ^ v3
- return finalizedHash!
- }
-
- @_inlineable // FIXME(sil-serialize-all)
- @_versioned // FIXME(sil-serialize-all)
- internal mutating func _finalizeAndReturnIntHash() -> Int {
- let hash: UInt64 = finalizeAndReturnHash()
-#if arch(i386) || arch(arm)
- return Int(truncatingIfNeeded: hash)
-#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
- return Int(Int64(bitPattern: hash))
-#endif
- }
-
- // FIXME(ABI)#64 (UnsafeRawBufferPointer): Use UnsafeRawBufferPointer.
- @_inlineable // FIXME(sil-serialize-all)
- public // @testable
- static func hash(
- data: UnsafeRawPointer,
- dataByteCount: Int,
- key: (UInt64, UInt64)
- ) -> UInt64 {
- return ${Self}._hash_alwaysInline(
- data: data,
- dataByteCount: dataByteCount,
- key: key)
- }
-
- // FIXME(ABI)#65 (UnsafeRawBufferPointer): Use UnsafeRawBufferPointer.
- @_inlineable // FIXME(sil-serialize-all)
- @inline(__always)
- public // @testable
- static func _hash_alwaysInline(
- data: UnsafeRawPointer,
- dataByteCount: Int,
- key: (UInt64, UInt64)
- ) -> UInt64 {
- var context = ${Self}(key: key)
- context._append_alwaysInline(data, byteCount: dataByteCount)
- return context._finalizeAndReturnHash_alwaysInline()
+ return (v0 ^ v1 ^ v2 ^ v3)
}
}
% end
diff --git a/stdlib/public/core/StringHashable.swift b/stdlib/public/core/StringHashable.swift
index 7607c9b..c87ff59 100644
--- a/stdlib/public/core/StringHashable.swift
+++ b/stdlib/public/core/StringHashable.swift
@@ -37,34 +37,33 @@
// @_inlineable // FIXME(sil-serialize-all)
// @_versioned // FIXME(sil-serialize-all)
internal static func hashASCII(
- _ string: UnsafeBufferPointer<UInt8>
- ) -> Int {
+ _ string: UnsafeBufferPointer<UInt8>,
+ into hasher: inout _Hasher
+ ) {
let collationTable = _swift_stdlib_unicode_getASCIICollationTable()
- var hasher = _SipHash13Context(key: _Hashing.secretKey)
for c in string {
_precondition(c <= 127)
let element = collationTable[Int(c)]
// Ignore zero valued collation elements. They don't participate in the
// ordering relation.
if element != 0 {
- hasher.append(element)
+ hasher.append(Int(truncatingIfNeeded: element))
}
}
- return hasher._finalizeAndReturnIntHash()
}
// FIXME: cannot be marked @_versioned. See <rdar://problem/34438258>
// @_inlineable // FIXME(sil-serialize-all)
// @_versioned // FIXME(sil-serialize-all)
internal static func hashUTF16(
- _ string: UnsafeBufferPointer<UInt16>
- ) -> Int {
+ _ string: UnsafeBufferPointer<UInt16>,
+ into hasher: inout _Hasher
+ ) {
let collationIterator = _swift_stdlib_unicodeCollationIterator_create(
string.baseAddress!,
UInt32(string.count))
defer { _swift_stdlib_unicodeCollationIterator_delete(collationIterator) }
- var hasher = _SipHash13Context(key: _Hashing.secretKey)
while true {
var hitEnd = false
let element =
@@ -75,10 +74,9 @@
// Ignore zero valued collation elements. They don't participate in the
// ordering relation.
if element != 0 {
- hasher.append(element)
+ hasher.append(Int(truncatingIfNeeded: element))
}
}
- return hasher._finalizeAndReturnIntHash()
}
}
@@ -100,7 +98,9 @@
// Swift.String.hashValue and NSString.hash being the same.
return stringHashOffset ^ hash
#else
- return Unicode.hashASCII(self.buffer)
+ var hasher = _Hasher()
+ Unicode.hashASCII(self.buffer, into: &hasher)
+ return Int(truncatingIfNeeded: hasher.finalize())
#endif // _runtime(_ObjC)
}
}
@@ -118,7 +118,9 @@
// Swift.String.hashValue and NSString.hash being the same.
return stringHashOffset ^ hash
#else
- return Unicode.hashUTF16(self.buffer)
+ var hasher = _Hasher()
+ Unicode.hashUTF16(self.buffer, into: &hasher)
+ return Int(truncatingIfNeeded: hasher.finalize())
#endif // _runtime(_ObjC)
}
}
@@ -139,7 +141,11 @@
defer { p.deallocate(capacity: count) }
let buffer = UnsafeMutableBufferPointer(start: p, count: count)
_copy(into: buffer)
- return Unicode.hashUTF16(UnsafeBufferPointer(buffer))
+ var hasher = _Hasher()
+ Unicode.hashUTF16(
+ UnsafeBufferPointer(start: p, count: count),
+ into: &hasher)
+ return Int(truncatingIfNeeded: hasher.finalize())
#endif
}
}
@@ -195,6 +201,11 @@
let gutsBits = _guts.rawBits
return _StringGuts._computeHashValue(_unsafeBitPattern: gutsBits)
}
+
+ @_inlineable
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(self.hashValue)
+ }
}
extension StringProtocol {
@@ -202,4 +213,9 @@
public var hashValue : Int {
return _wholeString._guts._computeHashValue(_encodedOffsetRange)
}
+
+ @_inlineable
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(self.hashValue)
+ }
}
diff --git a/stdlib/public/core/UnsafePointer.swift.gyb b/stdlib/public/core/UnsafePointer.swift.gyb
index 288b484..4e314bd 100644
--- a/stdlib/public/core/UnsafePointer.swift.gyb
+++ b/stdlib/public/core/UnsafePointer.swift.gyb
@@ -904,10 +904,15 @@
/// program runs.
@_inlineable
public var hashValue: Int {
- return Int(bitPattern: self)
+ return _hashValue(for: self)
+ }
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public func _hash(into hasher: inout _Hasher) {
+ hasher.append(Int(bitPattern: self))
}
}
-
+
extension ${Self}: Strideable {
/// Returns a pointer to the next consecutive instance.
///
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 5a70cf3..d1c2c77 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -2823,8 +2823,7 @@
return _fail(src, srcType, targetType, flags);
}
- // Unless we're always supposed to consume the input, retain the
- // object because the witness takes it at +1.
+ // TODO: Avoid the retain here in +0 mode if the input is never consumed.
bool alwaysConsumeSrc = (flags & DynamicCastFlags::TakeOnSuccess) &&
(flags & DynamicCastFlags::DestroyOnFailure);
if (!alwaysConsumeSrc) {
@@ -2880,6 +2879,7 @@
(HeapObject *)srcObject, (OpaqueValue *)optDestBuffer,
targetType, targetType, targetBridgeWitness);
}
+ SWIFT_CC_PLUSZERO_GUARD(swift_unknownRelease(srcObject));
// If we succeeded, take from the optional buffer into the
// destination buffer.
@@ -2887,8 +2887,6 @@
targetType->vw_initializeWithTake(dest, (OpaqueValue *)optDestBuffer);
}
- // Unless we're always supposed to consume the input, release the
- // input if we need to now.
if (!alwaysConsumeSrc && shouldDeallocateSource(success, flags)) {
swift_unknownRelease(srcObject);
}
diff --git a/stdlib/public/runtime/ErrorObject.mm b/stdlib/public/runtime/ErrorObject.mm
index d5303b3..fadba49 100644
--- a/stdlib/public/runtime/ErrorObject.mm
+++ b/stdlib/public/runtime/ErrorObject.mm
@@ -409,8 +409,10 @@
// initialization of the object happens-before the domain initialization so
// that the domain can be used alone as a flag for the initialization of the
// object.
- if (errorObject->domain.load(std::memory_order_acquire))
+ if (errorObject->domain.load(std::memory_order_acquire)) {
+ SWIFT_CC_PLUSZERO_GUARD([ns retain]);
return ns;
+ }
// Otherwise, calculate the domain, code, and user info, and
// initialize the NSError.
@@ -451,6 +453,7 @@
std::memory_order_acq_rel))
objc_release(domain);
+ SWIFT_CC_PLUSZERO_GUARD([ns retain]);
return ns;
}
diff --git a/stdlib/public/runtime/Errors.cpp b/stdlib/public/runtime/Errors.cpp
index a603936..d91e8cd 100644
--- a/stdlib/public/runtime/Errors.cpp
+++ b/stdlib/public/runtime/Errors.cpp
@@ -292,6 +292,12 @@
_swift_runtime_on_report(flags, message, details);
}
+bool swift::_swift_reportFatalErrorsToDebugger = true;
+
+bool swift::_swift_shouldReportFatalErrorsToDebugger() {
+ return _swift_reportFatalErrorsToDebugger;
+}
+
/// Report a fatal error to system console, stderr, and crash logs.
/// Does not crash by itself.
void swift::swift_reportError(uint32_t flags,
diff --git a/stdlib/public/runtime/ReflectionMirror.mm b/stdlib/public/runtime/ReflectionMirror.mm
index 7280fdf..637a217 100644
--- a/stdlib/public/runtime/ReflectionMirror.mm
+++ b/stdlib/public/runtime/ReflectionMirror.mm
@@ -635,19 +635,20 @@
/// TODO: Implement specialized mirror witnesses for all kinds.
case MetadataKind::Function:
- case MetadataKind::Existential: {
- OpaqueImpl impl;
- return call(&impl);
- }
+ case MetadataKind::Existential:
+ break;
// Types can't have these kinds.
case MetadataKind::HeapLocalVariable:
case MetadataKind::HeapGenericLocalVariable:
case MetadataKind::ErrorObject:
swift::crash("Swift mirror lookup failure");
- }
+ }
- swift_runtime_unreachable("Unhandled MetadataKind in switch.");
+ // If we have an unknown kind of type, or a type without special handling,
+ // treat it as opaque.
+ OpaqueImpl impl;
+ return call(&impl);
}
} // end anonymous namespace
@@ -738,7 +739,7 @@
return "(ErrorType Object)";
}
- swift_runtime_unreachable("Unhandled MetadataKind in switch.");
+ return "(Unknown)";
}
#if SWIFT_OBJC_INTEROP
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index 03e4816..02da955 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -1398,7 +1398,7 @@
"withoutActuallyEscaping block";
auto messageLength = strlen(message);
- if (_swift_reportFatalErrorsToDebugger)
+ if (_swift_shouldReportFatalErrorsToDebugger())
_swift_reportToDebugger(RuntimeErrorFlagFatal, message);
char *log;
diff --git a/stdlib/public/stubs/Assert.cpp b/stdlib/public/stubs/Assert.cpp
index a4b29ab..ceb369e 100644
--- a/stdlib/public/stubs/Assert.cpp
+++ b/stdlib/public/stubs/Assert.cpp
@@ -21,13 +21,11 @@
using namespace swift;
-bool swift::_swift_reportFatalErrorsToDebugger = true;
-
static void logPrefixAndMessageToDebugger(
const unsigned char *prefix, int prefixLength,
const unsigned char *message, int messageLength
) {
- if (!_swift_reportFatalErrorsToDebugger)
+ if (!_swift_shouldReportFatalErrorsToDebugger())
return;
char *debuggerMessage;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 64800a1..bc3ec41 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -158,7 +158,7 @@
foreach(ARCH ${SWIFT_SDK_${SDK}_ARCHITECTURES})
# Configure variables for this subdirectory.
set(VARIANT_SUFFIX "-${SWIFT_SDK_${SDK}_LIB_SUBDIR}-${ARCH}")
- set(VARIANT_TRIPLE "${SWIFT_SDK_${SDK}_ARCH_${ARCH}_TRIPLE}")
+ set(VARIANT_TRIPLE "${SWIFT_SDK_${SDK}_ARCH_${ARCH}_TRIPLE}${SWIFT_SDK_${SDK}_DEPLOYMENT_VERSION}")
set(VARIANT_SDK "${SWIFT_SDK_${SDK}_PATH}")
# A directory where to put the xUnit-style XML test results.
diff --git a/test/ClangImporter/availability_returns_twice.swift b/test/ClangImporter/availability_returns_twice.swift
index f0cee90..537c184 100644
--- a/test/ClangImporter/availability_returns_twice.swift
+++ b/test/ClangImporter/availability_returns_twice.swift
@@ -1,6 +1,6 @@
// RUN: %target-swift-frontend -typecheck -verify %s
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
typealias JumpBuffer = Int32
#else
diff --git a/test/ClangImporter/clang_builtins.swift b/test/ClangImporter/clang_builtins.swift
index 73ef91e..b9a72eb 100644
--- a/test/ClangImporter/clang_builtins.swift
+++ b/test/ClangImporter/clang_builtins.swift
@@ -3,7 +3,7 @@
// RUN: not %target-swift-frontend -swift-version 4 -typecheck %s 2> %t.4.txt
// RUN: %FileCheck -check-prefix=CHECK-4 -check-prefix=CHECK-%target-runtime-4 %s < %t.4.txt
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#else
import Glibc
@@ -27,7 +27,7 @@
// CHECK-4: [[@LINE-2]]:16: error: cannot convert value of type '({{.+}}) -> Int'{{( [(]aka .+[)])?}} to specified type 'Int'
}
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
// These functions aren't consistently available across platforms, so only
// test for them on Apple platforms.
func testApple() {
diff --git a/test/ClangImporter/objc_ir.swift b/test/ClangImporter/objc_ir.swift
index d95743d..7f9b8c2 100644
--- a/test/ClangImporter/objc_ir.swift
+++ b/test/ClangImporter/objc_ir.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-clang-importer-objc-overlays
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -emit-ir -g -o - -primary-file %s | %FileCheck %s
diff --git a/test/ClangImporter/optional.swift b/test/ClangImporter/optional.swift
index 9feb50b..c510215 100644
--- a/test/ClangImporter/optional.swift
+++ b/test/ClangImporter/optional.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -emit-silgen -o - %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/ClangImporter/plus_zero_objc_ir.swift b/test/ClangImporter/plus_zero_objc_ir.swift
new file mode 100644
index 0000000..4ea8181
--- /dev/null
+++ b/test/ClangImporter/plus_zero_objc_ir.swift
@@ -0,0 +1,349 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-clang-importer-objc-overlays
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -I %S/Inputs/custom-modules -emit-ir -g -o - -primary-file %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+// REQUIRES: OS=macosx
+
+// CHECK: %TSo1BC = type
+
+import ObjectiveC
+import Foundation
+import objc_ext
+import TestProtocols
+import ObjCIRExtras
+
+// CHECK: @"\01L_selector_data(method:withFloat:)" = private global [18 x i8] c"method:withFloat:\00"
+// CHECK: @"\01L_selector_data(method:withDouble:)" = private global [19 x i8] c"method:withDouble:\00"
+// CHECK: @"\01L_selector_data(method:separateExtMethod:)" = private global [26 x i8] c"method:separateExtMethod:\00", section "__TEXT,__objc_methname,cstring_literals"
+
+// Instance method invocation
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir15instanceMethodsyySo1BCF"(%TSo1BC*
+func instanceMethods(_ b: B) {
+ // CHECK: load i8*, i8** @"\01L_selector(method:withFloat:)"
+ // CHECK: call i32 bitcast (void ()* @objc_msgSend to i32
+ var i = b.method(1, with: 2.5 as Float)
+ // CHECK: load i8*, i8** @"\01L_selector(method:withDouble:)"
+ // CHECK: call i32 bitcast (void ()* @objc_msgSend to i32
+ i = i + b.method(1, with: 2.5 as Double)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir16extensionMethods1bySo1BC_tF"
+func extensionMethods(b b: B) {
+ // CHECK: load i8*, i8** @"\01L_selector(method:separateExtMethod:)", align 8
+ // CHECK: [[T0:%.*]] = call i8* bitcast (void ()* @objc_msgSend to i8*
+ // CHECK-NEXT: [[T1:%.*]] = {{.*}}call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+ // CHECK-NOT: [[T0]]
+ // CHECK: [[T1]]
+ b.method(1, separateExtMethod:1.5)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir19initCallToAllocInit1iys5Int32V_tF"
+func initCallToAllocInit(i i: CInt) {
+ // CHECK: call {{.*}} @"$SSo1BC3intABSgs5Int32V_tcfC"
+
+ B(int: i)
+}
+
+// CHECK-LABEL: linkonce_odr hidden {{.*}} @"$SSo1BC3intABSgs5Int32V_tcfC"
+// CHECK: call [[OPAQUE:%.*]]* @objc_allocWithZone
+
+// Indexed subscripting
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir19indexedSubscripting1b3idx1aySo1BC_SiSo1ACtF"
+func indexedSubscripting(b b: B, idx: Int, a: A) {
+ // CHECK: load i8*, i8** @"\01L_selector(setObject:atIndexedSubscript:)", align 8
+ b[idx] = a
+
+ // CHECK: load i8*, i8** @"\01L_selector(objectAtIndexedSubscript:)"
+ var a2 = b[idx] as! A
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir17keyedSubscripting1b3idx1aySo1BC_So1ACAItF"
+func keyedSubscripting(b b: B, idx: A, a: A) {
+ // CHECK: load i8*, i8** @"\01L_selector(setObject:forKeyedSubscript:)"
+ b[a] = a
+ // CHECK: load i8*, i8** @"\01L_selector(objectForKeyedSubscript:)"
+ var a2 = b[a] as! A
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir14propertyAccess1bySo1BC_tF"
+func propertyAccess(b b: B) {
+ // CHECK: load i8*, i8** @"\01L_selector(counter)"
+ // CHECK: load i8*, i8** @"\01L_selector(setCounter:)"
+ b.counter = b.counter + 1
+
+ // CHECK: load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
+ // CHECK: load i8*, i8** @"\01L_selector(sharedCounter)"
+ // CHECK: load i8*, i8** @"\01L_selector(setSharedCounter:)"
+ B.sharedCounter = B.sharedCounter + 1
+}
+
+// CHECK-LABEL: define hidden swiftcc %TSo1BC* @"$S7objc_ir8downcast1aSo1BCSo1AC_tF"(
+func downcast(a a: A) -> B {
+ // CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
+ // CHECK: [[T0:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[CLASS]])
+ // CHECK: [[T1:%.*]] = bitcast %objc_class* [[T0]] to i8*
+ // CHECK: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[A:%.*]], i8* [[T1]]) [[NOUNWIND:#[0-9]+]]
+ return a as! B
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir19almostSubscriptable3as11aySo06AlmostD0C_So1ACtF"
+func almostSubscriptable(as1 as1: AlmostSubscriptable, a: A) {
+ as1.objectForKeyedSubscript(a)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir13protocolTypes1a1bySo7NSMinceC_So9NSRuncing_ptF"(%TSo7NSMinceC*, %objc_object*) {{.*}} {
+func protocolTypes(a a: NSMince, b: NSRuncing) {
+ // - (void)eatWith:(id <NSRuncing>)runcer;
+ a.eat(with: b)
+ // CHECK: [[SEL:%.*]] = load i8*, i8** @"\01L_selector(eatWith:)", align 8
+ // CHECK: call void bitcast (void ()* @objc_msgSend to void ([[OPAQUE:%.*]]*, i8*, i8*)*)([[OPAQUE:%.*]]* {{%.*}}, i8* [[SEL]], i8* {{%.*}})
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir6getset1pySo8FooProto_p_tF"(%objc_object*) {{.*}} {
+func getset(p p: FooProto) {
+ // CHECK: load i8*, i8** @"\01L_selector(bar)"
+ // CHECK: load i8*, i8** @"\01L_selector(setBar:)"
+ let prop = p.bar
+ p.bar = prop
+}
+
+// CHECK-LABEL: define hidden swiftcc %swift.type* @"$S7objc_ir16protocolMetatype1pSo8FooProto_pXpSoAD_p_tF"(%objc_object*) {{.*}} {
+func protocolMetatype(p: FooProto) -> FooProto.Type {
+ // CHECK: = call %swift.type* @swift_getObjectType(%objc_object* %0)
+ // CHECK-NOT: {{retain|release}}
+ // CHECK: [[RAW_RESULT:%.+]] = call i8* @processFooType(i8* {{%.+}})
+ // CHECK: [[CASTED_RESULT:%.+]] = bitcast i8* [[RAW_RESULT]] to %objc_class*
+ // CHECK: [[SWIFT_RESULT:%.+]] = call %swift.type* @swift_getObjCClassMetadata(%objc_class* [[CASTED_RESULT]])
+ // CHECK-NOT: call void @swift_unknownRelease(%objc_object* %0)
+ // CHECK: ret %swift.type* [[SWIFT_RESULT]]
+ let type = processFooType(type(of: p))
+ return type
+} // CHECK: }
+
+class Impl: FooProto, AnotherProto {
+ @objc var bar: Int32 = 0
+}
+
+// CHECK-LABEL: define hidden swiftcc %swift.type* @"$S7objc_ir27protocolCompositionMetatype1pSo12AnotherProto_So03FooG0pXpAA4ImplC_tF"(%T7objc_ir4ImplC*) {{.*}} {
+func protocolCompositionMetatype(p: Impl) -> (FooProto & AnotherProto).Type {
+ // CHECK: = getelementptr inbounds %T7objc_ir4ImplC, %T7objc_ir4ImplC* %0, i32 0, i32 0, i32 0
+ // CHECK-NOT: {{retain|release}}
+ // CHECK: [[RAW_RESULT:%.+]] = call i8* @processComboType(i8* {{%.+}})
+ // CHECK: [[CASTED_RESULT:%.+]] = bitcast i8* [[RAW_RESULT]] to %objc_class*
+ // CHECK: [[SWIFT_RESULT:%.+]] = call %swift.type* @swift_getObjCClassMetadata(%objc_class* [[CASTED_RESULT]])
+ // CHECK-NOT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T7objc_ir4ImplC*)*)(%T7objc_ir4ImplC* %0)
+ // CHECK: ret %swift.type* [[SWIFT_RESULT]]
+ let type = processComboType(type(of: p))
+ return type
+} // CHECK: }
+
+// CHECK-LABEL: define hidden swiftcc %swift.type* @"$S7objc_ir28protocolCompositionMetatype21pSo12AnotherProto_So03FooG0pXpAA4ImplC_tF"(%T7objc_ir4ImplC*) {{.*}} {
+func protocolCompositionMetatype2(p: Impl) -> (FooProto & AnotherProto).Type {
+ // CHECK: = getelementptr inbounds %T7objc_ir4ImplC, %T7objc_ir4ImplC* %0, i32 0, i32 0, i32 0
+ // CHECK-NOT: {{retain|release}}
+ // CHECK: [[RAW_RESULT:%.+]] = call i8* @processComboType2(i8* {{%.+}})
+ // CHECK: [[CASTED_RESULT:%.+]] = bitcast i8* [[RAW_RESULT]] to %objc_class*
+ // CHECK: [[SWIFT_RESULT:%.+]] = call %swift.type* @swift_getObjCClassMetadata(%objc_class* [[CASTED_RESULT]])
+ // CHECK-NOT: @swift_release
+ // CHECK: ret %swift.type* [[SWIFT_RESULT]]
+ let type = processComboType2(type(of: p))
+ return type
+} // CHECK: }
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir17pointerPropertiesyySo14PointerWrapperCF"(%TSo14PointerWrapperC*) {{.*}} {
+func pointerProperties(_ obj: PointerWrapper) {
+ // CHECK: load i8*, i8** @"\01L_selector(setVoidPtr:)"
+ // CHECK: load i8*, i8** @"\01L_selector(setIntPtr:)"
+ // CHECK: load i8*, i8** @"\01L_selector(setIdPtr:)"
+ obj.voidPtr = nil as UnsafeMutableRawPointer?
+ obj.intPtr = nil as UnsafeMutablePointer?
+ obj.idPtr = nil as AutoreleasingUnsafeMutablePointer?
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir16strangeSelectorsyySo13SwiftNameTestCF"(%TSo13SwiftNameTestC*) {{.*}} {
+func strangeSelectors(_ obj: SwiftNameTest) {
+ // CHECK: load i8*, i8** @"\01L_selector(:b:)"
+ obj.empty(a: 0, b: 0)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir20customFactoryMethodsyyF"() {{.*}} {
+func customFactoryMethods() {
+ // CHECK: call swiftcc %TSo13SwiftNameTestC* @"$SSo13SwiftNameTestC10dummyParamAByt_tcfCTO"
+ // CHECK: call swiftcc %TSo13SwiftNameTestC* @"$SSo13SwiftNameTestC2ccABypSg_tcfCTO"
+ // CHECK: call swiftcc %TSo13SwiftNameTestC* @"$SSo13SwiftNameTestC5emptyABs5Int32V_tcfCTO"
+ _ = SwiftNameTest(dummyParam: ())
+ _ = SwiftNameTest(cc: nil)
+ _ = SwiftNameTest(empty: 0)
+
+ // CHECK: load i8*, i8** @"\01L_selector(testZ)"
+ // CHECK: load i8*, i8** @"\01L_selector(testY:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testX:xx:)"
+ // CHECK: load i8*, i8** @"\01L_selector(::)"
+ _ = SwiftNameTest.zz()
+ _ = SwiftNameTest.yy(aa: nil)
+ _ = SwiftNameTest.xx(nil, bb: nil)
+ _ = SwiftNameTest.empty(1, 2)
+
+ do {
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC5errorAByt_tKcfCTO"
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aa5errorABypSg_yttKcfCTO"
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aa5error5blockABypSg_ytyyctKcfCTO"
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC5error5blockAByt_yyctKcfCTO"
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aaABypSg_tKcfCTO"
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aa5blockABypSg_yyctKcfCTO"
+ // CHECK: call swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC5blockAByyc_tKcfCTO"
+ _ = try SwiftNameTestError(error: ())
+ _ = try SwiftNameTestError(aa: nil, error: ())
+ _ = try SwiftNameTestError(aa: nil, error: (), block: {})
+ _ = try SwiftNameTestError(error: (), block: {})
+
+ _ = try SwiftNameTestError(aa: nil)
+ _ = try SwiftNameTestError(aa: nil, block: {})
+ _ = try SwiftNameTestError(block: {})
+
+ // CHECK: load i8*, i8** @"\01L_selector(testW:error:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testW2:error:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testV:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testV2:)"
+ _ = try SwiftNameTestError.ww(nil)
+ _ = try SwiftNameTestError.w2(nil, error: ())
+ _ = try SwiftNameTestError.vv()
+ _ = try SwiftNameTestError.v2(error: ())
+ } catch _ {
+ }
+}
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo13SwiftNameTestC* @"$SSo13SwiftNameTestC10dummyParamAByt_tcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(b)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo13SwiftNameTestC* @"$SSo13SwiftNameTestC2ccABypSg_tcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(c:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC5errorAByt_tKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err1:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aa5errorABypSg_yttKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err2:error:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aa5error5blockABypSg_ytyyctKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err3:error:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC5error5blockAByt_yyctKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err4:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aaABypSg_tKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err5:error:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC2aa5blockABypSg_yyctKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err6:error:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo18SwiftNameTestErrorC* @"$SSo18SwiftNameTestErrorC5blockAByyc_tKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err7:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir29customFactoryMethodsInheritedyyF"() {{.*}} {
+func customFactoryMethodsInherited() {
+ // CHECK: call swiftcc %TSo16SwiftNameTestSubC* @"$SSo16SwiftNameTestSubC10dummyParamAByt_tcfCTO"
+ // CHECK: call swiftcc %TSo16SwiftNameTestSubC* @"$SSo16SwiftNameTestSubC2ccABypSg_tcfCTO"
+ _ = SwiftNameTestSub(dummyParam: ())
+ _ = SwiftNameTestSub(cc: nil)
+
+ // CHECK: load i8*, i8** @"\01L_selector(testZ)"
+ // CHECK: load i8*, i8** @"\01L_selector(testY:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testX:xx:)"
+ _ = SwiftNameTestSub.zz()
+ _ = SwiftNameTestSub.yy(aa: nil)
+ _ = SwiftNameTestSub.xx(nil, bb: nil)
+
+ do {
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC5errorAByt_tKcfCTO"
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aa5errorABypSg_yttKcfCTO"
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aa5error5blockABypSg_ytyyctKcfCTO"
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC5error5blockAByt_yyctKcfCTO"
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aaABypSg_tKcfCTO"
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aa5blockABypSg_yyctKcfCTO"
+ // CHECK: call swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC5blockAByyc_tKcfCTO"
+ _ = try SwiftNameTestErrorSub(error: ())
+ _ = try SwiftNameTestErrorSub(aa: nil, error: ())
+ _ = try SwiftNameTestErrorSub(aa: nil, error: (), block: {})
+ _ = try SwiftNameTestErrorSub(error: (), block: {})
+
+ _ = try SwiftNameTestErrorSub(aa: nil)
+ _ = try SwiftNameTestErrorSub(aa: nil, block: {})
+ _ = try SwiftNameTestErrorSub(block: {})
+
+ // CHECK: load i8*, i8** @"\01L_selector(testW:error:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testW2:error:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testV:)"
+ // CHECK: load i8*, i8** @"\01L_selector(testV2:)"
+ _ = try SwiftNameTestErrorSub.ww(nil)
+ _ = try SwiftNameTestErrorSub.w2(nil, error: ())
+ _ = try SwiftNameTestErrorSub.vv()
+ _ = try SwiftNameTestErrorSub.v2(error: ())
+ } catch _ {
+ }
+}
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo16SwiftNameTestSubC* @"$SSo16SwiftNameTestSubC10dummyParamAByt_tcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(b)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo16SwiftNameTestSubC* @"$SSo16SwiftNameTestSubC2ccABypSg_tcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(c:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC5errorAByt_tKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err1:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aa5errorABypSg_yttKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err2:error:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aa5error5blockABypSg_ytyyctKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err3:error:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC5error5blockAByt_yyctKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err4:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aaABypSg_tKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err5:error:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC2aa5blockABypSg_yyctKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err6:error:callback:)"
+// CHECK: }
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc %TSo21SwiftNameTestErrorSubC* @"$SSo21SwiftNameTestErrorSubC5blockAByyc_tKcfCTO"
+// CHECK: load i8*, i8** @"\01L_selector(err7:callback:)"
+// CHECK: }
+
+
+// CHECK-LABEL: define hidden swiftcc void @"$S7objc_ir30testCompatibilityAliasMangling3objySo13SwiftNameTestC_tF"
+func testCompatibilityAliasMangling(obj: SwiftNameAlias) {
+ // CHECK: call void @llvm.dbg.declare(metadata %TSo13SwiftNameTestC** {{%.+}}, metadata ![[SWIFT_NAME_ALIAS_VAR:[0-9]+]], metadata !DIExpression())
+}
+
+
+// CHECK: linkonce_odr hidden {{.*}} @"$SSo1BC3intABSgs5Int32V_tcfcTO"
+// CHECK: load i8*, i8** @"\01L_selector(initWithInt:)"
+// CHECK: call [[OPAQUE:%.*]]* bitcast (void ()* @objc_msgSend
+
+
+// CHECK: attributes [[NOUNWIND]] = { nounwind }
+
+// CHECK: ![[SWIFT_NAME_ALIAS_VAR]] = !DILocalVariable(name: "obj", arg: 1, scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: {{[0-9]+}}, type: ![[SWIFT_NAME_ALIAS_TYPE:[0-9]+]])
+// CHECK: ![[SWIFT_NAME_ALIAS_TYPE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "$SSo14SwiftNameAliasaD", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, baseType: !{{[0-9]+}})
+
diff --git a/test/ClangImporter/plus_zero_optional.swift b/test/ClangImporter/plus_zero_optional.swift
new file mode 100644
index 0000000..f36c2af
--- /dev/null
+++ b/test/ClangImporter/plus_zero_optional.swift
@@ -0,0 +1,83 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -enable-sil-ownership -emit-silgen -o - %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import ObjectiveC
+import Foundation
+import objc_ext
+import TestProtocols
+
+class A {
+ @objc func foo() -> String? {
+ return ""
+ }
+// CHECK-LABEL: sil hidden [thunk] @$S8optional1AC3fooSSSgyFTo : $@convention(objc_method) (A) -> @autoreleased Optional<NSString>
+// CHECK: bb0([[SELF:%.*]] : @unowned $A):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+// CHECK: [[T0:%.*]] = function_ref @$S8optional1AC3fooSSSgyF
+// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[BORROWED_SELF_COPY]])
+// CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+// CHECK-NEXT: destroy_value [[SELF_COPY]]
+// CHECK-NEXT: switch_enum [[T1]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// Something branch: project value, translate, inject into result.
+// CHECK: [[SOME_BB]]([[STR:%.*]] : @owned $String):
+// CHECK: [[T0:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+// CHECK-NEXT: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[BORROWED_STR]])
+// CHECK-NEXT: enum $Optional<NSString>, #Optional.some!enumelt.1, [[T1]]
+// CHECK-NEXT: end_borrow [[BORROWED_STR:%.*]] from [[STR]]
+// CHECK-NEXT: destroy_value [[STR]]
+// CHECK-NEXT: br
+// Nothing branch: inject nothing into result.
+//
+// CHECK: [[NONE_BB]]:
+// CHECK-NEXT: enum $Optional<NSString>, #Optional.none!enumelt
+// CHECK-NEXT: br
+// Continuation.
+// CHECK: bb3([[T0:%.*]] : @owned $Optional<NSString>):
+// CHECK-NEXT: return [[T0]]
+
+ @objc func bar(x x : String?) {}
+// CHECK-LABEL: sil hidden [thunk] @$S8optional1AC3bar1xySSSg_tFTo : $@convention(objc_method) (Optional<NSString>, A) -> ()
+// CHECK: bb0([[ARG:%.*]] : @unowned $Optional<NSString>, [[SELF:%.*]] : @unowned $A):
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: switch_enum [[ARG_COPY]] : $Optional<NSString>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// Something branch: project value, translate, inject into result.
+// CHECK: [[SOME_BB]]([[NSSTR:%.*]] : @owned $NSString):
+// CHECK: [[T0:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// Make a temporary initialized string that we're going to clobber as part of the conversion process (?).
+// CHECK-NEXT: [[NSSTR_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NSSTR]] : $NSString
+// CHECK-NEXT: [[STRING_META:%.*]] = metatype $@thin String.Type
+// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[NSSTR_BOX]], [[STRING_META]])
+// CHECK-NEXT: enum $Optional<String>, #Optional.some!enumelt.1, [[T1]]
+// CHECK-NEXT: destroy_value [[NSSTR_BOX]]
+// CHECK-NEXT: br
+//
+// Nothing branch: inject nothing into result.
+// CHECK: [[NONE_BB]]:
+// CHECK: enum $Optional<String>, #Optional.none!enumelt
+// CHECK-NEXT: br
+// Continuation.
+// CHECK: bb3([[T0:%.*]] : @owned $Optional<String>):
+// CHECK: [[BORROWED_T0:%.*]] = begin_borrow [[T0]]
+// CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+// CHECK: [[T1:%.*]] = function_ref @$S8optional1AC3bar1xySSSg_tF
+// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[BORROWED_T0]], [[BORROWED_SELF_COPY]])
+// CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+// CHECK-NEXT: end_borrow [[BORROWED_T0]] from [[T0]]
+// CHECK-NEXT: destroy_value [[T0]]
+// CHECK-NEXT: destroy_value [[SELF_COPY]]
+// CHECK-NEXT: return [[T2]] : $()
+}
+
+
+// rdar://15144951
+class TestWeak : NSObject {
+ weak var b : WeakObject? = nil
+}
+class WeakObject : NSObject {}
diff --git a/test/ClangImporter/plus_zero_serialization-sil.swift b/test/ClangImporter/plus_zero_serialization-sil.swift
new file mode 100644
index 0000000..2c063a6
--- /dev/null
+++ b/test/ClangImporter/plus_zero_serialization-sil.swift
@@ -0,0 +1,44 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module-path %t/Test.swiftmodule -emit-sil -o /dev/null -module-name Test %s -sdk "" -import-objc-header %S/Inputs/serialization-sil.h -enable-sil-ownership
+// RUN: %target-sil-func-extractor %t/Test.swiftmodule -sil-print-debuginfo -func='$S4Test16testPartialApplyyySoAA_pF' -o - | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+// @_transparent to force serialization.
+@_transparent
+public func testPartialApply(_ obj: Test) {
+ // CHECK-LABEL: @$S4Test16testPartialApplyyySoAA_pF : $@convention(thin) (@guaranteed Test) -> () {
+ if let curried1 = obj.normalObject {
+ // CHECK: dynamic_method_br [[CURRIED1_OBJ:%.+]] : $@opened([[CURRIED1_EXISTENTIAL:.+]]) Test, #Test.normalObject!1.foreign, [[CURRIED1_TRUE:[^,]+]], [[CURRIED1_FALSE:[^,]+]]
+ // CHECK: [[CURRIED1_FALSE]]:
+ // CHECK: [[CURRIED1_TRUE]]([[CURRIED1_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject):
+ // CHECK: [[CURRIED1_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[CURRIED1_METHOD]]([[CURRIED1_OBJ]]) : $@convention(objc_method) (@opened([[CURRIED1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject
+ // CHECK: [[CURRIED1_THUNK:%.+]] = function_ref @$SyXlIego_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @owned AnyObject) -> @out Any
+ // CHECK: = partial_apply [callee_guaranteed] [[CURRIED1_THUNK]]([[CURRIED1_PARTIAL]])
+ curried1()
+ }
+ if let curried2 = obj.innerPointer {
+ // CHECK: dynamic_method_br [[CURRIED2_OBJ:%.+]] : $@opened([[CURRIED2_EXISTENTIAL:.+]]) Test, #Test.innerPointer!1.foreign, [[CURRIED2_TRUE:[^,]+]], [[CURRIED2_FALSE:[^,]+]]
+ // CHECK: [[CURRIED2_FALSE]]:
+ // CHECK: [[CURRIED2_TRUE]]([[CURRIED2_METHOD:%.+]] : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutableRawPointer):
+ // CHECK: [[CURRIED2_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[CURRIED2_METHOD]]([[CURRIED2_OBJ]]) : $@convention(objc_method) (@opened([[CURRIED2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutableRawPointer
+ curried2()
+ }
+ if let prop1 = obj.normalObjectProp {
+ // CHECK: dynamic_method_br [[PROP1_OBJ:%.+]] : $@opened([[PROP1_EXISTENTIAL:.+]]) Test, #Test.normalObjectProp!getter.1.foreign, [[PROP1_TRUE:[^,]+]], [[PROP1_FALSE:[^,]+]]
+ // CHECK: [[PROP1_FALSE]]:
+ // CHECK: [[PROP1_TRUE]]([[PROP1_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject):
+ // CHECK: [[PROP1_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[PROP1_METHOD]]([[PROP1_OBJ]]) : $@convention(objc_method) (@opened([[PROP1_EXISTENTIAL]]) Test) -> @autoreleased AnyObject
+ // CHECK: = apply [[PROP1_PARTIAL]]() : $@callee_guaranteed () -> @owned AnyObject
+ _ = prop1
+ }
+ if let prop2 = obj.innerPointerProp {
+ // CHECK: dynamic_method_br [[PROP2_OBJ:%.+]] : $@opened([[PROP2_EXISTENTIAL:.+]]) Test, #Test.innerPointerProp!getter.1.foreign, [[PROP2_TRUE:[^,]+]], [[PROP2_FALSE:[^,]+]]
+ // CHECK: [[PROP2_FALSE]]:
+ // CHECK: [[PROP2_TRUE]]([[PROP2_METHOD:%.+]] : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutableRawPointer):
+ // CHECK: [[PROP2_PARTIAL:%.+]] = partial_apply [callee_guaranteed] [[PROP2_METHOD]]([[PROP2_OBJ]]) : $@convention(objc_method) (@opened([[PROP2_EXISTENTIAL]]) Test) -> @unowned_inner_pointer UnsafeMutableRawPointer
+ // CHECK: = apply [[PROP2_PARTIAL]]() : $@callee_guaranteed () -> UnsafeMutableRawPointer
+ _ = prop2
+ }
+} // CHECK: // end sil function '$S4Test16testPartialApplyyySoAA_pF'
diff --git a/test/ClangImporter/serialization-sil.swift b/test/ClangImporter/serialization-sil.swift
index dc43fdd..eeb1d66 100644
--- a/test/ClangImporter/serialization-sil.swift
+++ b/test/ClangImporter/serialization-sil.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module-path %t/Test.swiftmodule -emit-sil -o /dev/null -module-name Test %s -sdk "" -import-objc-header %S/Inputs/serialization-sil.h
// RUN: %target-sil-func-extractor %t/Test.swiftmodule -sil-print-debuginfo -func='$S4Test16testPartialApplyyySoAA_pF' -o - | %FileCheck %s
diff --git a/test/DebugInfo/apple-names-accel.swift b/test/DebugInfo/apple-names-accel.swift
new file mode 100644
index 0000000..ff28e6e
--- /dev/null
+++ b/test/DebugInfo/apple-names-accel.swift
@@ -0,0 +1,10 @@
+// Check that the apple-names section is emitted on Darwin.
+// Adapted from llvm/test/DebugInfo/X86/debugger-tune.ll
+// RUN: %target-swiftc_driver -emit-object -g %s -o %t
+// RUN: llvm-readobj -sections %t | %FileCheck --check-prefix=CHECK-LLDB %s
+
+// CHECK-LLDB-NOT: debug_pubnames
+// CHECK-LLDB: apple_names
+// CHECK-LLDB-NOT: debug_pubnames
+
+// REQUIRES: OS=macosx
diff --git a/test/DebugInfo/apple-types-accel.swift b/test/DebugInfo/apple-types-accel.swift
index 94e1fe1..7279181 100644
--- a/test/DebugInfo/apple-types-accel.swift
+++ b/test/DebugInfo/apple-types-accel.swift
@@ -4,12 +4,12 @@
// RUN: | %FileCheck --check-prefix=CHECK-ACCEL %s
// RUN: %llvm-dwarfdump --debug-info %t.o \
// RUN: | %FileCheck --check-prefix=CHECK-DWARF %s
-// DISABLED <rdar://problem/28232630>: dwarfdump --verify %t.o
+// RUN: %llvm-dwarfdump --verify %t.o
// REQUIRES: OS=macosx
// Verify that the unmangles basenames end up in the accelerator table.
-// CHECK-ACCEL-DAG: Name: {{.*}}"Int64"
-// CHECK-ACCEL-DAG: Name: {{.*}}"foo"
+// CHECK-ACCEL-DAG: String: {{.*}}"Int64"
+// CHECK-ACCEL-DAG: String: {{.*}}"foo"
// Verify that the mangled names end up in the debug info.
// CHECK-DWARF: TAG_module
diff --git a/test/DebugInfo/closure-multivalue.swift b/test/DebugInfo/closure-multivalue.swift
index bd541ab..c724ad1 100644
--- a/test/DebugInfo/closure-multivalue.swift
+++ b/test/DebugInfo/closure-multivalue.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// rdar://problem/23727705:
// RUN-DISABLED: %target-swift-frontend -O %s -disable-llvm-optzns -emit-ir -g -o - | %FileCheck %s
import StdlibUnittest
@@ -35,8 +36,8 @@
// Verify that a reabstraction thunk does not have a line number.
// CHECK-O0-NOT: DW_OP_bit_piece
// CHECK-O0-NOT: DW_OP_bit_piece
-// CHECK-O0: !DILocalVariable(name: "a", arg: 1{{.*}} line: 17,
+// CHECK-O0: !DILocalVariable(name: "a", arg: 1{{.*}} line: 18,
// CHECK-O0-NOT: DW_OP_bit_piece
-// CHECK-O0: !DILocalVariable(name: "b", arg: 2{{.*}} line: 17,
+// CHECK-O0: !DILocalVariable(name: "b", arg: 2{{.*}} line: 18,
// CHECK-O0-NOT: DW_OP_bit_piece
// CHECK-O0: !DISubprogram(linkageName: "$SS2SSbs5Error_pIgxxdzo_S2SSbsAA_pIegiidzo_TR",
diff --git a/test/DebugInfo/compiler-flags.swift b/test/DebugInfo/compiler-flags.swift
index a68fd68..f13b430 100644
--- a/test/DebugInfo/compiler-flags.swift
+++ b/test/DebugInfo/compiler-flags.swift
@@ -12,16 +12,6 @@
// CHECK-EXPLICIT-NOT: "
// CHECK-EXPLICIT-SAME: -resource-dir
-
-// Check that we tune the debug output for LLDB.
-// Adapted from llvm/test/DebugInfo/X86/debugger-tune.ll
-// RUN: %target-swiftc_driver -emit-object -g %s -o %t
-// RUN: llvm-readobj -sections %t | %FileCheck --check-prefix=CHECK-LLDB %s
-
-// CHECK-LLDB-NOT: debug_pubnames
-// CHECK-LLDB: apple_names
-// CHECK-LLDB-NOT: debug_pubnames
-
// Check that we don't write temporary file names in the debug info
// RUN: TMPDIR=abc/def %target-swift-frontend %s -I abc/def/xyz -g -emit-ir -o - | %FileCheck --check-prefix CHECK-TEMP %s
// CHECK-TEMP: !DICompileUnit({{.*}} flags: "{{.*}} -I <temporary-file>
diff --git a/test/DebugInfo/generic_args.swift b/test/DebugInfo/generic_args.swift
index 3f57123..a0974eb 100644
--- a/test/DebugInfo/generic_args.swift
+++ b/test/DebugInfo/generic_args.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -primary-file %s -emit-ir -verify -g -o - | %FileCheck %s
func markUsed<T>(_ t: T) {}
diff --git a/test/DebugInfo/local-vars.swift.gyb b/test/DebugInfo/local-vars.swift.gyb
index b8e5320..ab9a294 100644
--- a/test/DebugInfo/local-vars.swift.gyb
+++ b/test/DebugInfo/local-vars.swift.gyb
@@ -7,6 +7,7 @@
// RUN: %target-swift-frontend %t.swift -g -c -o %t.o
// RUN: %llvm-dwarfdump %t.o \
// RUN: | %FileCheck %t.swift --check-prefix=DWARF
+// RUN: %llvm-dwarfdump --verify %t.o
// RUN: %target-swift-frontend %t.swift -O -g -emit-ir -o - \
// RUN: | %FileCheck %t.swift --check-prefix=OPTZNS
diff --git a/test/DebugInfo/plus_zero_closure-multivalue.swift b/test/DebugInfo/plus_zero_closure-multivalue.swift
new file mode 100644
index 0000000..f77552f
--- /dev/null
+++ b/test/DebugInfo/plus_zero_closure-multivalue.swift
@@ -0,0 +1,43 @@
+// REQUIRES: plus_zero_runtime
+// rdar://problem/23727705:
+// RUN-DISABLED: %target-swift-frontend -O %s -disable-llvm-optzns -emit-ir -g -o - | %FileCheck %s
+import StdlibUnittest
+
+// CHECK: define {{.*}}i1 {{.*}}4main4sort
+// CHECK: call void @llvm.dbg.value(metadata i8*{{.*}}, metadata ![[A:.*]], metadata ![[P1:.*]])
+// CHECK: call void @llvm.dbg.value(metadata i{{[0-9]+}} {{.*}}, metadata ![[A]], metadata ![[P2:.*]])
+// CHECK: call void @llvm.dbg.value(metadata i{{[0-9]+}} {{.*}}, metadata ![[A]], metadata ![[P3:.*]])
+// CHECK: call void @llvm.dbg.value(metadata i8*{{.*}}, metadata ![[B:.*]], metadata ![[P1]])
+// CHECK: call void @llvm.dbg.value(metadata i{{[0-9]+}} {{.*}}, metadata ![[B]], metadata ![[P2]])
+// CHECK: call void @llvm.dbg.value(metadata i{{[0-9]+}} {{.*}}, metadata ![[B]], metadata ![[P3]])
+// CHECK-DAG: ![[A]] = !DILocalVariable(name: "a",{{.*}} line: 17
+// CHECK-DAG: ![[B]] = !DILocalVariable(name: "b",{{.*}} line: 17
+// CHECK-DAG: ![[P1]] = !DIExpression(DW_OP_bit_piece, 0, {{(32|64)}})
+// CHECK-DAG: ![[P2]] = !DIExpression(DW_OP_bit_piece, {{(32, 32|64, 64)}})
+// CHECK-DAG: ![[P3]] = !DIExpression(DW_OP_bit_piece, {{(64, 32|128, 64)}})
+public func sort(_ a: String, b: String) -> Bool {
+ _blackHole("Sorting..\(a) & \(b)")
+ return (a < b)
+}
+
+public func demo() {
+ let names = ["Sean", "Barry", "Kate"]
+ let sortedNames = names.sorted(by: sort)
+ var sortedNamesAsString : String = String()
+ for name in sortedNames {
+ sortedNamesAsString += ("\(name), ")
+ }
+ _blackHole(sortedNamesAsString)
+}
+demo()
+
+// At -O0, we should have a single aggregate argument.
+// RUN: %target-swift-frontend %s -emit-ir -g -o - | %FileCheck %s --check-prefix=CHECK-O0
+// Verify that a reabstraction thunk does not have a line number.
+// CHECK-O0-NOT: DW_OP_bit_piece
+// CHECK-O0-NOT: DW_OP_bit_piece
+// CHECK-O0: !DILocalVariable(name: "a", arg: 1{{.*}} line: 17,
+// CHECK-O0-NOT: DW_OP_bit_piece
+// CHECK-O0: !DILocalVariable(name: "b", arg: 2{{.*}} line: 17,
+// CHECK-O0-NOT: DW_OP_bit_piece
+// CHECK-O0: !DISubprogram(linkageName: "$SS2SSbs5Error_pIgggdzo_S2SSbsAA_pIegnndzo_TR",
diff --git a/test/DebugInfo/plus_zero_generic_args.swift b/test/DebugInfo/plus_zero_generic_args.swift
new file mode 100644
index 0000000..e4de262
--- /dev/null
+++ b/test/DebugInfo/plus_zero_generic_args.swift
@@ -0,0 +1,54 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -primary-file %s -emit-ir -verify -g -o - | %FileCheck %s
+
+func markUsed<T>(_ t: T) {}
+
+protocol AProtocol {
+ func f() -> String
+}
+class AClass : AProtocol {
+ func f() -> String { return "A" }
+}
+class AnotherClass : AProtocol {
+ func f() -> String { return "B" }
+}
+
+// CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "$S12generic_args9aFunction{{.*}}D",{{.*}} elements: ![[PROTOS:[0-9]+]]
+// CHECK-DAG: ![[PROTOS]] = !{![[INHERIT:.*]]}
+// CHECK-DAG: ![[INHERIT]] = !DIDerivedType(tag: DW_TAG_inheritance,{{.*}} baseType: ![[PROTOCOL:[0-9]+]]
+// CHECK-DAG: ![[PROTOCOL]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$S12generic_args9AProtocol_pmD",
+// CHECK-DAG: !DILocalVariable(name: "x", arg: 1,{{.*}} type: ![[T:.*]])
+// CHECK-DAG: ![[T]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$S12generic_args9aFunction
+// CHECK-DAG: !DILocalVariable(name: "y", arg: 2,{{.*}} type: ![[Q:.*]])
+// CHECK-DAG: ![[Q]] = !DICompositeType(tag: DW_TAG_structure_type, name: "$S12generic_args9aFunction
+func aFunction<T : AProtocol, Q : AProtocol>(_ x: T, _ y: Q, _ z: String) {
+ markUsed("I am in \(z): \(x.f()) \(y.f())")
+}
+
+aFunction(AClass(),AnotherClass(),"aFunction")
+
+struct Wrapper<T: AProtocol> {
+
+ init<U>(from : Wrapper<U>) {
+ // CHECK-DAG: !DICompositeType(tag: DW_TAG_structure_type, name: "Wrapper",{{.*}} identifier: "$S12generic_args7WrapperVyAC4fromACyxGACyqd__G_tcAA9AProtocolRd__lufcQq_GD")
+ var wrapped = from
+ wrapped = from
+ _ = wrapped
+ }
+
+ func passthrough(_ t: T) -> T {
+ // The type of local should have the context Wrapper<T>.
+ // CHECK-DAG: ![[WRAPPER:.*]] = !DICompositeType({{.*}}identifier: "$S12generic_args7WrapperVQq_D")
+ // CHECK-DAG: !DILocalVariable(name: "local",{{.*}} line: [[@LINE+1]],{{.*}} type: ![[WRAPPER]]
+ var local = t
+ local = t
+ return local
+ }
+}
+
+// CHECK-DAG: ![[FNTY:.*]] = !DICompositeType({{.*}}identifier: "$S12generic_args5apply_1fq_x_q_xXEtr0_lFQq_AaB_ACq_x_q_xXEtr0_lFQq0_Ignr_D"
+// CHECK-DAG: !DILocalVariable(name: "f", {{.*}}, line: [[@LINE+1]], type: ![[FNTY]])
+func apply<T, U> (_ x: T, f: (T) -> (U)) -> U {
+ return f(x)
+}
+
diff --git a/test/DebugInfo/plus_zero_resilience.swift b/test/DebugInfo/plus_zero_resilience.swift
new file mode 100644
index 0000000..0e50528
--- /dev/null
+++ b/test/DebugInfo/plus_zero_resilience.swift
@@ -0,0 +1,39 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+//
+// Compile the external swift module.
+// RUN: %target-swift-frontend -g -emit-module -enable-resilience \
+// RUN: -emit-module-path=%t/resilient_struct.swiftmodule \
+// RUN: -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+//
+// RUN: %target-swift-frontend -g -I %t -emit-ir -enable-resilience %s -o - \
+// RUN: | %FileCheck %s
+//
+// RUN: %target-swift-frontend -g -I %t -emit-sil -enable-resilience %s -o - \
+// RUN: | %FileCheck %s --check-prefix=CHECK-SIL
+// RUN: %target-swift-frontend -g -I %t -emit-sil -enable-resilience %s -o - \
+// RUN: -debugger-support | %FileCheck %s --check-prefix=CHECK-LLDB
+import resilient_struct
+
+func use<T>(_ t: T) {}
+
+public func f() {
+ let s1 = Size(w: 1, h: 2)
+ use(s1)
+ // CHECK: %[[ADDR:.*]] = alloca i8*
+ // CHECK: call void @llvm.dbg.declare(metadata i8** %[[ADDR]],
+ // CHECK-SAME: metadata ![[V1:[0-9]+]],
+ // CHECK-SAME: metadata !DIExpression(DW_OP_deref))
+ // CHECK: %[[S1:.*]] = alloca i8,
+ // CHECK: store i8* %[[S1]], i8** %[[ADDR]]
+ // CHECK: ![[V1]] = !DILocalVariable(name: "s1", {{.*}}type: ![[TY:[0-9]+]])
+ // CHECK: ![[TY]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Size",
+ // FIXME-NOT: size:
+ // CHECK: =
+}
+
+// CHECK-SIL: // f()
+// CHECK-LLDB: // f()
+// CHECK-SIL: %0 = alloc_stack $Size, let, name "s1"
+// CHECK-LLDB: %0 = metatype $@thin Size.Type
+// CHECK-LLDB: debug_value %{{.*}} : $Size, let, name "s1"
diff --git a/test/DebugInfo/resilience.swift b/test/DebugInfo/resilience.swift
index 34651fe..5f78283 100644
--- a/test/DebugInfo/resilience.swift
+++ b/test/DebugInfo/resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
//
// Compile the external swift module.
diff --git a/test/FixCode/Inputs/batch-mode-helper.swift b/test/FixCode/Inputs/batch-mode-helper.swift
new file mode 100644
index 0000000..8b3bcbd
--- /dev/null
+++ b/test/FixCode/Inputs/batch-mode-helper.swift
@@ -0,0 +1,10 @@
+enum E2 {
+ case x
+ case y
+ case z
+}
+
+func fooHelper(_ e: E2) {
+ switch e {
+ }
+}
diff --git a/test/FixCode/batch-mode.swift b/test/FixCode/batch-mode.swift
new file mode 100644
index 0000000..a2504ed
--- /dev/null
+++ b/test/FixCode/batch-mode.swift
@@ -0,0 +1,24 @@
+// RUN: not %swift -typecheck -target %target-triple -primary-file %s -emit-fixits-path %t.main.remap -primary-file %S/Inputs/batch-mode-helper.swift -emit-fixits-path %t.helper.remap -diagnostics-editor-mode
+// RUN: %FileCheck -check-prefix=CHECK-MAIN %s < %t.main.remap
+// RUN: %FileCheck -check-prefix=NEGATIVE-MAIN %s < %t.main.remap
+// RUN: %FileCheck -check-prefix=CHECK-HELPER %s < %t.helper.remap
+// RUN: %FileCheck -check-prefix=NEGATIVE-HELPER %s < %t.helper.remap
+
+// CHECK-MAIN: "file": "{{.+}}batch-mode.swift"
+// CHECK-MAIN: "text": "case .a:\n<#code#>\ncase .b:\n<#code#>\ncase .c:\n<#code#>\n"
+// NEGATIVE-MAIN-NOT: batch-mode-helper.swift
+
+// CHECK-HELPER: "file": "{{.+}}batch-mode-helper.swift"
+// CHECK-HELPER: "text": "case .x:\n<#code#>\ncase .y:\n<#code#>\ncase .z:\n<#code#>\n"
+// NEGATIVE-HELPER-NOT: batch-mode.swift
+
+enum E1 {
+ case a
+ case b
+ case c
+}
+
+func fooMain(_ e: E1) {
+ switch e {
+ }
+}
diff --git a/test/Frontend/embed-bitcode-tvos.ll b/test/Frontend/embed-bitcode-tvos.ll
index ccac443..d1b874d 100644
--- a/test/Frontend/embed-bitcode-tvos.ll
+++ b/test/Frontend/embed-bitcode-tvos.ll
@@ -12,7 +12,7 @@
; CHECK-IMPORTER: clang
; CHECK-IMPORTER: -fembed-bitcode
; CHECK-IMPORTER: -target
-; CHECK-IMPORTER: -mtvos-version-min=9
+; CHECK-IMPORTER: arm64-apple-tvos9
; CHECK-IMPORTER-NOT: argument unused
define i32 @f0() nounwind ssp {
diff --git a/test/Fuzzing/fuzzer_test.swift b/test/Fuzzing/fuzzer_test.swift
index 054bf41..3795c4c 100644
--- a/test/Fuzzing/fuzzer_test.swift
+++ b/test/Fuzzing/fuzzer_test.swift
@@ -8,7 +8,7 @@
// XFAIL: OS=watchos
// CHECK: Crash!
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin)
import Glibc
diff --git a/test/Fuzzing/fuzzer_test_simpler.swift b/test/Fuzzing/fuzzer_test_simpler.swift
index 94e9b6c..beade8e 100644
--- a/test/Fuzzing/fuzzer_test_simpler.swift
+++ b/test/Fuzzing/fuzzer_test_simpler.swift
@@ -8,7 +8,7 @@
// XFAIL: OS=tvos
// XFAIL: OS=watchos
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin)
import Glibc
diff --git a/test/IDE/coloring_configs.swift b/test/IDE/coloring_configs.swift
index 6bd6393..69445d0 100644
--- a/test/IDE/coloring_configs.swift
+++ b/test/IDE/coloring_configs.swift
@@ -280,8 +280,8 @@
// CHECK: <kw>class</kw> NestedPoundIf {
func foo1() {
// CHECK: <kw>func</kw> foo1() {
- #if os(OSX)
-// CHECK: <#kw>#if</#kw> <#id>os</#id>(<#id>OSX</#id>)
+ #if os(macOS)
+// CHECK: <#kw>#if</#kw> <#id>os</#id>(<#id>macOS</#id>)
var a = 1
// CHECK: <kw>var</kw> a = <int>1</int>
#if USE_METAL
diff --git a/test/IDE/structure.swift b/test/IDE/structure.swift
index edee06d..87bbdfd 100644
--- a/test/IDE/structure.swift
+++ b/test/IDE/structure.swift
@@ -154,7 +154,7 @@
class NestedPoundIf{
func foo1() {
- #if os(OSX)
+ #if os(macOS)
var a = 1
#if USE_METAL
var b = 2
diff --git a/test/IRGen/Inputs/ObjectiveC.swift b/test/IRGen/Inputs/ObjectiveC.swift
index 7457f48..0e155bb 100644
--- a/test/IRGen/Inputs/ObjectiveC.swift
+++ b/test/IRGen/Inputs/ObjectiveC.swift
@@ -2,8 +2,8 @@
@_exported import ObjectiveC
public struct ObjCBool : CustomStringConvertible {
-#if os(OSX) || (os(iOS) && (arch(i386) || arch(arm)))
- // On OS X and 32-bit iOS, Objective-C's BOOL type is a "signed char".
+#if os(macOS) || (os(iOS) && (arch(i386) || arch(arm)))
+ // On macOS and 32-bit iOS, Objective-C's BOOL type is a "signed char".
private var value: Int8
public init(_ value: Bool) {
diff --git a/test/IRGen/big_types_corner_cases.swift b/test/IRGen/big_types_corner_cases.swift
index 7dfb3eb..7d3886d 100644
--- a/test/IRGen/big_types_corner_cases.swift
+++ b/test/IRGen/big_types_corner_cases.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -enable-large-loadable-types %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// REQUIRES: optimized_stdlib
// UNSUPPORTED: resilient_stdlib
diff --git a/test/IRGen/builtin_math.swift b/test/IRGen/builtin_math.swift
index 43a84b5..04a3a39 100644
--- a/test/IRGen/builtin_math.swift
+++ b/test/IRGen/builtin_math.swift
@@ -20,21 +20,22 @@
return _exp(f)
}
-// LLVM's sqrt intrinsic does not have the same semantics as libm's sqrt.
-// In particular, llvm.sqrt(negative) is documented as being undef, but
-// we want sqrt(negative) to be defined to be NaN for IEEE 754 conformance.
-
// CHECK-LABEL: define {{.*}}test3
// CHECK: call double @sqrt
public func test3(d : Double) -> Double {
+ // This call uses the sqrt function imported from C.
return sqrt(d)
}
// CHECK-LABEL: define {{.*}}test4
-// CHECK: call float @sqrtf
+// CHECK: call float @llvm.sqrt.f32
public func test4(f : Float) -> Float {
+ // This call does not match the signature for the C sqrt function
+ // (as opposed to sqrtf) so instead it gets compiled using the generic
+ // sqrt function from the stdlib's tgmath.swift. That translates to
+ // _stdlib_squareRootf and then to __builtin_sqrtf via SwiftShims.
return sqrt(f)
}
diff --git a/test/IRGen/builtins.swift b/test/IRGen/builtins.swift
index 92d1f49..7046e14 100644
--- a/test/IRGen/builtins.swift
+++ b/test/IRGen/builtins.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-stdlib -primary-file %s -emit-ir -o - -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
// REQUIRES: CPU=x86_64
diff --git a/test/IRGen/class_bounded_generics.swift b/test/IRGen/class_bounded_generics.swift
index d66fc4a..f1db660 100644
--- a/test/IRGen/class_bounded_generics.swift
+++ b/test/IRGen/class_bounded_generics.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
// REQUIRES: CPU=x86_64
diff --git a/test/IRGen/enum_resilience.swift b/test/IRGen/enum_resilience.swift
index 8370768..7c3393a 100644
--- a/test/IRGen/enum_resilience.swift
+++ b/test/IRGen/enum_resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
diff --git a/test/IRGen/generic_metatypes.swift b/test/IRGen/generic_metatypes.swift
index ff14d93..fef162f 100644
--- a/test/IRGen/generic_metatypes.swift
+++ b/test/IRGen/generic_metatypes.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %swift -target x86_64-apple-macosx10.9 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
// RUN: %swift -target i386-apple-ios7.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
// RUN: %swift -target x86_64-apple-ios7.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
diff --git a/test/IRGen/generic_metatypes_arm.swift b/test/IRGen/generic_metatypes_arm.swift
index e5f28b0..58bfd76 100644
--- a/test/IRGen/generic_metatypes_arm.swift
+++ b/test/IRGen/generic_metatypes_arm.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %swift -target armv7-apple-ios7.0 -module-name generic_metatypes -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
// RUN: %swift -target arm64-apple-ios7.0 -emit-ir -module-name generic_metatypes -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
// RUN: %swift -target armv7-apple-tvos9.0 -emit-ir -module-name generic_metatypes -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
diff --git a/test/IRGen/generic_tuples.swift b/test/IRGen/generic_tuples.swift
index 99fd2ff..9f2968d 100644
--- a/test/IRGen/generic_tuples.swift
+++ b/test/IRGen/generic_tuples.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s | %FileCheck %s
// Make sure that optimization passes don't choke on storage types for generic tuples
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index 9c8636b..3c736a8 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// -- Convert <i32 0x...> constants to decimal constants that LLVM will print
// RUN: %utils/chex.py < %s > %t/keypaths.sil
diff --git a/test/IRGen/keypaths_objc.sil b/test/IRGen/keypaths_objc.sil
index 589fe23..bd94794 100644
--- a/test/IRGen/keypaths_objc.sil
+++ b/test/IRGen/keypaths_objc.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %utils/chex.py < %s > %t/keypaths_objc.sil
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir %t/keypaths_objc.sil | %FileCheck %t/keypaths_objc.sil --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
diff --git a/test/IRGen/lowered_optional_self_metadata.sil b/test/IRGen/lowered_optional_self_metadata.sil
index 11edc8f..8f14c95 100644
--- a/test/IRGen/lowered_optional_self_metadata.sil
+++ b/test/IRGen/lowered_optional_self_metadata.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s
sil_stage canonical
diff --git a/test/IRGen/objc.swift b/test/IRGen/objc.swift
index ec4d58a..0a15e37 100644
--- a/test/IRGen/objc.swift
+++ b/test/IRGen/objc.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-irgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s
diff --git a/test/IRGen/objc_retainAutoreleasedReturnValue.swift b/test/IRGen/objc_retainAutoreleasedReturnValue.swift
index a8d1a27..65c781c 100644
--- a/test/IRGen/objc_retainAutoreleasedReturnValue.swift
+++ b/test/IRGen/objc_retainAutoreleasedReturnValue.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.12 -assume-parsing-unqualified-ownership-sil -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s
// RUN: %target-swift-frontend -O -target x86_64-apple-macosx10.12 -assume-parsing-unqualified-ownership-sil -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s --check-prefix=OPT
diff --git a/test/IRGen/plus_zero_big_types_corner_cases.swift b/test/IRGen/plus_zero_big_types_corner_cases.swift
new file mode 100644
index 0000000..05b8339
--- /dev/null
+++ b/test/IRGen/plus_zero_big_types_corner_cases.swift
@@ -0,0 +1,236 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -enable-large-loadable-types %s -emit-ir | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
+// REQUIRES: optimized_stdlib
+// UNSUPPORTED: resilient_stdlib
+
+public struct BigStruct {
+ var i0 : Int32 = 0
+ var i1 : Int32 = 1
+ var i2 : Int32 = 2
+ var i3 : Int32 = 3
+ var i4 : Int32 = 4
+ var i5 : Int32 = 5
+ var i6 : Int32 = 6
+ var i7 : Int32 = 7
+ var i8 : Int32 = 8
+}
+
+func takeClosure(execute block: () -> Void) {
+}
+
+class OptionalInoutFuncType {
+ private var lp : BigStruct?
+ private var _handler : ((BigStruct?, Error?) -> ())?
+
+ func execute(_ error: Error?) {
+ var p : BigStruct?
+ var handler: ((BigStruct?, Error?) -> ())?
+
+ takeClosure {
+ p = self.lp
+ handler = self._handler
+ self._handler = nil
+ }
+
+ handler?(p, error)
+ }
+}
+
+// CHECK-LABEL: define{{( protected)?}} i32 @main(i32, i8**)
+// CHECK: call void @llvm.lifetime.start
+// CHECK: call void @llvm.memcpy
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret i32 0
+let bigStructGlobalArray : [BigStruct] = [
+ BigStruct()
+]
+
+// CHECK-LABEL: define{{( protected)?}} internal swiftcc void @"$S22big_types_corner_cases21OptionalInoutFuncTypeC7executeyys5Error_pSgFyyXEfU_"(%T22big_types_corner_cases9BigStructVSg* nocapture dereferenceable({{.*}}), %T22big_types_corner_cases21OptionalInoutFuncTypeC*, %T22big_types_corner_cases9BigStructVSgs5Error_pSgIegcg_Sg* nocapture dereferenceable({{.*}})
+// CHECK: call void @"$SSqWy
+// CHECK: call void @"$SSqWe
+// CHECK: ret void
+
+public func f1_returns_BigType(_ x: BigStruct) -> BigStruct {
+ return x
+}
+
+public func f2_returns_f1() -> (_ x: BigStruct) -> BigStruct {
+ return f1_returns_BigType
+}
+
+public func f3_uses_f2() {
+ let x = BigStruct()
+ let useOfF2 = f2_returns_f1()
+ let _ = useOfF2(x)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases10f3_uses_f2yyF"()
+// CHECK: call swiftcc void @"$S22big_types_corner_cases9BigStructVACycfC"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret
+// CHECK: call swiftcc { i8*, %swift.refcounted* } @"$S22big_types_corner_cases13f2_returns_f1AA9BigStructVADcyF"()
+// CHECK: call swiftcc void {{.*}}(%T22big_types_corner_cases9BigStructV* noalias nocapture sret {{.*}}, %T22big_types_corner_cases9BigStructV* noalias nocapture dereferenceable({{.*}}) {{.*}}, %swift.refcounted* swiftself {{.*}})
+// CHECK: ret void
+
+public func f4_tuple_use_of_f2() {
+ let x = BigStruct()
+ let tupleWithFunc = (f2_returns_f1(), x)
+ let useOfF2 = tupleWithFunc.0
+ let _ = useOfF2(x)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases18f4_tuple_use_of_f2yyF"()
+// CHECK: [[TUPLE:%.*]] = call swiftcc { i8*, %swift.refcounted* } @"$S22big_types_corner_cases13f2_returns_f1AA9BigStructVADcyF"()
+// CHECK: [[TUPLE_EXTRACT:%.*]] = extractvalue { i8*, %swift.refcounted* } [[TUPLE]], 0
+// CHECK: [[CAST_EXTRACT:%.*]] = bitcast i8* [[TUPLE_EXTRACT]] to void (%T22big_types_corner_cases9BigStructV*, %T22big_types_corner_cases9BigStructV*, %swift.refcounted*)*
+// CHECK: call swiftcc void [[CAST_EXTRACT]](%T22big_types_corner_cases9BigStructV* noalias nocapture sret {{.*}}, %T22big_types_corner_cases9BigStructV* noalias nocapture dereferenceable({{.*}}) {{.*}}, %swift.refcounted* swiftself %{{.*}})
+// CHECK: ret void
+
+public class BigClass {
+ public init() {
+ }
+
+ public var optVar: ((BigStruct)-> Void)? = nil
+
+ func useBigStruct(bigStruct: BigStruct) {
+ optVar!(bigStruct)
+ }
+}
+
+// CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases8BigClassC03useE6Struct0aH0yAA0eH0V_tF"(%T22big_types_corner_cases9BigStructV* noalias nocapture dereferenceable({{.*}}), %T22big_types_corner_cases8BigClassC* swiftself)
+// CHECK: [[BITCAST:%.*]] = bitcast i8* {{.*}} to void (%T22big_types_corner_cases9BigStructV*, %swift.refcounted*)*
+// CHECK: call swiftcc void [[BITCAST]](%T22big_types_corner_cases9BigStructV* noalias nocapture dereferenceable({{.*}}) %0, %swift.refcounted* swiftself
+// CHECK: ret void
+
+public struct MyStruct {
+ public let a: Int
+ public let b: String?
+ }
+
+typealias UploadFunction = ((MyStruct, Int?) -> Void) -> Void
+func takesUploader(_ u: UploadFunction) { }
+
+class Foo {
+ func blam() {
+ takesUploader(self.myMethod) // crash compiling this
+ }
+
+ func myMethod(_ callback: (MyStruct, Int) -> Void) -> Void { }
+}
+
+// CHECK-LABEL: define{{( protected)?}} linkonce_odr hidden swiftcc { i8*, %swift.refcounted* } @"$S22big_types_corner_cases3FooC8myMethodyyyAA8MyStructV_SitXEFTc"(%T22big_types_corner_cases3FooC*)
+// CHECK: getelementptr inbounds %T22big_types_corner_cases3FooC, %T22big_types_corner_cases3FooC*
+// CHECK: getelementptr inbounds void (i8*, %swift.opaque*, %T22big_types_corner_cases3FooC*)*, void (i8*, %swift.opaque*, %T22big_types_corner_cases3FooC*)**
+// CHECK: call noalias %swift.refcounted* @swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata*
+// CHECK: ret { i8*, %swift.refcounted* }
+
+public enum LargeEnum {
+ public enum InnerEnum {
+ case simple(Int64)
+ case hard(Int64, String?, Int64)
+ }
+ case Empty1
+ case Empty2
+ case Full(InnerEnum)
+}
+
+public func enumCallee(_ x: LargeEnum) {
+ switch x {
+ case .Full(let inner): print(inner)
+ case .Empty1: break
+ case .Empty2: break
+ }
+}
+// CHECK-LABEL-64: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases10enumCalleeyAA9LargeEnumOF"(%T22big_types_corner_cases9LargeEnumO* noalias nocapture dereferenceable({{.*}})) #0 {
+// CHECK-64: alloca %T22big_types_corner_cases9LargeEnumO05InnerF0O
+// CHECK-64: alloca %T22big_types_corner_cases9LargeEnumO
+// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK-64: call void @llvm.memcpy.p0i8.p0i8.i64
+// CHECK-64: $Ss5print_9separator10terminatoryypd_S2StF
+// CHECK-64: ret void
+
+// CHECK-LABEL: define{{( protected)?}} internal swiftcc void @"$S22big_types_corner_cases8SuperSubC1fyyFAA9BigStructVycfU_"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret, %T22big_types_corner_cases8SuperSubC*)
+// CHECK-64: [[ALLOC1:%.*]] = alloca %T22big_types_corner_cases9BigStructV
+// CHECK-64: [[ALLOC2:%.*]] = alloca %T22big_types_corner_cases9BigStructV
+// CHECK-64: [[ALLOC3:%.*]] = alloca %T22big_types_corner_cases9BigStructVSg
+// CHECK-64: [[ALLOC4:%.*]] = alloca %T22big_types_corner_cases9BigStructVSg
+// CHECK-64: call swiftcc void @"$S22big_types_corner_cases9SuperBaseC4boomAA9BigStructVyF"(%T22big_types_corner_cases9BigStructV* noalias nocapture sret [[ALLOC1]], %T22big_types_corner_cases9SuperBaseC* swiftself {{.*}})
+// CHECK: ret void
+class SuperBase {
+ func boom() -> BigStruct {
+ return BigStruct()
+ }
+}
+
+class SuperSub : SuperBase {
+ override func boom() -> BigStruct {
+ return BigStruct()
+ }
+ func f() {
+ let _ = {
+ nil ?? super.boom()
+ }
+ }
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases10MUseStructV16superclassMirrorAA03BigF0VSgvg"(%T22big_types_corner_cases9BigStructVSg* noalias nocapture sret, %T22big_types_corner_cases10MUseStructV* noalias nocapture swiftself dereferenceable({{.*}}))
+// CHECK: [[ALLOC:%.*]] = alloca %T22big_types_corner_cases9BigStructVSg
+// CHECK: [[LOAD:%.*]] = load %swift.refcounted*, %swift.refcounted** %.callInternalLet.data
+// CHECK: call swiftcc void %7(%T22big_types_corner_cases9BigStructVSg* noalias nocapture sret [[ALLOC]], %swift.refcounted* swiftself [[LOAD]])
+// CHECK: ret void
+public struct MUseStruct {
+ var x = BigStruct()
+ public var superclassMirror: BigStruct? {
+ return callInternalLet()
+ }
+
+ internal let callInternalLet: () -> BigStruct?
+}
+
+// CHECK-LABEL-64: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases18stringAndSubstringSS_s0G0VtyF"(<{ %TSS, %Ts9SubstringV }>* noalias nocapture sret) #0 {
+// CHECK-LABEL-32: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases18stringAndSubstringSS_s0G0VtyF"(<{ %TSS, [4 x i8], %Ts9SubstringV }>* noalias nocapture sret) #0 {
+// CHECK: alloca %Ts9SubstringV
+// CHECK: alloca %Ts9SubstringV
+// CHECK: ret void
+public func stringAndSubstring() -> (String, Substring) {
+ let s = "Hello, World"
+ let a = Substring(s).dropFirst()
+ return (s, a)
+}
+
+func bigStructGet() -> BigStruct {
+ return BigStruct()
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S22big_types_corner_cases11testGetFuncyyF"()
+// CHECK: ret void
+public func testGetFunc() {
+ let testGetPtr: @convention(thin) () -> BigStruct = bigStructGet
+}
+
+// CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases7TestBigC4testyyF"(%T22big_types_corner_cases7TestBigC* swiftself)
+// CHECK: [[CALL1:%.*]] = call %swift.type* @"$SSayy22big_types_corner_cases9BigStructVcSgGMa"
+// CHECK: [[CALL2:%.*]] = call i8** @"$SSayy22big_types_corner_cases9BigStructVcSgGSayxGs10CollectionsWl
+// CHECK: call swiftcc void @"$Ss10CollectionPsE5index5where5IndexQzSgSb7ElementQzKXE_tKF"(%TSq.{{.*}}* noalias nocapture sret {{.*}}, i8* bitcast (i1 (%T22big_types_corner_cases9BigStructVytIegnr_Sg*, %swift.refcounted*, %swift.error**)* @"$S22big_types_corner_cases9BigStructVIegy_SgSbs5Error_pIggdzo_ACytIegnr_SgSbsAE_pIegndzo_TRTA" to i8*), %swift.opaque* {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself
+// CHECK: ret void
+
+// CHECK-LABEL: define{{( protected)?}} hidden swiftcc void @"$S22big_types_corner_cases7TestBigC5test2yyF"(%T22big_types_corner_cases7TestBigC* swiftself)
+// CHECK: [[CALL1:%.*]] = call %swift.type* @"$SSaySS2ID_y22big_types_corner_cases9BigStructVcSg7handlertGMa"
+// CHECK: [[CALL2:%.*]] = call i8** @"$SSaySS2ID_y22big_types_corner_cases9BigStructVcSg7handlertGSayxGs10CollectionsWl"
+// CHECK: call swiftcc void @"$Ss10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF"(%Ts16IndexingIteratorV* noalias nocapture sret {{.*}}, %swift.type* [[CALL1]], i8** [[CALL2]], %swift.opaque* noalias nocapture swiftself {{.*}})
+// CHECK: ret void
+class TestBig {
+ typealias Handler = (BigStruct) -> Void
+
+ func test() {
+ let arr = [Handler?]()
+ let d = arr.index(where: { _ in true })
+ }
+
+ func test2() {
+ let arr: [(ID: String, handler: Handler?)] = []
+ for (_, handler) in arr {
+ takeClosure {
+ handler?(BigStruct())
+ }
+ }
+ }
+}
diff --git a/test/IRGen/plus_zero_builtins.swift b/test/IRGen/plus_zero_builtins.swift
new file mode 100644
index 0000000..b4479ad
--- /dev/null
+++ b/test/IRGen/plus_zero_builtins.swift
@@ -0,0 +1,872 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-stdlib -primary-file %s -emit-ir -o - -disable-objc-attr-requires-foundation-module | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
+
+// REQUIRES: CPU=x86_64
+
+import Swift
+
+// CHECK-DAG: [[REFCOUNT:%swift.refcounted.*]] = type
+// CHECK-DAG: [[X:%T8builtins1XC]] = type
+// CHECK-DAG: [[Y:%T8builtins1YC]] = type
+
+typealias Int = Builtin.Int32
+typealias Bool = Builtin.Int1
+
+// CHECK: call swiftcc void @swift_errorInMain(
+
+infix operator * {
+ associativity left
+ precedence 200
+}
+infix operator / {
+ associativity left
+ precedence 200
+}
+infix operator % {
+ associativity left
+ precedence 200
+}
+
+infix operator + {
+ associativity left
+ precedence 190
+}
+infix operator - {
+ associativity left
+ precedence 190
+}
+
+infix operator << {
+ associativity none
+ precedence 180
+}
+infix operator >> {
+ associativity none
+ precedence 180
+}
+
+infix operator ... {
+ associativity none
+ precedence 175
+}
+
+infix operator < {
+ associativity none
+ precedence 170
+}
+infix operator <= {
+ associativity none
+ precedence 170
+}
+infix operator > {
+ associativity none
+ precedence 170
+}
+infix operator >= {
+ associativity none
+ precedence 170
+}
+
+infix operator == {
+ associativity none
+ precedence 160
+}
+infix operator != {
+ associativity none
+ precedence 160
+}
+
+func * (lhs: Int, rhs: Int) -> Int {
+ return Builtin.mul_Int32(lhs, rhs)
+ // CHECK: mul i32
+}
+func / (lhs: Int, rhs: Int) -> Int {
+ return Builtin.sdiv_Int32(lhs, rhs)
+ // CHECK: sdiv i32
+}
+func % (lhs: Int, rhs: Int) -> Int {
+ return Builtin.srem_Int32(lhs, rhs)
+ // CHECK: srem i32
+}
+func + (lhs: Int, rhs: Int) -> Int {
+ return Builtin.add_Int32(lhs, rhs)
+ // CHECK: add i32
+}
+func - (lhs: Int, rhs: Int) -> Int {
+ return Builtin.sub_Int32(lhs, rhs)
+ // CHECK: sub i32
+}
+// In C, 180 is <<, >>
+func < (lhs: Int, rhs: Int) -> Bool {
+ return Builtin.cmp_slt_Int32(lhs, rhs)
+ // CHECK: icmp slt i32
+}
+func > (lhs: Int, rhs: Int) -> Bool {
+ return Builtin.cmp_sgt_Int32(lhs, rhs)
+ // CHECK: icmp sgt i32
+}
+func <=(lhs: Int, rhs: Int) -> Bool {
+ return Builtin.cmp_sle_Int32(lhs, rhs)
+ // CHECK: icmp sle i32
+}
+func >=(lhs: Int, rhs: Int) -> Bool {
+ return Builtin.cmp_sge_Int32(lhs, rhs)
+ // CHECK: icmp sge i32
+}
+func ==(lhs: Int, rhs: Int) -> Bool {
+ return Builtin.cmp_eq_Int32(lhs, rhs)
+ // CHECK: icmp eq i32
+}
+func !=(lhs: Int, rhs: Int) -> Bool {
+ return Builtin.cmp_ne_Int32(lhs, rhs)
+ // CHECK: icmp ne i32
+}
+
+func gepRaw_test(_ ptr: Builtin.RawPointer, offset: Builtin.Int64)
+ -> Builtin.RawPointer {
+ return Builtin.gepRaw_Int64(ptr, offset)
+ // CHECK: getelementptr inbounds i8, i8*
+}
+
+// CHECK: define hidden {{.*}}i64 @"$S8builtins9load_test{{[_0-9a-zA-Z]*}}F"
+func load_test(_ ptr: Builtin.RawPointer) -> Builtin.Int64 {
+ // CHECK: [[CASTPTR:%.*]] = bitcast i8* [[PTR:%.*]] to i64*
+ // CHECK-NEXT: load i64, i64* [[CASTPTR]]
+ // CHECK: ret
+ return Builtin.load(ptr)
+}
+
+// CHECK: define hidden {{.*}}i64 @"$S8builtins13load_raw_test{{[_0-9a-zA-Z]*}}F"
+func load_raw_test(_ ptr: Builtin.RawPointer) -> Builtin.Int64 {
+ // CHECK: [[CASTPTR:%.*]] = bitcast i8* [[PTR:%.*]] to i64*
+ // CHECK-NEXT: load i64, i64* [[CASTPTR]]
+ // CHECK: ret
+ return Builtin.loadRaw(ptr)
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins11assign_test{{[_0-9a-zA-Z]*}}F"
+func assign_test(_ value: Builtin.Int64, ptr: Builtin.RawPointer) {
+ Builtin.assign(value, ptr)
+ // CHECK: ret
+}
+
+// CHECK: define hidden {{.*}}%swift.refcounted* @"$S8builtins16load_object_test{{[_0-9a-zA-Z]*}}F"
+func load_object_test(_ ptr: Builtin.RawPointer) -> Builtin.NativeObject {
+ // CHECK: [[T0:%.*]] = load [[REFCOUNT]]*, [[REFCOUNT]]**
+ // CHECK: call [[REFCOUNT]]* @swift_retain([[REFCOUNT]]* returned [[T0]])
+ // CHECK: ret [[REFCOUNT]]* [[T0]]
+ return Builtin.load(ptr)
+}
+
+// CHECK: define hidden {{.*}}%swift.refcounted* @"$S8builtins20load_raw_object_test{{[_0-9a-zA-Z]*}}F"
+func load_raw_object_test(_ ptr: Builtin.RawPointer) -> Builtin.NativeObject {
+ // CHECK: [[T0:%.*]] = load [[REFCOUNT]]*, [[REFCOUNT]]**
+ // CHECK: call [[REFCOUNT]]* @swift_retain([[REFCOUNT]]* returned [[T0]])
+ // CHECK: ret [[REFCOUNT]]* [[T0]]
+ return Builtin.loadRaw(ptr)
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins18assign_object_test{{[_0-9a-zA-Z]*}}F"
+func assign_object_test(_ value: Builtin.NativeObject, ptr: Builtin.RawPointer) {
+ Builtin.assign(value, ptr)
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins16init_object_test{{[_0-9a-zA-Z]*}}F"
+func init_object_test(_ value: Builtin.NativeObject, ptr: Builtin.RawPointer) {
+ // CHECK: [[DEST:%.*]] = bitcast i8* {{%.*}} to [[REFCOUNT]]**
+ // CHECK-NEXT: call [[REFCOUNT]]* @swift_retain([[REFCOUNT]]* returned [[SRC:%.*]])
+ // CHECK-NEXT: store [[REFCOUNT]]* [[SRC]], [[REFCOUNT]]** [[DEST]]
+ Builtin.initialize(value, ptr)
+}
+
+func cast_test(_ ptr: inout Builtin.RawPointer, i8: inout Builtin.Int8,
+ i64: inout Builtin.Int64, f: inout Builtin.FPIEEE32,
+ d: inout Builtin.FPIEEE64
+) {
+ // CHECK: cast_test
+
+ i8 = Builtin.trunc_Int64_Int8(i64) // CHECK: trunc
+ i64 = Builtin.zext_Int8_Int64(i8) // CHECK: zext
+ i64 = Builtin.sext_Int8_Int64(i8) // CHECK: sext
+ i64 = Builtin.ptrtoint_Int64(ptr) // CHECK: ptrtoint
+ ptr = Builtin.inttoptr_Int64(i64) // CHECK: inttoptr
+ i64 = Builtin.fptoui_FPIEEE64_Int64(d) // CHECK: fptoui
+ i64 = Builtin.fptosi_FPIEEE64_Int64(d) // CHECK: fptosi
+ d = Builtin.uitofp_Int64_FPIEEE64(i64) // CHECK: uitofp
+ d = Builtin.sitofp_Int64_FPIEEE64(i64) // CHECK: sitofp
+ d = Builtin.fpext_FPIEEE32_FPIEEE64(f) // CHECK: fpext
+ f = Builtin.fptrunc_FPIEEE64_FPIEEE32(d) // CHECK: fptrunc
+ i64 = Builtin.bitcast_FPIEEE64_Int64(d) // CHECK: bitcast
+ d = Builtin.bitcast_Int64_FPIEEE64(i64) // CHECK: bitcast
+}
+
+func intrinsic_test(_ i32: inout Builtin.Int32, i16: inout Builtin.Int16) {
+ i32 = Builtin.int_bswap_Int32(i32) // CHECK: llvm.bswap.i32(
+
+ i16 = Builtin.int_bswap_Int16(i16) // CHECK: llvm.bswap.i16(
+
+ var x = Builtin.int_sadd_with_overflow_Int16(i16, i16) // CHECK: call { i16, i1 } @llvm.sadd.with.overflow.i16(
+
+ Builtin.int_trap() // CHECK: llvm.trap()
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins19sizeof_alignof_testyyF"()
+func sizeof_alignof_test() {
+ // CHECK: store i64 4, i64*
+ var xs = Builtin.sizeof(Int.self)
+ // CHECK: store i64 4, i64*
+ var xa = Builtin.alignof(Int.self)
+ // CHECK: store i64 1, i64*
+ var ys = Builtin.sizeof(Bool.self)
+ // CHECK: store i64 1, i64*
+ var ya = Builtin.alignof(Bool.self)
+
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins27generic_sizeof_alignof_testyyxlF"
+func generic_sizeof_alignof_test<T>(_: T) {
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 9
+ // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
+ // CHECK-NEXT: [[SIZE:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK-NEXT: store i64 [[SIZE]], i64* [[S:%.*]]
+ var s = Builtin.sizeof(T.self)
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 10
+ // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
+ // CHECK-NEXT: [[T2:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK-NEXT: [[T3:%.*]] = and i64 [[T2]], 65535
+ // CHECK-NEXT: [[ALIGN:%.*]] = add i64 [[T3]], 1
+ // CHECK-NEXT: store i64 [[ALIGN]], i64* [[A:%.*]]
+ var a = Builtin.alignof(T.self)
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins21generic_strideof_testyyxlF"
+func generic_strideof_test<T>(_: T) {
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 11
+ // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
+ // CHECK-NEXT: [[STRIDE:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK-NEXT: store i64 [[STRIDE]], i64* [[S:%.*]]
+ var s = Builtin.strideof(T.self)
+}
+
+class X {}
+
+class Y {}
+func move(_ ptr: Builtin.RawPointer) {
+ var temp : Y = Builtin.take(ptr)
+ // CHECK: define hidden {{.*}}void @"$S8builtins4move{{[_0-9a-zA-Z]*}}F"
+ // CHECK: [[SRC:%.*]] = bitcast i8* {{%.*}} to [[Y]]**
+ // CHECK-NEXT: [[VAL:%.*]] = load [[Y]]*, [[Y]]** [[SRC]]
+ // CHECK-NEXT: store [[Y]]* [[VAL]], [[Y]]** {{%.*}}
+}
+
+func allocDealloc(_ size: Builtin.Word, align: Builtin.Word) {
+ var ptr = Builtin.allocRaw(size, align)
+ Builtin.deallocRaw(ptr, size, align)
+}
+
+func fence_test() {
+ // CHECK: fence acquire
+ Builtin.fence_acquire()
+
+ // CHECK: fence syncscope("singlethread") acq_rel
+ Builtin.fence_acqrel_singlethread()
+}
+
+func cmpxchg_test(_ ptr: Builtin.RawPointer, a: Builtin.Int32, b: Builtin.Int32) {
+ // rdar://12939803 - ER: support atomic cmpxchg/xchg with pointers
+
+ // CHECK: [[Z_RES:%.*]] = cmpxchg i32* {{.*}}, i32 {{.*}}, i32 {{.*}} acquire acquire
+ // CHECK: [[Z_VAL:%.*]] = extractvalue { i32, i1 } [[Z_RES]], 0
+ // CHECK: [[Z_SUCCESS:%.*]] = extractvalue { i32, i1 } [[Z_RES]], 1
+ // CHECK: store i32 [[Z_VAL]], i32* {{.*}}, align 4
+ // CHECK: store i1 [[Z_SUCCESS]], i1* {{.*}}, align 1
+ var (z, zSuccess) = Builtin.cmpxchg_acquire_acquire_Int32(ptr, a, b)
+
+ // CHECK: [[Y_RES:%.*]] = cmpxchg volatile i32* {{.*}}, i32 {{.*}}, i32 {{.*}} monotonic monotonic
+ // CHECK: [[Y_VAL:%.*]] = extractvalue { i32, i1 } [[Y_RES]], 0
+ // CHECK: [[Y_SUCCESS:%.*]] = extractvalue { i32, i1 } [[Y_RES]], 1
+ // CHECK: store i32 [[Y_VAL]], i32* {{.*}}, align 4
+ // CHECK: store i1 [[Y_SUCCESS]], i1* {{.*}}, align 1
+ var (y, ySuccess) = Builtin.cmpxchg_monotonic_monotonic_volatile_Int32(ptr, a, b)
+
+ // CHECK: [[X_RES:%.*]] = cmpxchg volatile i32* {{.*}}, i32 {{.*}}, i32 {{.*}} syncscope("singlethread") acquire monotonic
+ // CHECK: [[X_VAL:%.*]] = extractvalue { i32, i1 } [[X_RES]], 0
+ // CHECK: [[X_SUCCESS:%.*]] = extractvalue { i32, i1 } [[X_RES]], 1
+ // CHECK: store i32 [[X_VAL]], i32* {{.*}}, align 4
+ // CHECK: store i1 [[X_SUCCESS]], i1* {{.*}}, align 1
+ var (x, xSuccess) = Builtin.cmpxchg_acquire_monotonic_volatile_singlethread_Int32(ptr, a, b)
+
+ // CHECK: [[W_RES:%.*]] = cmpxchg volatile i64* {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst
+ // CHECK: [[W_VAL:%.*]] = extractvalue { i64, i1 } [[W_RES]], 0
+ // CHECK: [[W_SUCCESS:%.*]] = extractvalue { i64, i1 } [[W_RES]], 1
+ // CHECK: [[W_VAL_PTR:%.*]] = inttoptr i64 [[W_VAL]] to i8*
+ // CHECK: store i8* [[W_VAL_PTR]], i8** {{.*}}, align 8
+ // CHECK: store i1 [[W_SUCCESS]], i1* {{.*}}, align 1
+ var (w, wSuccess) = Builtin.cmpxchg_seqcst_seqcst_volatile_singlethread_RawPointer(ptr, ptr, ptr)
+
+ // CHECK: [[V_RES:%.*]] = cmpxchg weak volatile i64* {{.*}}, i64 {{.*}}, i64 {{.*}} seq_cst seq_cst
+ // CHECK: [[V_VAL:%.*]] = extractvalue { i64, i1 } [[V_RES]], 0
+ // CHECK: [[V_SUCCESS:%.*]] = extractvalue { i64, i1 } [[V_RES]], 1
+ // CHECK: [[V_VAL_PTR:%.*]] = inttoptr i64 [[V_VAL]] to i8*
+ // CHECK: store i8* [[V_VAL_PTR]], i8** {{.*}}, align 8
+ // CHECK: store i1 [[V_SUCCESS]], i1* {{.*}}, align 1
+ var (v, vSuccess) = Builtin.cmpxchg_seqcst_seqcst_weak_volatile_singlethread_RawPointer(ptr, ptr, ptr)
+}
+
+func atomicrmw_test(_ ptr: Builtin.RawPointer, a: Builtin.Int32,
+ ptr2: Builtin.RawPointer) {
+ // CHECK: atomicrmw add i32* {{.*}}, i32 {{.*}} acquire
+ var z = Builtin.atomicrmw_add_acquire_Int32(ptr, a)
+
+ // CHECK: atomicrmw volatile max i32* {{.*}}, i32 {{.*}} monotonic
+ var y = Builtin.atomicrmw_max_monotonic_volatile_Int32(ptr, a)
+
+ // CHECK: atomicrmw volatile xchg i32* {{.*}}, i32 {{.*}} syncscope("singlethread") acquire
+ var x = Builtin.atomicrmw_xchg_acquire_volatile_singlethread_Int32(ptr, a)
+
+ // rdar://12939803 - ER: support atomic cmpxchg/xchg with pointers
+ // CHECK: atomicrmw volatile xchg i64* {{.*}}, i64 {{.*}} syncscope("singlethread") acquire
+ var w = Builtin.atomicrmw_xchg_acquire_volatile_singlethread_RawPointer(ptr, ptr2)
+
+}
+
+func addressof_test(_ a: inout Int, b: inout Bool) {
+ // CHECK: bitcast i32* {{.*}} to i8*
+ var ap : Builtin.RawPointer = Builtin.addressof(&a)
+ // CHECK: bitcast i1* {{.*}} to i8*
+ var bp : Builtin.RawPointer = Builtin.addressof(&b)
+}
+
+func fneg_test(_ half: Builtin.FPIEEE16,
+ single: Builtin.FPIEEE32,
+ double: Builtin.FPIEEE64)
+ -> (Builtin.FPIEEE16, Builtin.FPIEEE32, Builtin.FPIEEE64)
+{
+ // CHECK: fsub half 0xH8000, {{%.*}}
+ // CHECK: fsub float -0.000000e+00, {{%.*}}
+ // CHECK: fsub double -0.000000e+00, {{%.*}}
+ return (Builtin.fneg_FPIEEE16(half),
+ Builtin.fneg_FPIEEE32(single),
+ Builtin.fneg_FPIEEE64(double))
+}
+
+// The call to the builtins should get removed before we reach IRGen.
+func testStaticReport(_ b: Bool, ptr: Builtin.RawPointer) -> () {
+ Builtin.staticReport(b, b, ptr);
+ return Builtin.staticReport(b, b, ptr);
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins12testCondFail{{[_0-9a-zA-Z]*}}F"(i1, i1)
+func testCondFail(_ b: Bool, c: Bool) {
+ // CHECK: br i1 %0, label %[[FAIL:.*]], label %[[CONT:.*]]
+ Builtin.condfail(b)
+ // CHECK: <label>:[[CONT]]
+ // CHECK: br i1 %1, label %[[FAIL2:.*]], label %[[CONT:.*]]
+ Builtin.condfail(c)
+ // CHECK: <label>:[[CONT]]
+ // CHECK: ret void
+
+ // CHECK: <label>:[[FAIL]]
+ // CHECK: call void @llvm.trap()
+ // CHECK: unreachable
+
+ // CHECK: <label>:[[FAIL2]]
+ // CHECK: call void @llvm.trap()
+ // CHECK: unreachable
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins8testOnce{{[_0-9a-zA-Z]*}}F"(i8*, i8*) {{.*}} {
+// CHECK: [[PRED_PTR:%.*]] = bitcast i8* %0 to [[WORD:i64|i32]]*
+// CHECK-objc: [[PRED:%.*]] = load {{.*}} [[WORD]]* [[PRED_PTR]]
+// CHECK-objc: [[IS_DONE:%.*]] = icmp eq [[WORD]] [[PRED]], -1
+// CHECK-objc: br i1 [[IS_DONE]], label %[[DONE:.*]], label %[[NOT_DONE:.*]]
+// CHECK-objc: [[NOT_DONE]]:
+// CHECK: call void @swift_once([[WORD]]* [[PRED_PTR]], i8* %1, i8* undef)
+// CHECK-objc: br label %[[DONE]]
+// CHECK-objc: [[DONE]]:
+// CHECK-objc: [[PRED:%.*]] = load {{.*}} [[WORD]]* [[PRED_PTR]]
+// CHECK-objc: [[IS_DONE:%.*]] = icmp eq [[WORD]] [[PRED]], -1
+// CHECK-objc: call void @llvm.assume(i1 [[IS_DONE]])
+
+func testOnce(_ p: Builtin.RawPointer, f: @escaping @convention(c) () -> ()) {
+ Builtin.once(p, f)
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins19testOnceWithContext{{[_0-9a-zA-Z]*}}F"(i8*, i8*, i8*) {{.*}} {
+// CHECK: [[PRED_PTR:%.*]] = bitcast i8* %0 to [[WORD:i64|i32]]*
+// CHECK-objc: [[PRED:%.*]] = load {{.*}} [[WORD]]* [[PRED_PTR]]
+// CHECK-objc: [[IS_DONE:%.*]] = icmp eq [[WORD]] [[PRED]], -1
+// CHECK-objc: br i1 [[IS_DONE]], label %[[DONE:.*]], label %[[NOT_DONE:.*]]
+// CHECK-objc: [[NOT_DONE]]:
+// CHECK: call void @swift_once([[WORD]]* [[PRED_PTR]], i8* %1, i8* %2)
+// CHECK-objc: br label %[[DONE]]
+// CHECK-objc: [[DONE]]:
+// CHECK-objc: [[PRED:%.*]] = load {{.*}} [[WORD]]* [[PRED_PTR]]
+// CHECK-objc: [[IS_DONE:%.*]] = icmp eq [[WORD]] [[PRED]], -1
+// CHECK-objc: call void @llvm.assume(i1 [[IS_DONE]])
+func testOnceWithContext(_ p: Builtin.RawPointer, f: @escaping @convention(c) (Builtin.RawPointer) -> (), k: Builtin.RawPointer) {
+ Builtin.onceWithContext(p, f, k)
+}
+
+class C {}
+struct S {}
+@objc class O {}
+@objc protocol OP1 {}
+@objc protocol OP2 {}
+protocol P {}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins10canBeClass{{[_0-9a-zA-Z]*}}F"
+func canBeClass<T>(_ f: @escaping (Builtin.Int8) -> (), _: T) {
+ // CHECK: call {{.*}}void {{%.*}}(i8 1
+ f(Builtin.canBeClass(O.self))
+ // CHECK: call {{.*}}void {{%.*}}(i8 1
+ f(Builtin.canBeClass(OP1.self))
+ typealias ObjCCompo = OP1 & OP2
+ // CHECK: call {{.*}}void {{%.*}}(i8 1
+ f(Builtin.canBeClass(ObjCCompo.self))
+
+ // CHECK: call {{.*}}void {{%.*}}(i8 0
+ f(Builtin.canBeClass(S.self))
+ // CHECK: call {{.*}}void {{%.*}}(i8 1
+ f(Builtin.canBeClass(C.self))
+ // CHECK: call {{.*}}void {{%.*}}(i8 0
+ f(Builtin.canBeClass(P.self))
+ typealias MixedCompo = OP1 & P
+ // CHECK: call {{.*}}void {{%.*}}(i8 0
+ f(Builtin.canBeClass(MixedCompo.self))
+
+ // CHECK: call {{.*}}void {{%.*}}(i8 2
+ f(Builtin.canBeClass(T.self))
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins15destroyPODArray{{[_0-9a-zA-Z]*}}F"(i8*, i64)
+// CHECK-NOT: loop:
+// CHECK: ret void
+func destroyPODArray(_ array: Builtin.RawPointer, count: Builtin.Word) {
+ Builtin.destroyArray(Int.self, array, count)
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins18destroyNonPODArray{{[_0-9a-zA-Z]*}}F"(i8*, i64) {{.*}} {
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayDestroy(
+func destroyNonPODArray(_ array: Builtin.RawPointer, count: Builtin.Word) {
+ Builtin.destroyArray(C.self, array, count)
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins15destroyGenArray_5count_yBp_BwxtlF"(i8*, i64, %swift.opaque* noalias nocapture, %swift.type* %T)
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayDestroy
+func destroyGenArray<T>(_ array: Builtin.RawPointer, count: Builtin.Word, _: T) {
+ Builtin.destroyArray(T.self, array, count)
+}
+
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins12copyPODArray{{[_0-9a-zA-Z]*}}F"(i8*, i8*, i64)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+// check: mul nuw i64 4, %2
+// check: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 4, i1 false)
+func copyPODArray(_ dest: Builtin.RawPointer, src: Builtin.RawPointer, count: Builtin.Word) {
+ Builtin.copyArray(Int.self, dest, src, count)
+ Builtin.takeArrayFrontToBack(Int.self, dest, src, count)
+ Builtin.takeArrayBackToFront(Int.self, dest, src, count)
+ Builtin.assignCopyArrayNoAlias(Int.self, dest, src, count)
+ Builtin.assignCopyArrayFrontToBack(Int.self, dest, src, count)
+ Builtin.assignCopyArrayBackToFront(Int.self, dest, src, count)
+ Builtin.assignTakeArray(Int.self, dest, src, count)
+}
+
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins11copyBTArray{{[_0-9a-zA-Z]*}}F"(i8*, i8*, i64) {{.*}} {
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayInitWithCopy
+// CHECK: mul nuw i64 8, %2
+// CHECK: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 8, i1 false)
+// CHECK: mul nuw i64 8, %2
+// CHECK: call void @llvm.memmove.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 {{.*}}, i32 8, i1 false)
+// CHECK: call void @swift_arrayAssignWithCopyNoAlias(
+// CHECK: call void @swift_arrayAssignWithCopyFrontToBack(
+// CHECK: call void @swift_arrayAssignWithCopyBackToFront(
+// CHECK: call void @swift_arrayAssignWithTake(
+func copyBTArray(_ dest: Builtin.RawPointer, src: Builtin.RawPointer, count: Builtin.Word) {
+ Builtin.copyArray(C.self, dest, src, count)
+ Builtin.takeArrayFrontToBack(C.self, dest, src, count)
+ Builtin.takeArrayBackToFront(C.self, dest, src, count)
+ Builtin.assignCopyArrayNoAlias(C.self, dest, src, count)
+ Builtin.assignCopyArrayFrontToBack(C.self, dest, src, count)
+ Builtin.assignCopyArrayBackToFront(C.self, dest, src, count)
+ Builtin.assignTakeArray(C.self, dest, src, count)
+}
+
+struct W { weak var c: C? }
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins15copyNonPODArray{{[_0-9a-zA-Z]*}}F"(i8*, i8*, i64) {{.*}} {
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayInitWithCopy(
+// CHECK-NOT: loop{{.*}}:
+// CHECK: call void @swift_arrayInitWithTakeFrontToBack(
+// CHECK-NOT: loop{{.*}}:
+// CHECK: call void @swift_arrayInitWithTakeBackToFront(
+// CHECK: call void @swift_arrayAssignWithCopyNoAlias(
+// CHECK: call void @swift_arrayAssignWithCopyFrontToBack(
+// CHECK: call void @swift_arrayAssignWithCopyBackToFront(
+// CHECK: call void @swift_arrayAssignWithTake(
+func copyNonPODArray(_ dest: Builtin.RawPointer, src: Builtin.RawPointer, count: Builtin.Word) {
+ Builtin.copyArray(W.self, dest, src, count)
+ Builtin.takeArrayFrontToBack(W.self, dest, src, count)
+ Builtin.takeArrayBackToFront(W.self, dest, src, count)
+ Builtin.assignCopyArrayNoAlias(W.self, dest, src, count)
+ Builtin.assignCopyArrayFrontToBack(W.self, dest, src, count)
+ Builtin.assignCopyArrayBackToFront(W.self, dest, src, count)
+ Builtin.assignTakeArray(W.self, dest, src, count)
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins12copyGenArray{{[_0-9a-zA-Z]*}}F"(i8*, i8*, i64, %swift.opaque* noalias nocapture, %swift.type* %T)
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayInitWithCopy
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayInitWithTakeFrontToBack(
+// CHECK-NOT: loop:
+// CHECK: call void @swift_arrayInitWithTakeBackToFront(
+// CHECK: call void @swift_arrayAssignWithCopyNoAlias(
+// CHECK: call void @swift_arrayAssignWithCopyFrontToBack(
+// CHECK: call void @swift_arrayAssignWithCopyBackToFront(
+// CHECK: call void @swift_arrayAssignWithTake(
+func copyGenArray<T>(_ dest: Builtin.RawPointer, src: Builtin.RawPointer, count: Builtin.Word, _: T) {
+ Builtin.copyArray(T.self, dest, src, count)
+ Builtin.takeArrayFrontToBack(T.self, dest, src, count)
+ Builtin.takeArrayBackToFront(T.self, dest, src, count)
+ Builtin.assignCopyArrayNoAlias(T.self, dest, src, count)
+ Builtin.assignCopyArrayFrontToBack(T.self, dest, src, count)
+ Builtin.assignCopyArrayBackToFront(T.self, dest, src, count)
+ Builtin.assignTakeArray(T.self, dest, src, count)
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins24conditionallyUnreachableyyF"
+// CHECK-NEXT: entry
+// CHECK-NEXT: unreachable
+func conditionallyUnreachable() {
+ Builtin.conditionallyUnreachable()
+}
+
+struct Abc {
+ var value : Builtin.Word
+}
+
+// CHECK-LABEL: define hidden {{.*}}@"$S8builtins22assumeNonNegative_testyBwAA3AbcVzF"
+func assumeNonNegative_test(_ x: inout Abc) -> Builtin.Word {
+ // CHECK: load {{.*}}, !range ![[R:[0-9]+]]
+ return Builtin.assumeNonNegative_Word(x.value)
+}
+
+@inline(never)
+func return_word(_ x: Builtin.Word) -> Builtin.Word {
+ return x
+}
+
+// CHECK-LABEL: define hidden {{.*}}@"$S8builtins23assumeNonNegative_test2yBwBwF"
+func assumeNonNegative_test2(_ x: Builtin.Word) -> Builtin.Word {
+ // CHECK: call {{.*}}, !range ![[R]]
+ return Builtin.assumeNonNegative_Word(return_word(x))
+}
+
+struct Empty {}
+struct Pair { var i: Int, b: Bool }
+
+// CHECK-LABEL: define hidden {{.*}}i64 @"$S8builtins15zeroInitializerAA5EmptyV_AA4PairVtyF"() {{.*}} {
+// CHECK: [[ALLOCA:%.*]] = alloca { i64 }
+// CHECK: bitcast
+// CHECK: lifetime.start
+// CHECK: [[EMPTYPAIR:%.*]] = bitcast { i64 }* [[ALLOCA]]
+// CHECK: [[PAIR:%.*]] = getelementptr inbounds {{.*}} [[EMPTYPAIR]], i32 0, i32 0
+// CHECK: [[FLDI:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 0
+// CHECK: store i32 0, i32* [[FLDI]]
+// CHECK: [[FLDB:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 1
+// CHECK: store i1 false, i1* [[FLDB]]
+// CHECK: [[RET:%.*]] = getelementptr inbounds {{.*}} [[ALLOCA]], i32 0, i32 0
+// CHECK: [[RES:%.*]] = load i64, i64* [[RET]]
+// CHECK: ret i64 [[RES]]
+func zeroInitializer() -> (Empty, Pair) {
+ return (Builtin.zeroInitializer(), Builtin.zeroInitializer())
+}
+
+// CHECK-LABEL: define hidden {{.*}}i64 @"$S8builtins20zeroInitializerTupleAA5EmptyV_AA4PairVtyF"() {{.*}} {
+// CHECK: [[ALLOCA:%.*]] = alloca { i64 }
+// CHECK: bitcast
+// CHECK: lifetime.start
+// CHECK: [[EMPTYPAIR:%.*]] = bitcast { i64 }* [[ALLOCA]]
+// CHECK: [[PAIR:%.*]] = getelementptr inbounds {{.*}} [[EMPTYPAIR]], i32 0, i32 0
+// CHECK: [[FLDI:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 0
+// CHECK: store i32 0, i32* [[FLDI]]
+// CHECK: [[FLDB:%.*]] = getelementptr inbounds {{.*}} [[PAIR]], i32 0, i32 1
+// CHECK: store i1 false, i1* [[FLDB]]
+// CHECK: [[RET:%.*]] = getelementptr inbounds {{.*}} [[ALLOCA]], i32 0, i32 0
+// CHECK: [[RES:%.*]] = load i64, i64* [[RET]]
+// CHECK: ret i64 [[RES]]
+func zeroInitializerTuple() -> (Empty, Pair) {
+ return Builtin.zeroInitializer()
+}
+
+// CHECK-LABEL: define hidden {{.*}}void @"$S8builtins20zeroInitializerEmptyyyF"() {{.*}} {
+// CHECK: ret void
+func zeroInitializerEmpty() {
+ return Builtin.zeroInitializer()
+}
+
+// ----------------------------------------------------------------------------
+// isUnique variants
+// ----------------------------------------------------------------------------
+
+// CHECK: define hidden {{.*}}void @"$S8builtins26acceptsBuiltinNativeObjectyyBoSgzF"([[BUILTIN_NATIVE_OBJECT_TY:%.*]]* nocapture dereferenceable({{.*}})) {{.*}} {
+func acceptsBuiltinNativeObject(_ ref: inout Builtin.NativeObject?) {}
+
+// native
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins8isUniqueyBi1_BoSgzF"({{%.*}}* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: bitcast [[BUILTIN_NATIVE_OBJECT_TY]]* %0 to %swift.refcounted**
+// CHECK-NEXT: load %swift.refcounted*, %swift.refcounted** %1
+// CHECK-NEXT: call i1 @swift_isUniquelyReferenced_native(%swift.refcounted* %2)
+// CHECK-NEXT: ret i1 %3
+func isUnique(_ ref: inout Builtin.NativeObject?) -> Bool {
+ return Builtin.isUnique(&ref)
+}
+
+// native nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins8isUniqueyBi1_BozF"(%swift.refcounted** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: load %swift.refcounted*, %swift.refcounted** %0
+// CHECK-NEXT: call i1 @swift_isUniquelyReferenced_nonNull_native(%swift.refcounted* %1)
+// CHECK-NEXT: ret i1 %2
+func isUnique(_ ref: inout Builtin.NativeObject) -> Bool {
+ return Builtin.isUnique(&ref)
+}
+
+// native pinned
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins16isUniqueOrPinnedyBi1_BoSgzF"({{%.*}}* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: bitcast [[BUILTIN_NATIVE_OBJECT_TY]]* %0 to %swift.refcounted**
+// CHECK-NEXT: load %swift.refcounted*, %swift.refcounted** %1
+// CHECK-NEXT: call i1 @swift_isUniquelyReferencedOrPinned_native(%swift.refcounted* %2)
+// CHECK-NEXT: ret i1 %3
+func isUniqueOrPinned(_ ref: inout Builtin.NativeObject?) -> Bool {
+ return Builtin.isUniqueOrPinned(&ref)
+}
+
+// native pinned nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins16isUniqueOrPinnedyBi1_BozF"(%swift.refcounted** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: load %swift.refcounted*, %swift.refcounted** %0
+// CHECK-NEXT: call i1 @swift_isUniquelyReferencedOrPinned_nonNull_native(%swift.refcounted* %1)
+// CHECK-NEXT: ret i1 %2
+func isUniqueOrPinned(_ ref: inout Builtin.NativeObject) -> Bool {
+ return Builtin.isUniqueOrPinned(&ref)
+}
+
+// CHECK: define hidden {{.*}}void @"$S8builtins27acceptsBuiltinUnknownObjectyyBOSgzF"([[BUILTIN_UNKNOWN_OBJECT_TY:%.*]]* nocapture dereferenceable({{.*}})) {{.*}} {
+func acceptsBuiltinUnknownObject(_ ref: inout Builtin.UnknownObject?) {}
+
+// ObjC
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins8isUniqueyBi1_BOSgzF"({{%.*}}* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: bitcast [[BUILTIN_UNKNOWN_OBJECT_TY]]* %0 to [[UNKNOWN_OBJECT:%objc_object|%swift\.refcounted]]**
+// CHECK-NEXT: load [[UNKNOWN_OBJECT]]*, [[UNKNOWN_OBJECT]]** %1
+// CHECK-objc-NEXT: call i1 @swift_isUniquelyReferencedNonObjC([[UNKNOWN_OBJECT]]* %2)
+// CHECK-native-NEXT: call i1 @swift_isUniquelyReferenced_native([[UNKNOWN_OBJECT]]* %2)
+// CHECK-NEXT: ret i1 %3
+func isUnique(_ ref: inout Builtin.UnknownObject?) -> Bool {
+ return Builtin.isUnique(&ref)
+}
+
+// ObjC nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins8isUniqueyBi1_BOzF"
+// CHECK-SAME: ([[UNKNOWN_OBJECT]]** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: load [[UNKNOWN_OBJECT]]*, [[UNKNOWN_OBJECT]]** %0
+// CHECK-objc-NEXT: call i1 @swift_isUniquelyReferencedNonObjC_nonNull([[UNKNOWN_OBJECT]]* %1)
+// CHECK-native-NEXT: call i1 @swift_isUniquelyReferenced_nonNull_native([[UNKNOWN_OBJECT]]* %1)
+// CHECK-NEXT: ret i1 %2
+func isUnique(_ ref: inout Builtin.UnknownObject) -> Bool {
+ return Builtin.isUnique(&ref)
+}
+
+// ObjC pinned nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins16isUniqueOrPinnedyBi1_BOzF"
+// CHECK-SAME: ([[UNKNOWN_OBJECT]]** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: load [[UNKNOWN_OBJECT]]*, [[UNKNOWN_OBJECT]]** %0
+// CHECK-native-NEXT: call i1 @swift_isUniquelyReferencedOrPinned_nonNull_native([[UNKNOWN_OBJECT]]* %1)
+// CHECK-objc-NEXT: call i1 @swift_isUniquelyReferencedOrPinnedNonObjC_nonNull([[UNKNOWN_OBJECT]]* %1)
+// CHECK-NEXT: ret i1 %2
+func isUniqueOrPinned(_ ref: inout Builtin.UnknownObject) -> Bool {
+ return Builtin.isUniqueOrPinned(&ref)
+}
+
+// BridgeObject nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins8isUniqueyBi1_BbzF"(%swift.bridge** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: load %swift.bridge*, %swift.bridge** %0
+// CHECK-NEXT: call i1 @swift_isUniquelyReferencedNonObjC_nonNull_bridgeObject(%swift.bridge* %1)
+// CHECK-NEXT: ret i1 %2
+func isUnique(_ ref: inout Builtin.BridgeObject) -> Bool {
+ return Builtin.isUnique(&ref)
+}
+
+// Bridge pinned nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins16isUniqueOrPinnedyBi1_BbzF"(%swift.bridge** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: load %swift.bridge*, %swift.bridge** %0
+// CHECK-NEXT: call i1 @swift_isUniquelyReferencedOrPinnedNonObjC_nonNull_bridgeObject(%swift.bridge* %1)
+// CHECK-NEXT: ret i1 %2
+func isUniqueOrPinned(_ ref: inout Builtin.BridgeObject) -> Bool {
+ return Builtin.isUniqueOrPinned(&ref)
+}
+
+// BridgeObject nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins15isUnique_nativeyBi1_BbzF"(%swift.bridge** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: bitcast %swift.bridge** %0 to %swift.refcounted**
+// CHECK-NEXT: load %swift.refcounted*, %swift.refcounted** %1
+// CHECK-NEXT: call i1 @swift_isUniquelyReferenced_nonNull_native(%swift.refcounted* %2)
+// CHECK-NEXT: ret i1 %3
+func isUnique_native(_ ref: inout Builtin.BridgeObject) -> Bool {
+ return Builtin.isUnique_native(&ref)
+}
+
+// Bridge pinned nonNull
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins23isUniqueOrPinned_nativeyBi1_BbzF"(%swift.bridge** nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: bitcast %swift.bridge** %0 to %swift.refcounted**
+// CHECK-NEXT: load %swift.refcounted*, %swift.refcounted** %1
+// CHECK-NEXT: call i1 @swift_isUniquelyReferencedOrPinned_nonNull_native(%swift.refcounted* %2)
+// CHECK-NEXT: ret i1 %3
+func isUniqueOrPinned_native(_ ref: inout Builtin.BridgeObject) -> Bool {
+ return Builtin.isUniqueOrPinned_native(&ref)
+}
+
+// ImplicitlyUnwrappedOptional argument to isUnique.
+// CHECK-LABEL: define hidden {{.*}}i1 @"$S8builtins11isUniqueIUOyBi1_BoSgzF"(%{{.*}}* nocapture dereferenceable({{.*}})) {{.*}} {
+// CHECK-NEXT: entry:
+// CHECK: call i1 @swift_isUniquelyReferenced_native(%swift.refcounted*
+// CHECK: ret i1
+func isUniqueIUO(_ ref: inout Builtin.NativeObject?) -> Bool {
+ var iuo : Builtin.NativeObject! = ref
+ return Builtin.isUnique(&iuo)
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}generic_ispod_test
+func generic_ispod_test<T>(_: T) {
+ // CHECK: [[T0:%.*]] = getelementptr inbounds i8*, i8** [[T:%.*]], i32 10
+ // CHECK-NEXT: [[T1:%.*]] = load i8*, i8** [[T0]]
+ // CHECK-NEXT: [[FLAGS:%.*]] = ptrtoint i8* [[T1]] to i64
+ // CHECK-NEXT: [[ISNOTPOD:%.*]] = and i64 [[FLAGS]], 65536
+ // CHECK-NEXT: [[ISPOD:%.*]] = icmp eq i64 [[ISNOTPOD]], 0
+ // CHECK-NEXT: store i1 [[ISPOD]], i1* [[S:%.*]]
+ var s = Builtin.ispod(T.self)
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}ispod_test
+func ispod_test() {
+ // CHECK: store i1 true, i1*
+ // CHECK: store i1 false, i1*
+ var t = Builtin.ispod(Int.self)
+ var f = Builtin.ispod(Builtin.NativeObject)
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}is_same_metatype
+func is_same_metatype_test(_ t1: Any.Type, _ t2: Any.Type) {
+ // CHECK: [[MT1_AS_PTR:%.*]] = bitcast %swift.type* %0 to i8*
+ // CHECK: [[MT2_AS_PTR:%.*]] = bitcast %swift.type* %1 to i8*
+ // CHECK: icmp eq i8* [[MT1_AS_PTR]], [[MT2_AS_PTR]]
+ var t = Builtin.is_same_metatype(t1, t2)
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}generic_unsafeGuaranteed_test
+// CHECK: call {{.*}}* @{{.*}}swift_{{.*}}etain({{.*}}* returned %0)
+// CHECK: call void @{{.*}}swift_{{.*}}elease({{.*}}* %0)
+// CHECK: ret {{.*}}* %0
+func generic_unsafeGuaranteed_test<T: AnyObject>(_ t : T) -> T {
+ let (g, _) = Builtin.unsafeGuaranteed(t)
+ return g
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}unsafeGuaranteed_test
+// CHECK: [[LOCAL:%.*]] = alloca %swift.refcounted*
+// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned %0)
+// CHECK: store %swift.refcounted* %0, %swift.refcounted** [[LOCAL]]
+// CHECK: call void @swift_release(%swift.refcounted* %0)
+// CHECK: ret %swift.refcounted* %0
+func unsafeGuaranteed_test(_ x: Builtin.NativeObject) -> Builtin.NativeObject {
+ var (g,t) = Builtin.unsafeGuaranteed(x)
+ Builtin.unsafeGuaranteedEnd(t)
+ return g
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}unsafeGuaranteedEnd_test
+// CHECK-NEXT: {{.*}}:
+// CHECK-NEXT: ret void
+func unsafeGuaranteedEnd_test(_ x: Builtin.Int8) {
+ Builtin.unsafeGuaranteedEnd(x)
+}
+
+// CHECK-LABEL: define {{.*}} @{{.*}}atomicload
+func atomicload(_ p: Builtin.RawPointer) {
+ // CHECK: [[A:%.*]] = load atomic i8*, i8** {{%.*}} unordered, align 8
+ let a: Builtin.RawPointer = Builtin.atomicload_unordered_RawPointer(p)
+ // CHECK: [[B:%.*]] = load atomic i32, i32* {{%.*}} syncscope("singlethread") monotonic, align 4
+ let b: Builtin.Int32 = Builtin.atomicload_monotonic_singlethread_Int32(p)
+ // CHECK: [[C:%.*]] = load atomic volatile i64, i64* {{%.*}} syncscope("singlethread") acquire, align 8
+ let c: Builtin.Int64 =
+ Builtin.atomicload_acquire_volatile_singlethread_Int64(p)
+ // CHECK: [[D0:%.*]] = load atomic volatile i32, i32* {{%.*}} seq_cst, align 4
+ // CHECK: [[D:%.*]] = bitcast i32 [[D0]] to float
+ let d: Builtin.FPIEEE32 = Builtin.atomicload_seqcst_volatile_FPIEEE32(p)
+
+ // CHECK: store atomic i8* [[A]], i8** {{%.*}} unordered, align 8
+ Builtin.atomicstore_unordered_RawPointer(p, a)
+ // CHECK: store atomic i32 [[B]], i32* {{%.*}} syncscope("singlethread") monotonic, align 4
+ Builtin.atomicstore_monotonic_singlethread_Int32(p, b)
+ // CHECK: store atomic volatile i64 [[C]], i64* {{%.*}} syncscope("singlethread") release, align 8
+ Builtin.atomicstore_release_volatile_singlethread_Int64(p, c)
+ // CHECK: [[D1:%.*]] = bitcast float [[D]] to i32
+ // CHECK: store atomic volatile i32 [[D1]], i32* {{.*}} seq_cst, align 4
+ Builtin.atomicstore_seqcst_volatile_FPIEEE32(p, d)
+}
+
+// CHECK-LABEL: define {{.*}} @"$S8builtins14stringObjectOryS2u_SutF"(i64, i64)
+// CHECK-NEXT: {{.*}}:
+// CHECK-NEXT: %2 = or i64 %0, %1
+// CHECK-NEXT: ret i64 %2
+func stringObjectOr(_ x: UInt, _ y: UInt) -> UInt {
+ return UInt(Builtin.stringObjectOr_Int64(
+ x._value, y._value))
+}
+
+func createInt(_ fn: () -> ()) throws {}
+// CHECK-LABEL: define {{.*}}testForceTry
+// CHECK: call swiftcc void @swift_unexpectedError(%swift.error*
+func testForceTry(_ fn: () -> ()) {
+ try! createInt(fn)
+}
+
+// CHECK-LABEL: declare swiftcc void @swift_unexpectedError(%swift.error*
+
+enum MyError : Error {
+ case A, B
+}
+
+throw MyError.A
+
+
+
+// CHECK: ![[R]] = !{i64 0, i64 9223372036854775807}
+
diff --git a/test/IRGen/plus_zero_class_bounded_generics.swift b/test/IRGen/plus_zero_class_bounded_generics.swift
new file mode 100644
index 0000000..304f545
--- /dev/null
+++ b/test/IRGen/plus_zero_class_bounded_generics.swift
@@ -0,0 +1,312 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-ir -primary-file %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
+
+// REQUIRES: CPU=x86_64
+// XFAIL: linux
+
+protocol ClassBound : class {
+ func classBoundMethod()
+}
+protocol ClassBound2 : class {
+ func classBoundMethod2()
+}
+protocol ClassBoundBinary : ClassBound {
+ func classBoundBinaryMethod(_ x: Self)
+}
+@objc protocol ObjCClassBound {
+ func objCClassBoundMethod()
+}
+@objc protocol ObjCClassBound2 {
+ func objCClassBoundMethod2()
+}
+protocol NotClassBound {
+ func notClassBoundMethod()
+ func notClassBoundBinaryMethod(_ x: Self)
+}
+
+struct ClassGenericFieldStruct<T:ClassBound> {
+ var x : Int
+ var y : T
+ var z : Int
+}
+
+struct ClassProtocolFieldStruct {
+ var x : Int
+ var y : ClassBound
+ var z : Int
+}
+
+class ClassGenericFieldClass<T:ClassBound> {
+ final var x : Int = 0
+ final var y : T
+ final var z : Int = 0
+
+ init(t: T) {
+ y = t
+ }
+}
+
+class ClassProtocolFieldClass {
+ var x : Int = 0
+ var y : ClassBound
+ var z : Int = 0
+
+ init(classBound cb: ClassBound) {
+ y = cb
+ }
+}
+
+// CHECK-DAG: %T22class_bounded_generics017ClassGenericFieldD0C = type <{ %swift.refcounted, %TSi, %objc_object*, %TSi }>
+// CHECK-DAG: %T22class_bounded_generics23ClassGenericFieldStructV = type <{ %TSi, %objc_object*, %TSi }>
+// CHECK-DAG: %T22class_bounded_generics24ClassProtocolFieldStructV = type <{ %TSi, %T22class_bounded_generics10ClassBoundP, %TSi }>
+
+// CHECK-LABEL: define hidden swiftcc %objc_object* @"$S22class_bounded_generics0a1_B10_archetype{{[_0-9a-zA-Z]*}}F"(%objc_object*, %swift.type* %T, i8** %T.ClassBound)
+func class_bounded_archetype<T : ClassBound>(_ x: T) -> T {
+ return x
+}
+
+class SomeClass {}
+class SomeSubclass : SomeClass {}
+
+// CHECK-LABEL: define hidden swiftcc %T22class_bounded_generics9SomeClassC* @"$S22class_bounded_generics011superclass_B10_archetype{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics9SomeClassC*, %swift.type* %T)
+func superclass_bounded_archetype<T : SomeClass>(_ x: T) -> T {
+ return x
+}
+
+// CHECK-LABEL: define hidden swiftcc { %T22class_bounded_generics9SomeClassC*, %T22class_bounded_generics12SomeSubclassC* } @"$S22class_bounded_generics011superclass_B15_archetype_call{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics9SomeClassC*, %T22class_bounded_generics12SomeSubclassC*)
+func superclass_bounded_archetype_call(_ x: SomeClass, y: SomeSubclass) -> (SomeClass, SomeSubclass) {
+ return (superclass_bounded_archetype(x),
+ superclass_bounded_archetype(y));
+ // CHECK: [[SOMECLASS_RESULT:%.*]] = call swiftcc %T22class_bounded_generics9SomeClassC* @"$S22class_bounded_generics011superclass_B10_archetype{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics9SomeClassC* {{%.*}}, {{.*}})
+ // CHECK: [[SOMESUPERCLASS_IN:%.*]] = bitcast %T22class_bounded_generics12SomeSubclassC* {{%.*}} to %T22class_bounded_generics9SomeClassC*
+ // CHECK: [[SOMESUPERCLASS_RESULT:%.*]] = call swiftcc %T22class_bounded_generics9SomeClassC* @"$S22class_bounded_generics011superclass_B10_archetype{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics9SomeClassC* [[SOMESUPERCLASS_IN]], {{.*}})
+ // CHECK: bitcast %T22class_bounded_generics9SomeClassC* [[SOMESUPERCLASS_RESULT]] to %T22class_bounded_generics12SomeSubclassC*
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics0a1_B17_archetype_method{{[_0-9a-zA-Z]*}}F"(%objc_object*, %objc_object*, %swift.type* %T, i8** %T.ClassBoundBinary)
+func class_bounded_archetype_method<T : ClassBoundBinary>(_ x: T, y: T) {
+ x.classBoundMethod()
+ // CHECK: [[INHERITED_GEP:%.*]] = getelementptr inbounds i8*, i8** %T.ClassBoundBinary, i32 1
+ // CHECK: [[INHERITED:%.*]] = load i8*, i8** [[INHERITED_GEP]]
+ // CHECK: [[INHERITED_WTBL:%.*]] = bitcast i8* [[INHERITED]] to i8**
+ // CHECK: [[WITNESS_GEP:%.*]] = getelementptr inbounds i8*, i8** [[INHERITED_WTBL]], i32 1
+ // CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_GEP]], align 8
+ // CHECK: [[WITNESS_FUNC:%.*]] = bitcast i8* [[WITNESS]] to void (%objc_object*, %swift.type*, i8**)
+ // CHECK: call swiftcc void [[WITNESS_FUNC]](%objc_object* swiftself %0, %swift.type* {{.*}}, i8** [[INHERITED_WTBL]])
+ x.classBoundBinaryMethod(y)
+ // CHECK-NOT: call %objc_object* @swift_unknownRetain(%objc_object* returned [[Y:%.*]])
+ // CHECK: [[WITNESS_ENTRY:%.*]] = getelementptr inbounds i8*, i8** %T.ClassBoundBinary, i32 2
+ // CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ENTRY]], align 8
+ // CHECK: [[WITNESS_FUNC:%.*]] = bitcast i8* [[WITNESS]] to void (%objc_object*, %objc_object*, %swift.type*, i8**)
+ // CHECK: call swiftcc void [[WITNESS_FUNC]](%objc_object* %1, %objc_object* swiftself %0, %swift.type* %T, i8** %T.ClassBoundBinary)
+}
+
+// CHECK-LABEL: define hidden swiftcc { %objc_object*, %objc_object* } @"$S22class_bounded_generics0a1_B16_archetype_tuple{{[_0-9a-zA-Z]*}}F"(%objc_object*, %swift.type* %T, i8** %T.ClassBound)
+func class_bounded_archetype_tuple<T : ClassBound>(_ x: T) -> (T, T) {
+ return (x, x)
+}
+
+class ConcreteClass : ClassBoundBinary, NotClassBound {
+ func classBoundMethod() {}
+ func classBoundBinaryMethod(_ x: ConcreteClass) {}
+ func notClassBoundMethod() {}
+ func notClassBoundBinaryMethod(_ x: ConcreteClass) {}
+}
+
+// CHECK-LABEL: define hidden swiftcc %T22class_bounded_generics13ConcreteClassC* @"$S22class_bounded_generics05call_a1_B10_archetype{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics13ConcreteClassC*) {{.*}} {
+func call_class_bounded_archetype(_ x: ConcreteClass) -> ConcreteClass {
+ return class_bounded_archetype(x)
+ // CHECK: [[IN:%.*]] = bitcast %T22class_bounded_generics13ConcreteClassC* {{%.*}} to %objc_object*
+ // CHECK: [[OUT_ORIG:%.*]] = call swiftcc %objc_object* @"$S22class_bounded_generics0a1_B10_archetype{{[_0-9a-zA-Z]*}}F"(%objc_object* [[IN]], {{.*}})
+ // CHECK: [[OUT:%.*]] = bitcast %objc_object* [[OUT_ORIG]] to %T22class_bounded_generics13ConcreteClassC*
+ // CHECK: ret %T22class_bounded_generics13ConcreteClassC* [[OUT]]
+}
+
+// CHECK: define hidden swiftcc void @"$S22class_bounded_generics04not_a1_B10_archetype{{[_0-9a-zA-Z]*}}F"(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.NotClassBound)
+func not_class_bounded_archetype<T : NotClassBound>(_ x: T) -> T {
+ return x
+}
+
+// CHECK-LABEL: define hidden swiftcc %objc_object* @"$S22class_bounded_generics0a1_b18_archetype_to_not_a1_B0{{[_0-9a-zA-Z]*}}F"(%objc_object*, %swift.type* %T, i8** %T.ClassBound, i8** %T.NotClassBound) {{.*}} {
+func class_bounded_archetype_to_not_class_bounded
+<T: ClassBound & NotClassBound>(_ x:T) -> T {
+ // CHECK: alloca %objc_object*, align 8
+ return not_class_bounded_archetype(x)
+}
+
+/* TODO Abstraction remapping to non-class-bounded witnesses
+func class_and_not_class_bounded_archetype_methods
+<T: ClassBound & NotClassBound>(_ x:T, y:T) {
+ x.classBoundMethod()
+ x.classBoundBinaryMethod(y)
+ x.notClassBoundMethod()
+ x.notClassBoundBinaryMethod(y)
+}
+*/
+
+// CHECK-LABEL: define hidden swiftcc { %objc_object*, i8** } @"$S22class_bounded_generics0a1_B8_erasure{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics13ConcreteClassC*) {{.*}} {
+func class_bounded_erasure(_ x: ConcreteClass) -> ClassBound {
+ return x
+ // CHECK: [[INSTANCE_OPAQUE:%.*]] = bitcast %T22class_bounded_generics13ConcreteClassC* [[INSTANCE:%.*]] to %objc_object*
+ // CHECK: [[T0:%.*]] = insertvalue { %objc_object*, i8** } undef, %objc_object* [[INSTANCE_OPAQUE]], 0
+ // CHECK: [[T1:%.*]] = insertvalue { %objc_object*, i8** } [[T0]], i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @"$S22class_bounded_generics13ConcreteClassCAA0E5BoundAAWP", i32 0, i32 0), 1
+ // CHECK: ret { %objc_object*, i8** } [[T1]]
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics0a1_B16_protocol_method{{[_0-9a-zA-Z]*}}F"(%objc_object*, i8**) {{.*}} {
+func class_bounded_protocol_method(_ x: ClassBound) {
+ x.classBoundMethod()
+ // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getObjectType(%objc_object* %0)
+ // CHECK: [[WITNESS_GEP:%.*]] = getelementptr inbounds i8*, i8** [[WITNESS_TABLE:%.*]], i32 1
+ // CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_GEP]], align 8
+ // CHECK: [[WITNESS_FN:%.*]] = bitcast i8* [[WITNESS]] to void (%objc_object*, %swift.type*, i8**)
+ // CHECK: call swiftcc void [[WITNESS_FN]](%objc_object* swiftself %0, %swift.type* [[METADATA]], i8** [[WITNESS_TABLE]])
+}
+
+// CHECK-LABEL: define hidden swiftcc %T22class_bounded_generics13ConcreteClassC* @"$S22class_bounded_generics0a1_B15_archetype_cast{{[_0-9a-zA-Z]*}}F"(%objc_object*, %swift.type* %T, i8** %T.ClassBound)
+func class_bounded_archetype_cast<T : ClassBound>(_ x: T) -> ConcreteClass {
+ return x as! ConcreteClass
+ // CHECK: [[IN_PTR:%.*]] = bitcast %objc_object* {{%.*}} to i8*
+ // CHECK: [[T0:%.*]] = call %swift.type* @"$S22class_bounded_generics13ConcreteClassCMa"()
+ // CHECK: [[T1:%.*]] = bitcast %swift.type* [[T0]] to i8*
+ // CHECK: [[OUT_PTR:%.*]] = call i8* @swift_dynamicCastClassUnconditional(i8* [[IN_PTR]], i8* [[T1]])
+ // CHECK: [[OUT:%.*]] = bitcast i8* [[OUT_PTR]] to %T22class_bounded_generics13ConcreteClassC*
+ // CHECK: ret %T22class_bounded_generics13ConcreteClassC* [[OUT]]
+}
+
+// CHECK-LABEL: define hidden swiftcc %T22class_bounded_generics13ConcreteClassC* @"$S22class_bounded_generics0a1_B14_protocol_cast{{[_0-9a-zA-Z]*}}F"(%objc_object*, i8**)
+func class_bounded_protocol_cast(_ x: ClassBound) -> ConcreteClass {
+ return x as! ConcreteClass
+ // CHECK: [[IN_PTR:%.*]] = bitcast %objc_object* {{%.*}} to i8*
+ // CHECK: [[T0:%.*]] = call %swift.type* @"$S22class_bounded_generics13ConcreteClassCMa"()
+ // CHECK: [[T1:%.*]] = bitcast %swift.type* [[T0]] to i8*
+ // CHECK: [[OUT_PTR:%.*]] = call i8* @swift_dynamicCastClassUnconditional(i8* [[IN_PTR]], i8* [[T1]])
+ // CHECK: [[OUT:%.*]] = bitcast i8* [[OUT_PTR]] to %T22class_bounded_generics13ConcreteClassC*
+ // CHECK: ret %T22class_bounded_generics13ConcreteClassC* [[OUT]]
+}
+
+// CHECK-LABEL: define hidden swiftcc { %objc_object*, i8** } @"$S22class_bounded_generics0a1_B22_protocol_conversion_{{.*}}"(%objc_object*, i8**, i8**) {{.*}} {
+func class_bounded_protocol_conversion_1(_ x: ClassBound & ClassBound2)
+-> ClassBound {
+ return x
+}
+// CHECK-LABEL: define hidden swiftcc { %objc_object*, i8** } @"$S22class_bounded_generics0a1_B22_protocol_conversion_{{.*}}"(%objc_object*, i8**, i8**) {{.*}} {
+func class_bounded_protocol_conversion_2(_ x: ClassBound & ClassBound2)
+-> ClassBound2 {
+ return x
+}
+
+// CHECK-LABEL: define hidden swiftcc { %objc_object*, i8** } @"$S22class_bounded_generics05objc_a1_B22_protocol_conversion_{{.*}}"(%objc_object*, i8**) {{.*}} {
+func objc_class_bounded_protocol_conversion_1
+(_ x: ClassBound & ObjCClassBound) -> ClassBound {
+ return x
+}
+// CHECK-LABEL: define hidden swiftcc %objc_object* @"$S22class_bounded_generics05objc_a1_B22_protocol_conversion_{{.*}}"(%objc_object*, i8**) {{.*}} {
+func objc_class_bounded_protocol_conversion_2
+(_ x: ClassBound & ObjCClassBound) -> ObjCClassBound {
+ return x
+}
+// CHECK-LABEL: define hidden swiftcc %objc_object* @"$S22class_bounded_generics05objc_a1_B22_protocol_conversion_{{.*}}"(%objc_object*)
+func objc_class_bounded_protocol_conversion_3
+(_ x: ObjCClassBound & ObjCClassBound2) -> ObjCClassBound {
+ return x
+}
+// CHECK-LABEL: define hidden swiftcc %objc_object* @"$S22class_bounded_generics05objc_a1_B22_protocol_conversion_{{.*}}"(%objc_object*)
+func objc_class_bounded_protocol_conversion_4
+(_ x: ObjCClassBound & ObjCClassBound2) -> ObjCClassBound2 {
+ return x
+}
+
+// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i64 } @"$S22class_bounded_generics0A28_generic_field_struct_fields{{[_0-9a-zA-Z]*}}F"(i64, %objc_object*, i64, %swift.type* %T, i8** %T.ClassBound)
+func class_generic_field_struct_fields<T>
+(_ x:ClassGenericFieldStruct<T>) -> (Int, T, Int) {
+ return (x.x, x.y, x.z)
+}
+
+// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i8**, i64 } @"$S22class_bounded_generics0A29_protocol_field_struct_fields{{[_0-9a-zA-Z]*}}F"(i64, %objc_object*, i8**, i64)
+func class_protocol_field_struct_fields
+(_ x:ClassProtocolFieldStruct) -> (Int, ClassBound, Int) {
+ return (x.x, x.y, x.z)
+}
+
+// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i64 } @"$S22class_bounded_generics0a15_generic_field_A7_fields{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics017ClassGenericFieldD0C*)
+func class_generic_field_class_fields<T>
+(_ x:ClassGenericFieldClass<T>) -> (Int, T, Int) {
+ return (x.x, x.y, x.z)
+ // CHECK: getelementptr inbounds %T22class_bounded_generics017ClassGenericFieldD0C, %T22class_bounded_generics017ClassGenericFieldD0C* %0, i32 0, i32 1
+ // CHECK: getelementptr inbounds %T22class_bounded_generics017ClassGenericFieldD0C, %T22class_bounded_generics017ClassGenericFieldD0C* %0, i32 0, i32 2
+ // CHECK: getelementptr inbounds %T22class_bounded_generics017ClassGenericFieldD0C, %T22class_bounded_generics017ClassGenericFieldD0C* %0, i32 0, i32 3
+}
+
+// CHECK-LABEL: define hidden swiftcc { i64, %objc_object*, i8**, i64 } @"$S22class_bounded_generics0a16_protocol_field_A7_fields{{[_0-9a-zA-Z]*}}F"(%T22class_bounded_generics018ClassProtocolFieldD0C*)
+func class_protocol_field_class_fields(_ x: ClassProtocolFieldClass)
+-> (Int, ClassBound, Int) {
+ return (x.x, x.y, x.z)
+ // CHECK: = call swiftcc i64 %{{[0-9]+}}
+ // CHECK: = call swiftcc { %objc_object*, i8** } %{{[0-9]+}}
+ // CHECK: = call swiftcc i64 %{{[0-9]+}}
+}
+
+class SomeSwiftClass {
+ class func foo() {}
+}
+
+// T must have a Swift layout, so we can load this metatype with a direct access.
+// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics0a1_B9_metatype{{[_0-9a-zA-Z]*}}F"
+// CHECK: [[T0:%.*]] = getelementptr inbounds %T22class_bounded_generics14SomeSwiftClassC, %T22class_bounded_generics14SomeSwiftClassC* {{%.*}}, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[T1:%.*]] = load %swift.type*, %swift.type** [[T0]], align 8
+// CHECK-NEXT: [[T2:%.*]] = bitcast %swift.type* [[T1]] to void (%swift.type*)**
+// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds void (%swift.type*)*, void (%swift.type*)** [[T2]], i64 10
+// CHECK-NEXT: load void (%swift.type*)*, void (%swift.type*)** [[T3]], align 8
+func class_bounded_metatype<T: SomeSwiftClass>(_ t : T) {
+ type(of: t).foo()
+}
+
+class WeakRef<T: AnyObject> {
+ weak var value: T?
+}
+
+class A<T> {
+ required init() {}
+}
+
+class M<T, S: A<T>> {
+ private var s: S
+ init() {
+ // Don't crash generating the reference to 's'.
+ s = S.init()
+ }
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics14takes_metatypeyyxmlF"(%swift.type*, %swift.type* %T)
+func takes_metatype<T>(_: T.Type) {}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics023archetype_with_generic_A11_constraint1tyx_tAA1ACyq_GRbzr0_lF"(%T22class_bounded_generics1AC.2*, %swift.type* %T)
+// CHECK: [[ISA_ADDR:%.*]] = bitcast %T22class_bounded_generics1AC.2* %0 to %swift.type**
+// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
+// CHECK-NEXT: call swiftcc void @"$S22class_bounded_generics14takes_metatypeyyxmlF"(%swift.type* %T, %swift.type* %T)
+// CHECK-NEXT: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
+// CHECK-NEXT: [[U_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ISA_PTR]], i64 10
+// CHECK-NEXT: [[U:%.*]] = load %swift.type*, %swift.type** [[U_ADDR]]
+// CHECK-NEXT: call swiftcc void @"$S22class_bounded_generics14takes_metatypeyyxmlF"(%swift.type* %U, %swift.type* %U)
+// CHECK: ret void
+
+func archetype_with_generic_class_constraint<T, U>(t: T) where T : A<U> {
+ takes_metatype(T.self)
+ takes_metatype(U.self)
+}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S22class_bounded_generics029calls_archetype_with_generic_A11_constraint1ayAA1ACyxG_tlF"(%T22class_bounded_generics1AC*) #0 {
+// CHECK: [[ISA_ADDR:%.*]] = getelementptr inbounds %T22class_bounded_generics1AC, %T22class_bounded_generics1AC* %0, i32 0, i32 0, i32 0
+// CHECK-NEXT: [[ISA:%.*]] = load %swift.type*, %swift.type** [[ISA_ADDR]]
+// CHECK: [[SELF:%.*]] = bitcast %T22class_bounded_generics1AC* %0 to %T22class_bounded_generics1AC.2*
+// CHECK-NEXT: [[ISA_PTR:%.*]] = bitcast %swift.type* [[ISA]] to %swift.type**
+// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[ISA_PTR]], i64 10
+// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T_ADDR]]
+// CHECK-NEXT: [[A_OF_T:%.*]] = call %swift.type* @"$S22class_bounded_generics1ACMa"(%swift.type* [[T]])
+// CHECK-NEXT: call swiftcc void @"$S22class_bounded_generics023archetype_with_generic_A11_constraint1tyx_tAA1ACyq_GRbzr0_lF"(%T22class_bounded_generics1AC.2* [[SELF]], %swift.type* [[A_OF_T]])
+// CHECK: ret void
+
+func calls_archetype_with_generic_class_constraint<T>(a: A<T>) {
+ archetype_with_generic_class_constraint(t: a)
+}
diff --git a/test/IRGen/plus_zero_enum_resilience.swift b/test/IRGen/plus_zero_enum_resilience.swift
new file mode 100644
index 0000000..8332486
--- /dev/null
+++ b/test/IRGen/plus_zero_enum_resilience.swift
@@ -0,0 +1,275 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
+// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience %s | %FileCheck %s
+// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience -O %s
+
+import resilient_enum
+import resilient_struct
+
+// CHECK: %swift.type = type { [[INT:i32|i64]] }
+
+// CHECK: %T15enum_resilience5ClassC = type <{ %swift.refcounted }>
+// CHECK: %T15enum_resilience9ReferenceV = type <{ %T15enum_resilience5ClassC* }>
+
+// Public fixed layout struct contains a public resilient struct,
+// cannot use spare bits
+
+// CHECK: %T15enum_resilience6EitherO = type <{ [[REFERENCE_TYPE:\[(4|8) x i8\]]], [1 x i8] }>
+
+// Public resilient struct contains a public resilient struct,
+// can use spare bits
+
+// CHECK: %T15enum_resilience15ResilientEitherO = type <{ [[REFERENCE_TYPE]] }>
+
+// Internal fixed layout struct contains a public resilient struct,
+// can use spare bits
+
+// CHECK: %T15enum_resilience14InternalEitherO = type <{ [[REFERENCE_TYPE]] }>
+
+// Public fixed layout struct contains a fixed layout struct,
+// can use spare bits
+
+// CHECK: %T15enum_resilience10EitherFastO = type <{ [[REFERENCE_TYPE]] }>
+
+public class Class {}
+
+public struct Reference {
+ public var n: Class
+}
+
+@_fixed_layout public enum Either {
+ case Left(Reference)
+ case Right(Reference)
+}
+
+public enum ResilientEither {
+ case Left(Reference)
+ case Right(Reference)
+}
+
+enum InternalEither {
+ case Left(Reference)
+ case Right(Reference)
+}
+
+@_fixed_layout public struct ReferenceFast {
+ public var n: Class
+}
+
+@_fixed_layout public enum EitherFast {
+ case Left(ReferenceFast)
+ case Right(ReferenceFast)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S15enum_resilience25functionWithResilientEnumy010resilient_A06MediumOAEF"(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture)
+public func functionWithResilientEnum(_ m: Medium) -> Medium {
+
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S14resilient_enum6MediumOMa"()
+// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
+// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT:i32|i64]] -1
+// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
+// This is copying the +0 argument to be used as a return value.
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK-NEXT: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]]
+// CHECK-NEXT: call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* [[METADATA]])
+// CHECK-NEXT: ret void
+
+ return m
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S15enum_resilience33functionWithIndirectResilientEnumy010resilient_A00E8ApproachOAEF"(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture)
+public func functionWithIndirectResilientEnum(_ ia: IndirectApproach) -> IndirectApproach {
+
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S14resilient_enum16IndirectApproachOMa"()
+// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
+// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT:i32|i64]] -1
+// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
+// This is copying the +0 argument into the return slot.
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK-NEXT: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]]
+// CHECK-NEXT: call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* [[METADATA]])
+// CHECK-NEXT: ret void
+
+ return ia
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S15enum_resilience31constructResilientEnumNoPayload010resilient_A06MediumOyF"
+public func constructResilientEnumNoPayload() -> Medium {
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S14resilient_enum6MediumOMa"()
+// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
+// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT:i32|i64]] -1
+// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
+
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 17
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK-NEXT: [[WITNESS_FN:%.*]] = bitcast i8* [[WITNESS]]
+// CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 0, %swift.type* [[METADATA]])
+
+// CHECK-NEXT: ret void
+ return Medium.Paper
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S15enum_resilience29constructResilientEnumPayloady010resilient_A06MediumO0G7_struct4SizeVF"
+public func constructResilientEnumPayload(_ s: Size) -> Medium {
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S16resilient_struct4SizeVMa"()
+// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
+// CHECK-NEXT: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT:i32|i64]] -1
+// CHECK-NEXT: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
+
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK-NEXT: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]]
+// CHECK-NEXT: [[COPY:%.*]] = call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias %0, %swift.opaque* noalias %1, %swift.type* [[METADATA]])
+
+// CHECK-NEXT: [[METADATA2:%.*]] = call %swift.type* @"$S14resilient_enum6MediumOMa"()
+// CHECK-NEXT: [[METADATA_ADDR2:%.*]] = bitcast %swift.type* [[METADATA2]] to i8***
+// CHECK-NEXT: [[VWT_ADDR2:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR2]], [[INT:i32|i64]] -1
+// CHECK-NEXT: [[VWT2:%.*]] = load i8**, i8*** [[VWT_ADDR2]]
+
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT2]], i32 17
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK-NEXT: [[WITNESS_FN:%destructiveInjectEnumTag]] = bitcast i8* [[WITNESS]]
+// CHECK-NEXT: call void [[WITNESS_FN]](%swift.opaque* noalias %0, i32 -2, %swift.type* [[METADATA2]])
+// CHECK-NEXT: ret void
+
+ return Medium.Postcard(s)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc {{i32|i64}} @"$S15enum_resilience19resilientSwitchTestySi0c1_A06MediumOF"(%swift.opaque* noalias nocapture)
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S14resilient_enum6MediumOMa"()
+// CHECK: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to i8***
+// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[METADATA_ADDR]], [[INT]] -1
+// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
+
+// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
+// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK: [[WITNESS_FOR_SIZE:%size]] = ptrtoint i8* [[WITNESS]]
+// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
+// CHECK: [[ALLOCA:%.*]] = alloca i8, {{.*}} [[WITNESS_FOR_SIZE]], align 16
+// CHECK: [[ENUM_STORAGE:%.*]] = bitcast i8* [[ALLOCA]] to %swift.opaque*
+
+// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
+// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK: [[WITNESS_FN:%initializeWithCopy]] = bitcast i8* [[WITNESS]]
+// CHECK: [[ENUM_COPY:%.*]] = call %swift.opaque* [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.opaque* noalias %0, %swift.type* [[METADATA]])
+
+// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 15
+// CHECK: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
+// CHECK: [[WITNESS_FN:%getEnumTag]] = bitcast i8* [[WITNESS]]
+// CHECK: [[TAG:%.*]] = call i32 [[WITNESS_FN]](%swift.opaque* noalias [[ENUM_STORAGE]], %swift.type* [[METADATA]])
+
+// CHECK: switch i32 [[TAG]], label %[[DEFAULT_CASE:.*]] [
+// CHECK: i32 -1, label %[[PAMPHLET_CASE:.*]]
+// CHECK: i32 0, label %[[PAPER_CASE:.*]]
+// CHECK: i32 1, label %[[CANVAS_CASE:.*]]
+// CHECK: ]
+
+// CHECK: ; <label>:[[PAPER_CASE]]
+// CHECK: br label %[[END:.*]]
+
+// CHECK: ; <label>:[[CANVAS_CASE]]
+// CHECK: br label %[[END]]
+
+// CHECK: ; <label>:[[PAMPHLET_CASE]]
+// CHECK: br label %[[END]]
+
+// CHECK: ; <label>:[[DEFAULT_CASE]]
+// CHECK: br label %[[END]]
+
+// CHECK: ; <label>:[[END]]
+// CHECK: ret
+
+public func resilientSwitchTest(_ m: Medium) -> Int {
+ switch m {
+ case .Paper:
+ return 1
+ case .Canvas:
+ return 2
+ case .Pamphlet(let m):
+ return resilientSwitchTest(m)
+ default:
+ return 3
+ }
+}
+
+public func reabstraction<T>(_ f: (Medium) -> T) {}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S15enum_resilience25resilientEnumPartialApplyyySi0c1_A06MediumOXEF"(i8*, %swift.opaque*)
+public func resilientEnumPartialApply(_ f: (Medium) -> Int) {
+
+// CHECK: [[CONTEXT:%.*]] = call noalias %swift.refcounted* @swift_allocObject
+// CHECK: call swiftcc void @"$S15enum_resilience13reabstractionyyx010resilient_A06MediumOXElF"(i8* bitcast (void (%TSi*, %swift.opaque*, %swift.refcounted*)* @"$S14resilient_enum6MediumOSiIgnd_ACSiIegnr_TRTA" to i8*), %swift.opaque* [[CONTEXT:%.*]], %swift.type* @"$SSiN")
+ reabstraction(f)
+
+// CHECK: ret void
+}
+
+// CHECK-LABEL: define internal swiftcc void @"$S14resilient_enum6MediumOSiIgnd_ACSiIegnr_TRTA"(%TSi* noalias nocapture sret, %swift.opaque* noalias nocapture, %swift.refcounted* swiftself)
+
+
+// Enums with resilient payloads from a different resilience domain
+// require runtime metadata instantiation, just like generics.
+
+public enum EnumWithResilientPayload {
+ case OneSize(Size)
+ case TwoSizes(Size, Size)
+}
+
+// Make sure we call a function to access metadata of enums with
+// resilient layout.
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @"$S15enum_resilience20getResilientEnumTypeypXpyF"()
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S15enum_resilience24EnumWithResilientPayloadOMa"()
+// CHECK-NEXT: ret %swift.type* [[METADATA]]
+
+public func getResilientEnumType() -> Any.Type {
+ return EnumWithResilientPayload.self
+}
+
+// Public metadata accessor for our resilient enum
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @"$S15enum_resilience24EnumWithResilientPayloadOMa"()
+// CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** @"$S15enum_resilience24EnumWithResilientPayloadOML"
+// CHECK-NEXT: [[COND:%.*]] = icmp eq %swift.type* [[METADATA]], null
+// CHECK-NEXT: br i1 [[COND]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: call void @swift_once([[INT]]* @"$S15enum_resilience24EnumWithResilientPayloadOMa.once_token", i8* bitcast (void (i8*)* @initialize_metadata_EnumWithResilientPayload to i8*), i8* undef)
+// CHECK-NEXT: [[METADATA2:%.*]] = load %swift.type*, %swift.type** @"$S15enum_resilience24EnumWithResilientPayloadOML"
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: [[RESULT:%.*]] = phi %swift.type* [ [[METADATA]], %entry ], [ [[METADATA2]], %cacheIsNull ]
+// CHECK-NEXT: ret %swift.type* [[RESULT]]
+
+// Methods inside extensions of resilient enums fish out type parameters
+// from metadata -- make sure we can do that
+extension ResilientMultiPayloadGenericEnum {
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc %swift.type* @"$S14resilient_enum32ResilientMultiPayloadGenericEnumO0B11_resilienceE16getTypeParameterxmyF"(%swift.type* %"ResilientMultiPayloadGenericEnum<T>", %swift.opaque* noalias nocapture swiftself)
+// CHECK: [[METADATA:%.*]] = bitcast %swift.type* %"ResilientMultiPayloadGenericEnum<T>" to %swift.type**
+// CHECK-NEXT: [[T_ADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA]], [[INT]] 2
+// CHECK-NEXT: [[T:%.*]] = load %swift.type*, %swift.type** [[T_ADDR]]
+ public func getTypeParameter() -> T.Type {
+ return T.self
+ }
+}
+
+// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_EnumWithResilientPayload(i8*)
+// CHECK: call void @swift_initEnumMetadataMultiPayload(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 2, i8*** {{.*}})
+
+
+
+public protocol Prot {
+}
+
+private enum ProtGenEnumWithSize<T: Prot> {
+ case c1(s1: Size)
+ case c2(s2: Size)
+}
+
+// CHECK-LABEL: define{{( protected)?}} internal %T15enum_resilience19ProtGenEnumWithSize33_59077B69D65A4A3BEE0C93708067D5F0LLO* @"$S15enum_resilienceytWh2_"(%T15enum_resilience19ProtGenEnumWithSize
+// CHECK: ret %T15enum_resilience19ProtGenEnumWithSize33_59077B69D65A4A3BEE0C93708067D5F0LLO* %0
diff --git a/test/IRGen/plus_zero_generic_metatypes.swift b/test/IRGen/plus_zero_generic_metatypes.swift
new file mode 100644
index 0000000..0249939
--- /dev/null
+++ b/test/IRGen/plus_zero_generic_metatypes.swift
@@ -0,0 +1,181 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %swift -target x86_64-apple-macosx10.9 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+// RUN: %swift -target i386-apple-ios7.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+// RUN: %swift -target x86_64-apple-ios7.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+// RUN: %swift -target i386-apple-tvos9.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+// RUN: %swift -target x86_64-apple-tvos9.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+// RUN: %swift -target i386-apple-watchos2.0 -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+// RUN: %swift -target x86_64-unknown-linux-gnu -disable-objc-interop -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+
+// REQUIRES: CODEGENERATOR=X86
+
+// CHECK: define hidden swiftcc %swift.type* [[GENERIC_TYPEOF:@"\$S17generic_metatypes0A6TypeofyxmxlF"]](%swift.opaque* noalias nocapture, %swift.type* [[TYPE:%.*]])
+func genericTypeof<T>(_ x: T) -> T.Type {
+ // CHECK: [[METATYPE:%.*]] = call %swift.type* @swift_getDynamicType(%swift.opaque* {{.*}}, %swift.type* [[TYPE]], i1 false)
+ // CHECK: ret %swift.type* [[METATYPE]]
+ return type(of: x)
+}
+
+struct Foo {}
+class Bar {}
+
+// CHECK-LABEL: define hidden swiftcc %swift.type* @"$S17generic_metatypes27remapToSubstitutedMetatypes{{.*}}"(%T17generic_metatypes3BarC*) {{.*}} {
+func remapToSubstitutedMetatypes(_ x: Foo, y: Bar)
+ -> (Foo.Type, Bar.Type)
+{
+ // CHECK: call swiftcc %swift.type* [[GENERIC_TYPEOF]](%swift.opaque* noalias nocapture undef, %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}})
+ // CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+ // CHECK: [[BAR_META:%.*]] = call swiftcc %swift.type* [[GENERIC_TYPEOF]](%swift.opaque* noalias nocapture {{%.*}}, %swift.type* [[T0]])
+ // CHECK: ret %swift.type* [[BAR_META]]
+ return (genericTypeof(x), genericTypeof(y))
+}
+
+
+// CHECK-LABEL: define hidden swiftcc void @"$S17generic_metatypes23remapToGenericMetatypesyyF"()
+func remapToGenericMetatypes() {
+ // CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+ // CHECK: call swiftcc void @"$S17generic_metatypes0A9Metatypes{{.*}}"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}} %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}} %swift.type* [[T0]])
+ genericMetatypes(Foo.self, Bar.self)
+}
+
+func genericMetatypes<T, U>(_ t: T.Type, _ u: U.Type) {}
+
+protocol Bas {}
+
+// CHECK: define hidden swiftcc { %swift.type*, i8** } @"$S17generic_metatypes14protocolTypeof{{.*}}"(%T17generic_metatypes3BasP* noalias nocapture dereferenceable({{.*}}))
+func protocolTypeof(_ x: Bas) -> Bas.Type {
+ // CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T17generic_metatypes3BasP, %T17generic_metatypes3BasP* [[X:%.*]], i32 0, i32 1
+ // CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
+ // CHECK: [[BUFFER:%.*]] = getelementptr inbounds %T17generic_metatypes3BasP, %T17generic_metatypes3BasP* [[X]], i32 0, i32 0
+ // CHECK: [[VALUE_ADDR:%.*]] = call %swift.opaque* @__swift_project_boxed_opaque_existential_1({{.*}} [[BUFFER]], %swift.type* [[METADATA]])
+ // CHECK: [[METATYPE:%.*]] = call %swift.type* @swift_getDynamicType(%swift.opaque* [[VALUE_ADDR]], %swift.type* [[METADATA]], i1 true)
+ // CHECK: [[WTABLE_ADDR:%.*]] = getelementptr inbounds %T17generic_metatypes3BasP, %T17generic_metatypes3BasP* %0, i32 0, i32 2
+ // CHECK: [[WTABLE:%.*]] = load i8**, i8*** [[WTABLE_ADDR]]
+ // CHECK-NOT: call void @__swift_destroy_boxed_opaque_existential_1(%T17generic_metatypes3BasP* %0)
+ // CHECK: [[T0:%.*]] = insertvalue { %swift.type*, i8** } undef, %swift.type* [[METATYPE]], 0
+ // CHECK: [[T1:%.*]] = insertvalue { %swift.type*, i8** } [[T0]], i8** [[WTABLE]], 1
+ // CHECK: ret { %swift.type*, i8** } [[T1]]
+ return type(of: x)
+}
+
+struct Zim : Bas {}
+class Zang : Bas {}
+
+// CHECK-LABEL: define hidden swiftcc { %swift.type*, i8** } @"$S17generic_metatypes15metatypeErasureyAA3Bas_pXpAA3ZimVmF"() #0
+func metatypeErasure(_ z: Zim.Type) -> Bas.Type {
+ // CHECK: ret { %swift.type*, i8** } {{.*}} @"$S17generic_metatypes3ZimVMf", {{.*}} @"$S17generic_metatypes3ZimVAA3BasAAWP"
+ return z
+}
+
+// CHECK-LABEL: define hidden swiftcc { %swift.type*, i8** } @"$S17generic_metatypes15metatypeErasureyAA3Bas_pXpAA4ZangCmF"(%swift.type*) #0
+func metatypeErasure(_ z: Zang.Type) -> Bas.Type {
+ // CHECK: [[RET:%.*]] = insertvalue { %swift.type*, i8** } undef, %swift.type* %0, 0
+ // CHECK: [[RET2:%.*]] = insertvalue { %swift.type*, i8** } [[RET]], i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$S17generic_metatypes4ZangCAA3BasAAWP", i32 0, i32 0), 1
+ // CHECK: ret { %swift.type*, i8** } [[RET2]]
+ return z
+}
+
+struct OneArg<T> {}
+struct TwoArgs<T, U> {}
+struct ThreeArgs<T, U, V> {}
+struct FourArgs<T, U, V, W> {}
+struct FiveArgs<T, U, V, W, X> {}
+
+func genericMetatype<A>(_ x: A.Type) {}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S17generic_metatypes20makeGenericMetatypesyyF"() {{.*}} {
+func makeGenericMetatypes() {
+ // CHECK: call %swift.type* @"$S17generic_metatypes6OneArgVyAA3FooVGMa"() [[NOUNWIND_READNONE:#[0-9]+]]
+ genericMetatype(OneArg<Foo>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes7TwoArgsVyAA3FooVAA3BarCGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(TwoArgs<Foo, Bar>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes9ThreeArgsVyAA3FooVAA3BarCAEGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(ThreeArgs<Foo, Bar, Foo>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes8FourArgsVyAA3FooVAA3BarCAeGGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(FourArgs<Foo, Bar, Foo, Bar>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes8FiveArgsVyAA3FooVAA3BarCAegEGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(FiveArgs<Foo, Bar, Foo, Bar, Foo>.self)
+}
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes6OneArgVyAA3FooVGMa"() [[NOUNWIND_READNONE_OPT:#[0-9]+]]
+// CHECK: call %swift.type* @"$S17generic_metatypes6OneArgVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes6OneArgVMa"(%swift.type*)
+// CHECK: [[BUFFER:%.*]] = alloca { %swift.type* }
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.start
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type* }, { %swift.type* }* [[BUFFER]], i32 0, i32 0
+// CHECK: store %swift.type* %0, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type* }* [[BUFFER]] to i8*
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes6OneArgVMn" {{.*}}, i8* [[BUFFER_PTR]])
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret %swift.type* [[METADATA]]
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes7TwoArgsVyAA3FooVAA3BarCGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes7TwoArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]])
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes7TwoArgsVMa"(%swift.type*, %swift.type*)
+// CHECK: [[BUFFER:%.*]] = alloca { %swift.type*, %swift.type* }
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.start
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type* }, { %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 0
+// CHECK: store %swift.type* %0, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type* }, { %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 1
+// CHECK: store %swift.type* %1, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes7TwoArgsVMn" {{.*}}, i8* [[BUFFER_PTR]])
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret %swift.type* [[METADATA]]
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes9ThreeArgsVyAA3FooVAA3BarCAEGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes9ThreeArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}) [[NOUNWIND_READNONE]]
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes9ThreeArgsVMa"(%swift.type*, %swift.type*, %swift.type*)
+// CHECK: [[BUFFER:%.*]] = alloca { %swift.type*, %swift.type*, %swift.type* }
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.start
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type*, %swift.type* }, { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 0
+// CHECK: store %swift.type* %0, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type*, %swift.type* }, { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 1
+// CHECK: store %swift.type* %1, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type*, %swift.type* }, { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 2
+// CHECK: store %swift.type* %2, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes9ThreeArgsVMn" {{.*}}, i8* [[BUFFER_PTR]])
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret %swift.type* [[METADATA]]
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes8FourArgsVyAA3FooVAA3BarCAeGGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[BUFFER:%.*]] = alloca [4 x i8*]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call void @llvm.lifetime.start
+// CHECK-NEXT: [[SLOT_3:%.*]] = getelementptr inbounds [4 x i8*], [4 x i8*]* [[BUFFER]], i32 0, i32 3
+// CHECK-NEXT: [[T0_AS_VOIDPTR:%.*]] = bitcast %swift.type* [[T0]] to i8*
+// CHECK-NEXT: store i8* [[T0_AS_VOIDPTR]], i8** [[SLOT_3]]
+// CHECK-NEXT: [[BUFFER_PTR:%.*]] = bitcast [4 x i8*]* [[BUFFER]] to i8**
+// CHECK-NEXT: call %swift.type* @"$S17generic_metatypes8FourArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, i8** [[BUFFER_PTR]]) [[NOUNWIND_ARGMEM:#[0-9]+]]
+// CHECK: call void @llvm.lifetime.end.p0i8
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes8FiveArgsVyAA3FooVAA3BarCAegEGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes8FiveArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, i8**
+
+// CHECK: define hidden %swift.type* @"$S17generic_metatypes8FiveArgsVMa"(%swift.type*, %swift.type*, %swift.type*, i8**) [[NOUNWIND_OPT:#[0-9]+]]
+// CHECK-NOT: alloc
+// CHECK: call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes8FiveArgsVMn" {{.*}}, i8*
+// CHECK-NOT: call void @llvm.lifetime.end
+// CHECK: ret %swift.type*
+
+// CHECK: attributes [[NOUNWIND_READNONE_OPT]] = { nounwind readnone "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"
+// CHECK: attributes [[NOUNWIND_OPT]] = { nounwind "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"
+// CHECK: attributes [[NOUNWIND_READNONE]] = { nounwind readnone }
+// CHECK: attributes [[NOUNWIND_ARGMEM]] = { inaccessiblemem_or_argmemonly nounwind }
diff --git a/test/IRGen/plus_zero_generic_metatypes_arm.swift b/test/IRGen/plus_zero_generic_metatypes_arm.swift
new file mode 100644
index 0000000..ad87734
--- /dev/null
+++ b/test/IRGen/plus_zero_generic_metatypes_arm.swift
@@ -0,0 +1,176 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %swift -target armv7-apple-ios7.0 -module-name generic_metatypes -emit-ir -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+// RUN: %swift -target arm64-apple-ios7.0 -emit-ir -module-name generic_metatypes -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+// RUN: %swift -target armv7-apple-tvos9.0 -emit-ir -module-name generic_metatypes -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+// RUN: %swift -target arm64-apple-tvos9.0 -emit-ir -module-name generic_metatypes -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+// RUN: %swift -target armv7k-apple-watchos2.0 -emit-ir -module-name generic_metatypes -parse-stdlib -primary-file %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+
+// REQUIRES: CODEGENERATOR=ARM
+
+// CHECK: define hidden swiftcc %swift.type* [[GENERIC_TYPEOF:@"\$S17generic_metatypes0A6TypeofyxmxlF"]](%swift.opaque* noalias nocapture, %swift.type* [[TYPE:%.*]])
+func genericTypeof<T>(_ x: T) -> T.Type {
+ // CHECK: [[METATYPE:%.*]] = call %swift.type* @swift_getDynamicType(%swift.opaque* {{.*}}, %swift.type* [[TYPE]], i1 false)
+ // CHECK: ret %swift.type* [[METATYPE]]
+ return type(of: x)
+}
+
+struct Foo {}
+class Bar {}
+
+// CHECK-LABEL: define hidden swiftcc %swift.type* @"$S17generic_metatypes27remapToSubstitutedMetatypes{{.*}}"(%T17generic_metatypes3BarC*) {{.*}} {
+func remapToSubstitutedMetatypes(_ x: Foo, y: Bar)
+ -> (Foo.Type, Bar.Type)
+{
+ // CHECK: call swiftcc %swift.type* [[GENERIC_TYPEOF]](%swift.opaque* noalias nocapture undef, %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}})
+ // CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+ // CHECK: [[BAR_META:%.*]] = call swiftcc %swift.type* [[GENERIC_TYPEOF]](%swift.opaque* noalias nocapture {{%.*}}, %swift.type* [[T0]])
+ // CHECK: ret %swift.type* [[BAR_META]]
+ return (genericTypeof(x), genericTypeof(y))
+}
+
+
+// CHECK-LABEL: define hidden swiftcc void @"$S17generic_metatypes23remapToGenericMetatypesyyF"()
+func remapToGenericMetatypes() {
+ // CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+ // CHECK: call swiftcc void @"$S17generic_metatypes0A9Metatypes{{.*}}"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}} %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}} %swift.type* [[T0]])
+ genericMetatypes(Foo.self, Bar.self)
+}
+
+func genericMetatypes<T, U>(_ t: T.Type, _ u: U.Type) {}
+
+protocol Bas {}
+
+// CHECK: define hidden swiftcc { %swift.type*, i8** } @"$S17generic_metatypes14protocolTypeof{{.*}}"(%T17generic_metatypes3BasP* noalias nocapture dereferenceable({{.*}}))
+func protocolTypeof(_ x: Bas) -> Bas.Type {
+ // CHECK: [[METADATA_ADDR:%.*]] = getelementptr inbounds %T17generic_metatypes3BasP, %T17generic_metatypes3BasP* [[X:%.*]], i32 0, i32 1
+ // CHECK: [[METADATA:%.*]] = load %swift.type*, %swift.type** [[METADATA_ADDR]]
+ // CHECK: [[BUFFER:%.*]] = getelementptr inbounds %T17generic_metatypes3BasP, %T17generic_metatypes3BasP* [[X]], i32 0, i32 0
+ // CHECK: [[VALUE_ADDR:%.*]] = call %swift.opaque* @__swift_project_boxed_opaque_existential_1({{.*}} [[BUFFER]], %swift.type* [[METADATA]])
+ // CHECK: [[METATYPE:%.*]] = call %swift.type* @swift_getDynamicType(%swift.opaque* [[VALUE_ADDR]], %swift.type* [[METADATA]], i1 true)
+ // CHECK: [[WTABLE_ADDR:%.*]] = getelementptr inbounds %T17generic_metatypes3BasP, %T17generic_metatypes3BasP* %0, i32 0, i32 2
+ // CHECK: [[WTABLE:%.*]] = load i8**, i8*** [[WTABLE_ADDR]]
+ // CHECK-NOT: call void @__swift_destroy_boxed_opaque_existential_1(%T17generic_metatypes3BasP* %0)
+ // CHECK: [[T0:%.*]] = insertvalue { %swift.type*, i8** } undef, %swift.type* [[METATYPE]], 0
+ // CHECK: [[T1:%.*]] = insertvalue { %swift.type*, i8** } [[T0]], i8** [[WTABLE]], 1
+ // CHECK: ret { %swift.type*, i8** } [[T1]]
+ return type(of: x)
+}
+
+struct Zim : Bas {}
+class Zang : Bas {}
+
+// CHECK-LABEL: define hidden swiftcc { %swift.type*, i8** } @"$S17generic_metatypes15metatypeErasureyAA3Bas_pXpAA3ZimVmF"() #0
+func metatypeErasure(_ z: Zim.Type) -> Bas.Type {
+ // CHECK: ret { %swift.type*, i8** } {{.*}} @"$S17generic_metatypes3ZimVMf", {{.*}} @"$S17generic_metatypes3ZimVAA3BasAAWP"
+ return z
+}
+
+// CHECK-LABEL: define hidden swiftcc { %swift.type*, i8** } @"$S17generic_metatypes15metatypeErasureyAA3Bas_pXpAA4ZangCmF"(%swift.type*) #0
+func metatypeErasure(_ z: Zang.Type) -> Bas.Type {
+ // CHECK: [[RET:%.*]] = insertvalue { %swift.type*, i8** } undef, %swift.type* %0, 0
+ // CHECK: [[RET2:%.*]] = insertvalue { %swift.type*, i8** } [[RET]], i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$S17generic_metatypes4ZangCAA3BasAAWP", i32 0, i32 0), 1
+ // CHECK: ret { %swift.type*, i8** } [[RET2]]
+ return z
+}
+
+struct OneArg<T> {}
+struct TwoArgs<T, U> {}
+struct ThreeArgs<T, U, V> {}
+struct FourArgs<T, U, V, W> {}
+struct FiveArgs<T, U, V, W, X> {}
+
+func genericMetatype<A>(_ x: A.Type) {}
+
+// CHECK-LABEL: define hidden swiftcc void @"$S17generic_metatypes20makeGenericMetatypesyyF"() {{.*}} {
+func makeGenericMetatypes() {
+ // CHECK: call %swift.type* @"$S17generic_metatypes6OneArgVyAA3FooVGMa"() [[NOUNWIND_READNONE:#[0-9]+]]
+ genericMetatype(OneArg<Foo>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes7TwoArgsVyAA3FooVAA3BarCGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(TwoArgs<Foo, Bar>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes9ThreeArgsVyAA3FooVAA3BarCAEGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(ThreeArgs<Foo, Bar, Foo>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes8FourArgsVyAA3FooVAA3BarCAeGGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(FourArgs<Foo, Bar, Foo, Bar>.self)
+
+ // CHECK: call %swift.type* @"$S17generic_metatypes8FiveArgsVyAA3FooVAA3BarCAegEGMa"() [[NOUNWIND_READNONE]]
+ genericMetatype(FiveArgs<Foo, Bar, Foo, Bar, Foo>.self)
+}
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes6OneArgVyAA3FooVGMa"() [[NOUNWIND_READNONE_OPT:#[0-9]+]]
+// CHECK: call %swift.type* @"$S17generic_metatypes6OneArgVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}) [[NOUNWIND_READNONE:#[0-9]+]]
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes6OneArgVMa"(%swift.type*)
+// CHECK: [[BUFFER:%.*]] = alloca { %swift.type* }
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.start
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type* }, { %swift.type* }* [[BUFFER]], i32 0, i32 0
+// CHECK: store %swift.type* %0, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type* }* [[BUFFER]] to i8*
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes6OneArgVMn" {{.*}}, i8* [[BUFFER_PTR]])
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret %swift.type* [[METADATA]]
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes7TwoArgsVyAA3FooVAA3BarCGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes7TwoArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]])
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes7TwoArgsVMa"(%swift.type*, %swift.type*)
+// CHECK: [[BUFFER:%.*]] = alloca { %swift.type*, %swift.type* }
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.start
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type* }, { %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 0
+// CHECK: store %swift.type* %0, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type* }, { %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 1
+// CHECK: store %swift.type* %1, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes7TwoArgsVMn" {{.*}}, i8* [[BUFFER_PTR]])
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret %swift.type* [[METADATA]]
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes9ThreeArgsVyAA3FooVAA3BarCAEGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes9ThreeArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}) [[NOUNWIND_READNONE]]
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes9ThreeArgsVMa"(%swift.type*, %swift.type*, %swift.type*)
+// CHECK: [[BUFFER:%.*]] = alloca { %swift.type*, %swift.type*, %swift.type* }
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.start
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type*, %swift.type* }, { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 0
+// CHECK: store %swift.type* %0, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type*, %swift.type* }, { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 1
+// CHECK: store %swift.type* %1, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_ELT:%.*]] = getelementptr inbounds { %swift.type*, %swift.type*, %swift.type* }, { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]], i32 0, i32 2
+// CHECK: store %swift.type* %2, %swift.type** [[BUFFER_ELT]]
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes9ThreeArgsVMn" {{.*}}, i8* [[BUFFER_PTR]])
+// CHECK: [[BUFFER_PTR:%.*]] = bitcast { %swift.type*, %swift.type*, %swift.type* }* [[BUFFER]] to i8*
+// CHECK: call void @llvm.lifetime.end
+// CHECK: ret %swift.type* [[METADATA]]
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes8FourArgsVyAA3FooVAA3BarCAeGGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes8FourArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, i8**
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes8FourArgsVMa"(%swift.type*, %swift.type*, %swift.type*, i8**)
+// CHECK-NOT: alloc
+// CHECK: call %swift.type* @swift_getGenericMetadata(
+// CHECK-NOT: call void @llvm.lifetime.end
+// CHECK: ret %swift.type*
+
+// CHECK: define linkonce_odr hidden %swift.type* @"$S17generic_metatypes8FiveArgsVyAA3FooVAA3BarCAegEGMa"() [[NOUNWIND_READNONE_OPT]]
+// CHECK: [[T0:%.*]] = call %swift.type* @"$S17generic_metatypes3BarCMa"()
+// CHECK: call %swift.type* @"$S17generic_metatypes8FiveArgsVMa"(%swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, %swift.type* [[T0]], %swift.type* {{.*}} @"$S17generic_metatypes3FooVMf", {{.*}}, i8**
+
+// CHECK-LABEL: define hidden %swift.type* @"$S17generic_metatypes8FiveArgsVMa"(%swift.type*, %swift.type*, %swift.type*, i8**)
+// CHECK-NOT: alloca
+// CHECK: call %swift.type* @swift_getGenericMetadata(%swift.type_descriptor* {{.*}} @"$S17generic_metatypes8FiveArgsVMn" {{.*}}, i8*
+// CHECK-NOT: call void @llvm.lifetime.end
+// CHECK: ret %swift.type*
+
+// CHECK: attributes [[NOUNWIND_READNONE_OPT]] = { nounwind readnone "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "target-cpu"
+// CHECK: attributes [[NOUNWIND_READNONE]] = { nounwind readnone }
diff --git a/test/IRGen/plus_zero_generic_tuples.swift b/test/IRGen/plus_zero_generic_tuples.swift
new file mode 100644
index 0000000..c45781d
--- /dev/null
+++ b/test/IRGen/plus_zero_generic_tuples.swift
@@ -0,0 +1,120 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -primary-file %s | %FileCheck %s
+
+// Make sure that optimization passes don't choke on storage types for generic tuples
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir -O %s
+
+// REQUIRES: CPU=x86_64
+
+// CHECK: [[TYPE:%swift.type]] = type {
+// CHECK: [[OPAQUE:%swift.opaque]] = type opaque
+// CHECK: [[TUPLE_TYPE:%swift.tuple_type]] = type { [[TYPE]], i64, i8*, [0 x %swift.tuple_element_type] }
+// CHECK: %swift.tuple_element_type = type { [[TYPE]]*, i64 }
+
+func dup<T>(_ x: T) -> (T, T) { var x = x; return (x,x) }
+// CHECK: define hidden swiftcc void @"$S14generic_tuples3dupyx_xtxlF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+// CHECK: entry:
+// Allocate a local variable for 'x'.
+// CHECK: [[TYPE_ADDR:%.*]] = bitcast %swift.type* %T to i8***
+// CHECK: [[VWT_ADDR:%.*]] = getelementptr inbounds i8**, i8*** [[TYPE_ADDR]], i64 -1
+// CHECK: [[VWT:%.*]] = load i8**, i8*** [[VWT_ADDR]]
+// CHECK: [[SIZE_WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
+// CHECK: [[SIZE_WITNESS:%.*]] = load i8*, i8** [[SIZE_WITNESS_ADDR]]
+// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[SIZE_WITNESS]]
+// CHECK: [[X_ALLOCA:%.*]] = alloca i8, {{.*}} [[SIZE]], align 16
+// CHECK: [[X_TMP:%.*]] = bitcast i8* [[X_ALLOCA]] to %swift.opaque*
+// Debug info shadow copy.
+// CHECK-NEXT: store i8* [[X_ALLOCA]]
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 2
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]], align 8
+// CHECK-NEXT: [[INITIALIZE_WITH_COPY:%.*]] = bitcast i8* [[WITNESS]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)*
+// CHECK-NEXT: [[X:%.*]] = call [[OPAQUE]]* [[INITIALIZE_WITH_COPY]]([[OPAQUE]]* noalias [[X_TMP]], [[OPAQUE]]* noalias {{.*}}, [[TYPE]]* %T)
+// Copy 'x' into the first result.
+// CHECK-NEXT: call [[OPAQUE]]* [[INITIALIZE_WITH_COPY]]([[OPAQUE]]* noalias %0, [[OPAQUE]]* noalias [[X_TMP]], [[TYPE]]* %T)
+// Copy 'x' into the second element.
+// CHECK-NEXT: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 4
+// CHECK-NEXT: [[WITNESS:%.*]] = load i8*, i8** [[WITNESS_ADDR]], align 8
+// CHECK-NEXT: [[TAKE_FN:%.*]] = bitcast i8* [[WITNESS]] to [[OPAQUE]]* ([[OPAQUE]]*, [[OPAQUE]]*, [[TYPE]]*)*
+// CHECK-NEXT: call [[OPAQUE]]* [[TAKE_FN]]([[OPAQUE]]* noalias %1, [[OPAQUE]]* noalias [[X_TMP]], [[TYPE]]* %T)
+
+struct S {}
+
+
+func callDup(_ s: S) { _ = dup(s) }
+// CHECK-LABEL: define hidden swiftcc void @"$S14generic_tuples7callDupyyAA1SVF"()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call swiftcc void @"$S14generic_tuples3dupyx_xtxlF"({{.*}} undef, {{.*}} undef, %swift.type* {{.*}} @"$S14generic_tuples1SVMf", {{.*}})
+// CHECK-NEXT: ret void
+
+class C {}
+
+func dupC<T : C>(_ x: T) -> (T, T) { return (x, x) }
+// CHECK-LABEL: define hidden swiftcc { %T14generic_tuples1CC*, %T14generic_tuples1CC* } @"$S14generic_tuples4dupCyx_xtxAA1CCRbzlF"(%T14generic_tuples1CC*, %swift.type* %T)
+// CHECK-NEXT: entry:
+// CHECK: [[REF:%.*]] = bitcast %T14generic_tuples1CC* %0 to %swift.refcounted*
+// CHECK-NEXT: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[REF]])
+// CHECK-NEXT: [[REF:%.*]] = bitcast %T14generic_tuples1CC* %0 to %swift.refcounted*
+// CHECK-NEXT: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[REF]])
+// CHECK-NEXT: [[TUP1:%.*]] = insertvalue { %T14generic_tuples1CC*, %T14generic_tuples1CC* } undef, %T14generic_tuples1CC* %0, 0
+// CHECK-NEXT: [[TUP2:%.*]] = insertvalue { %T14generic_tuples1CC*, %T14generic_tuples1CC* } [[TUP1:%.*]], %T14generic_tuples1CC* %0, 1
+// CHECK-NEXT: ret { %T14generic_tuples1CC*, %T14generic_tuples1CC* } [[TUP2]]
+
+func callDupC(_ c: C) { _ = dupC(c) }
+// CHECK-LABEL: define hidden swiftcc void @"$S14generic_tuples8callDupCyyAA1CCF"(%T14generic_tuples1CC*)
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[METATYPE:%.*]] = call %swift.type* @"$S14generic_tuples1CCMa"()
+// CHECK-NEXT: [[TUPLE:%.*]] = call swiftcc { %T14generic_tuples1CC*, %T14generic_tuples1CC* } @"$S14generic_tuples4dupCyx_xtxAA1CCRbzlF"(%T14generic_tuples1CC* %0, %swift.type* [[METATYPE]])
+// CHECK-NEXT: [[LEFT:%.*]] = extractvalue { %T14generic_tuples1CC*, %T14generic_tuples1CC* } [[TUPLE]], 0
+// CHECK-NEXT: [[RIGHT:%.*]] = extractvalue { %T14generic_tuples1CC*, %T14generic_tuples1CC* } [[TUPLE]], 1
+// CHECK-NEXT: [[LEFT_CAST:%.*]] = bitcast %T14generic_tuples1CC* [[LEFT]] to %swift.refcounted*
+// CHECK-NEXT: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[LEFT_CAST]]
+// CHECK-NEXT: [[RIGHT_CAST:%.*]] = bitcast %T14generic_tuples1CC* [[RIGHT]] to %swift.refcounted*
+// CHECK-NEXT: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[RIGHT_CAST]]
+// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T14generic_tuples1CC*)*)(%T14generic_tuples1CC* [[LEFT]])
+// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T14generic_tuples1CC*)*)(%T14generic_tuples1CC* [[RIGHT]])
+// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T14generic_tuples1CC*)*)(%T14generic_tuples1CC* [[RIGHT]])
+// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_release to void (%T14generic_tuples1CC*)*)(%T14generic_tuples1CC* [[LEFT]])
+// CHECK-NEXT: ret void
+
+// CHECK: define hidden swiftcc i64 @"$S14generic_tuples4lumpySi_xxtxlF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+func lump<T>(_ x: T) -> (Int, T, T) { return (0,x,x) }
+// CHECK: define hidden swiftcc { i64, i64 } @"$S14generic_tuples5lump2ySi_SixtxlF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+func lump2<T>(_ x: T) -> (Int, Int, T) { return (0,0,x) }
+// CHECK: define hidden swiftcc void @"$S14generic_tuples5lump3yx_xxtxlF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+func lump3<T>(_ x: T) -> (T, T, T) { return (x,x,x) }
+// CHECK: define hidden swiftcc i64 @"$S14generic_tuples5lump4yx_SixtxlF"(%swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+func lump4<T>(_ x: T) -> (T, Int, T) { return (x,0,x) }
+
+// CHECK: define hidden swiftcc i64 @"$S14generic_tuples6unlumpyS2i_xxt_tlF"(i64, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+func unlump<T>(_ x: (Int, T, T)) -> Int { return x.0 }
+// CHECK: define hidden swiftcc void @"$S14generic_tuples7unlump1yxSi_xxt_tlF"(%swift.opaque* noalias nocapture sret, i64, %swift.opaque* noalias nocapture, %swift.opaque* noalias nocapture, %swift.type* %T)
+func unlump1<T>(_ x: (Int, T, T)) -> T { return x.1 }
+// CHECK: define hidden swiftcc void @"$S14generic_tuples7unlump2yxx_Sixt_tlF"(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, i64, %swift.opaque* noalias nocapture, %swift.type* %T)
+func unlump2<T>(_ x: (T, Int, T)) -> T { return x.0 }
+// CHECK: define hidden swiftcc i64 @"$S14generic_tuples7unlump3ySix_Sixt_tlF"(%swift.opaque* noalias nocapture, i64, %swift.opaque* noalias nocapture, %swift.type* %T)
+func unlump3<T>(_ x: (T, Int, T)) -> Int { return x.1 }
+
+
+// CHECK: tuple_existentials
+func tuple_existentials() {
+ // Empty tuple:
+ var a : Any = ()
+ // CHECK: store %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$SytN", i32 0, i32 1),
+
+ // 2 element tuple
+ var t2 = (1,2.0)
+ a = t2
+ // CHECK: call %swift.type* @swift_getTupleTypeMetadata2({{.*}}@"$SSiN{{.*}}",{{.*}}@"$SSdN{{.*}}", i8* null, i8** null)
+
+
+ // 3 element tuple
+ var t3 = ((),(),())
+ a = t3
+ // CHECK: call %swift.type* @swift_getTupleTypeMetadata3({{.*}}@"$SytN{{.*}},{{.*}}@"$SytN{{.*}},{{.*}}@"$SytN{{.*}}, i8* null, i8** null)
+
+ // 4 element tuple
+ var t4 = (1,2,3,4)
+ a = t4
+ // CHECK: call %swift.type* @swift_getTupleTypeMetadata(i64 4, {{.*}}, i8* null, i8** null)
+}
+
diff --git a/test/IRGen/plus_zero_keypaths.sil b/test/IRGen/plus_zero_keypaths.sil
new file mode 100644
index 0000000..7cafbd0
--- /dev/null
+++ b/test/IRGen/plus_zero_keypaths.sil
@@ -0,0 +1,438 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// -- Convert <i32 0x...> constants to decimal constants that LLVM will print
+// RUN: %utils/chex.py < %s > %t/keypaths.sil
+// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %t/keypaths.sil --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-os
+
+sil_stage canonical
+import Swift
+
+struct S: Hashable {
+ var x: Int
+ let y: String
+ var z: C
+ var reabstracted: () -> ()
+
+ var hashValue: Int { get }
+ static func ==(_: S, _: S) -> Bool
+}
+class C: Hashable {
+ final var x: Int
+ final let y: String
+ final var z: S
+ var w: Int { get set }
+
+ init()
+
+ var hashValue: Int { get }
+ static func ==(_: C, _: C) -> Bool
+}
+
+struct G<T> {
+ var x: T
+ subscript<U: Hashable>(x: U) -> T { get set }
+}
+
+sil_vtable C {}
+
+// CHECK: %TSi = type <{ [[WORD:i.*]] }>
+
+// -- %a: S.x
+// CHECK: [[KP_A:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 4
+// CHECK-SAME: <i32 0x8000_0004>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- offset of S.x
+// CHECK-SAME: i32 0 }>
+
+// -- %b: S.y
+// CHECK: [[KP_B:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 4
+// CHECK-SAME: <i32 0x8000_0004>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- offset of S.y
+// CHECK-32-SAME: i32 4 }>
+// CHECK-64-SAME: i32 8 }>
+
+// -- %c: S.z
+// CHECK: [[KP_C:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 4
+// CHECK-SAME: <i32 0x8000_0004>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- offset of S.z
+// CHECK-32-SAME: i32 16 }>
+// CHECK-64-SAME: i32 24 }>
+
+// -- %d: C.x
+// CHECK: [[KP_D:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 4
+// CHECK-SAME: <i32 0x8000_0004>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- 0x0200_0000 (class) + offset of C.x
+// CHECK-32-SAME: <i32 0x0200_0008> }>
+// CHECK-64-SAME: <i32 0x0200_0010> }>
+
+// -- %e: C.y
+// CHECK: [[KP_E:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 4
+// CHECK-SAME: <i32 0x8000_0004>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- 0x0200_0000 (class) + offset of C.y
+// CHECK-32-SAME: <i32 0x0200_000c> }>
+// CHECK-64-SAME: <i32 0x0200_0018> }>
+
+// -- %f: C.z
+// CHECK: [[KP_F:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 4
+// CHECK-SAME: <i32 0x8000_0004>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- 0x0200_0000 (class) + offset of C.z
+// CHECK-32-SAME: <i32 0x0200_0018> }>
+// CHECK-64-SAME: <i32 0x0200_0028> }>
+
+// -- %g: S.z.x
+// CHECK: [[KP_G:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 12
+// CHECK-32-SAME: <i32 0x8000_000c>,
+// -- instantiable in-line, size 20
+// CHECK-64-SAME: <i32 0x8000_0014>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- offset of S.z
+// CHECK-32-SAME: i32 16,
+// CHECK-64-SAME: i32 24,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// CHECK: %swift.type* (i8*)*
+// -- 0x0200_0000 (class) + offset of C.x
+// CHECK-32-SAME: <i32 0x0200_0008> }>
+// CHECK-64-SAME: <i32 0x0200_0010> }>
+
+// -- %h: C.z.x
+// CHECK: [[KP_H:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 12
+// CHECK-32-SAME: <i32 0x8000_000c>,
+// -- instantiable in-line, size 20
+// CHECK-64-SAME: <i32 0x8000_0014>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- 0x0200_0000 (class) + offset of C.z
+// CHECK-32-SAME: <i32 0x0200_0018>,
+// CHECK-64-SAME: <i32 0x0200_0028>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// CHECK: %swift.type* (i8*)*
+// -- offset of S.x
+// CHECK-SAME: i32 0 }>
+
+// -- %k: computed
+// CHECK: [[KP_K:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 24
+// CHECK-64-SAME: <i32 0x8000_0018>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- instantiable in-line, size 12
+// CHECK-32-SAME: <i32 0x8000_000c>,
+// -- computed, get-only, identified by function pointer, no args
+// CHECK-SAME: <i32 0x0100_0000>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// CHECK-SAME: void ()* @k_id,
+// CHECK-SAME: void (%TSi*, %T8keypaths1SV*)* @k_get }>
+
+// -- %l: computed
+// CHECK: [[KP_L:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 32
+// CHECK-64-SAME: <i32 0x8000_0020>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- instantiable in-line, size 16
+// CHECK-32-SAME: <i32 0x8000_0010>,
+// -- computed, settable, nonmutating, identified by vtable, no args
+// CHECK-SAME: <i32 0x0150_0000>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// CHECK-SAME: [[WORD]]
+// CHECK-SAME: void (%TSi*, %T8keypaths1CC**)* @l_get,
+// CHECK-SAME: void (%TSi*, %T8keypaths1CC**)* @l_set }>
+
+// -- %m: computed
+// CHECK: [[KP_M:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)*
+// CHECK-SAME: %swift.type* (i8*)*
+// -- instantiable in-line, size 32
+// CHECK-64-SAME: <i32 0x8000_0020>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- instantiable in-line, size 16
+// CHECK-32-SAME: <i32 0x8000_0010>,
+// -- computed, settable, nonmutating, identified by property offset, no args
+// CHECK-SAME: <i32 0x01e0_0000>,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// CHECK-SAME: [[WORD]]
+// CHECK-SAME: void (%swift.function*, %T8keypaths1SV*)* @m_get,
+// CHECK-SAME: void (%swift.function*, %T8keypaths1SV*)* @m_set }>
+
+
+// -- %i: Gen<A>.x
+// CHECK: [[KP_I:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)* [[I_GET_GEN_A_A:@[a-z_.0-9]+]],
+// CHECK-SAME: %swift.type* (i8*)* [[I_GET_A:@[a-z_.0-9]+]],
+// -- size 8
+// CHECK-SAME: i32 8,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- struct with runtime-resolved offset
+// CHECK-SAME: <i32 0x00fffffe>,
+// CHECK-32-SAME: i32 16 }>
+// CHECK-64-SAME: i32 32 }>
+
+// -- %j: Gen<A>.y
+// CHECK: [[KP_J:@keypath.*]] = private global <{ {{.*}} }> <{
+// CHECK-SAME: [[WORD]] 0,
+// CHECK-SAME: %swift.type* (i8*)* [[J_GET_GEN_A_A:@[a-z_.0-9]+]],
+// CHECK-SAME: %swift.type* (i8*)* [[J_GET_A:@[a-z_.0-9]+]],
+// -- size 8
+// CHECK-SAME: i32 8,
+// CHECK-64-SAME: [4 x i8] zeroinitializer,
+// -- struct with runtime-resolved offset
+// CHECK-SAME: <i32 0x00fffffe>,
+// CHECK-32-SAME: i32 20 }>
+// CHECK-64-SAME: i32 40 }>
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @stored_property_fixed_offsets()
+sil @stored_property_fixed_offsets : $@convention(thin) () -> () {
+entry:
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_A]] to i8*), i8* undef)
+ %a = keypath $KeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_B]] to i8*), i8* undef)
+ %b = keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_C]] to i8*), i8* undef)
+ %c = keypath $KeyPath<S, C>, (root $S; stored_property #S.z : $C)
+
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_D]] to i8*), i8* undef)
+ %d = keypath $KeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_E]] to i8*), i8* undef)
+ %e = keypath $KeyPath<C, String>, (root $C; stored_property #C.y : $String)
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_F]] to i8*), i8* undef)
+ %f = keypath $KeyPath<C, S>, (root $C; stored_property #C.z : $S)
+
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_G]] to i8*), i8* undef)
+ %g = keypath $KeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_H]] to i8*), i8* undef)
+ %h = keypath $KeyPath<C, Int>, (root $C; stored_property #C.z : $S; stored_property #S.x : $Int)
+
+ %k = keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @k_id : $@convention(thin) () -> (), getter @k_get : $@convention(thin) (@in_guaranteed S) -> @out Int)
+ %l = keypath $KeyPath<C, Int>, (root $C; settable_property $Int, id #C.w!getter.1, getter @l_get : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @l_set : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+ %m = keypath $KeyPath<S, () -> ()>, (root $S; settable_property $() -> (), id ##S.reabstracted, getter @m_get : $@convention(thin) (@in_guaranteed S) -> @out @callee_guaranteed (@in_guaranteed ()) -> @out (), setter @m_set : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out (), @inout S) -> ())
+
+ return undef : $()
+}
+
+sil @k_id : $@convention(thin) () -> ()
+sil @k_get : $@convention(thin) (@in_guaranteed S) -> @out Int
+
+sil @l_get : $@convention(thin) (@in_guaranteed C) -> @out Int
+sil @l_set : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ()
+
+sil @m_get : $@convention(thin) (@in_guaranteed S) -> @out @callee_guaranteed (@in_guaranteed ()) -> @out ()
+sil @m_set : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out (), @inout S) -> ()
+
+struct Gen<T, U> {
+ var x: T
+ var y: U
+}
+
+struct Foo<T> {
+ var foo: T
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @stored_property_generics(%swift.type* %T, %swift.type* %U)
+sil @stored_property_generics : $@convention(thin) <T, U> () -> () {
+entry:
+ // CHECK: [[PTR:%.*]] = bitcast i8* [[ARGS:%.*]] to
+ // CHECK: store %swift.type* %T, %swift.type** [[PTR]]
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_I]] to i8*), i8* [[ARGS]])
+ %i = keypath $KeyPath<Gen<T,T>, T>, <A> (root $Gen<A, A>; stored_property #Gen.x : $A) <T>
+
+ // CHECK: [[PTR:%.*]] = bitcast i8* [[ARGS:%.*]] to
+ // CHECK: store %swift.type* %U, %swift.type** [[PTR]]
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_J]] to i8*), i8* [[ARGS]])
+ %j = keypath $KeyPath<Gen<U,U>, U>, <A> (root $Gen<A, A>; stored_property #Gen.y : $A) <U>
+
+ // CHECK: [[PTR:%.*]] = bitcast i8* [[ARGS:%.*]] to
+ // CHECK: [[FOO_T:%.*]] = call %swift.type* @"$S8keypaths3FooVMa"(%swift.type* %T)
+ // CHECK: store %swift.type* [[FOO_T]], %swift.type** [[PTR]]
+ // CHECK: call %swift.refcounted* @swift_getKeyPath(i8* bitcast ({{.*}} [[KP_I]] to i8*), i8* [[ARGS]])
+ %i2 = keypath $KeyPath<Gen<Foo<T>,Foo<T>>, Foo<T>>, <A> (root $Gen<A, A>; stored_property #Gen.x : $A) <Foo<T>>
+
+ return undef : $()
+}
+
+// CHECK: define private %swift.type* [[I_GET_GEN_A_A]](i8*)
+// CHECK: [[BUF:%.*]] = bitcast i8* %0
+// CHECK: [[A:%.*]] = load %swift.type*, %swift.type** [[BUF]]
+// CHECK: [[GEN:%.*]] = call %swift.type* @"$S8keypaths3GenVMa"(%swift.type* [[A]], %swift.type* [[A]])
+// CHECK: ret %swift.type* [[GEN]]
+
+
+// CHECK: define private %swift.type* [[I_GET_A]](i8*)
+// CHECK: [[BUF:%.*]] = bitcast i8* %0
+// CHECK: [[A:%.*]] = load %swift.type*, %swift.type** [[BUF]]
+// CHECK: ret %swift.type* [[A]]
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @computed_property_generics
+sil @computed_property_generics : $@convention(thin) <T, U> () -> () {
+entry:
+ %n = keypath $WritableKeyPath<T, U>, <UUU, TTT> (root $TTT; settable_property $UUU, id @n_get : $@convention(thin) <UU, TT> (@in_guaranteed TT) -> @out UU, getter @n_get : $@convention(thin) <UU, TT> (@in_guaranteed TT) -> @out UU, setter @n_set : $@convention(thin) <UU, TT> (@in_guaranteed UU, @in_guaranteed TT) -> ()) <U, T>
+
+ return undef : $()
+}
+
+sil @n_get : $@convention(thin) <UU, TT> (@in_guaranteed TT) -> @out UU
+sil @n_set : $@convention(thin) <UU, TT> (@in_guaranteed UU, @in_guaranteed TT) -> ()
+
+sil @computed_property_indices : $@convention(thin) (C, S, C, S, C, S) -> () {
+entry(%0 : $C, %1 : $S, %2 : $C, %3 : $S, %4 : $C, %5 : $S):
+ %o = keypath $WritableKeyPath<S, C>, (
+ root $S;
+ settable_property $C,
+ id @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C,
+ getter @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C,
+ setter @o_set : $@convention(thin) (@in_guaranteed C, @in_guaranteed S, UnsafeRawPointer) -> (),
+ indices [%$0 : $C : $C],
+ indices_equals @o_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @o_hash : $@convention(thin) (UnsafeRawPointer) -> Int
+ ) (%0)
+ %p = keypath $WritableKeyPath<S, C>, (
+ root $S;
+ settable_property $C,
+ id @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C,
+ getter @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C,
+ setter @o_set : $@convention(thin) (@in_guaranteed C, @in_guaranteed S, UnsafeRawPointer) -> (),
+ indices [%$0 : $S : $S, %$1 : $C : $C],
+ indices_equals @o_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @o_hash : $@convention(thin) (UnsafeRawPointer) -> Int
+ ) (%1, %2)
+ %r = keypath $WritableKeyPath<S, S>, (
+ root $S;
+ settable_property $C,
+ id @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C,
+ getter @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C,
+ setter @o_set : $@convention(thin) (@in_guaranteed C, @in_guaranteed S, UnsafeRawPointer) -> (),
+ indices [%$0 : $S : $S, %$1 : $C : $C],
+ indices_equals @o_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @o_hash : $@convention(thin) (UnsafeRawPointer) -> Int;
+ settable_property $S,
+ id @r_get : $@convention(thin) (@in_guaranteed C, UnsafeRawPointer) -> @out S,
+ getter @r_get : $@convention(thin) (@in_guaranteed C, UnsafeRawPointer) -> @out S,
+ setter @r_set : $@convention(thin) (@in_guaranteed S, @in_guaranteed C, UnsafeRawPointer) -> (),
+ indices [%$2 : $S : $S],
+ indices_equals @o_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @o_hash : $@convention(thin) (UnsafeRawPointer) -> Int
+ ) (%3, %4, %5)
+
+ return undef : $()
+}
+
+sil @o_get : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out C
+sil @o_set : $@convention(thin) (@in_guaranteed C, @in_guaranteed S, UnsafeRawPointer) -> ()
+sil @o_equals : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @o_hash : $@convention(thin) (UnsafeRawPointer) -> Int
+
+sil @r_get : $@convention(thin) (@in_guaranteed C, UnsafeRawPointer) -> @out S
+sil @r_set : $@convention(thin) (@in_guaranteed S, @in_guaranteed C, UnsafeRawPointer) -> ()
+
+sil @generic_computed_property_indices : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B) -> () {
+entry(%0 : $*A, %1 : $*B, %2 : $*A, %3 : $*B, %4 : $*A, %5 : $*B):
+ %s = keypath $WritableKeyPath<A, B>, <X: Hashable, Y: Hashable> (
+ root $X;
+ settable_property $Y,
+ id @s_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, UnsafeRawPointer) -> @out U,
+ getter @s_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, UnsafeRawPointer) -> @out U,
+ setter @s_set : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed T, UnsafeRawPointer) -> (),
+ indices [%$0 : $X : $*X],
+ indices_equals @s_equals : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @s_hash : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer) -> Int
+ ) <A, B> (%0)
+ %t = keypath $WritableKeyPath<A, B>, <X: Hashable, Y: Hashable> (
+ root $X;
+ settable_property $Y,
+ id @s_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, UnsafeRawPointer) -> @out U,
+ getter @s_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, UnsafeRawPointer) -> @out U,
+ setter @s_set : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed T, UnsafeRawPointer) -> (),
+ indices [%$0 : $Y : $*Y, %$1 : $X : $*X],
+ indices_equals @s_equals : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @s_hash : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer) -> Int
+ ) <A, B> (%1, %2)
+ %v = keypath $WritableKeyPath<A, A>, <X: Hashable, Y: Hashable> (
+ root $X;
+ settable_property $Y,
+ id @s_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, UnsafeRawPointer) -> @out U,
+ getter @s_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, UnsafeRawPointer) -> @out U,
+ setter @s_set : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed U, @in_guaranteed T, UnsafeRawPointer) -> (),
+ indices [%$0 : $Y : $*Y, %$1 : $X : $*X],
+ indices_equals @s_equals : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @s_hash : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer) -> Int;
+ settable_property $X,
+ id @v_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed U, UnsafeRawPointer) -> @out T,
+ getter @v_get : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed U, UnsafeRawPointer) -> @out T,
+ setter @v_set : $@convention(thin) <T: Hashable, U: Hashable> (@in_guaranteed T, @in_guaranteed U, UnsafeRawPointer) -> (),
+ indices [%$2 : $Y : $*Y],
+ indices_equals @s_equals : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @s_hash : $@convention(thin) <T: Hashable, U: Hashable> (UnsafeRawPointer) -> Int
+ ) <A, B> (%3, %4, %5)
+
+ return undef : $()
+}
+
+sil @generic_external : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B, @in_guaranteed A, @in_guaranteed B) -> () {
+entry(%0 : $*A, %1 : $*B, %2 : $*A, %3 : $*B, %4 : $*A, %5 : $*B):
+ %t = keypath $KeyPath<G<B>, B>, <Z> (
+ root $G<Z>;
+ external #G.x<Z> : $Z
+ ) <B>
+
+ %u = keypath $KeyPath<G<A>, A>, <X: Hashable, Y: Hashable> (
+ root $G<Y>;
+ external #G.subscript<Y, X> [%$0 : $X : $*X] : $Y
+ ) <B, A> (%1)
+
+ %v = keypath $KeyPath<G<G<B>>, B>, <X: Hashable, Y: Hashable> (
+ root $G<G<X>>;
+ external #G.subscript<G<X>, Y> [%$1 : $Y : $*Y] : $G<X>;
+ external #G.subscript<X, X> [%$0 : $X : $*X] : $X
+ ) <B, A> (%3, %4)
+
+ return undef : $()
+}
+
+sil @s_get : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, UnsafeRawPointer) -> @out B
+sil @s_set : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed B, @in_guaranteed A, UnsafeRawPointer) -> ()
+sil @s_equals : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @s_hash : $@convention(thin) <A: Hashable, B: Hashable> (UnsafeRawPointer) -> Int
+
+sil @v_get : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed B, UnsafeRawPointer) -> @out A
+sil @v_set : $@convention(thin) <A: Hashable, B: Hashable> (@in_guaranteed A, @in_guaranteed B, UnsafeRawPointer) -> ()
diff --git a/test/IRGen/plus_zero_keypaths_objc.sil b/test/IRGen/plus_zero_keypaths_objc.sil
new file mode 100644
index 0000000..1504309
--- /dev/null
+++ b/test/IRGen/plus_zero_keypaths_objc.sil
@@ -0,0 +1,53 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %utils/chex.py < %s > %t/keypaths_objc.sil
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir %t/keypaths_objc.sil | %FileCheck %t/keypaths_objc.sil --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
+// REQUIRES: objc_interop
+
+import Swift
+import Foundation
+
+class C: NSObject {
+ dynamic var x: NSString { get }
+ @sil_stored final var stored: Int
+ override init()
+}
+
+sil_vtable C {}
+
+sil @x_get : $@convention(thin) (@in_guaranteed C) -> @out NSString
+
+// CHECK: [[KEYPATH_A:@keypath.*]] = private global
+// -- 0x0100_0002: computed, get-only, indirect identifier
+// CHECK-SAME: <i32 0x0100_0002>,
+// CHECK-SAME: i8** @"\01L_selector(x)"
+
+// CHECK: [[KEYPATH_B:@keypath.*]] = private global
+// -- 0x02fffffd: class stored property with indirect offset
+// CHECK-SAME: <i32 0x02fffffd>,
+// CHECK-SAME: @"$S13keypaths_objc1CC6storedSivpWvd"
+
+// CHECK-LABEL: define swiftcc void @objc_only_property()
+sil @objc_only_property : $@convention(thin) () -> () {
+entry:
+ // CHECK: call %swift.refcounted* @swift_getKeyPath({{.*}} [[KEYPATH_A]]
+ %a = keypath $KeyPath<C, NSString>, (objc "x"; root $C; gettable_property $NSString, id #C.x!getter.1.foreign, getter @x_get : $@convention(thin) (@in_guaranteed C) -> @out NSString)
+ unreachable
+}
+
+sil hidden @$S13keypaths_objc1CC1xSo8NSStringCvgTo : $@convention(objc_method) (@guaranteed C) -> NSString {
+entry(%0 : $C):
+ unreachable
+}
+
+sil hidden @$S13keypaths_objc1CCACycfcTo : $@convention(objc_method) (@objc_metatype C.Type) -> @owned C {
+entry(%0 : $@objc_metatype C.Type):
+ unreachable
+}
+
+sil @objc_stored_property : $@convention(thin) () -> () {
+entry:
+ // CHECK: call %swift.refcounted* @swift_getKeyPath({{.*}} [[KEYPATH_B]]
+ %b = keypath $KeyPath<C, Int>, (objc "stored"; root $C; stored_property #C.stored : $Int)
+ unreachable
+}
diff --git a/test/IRGen/plus_zero_lowered_optional_self_metadata.sil b/test/IRGen/plus_zero_lowered_optional_self_metadata.sil
new file mode 100644
index 0000000..005e8bb
--- /dev/null
+++ b/test/IRGen/plus_zero_lowered_optional_self_metadata.sil
@@ -0,0 +1,33 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s
+sil_stage canonical
+
+import Swift
+
+public protocol Protocol {
+ static func foo(_: Self?)
+}
+
+// SR-3021: Ensure we pass the Self type metadata for Optional methods using the
+// formal Optional type and not a lowered SIL type.
+
+// CHECK-LABEL: @_TMaGSqFT_T__
+
+sil @optional_method : $@convention(method) <T> (@in_guaranteed Optional<T>) -> ()
+
+sil @call_optional_method_with_lowered_function : $@convention(thin) (@in_guaranteed Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>) -> () {
+entry(%x : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>):
+ %f = function_ref @optional_method : $@convention(method) <T> (@in_guaranteed Optional<T>) -> ()
+ apply %f<() -> ()>(%x) : $@convention(method) <T> (@in_guaranteed Optional<T>) -> ()
+ %p = partial_apply [callee_guaranteed] %f<() -> ()>() : $@convention(method) <T> (@in_guaranteed Optional<T>) -> ()
+ return undef : $()
+}
+
+// SR-3548: Ensure we correctly emit "metadata for layout" for lowered Optional types.
+
+sil @alloc_stack_optional_with_generic : $@convention(thin) <T> () -> () {
+ %a = alloc_stack $*Optional<(T, @convention(thin) () -> ())>
+ dealloc_stack %a : $*Optional<(T, @convention(thin) () -> ())>
+ %t = tuple ()
+ return %t : $()
+}
diff --git a/test/IRGen/plus_zero_objc.swift b/test/IRGen/plus_zero_objc.swift
new file mode 100644
index 0000000..634a5a6
--- /dev/null
+++ b/test/IRGen/plus_zero_objc.swift
@@ -0,0 +1,148 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-irgen-test-overlays
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -primary-file %s -emit-ir -disable-objc-attr-requires-foundation-module | %FileCheck %s
+
+// REQUIRES: CPU=x86_64
+// REQUIRES: objc_interop
+
+import Foundation
+import gizmo
+
+// CHECK: [[TYPE:%swift.type]] = type
+// CHECK: [[BLAMMO:%T4objc6BlammoC]] = type
+// CHECK: [[MYBLAMMO:%T4objc8MyBlammoC]] = type
+// CHECK: [[TEST2:%T4objc5Test2C]] = type
+// CHECK: [[OBJC:%objc_object]] = type
+// CHECK: [[ID:%T4objc2idV]] = type <{ %AnyObject }>
+// CHECK: [[GIZMO:%TSo5GizmoC]] = type
+// CHECK: [[RECT:%TSo4RectV]] = type
+// CHECK: [[FLOAT:%TSf]] = type
+
+// CHECK: @"\01L_selector_data(bar)" = private global [4 x i8] c"bar\00", section "__TEXT,__objc_methname,cstring_literals", align 1
+// CHECK: @"\01L_selector(bar)" = private externally_initialized global i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01L_selector_data(bar)", i64 0, i64 0), section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip", align 8
+
+// CHECK: @"$SSo4RectVMn" = linkonce_odr hidden constant
+// CHECK: @"$SSo4RectVN" = linkonce_odr hidden global
+
+// CHECK: @"\01L_selector_data(acquiesce)"
+// CHECK-NOT: @"\01L_selector_data(disharmonize)"
+// CHECK: @"\01L_selector_data(eviscerate)"
+
+struct id {
+ var data : AnyObject
+}
+
+// Exporting something as [objc] doesn't make it an ObjC class.
+@objc class Blammo {
+}
+// Class and methods are [objc] by inheritance.
+class MyBlammo : Blammo {
+ func foo() {}
+// CHECK: define hidden swiftcc void @"$S4objc8MyBlammoC3fooyyF"([[MYBLAMMO]]* swiftself) {{.*}} {
+// CHECK: call {{.*}} @swift_release
+// CHECK: ret void
+}
+
+// Class and methods are [objc] by inheritance.
+class Test2 : Gizmo {
+ func foo() {}
+// CHECK: define hidden swiftcc void @"$S4objc5Test2C3fooyyF"([[TEST2]]* swiftself) {{.*}} {
+// CHECK: call {{.*}} @objc_release
+// CHECK: ret void
+
+ dynamic func bar() {}
+}
+
+// Test @nonobjc.
+class Contrarian : Blammo {
+ func acquiesce() {}
+ @nonobjc func disharmonize() {}
+ @nonobjc func eviscerate() {}
+}
+
+class Octogenarian : Contrarian {
+ // Override of @nonobjc is @objc again unless made @nonobjc.
+ @nonobjc override func disharmonize() {}
+
+ // Override of @nonobjc can be @objc.
+ @objc override func eviscerate() {}
+}
+
+@_silgen_name("unknown")
+func unknown(_ x: id) -> id
+
+// CHECK: define hidden swiftcc %objc_object* @"$S4objc5test0{{[_0-9a-zA-Z]*}}F"(%objc_object*)
+// CHECK-NOT: call {{.*}} @swift_unknownRetain
+// CHECK: call {{.*}} @swift_unknownRetain
+// CHECK-NOT: call {{.*}} @swift_unknownRelease
+// CHECK: call {{.*}} @swift_unknownRelease
+// CHECK: ret %objc_object*
+func test0(_ arg: id) -> id {
+ var x : id
+ x = arg
+ unknown(x)
+ var y = x
+ return y
+}
+
+func test1(_ cell: Blammo) {}
+// CHECK: define hidden swiftcc void @"$S4objc5test1{{[_0-9a-zA-Z]*}}F"([[BLAMMO]]*) {{.*}} {
+// CHECK-NEXT: entry
+// CHECK-NEXT: ret void
+
+
+// FIXME: These ownership convention tests should become SILGen tests.
+func test2(_ v: Test2) { v.bar() }
+func test3() -> NSObject {
+ return Gizmo()
+}
+// Normal message send with argument, no transfers.
+func test5(_ g: Gizmo) {
+ Gizmo.inspect(g)
+}
+// The argument to consume: is __attribute__((ns_consumed)).
+func test6(_ g: Gizmo) {
+ Gizmo.consume(g)
+}
+// fork is __attribute__((ns_consumes_self)).
+func test7(_ g: Gizmo) {
+ g.fork()
+}
+// clone is __attribute__((ns_returns_retained)).
+func test8(_ g: Gizmo) {
+ g.clone()
+}
+// duplicate has an object returned at +0.
+func test9(_ g: Gizmo) {
+ g.duplicate()
+}
+
+func test10(_ g: Gizmo, r: Rect) {
+ Gizmo.run(with: r, andGizmo:g);
+}
+
+// Force the emission of the Rect metadata.
+func test11_helper<T>(_ t: T) {}
+// NSRect's metadata needs to be uniqued at runtime using getForeignTypeMetadata.
+// CHECK-LABEL: define hidden swiftcc void @"$S4objc6test11yySo4RectVF"
+// CHECK: call %swift.type* @swift_getForeignTypeMetadata({{.*}} @"$SSo4RectVN"
+func test11(_ r: Rect) { test11_helper(r) }
+
+class WeakObjC {
+ weak var obj: NSObject?
+ weak var id: AnyObject?
+
+ init() {
+ var foo = obj
+ var bar: AnyObject? = id
+ }
+}
+
+// rdar://17528908
+// CHECK: i32 1, !"Objective-C Version", i32 2}
+// CHECK: i32 1, !"Objective-C Image Info Version", i32 0}
+// CHECK: i32 1, !"Objective-C Image Info Section", !"__DATA,__objc_imageinfo,regular,no_dead_strip"}
+// 1536 == (6 << 8). 6 is the Swift ABI version.
+// CHECK: i32 4, !"Objective-C Garbage Collection", i32 1536}
+// CHECK: i32 1, !"Swift Version", i32 6}
diff --git a/test/IRGen/plus_zero_objc_retainAutoreleasedReturnValue.swift b/test/IRGen/plus_zero_objc_retainAutoreleasedReturnValue.swift
new file mode 100644
index 0000000..67bf5d9
--- /dev/null
+++ b/test/IRGen/plus_zero_objc_retainAutoreleasedReturnValue.swift
@@ -0,0 +1,40 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -target x86_64-apple-macosx10.12 -assume-parsing-unqualified-ownership-sil -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s
+// RUN: %target-swift-frontend -O -target x86_64-apple-macosx10.12 -assume-parsing-unqualified-ownership-sil -import-objc-header %S/Inputs/StaticInline.h %s -emit-ir | %FileCheck %s --check-prefix=OPT
+
+// REQUIRES: objc_interop
+// REQUIRES: CPU=x86_64
+// REQUIRES: OS=macosx
+import Foundation
+
+@inline(never)
+public func useClosure(_ dict: NSDictionary, _ action : (NSDictionary) -> ()) {
+ action(dict)
+}
+
+@inline(never)
+public func test(_ dict: NSDictionary) {
+ useClosure(dict, { $0.objectEnumerator()} )
+}
+
+// Don't tail call objc_retainAutoreleasedReturnValue as this would block the
+// autorelease return value optimization.
+
+// callq 0x01ec08 ; symbol stub for: objc_msgSend
+// movq %rax, %rdi
+// popq %rbp ;<== Blocks the handshake from objc_autoreleaseReturnValue
+// jmp 0x01ec20 ; symbol stub for: objc_retainAutoreleasedReturnValue
+
+// CHECK-LABEL: define {{.*}}swiftcc void @"$S34objc_retainAutoreleasedReturnValue4testyySo12NSDictionaryCFyADXEfU_"(%TSo12NSDictionaryC*)
+// CHECK: entry:
+// CHECK: call {{.*}}@objc_msgSend
+// CHECK: notail call i8* @objc_retainAutoreleasedReturnValue
+// CHECK: ret void
+
+// CHECK-LABEL: define {{.*}}swiftcc void @"$SSo12NSDictionaryCSo12NSEnumeratorCIggo_ABIegg_TR"(%TSo12NSDictionaryC*, i8*, %swift.opaque*)
+
+// OPT-LABEL: define {{.*}}swiftcc void @"$S34objc_retainAutoreleasedReturnValue10useClosureyySo12NSDictionaryC_yADXEtF06$SSo12h44CSo12NSEnumeratorCIggo_ABIegg_TR049$S34objc_bcD42Value4testyySo12a6CFSo12B8CADXEfU_Tf3npf_nTf1nc_n"(%TSo12NSDictionaryC*)
+// OPT: entry:
+// OPT: call {{.*}}@objc_msgSend
+// OPT: notail call i8* @objc_retainAutoreleasedReturnValue
+// OPT: ret void
diff --git a/test/IRGen/plus_zero_runtime_calling_conventions.swift b/test/IRGen/plus_zero_runtime_calling_conventions.swift
new file mode 100644
index 0000000..8322258
--- /dev/null
+++ b/test/IRGen/plus_zero_runtime_calling_conventions.swift
@@ -0,0 +1,19 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-as-library -emit-ir %s | %FileCheck %s
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-as-library -O -emit-ir %s | %FileCheck --check-prefix=OPT-CHECK %s
+
+// Test that runtime functions are invoked using the new calling convention.
+
+public class C {
+}
+
+// CHECK-LABEL: define {{(protected )?}}swiftcc void @"$S27runtime_calling_conventions3fooyyAA1CCF"(%T27runtime_calling_conventions1CC*)
+// Check that runtime functions use a proper calling convention.
+// CHECK-NOT: call void {{.*}} @swift_release
+
+// OPT-CHECK-LABEL: define {{(protected )?}}swiftcc void @"$S27runtime_calling_conventions3fooyyAA1CCF"(%T27runtime_calling_conventions1CC* nocapture)
+// Check that runtime functions use a proper calling convention.
+// OPT-CHECK-NOT: tail call void @swift_release
+
+public func foo(_ c: C) {
+}
diff --git a/test/IRGen/plus_zero_struct_resilience.swift b/test/IRGen/plus_zero_struct_resilience.swift
new file mode 100644
index 0000000..6f0bdf7
--- /dev/null
+++ b/test/IRGen/plus_zero_struct_resilience.swift
@@ -0,0 +1,173 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
+// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience %s | %FileCheck %s
+// RUN: %target-swift-frontend -I %t -emit-ir -enable-resilience -O %s
+
+import resilient_struct
+import resilient_enum
+
+// CHECK: %TSi = type <{ [[INT:i32|i64]] }>
+
+// CHECK-LABEL: @"$S17struct_resilience26StructWithResilientStorageVMf" = internal global
+
+// Resilient structs from outside our resilience domain are manipulated via
+// value witnesses
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S17struct_resilience26functionWithResilientTypes_1f010resilient_A04SizeVAF_A2FXEtF"(%swift.opaque* noalias nocapture sret, %swift.opaque* noalias nocapture, i8*, %swift.opaque*)
+
+public func functionWithResilientTypes(_ s: Size, f: (Size) -> Size) -> Size {
+// CHECK: entry:
+// CHECK-NEXT: [[FN:%.*]] = bitcast i8* %2 to void (%swift.opaque*, %swift.opaque*, %swift.refcounted*)*
+// CHECK-NEXT: [[SELF:%.*]] = bitcast %swift.opaque* %3 to %swift.refcounted*
+// CHECK-NEXT: call swiftcc void [[FN]](%swift.opaque* noalias nocapture sret %0, %swift.opaque* noalias nocapture %1, %swift.refcounted* swiftself [[SELF]])
+// CHECK-NEXT: ret void
+
+ return f(s)
+}
+
+// Rectangle has fixed layout inside its resilience domain, and dynamic
+// layout on the outside.
+//
+// Make sure we use a type metadata accessor function, and load indirect
+// field offsets from it.
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S17struct_resilience26functionWithResilientTypesyy010resilient_A09RectangleVF"(%T16resilient_struct9RectangleV* noalias nocapture)
+public func functionWithResilientTypes(_ r: Rectangle) {
+
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S16resilient_struct9RectangleVMa"()
+// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
+// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 2
+// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
+// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
+// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T16resilient_struct9RectangleV* %0 to i8*
+// CHECK-NEXT: [[FIELD_ADDR:%.*]] = getelementptr inbounds i8, i8* [[STRUCT_ADDR]], [[INT]] [[FIELD_OFFSET]]
+// CHECK-NEXT: [[FIELD_PTR:%.*]] = bitcast i8* [[FIELD_ADDR]] to %TSi*
+// CHECK-NEXT: [[FIELD_PAYLOAD_PTR:%.*]] = getelementptr inbounds %TSi, %TSi* [[FIELD_PTR]], i32 0, i32 0
+// CHECK-NEXT: [[FIELD_PAYLOAD:%.*]] = load [[INT]], [[INT]]* [[FIELD_PAYLOAD_PTR]]
+
+ _ = r.color
+
+// CHECK-NEXT: ret void
+
+}
+
+// Resilient structs from inside our resilience domain are manipulated
+// directly.
+
+public struct MySize {
+ public let w: Int
+ public let h: Int
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S17struct_resilience28functionWithMyResilientTypes_1fAA0E4SizeVAE_A2EXEtF"(%T17struct_resilience6MySizeV* {{.*}}, %T17struct_resilience6MySizeV* {{.*}}, i8*, %swift.opaque*)
+public func functionWithMyResilientTypes(_ s: MySize, f: (MySize) -> MySize) -> MySize {
+// CHECK: entry:
+// CHECK-NEXT: [[FN:%.*]] = bitcast i8* %2
+// CHECK-NEXT: [[SELF:%.*]] = bitcast %swift.opaque* %3
+// CHECK-NEXT: call swiftcc void [[FN]](%T17struct_resilience6MySizeV* {{.*}} %0, {{.*}} %1, %swift.refcounted* swiftself [[SELF]])
+// CHECK-NEXT: ret void
+ return f(s)
+}
+
+// CHECK-LABEL: declare %swift.type* @"$S16resilient_struct4SizeVMa"()
+
+// Structs with resilient storage from a different resilience domain require
+// runtime metadata instantiation, just like generics.
+
+public struct StructWithResilientStorage {
+ public let s: Size
+ public let ss: (Size, Size)
+ public let n: Int
+ public let i: ResilientInt
+}
+
+// Make sure we call a function to access metadata of structs with
+// resilient layout, and go through the field offset vector in the
+// metadata when accessing stored properties.
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc {{i32|i64}} @"$S17struct_resilience26StructWithResilientStorageV1nSivg"(%T17struct_resilience26StructWithResilientStorageV* {{.*}})
+// CHECK: [[METADATA:%.*]] = call %swift.type* @"$S17struct_resilience26StructWithResilientStorageVMa"()
+// CHECK-NEXT: [[METADATA_ADDR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
+// CHECK-NEXT: [[FIELD_OFFSET_VECTOR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_ADDR]], [[INT]] 2
+// CHECK-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[FIELD_OFFSET_VECTOR]], i32 2
+// CHECK-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
+// CHECK-NEXT: [[STRUCT_ADDR:%.*]] = bitcast %T17struct_resilience26StructWithResilientStorageV* %0 to i8*
+// CHECK-NEXT: [[FIELD_ADDR:%.*]] = getelementptr inbounds i8, i8* [[STRUCT_ADDR]], [[INT]] [[FIELD_OFFSET]]
+// CHECK-NEXT: [[FIELD_PTR:%.*]] = bitcast i8* [[FIELD_ADDR]] to %TSi*
+// CHECK-NEXT: [[FIELD_PAYLOAD_PTR:%.*]] = getelementptr inbounds %TSi, %TSi* [[FIELD_PTR]], i32 0, i32 0
+// CHECK-NEXT: [[FIELD_PAYLOAD:%.*]] = load [[INT]], [[INT]]* [[FIELD_PAYLOAD_PTR]]
+// CHECK-NEXT: ret [[INT]] [[FIELD_PAYLOAD]]
+
+
+// Indirect enums with resilient payloads are still fixed-size.
+
+public struct StructWithIndirectResilientEnum {
+ public let s: FunnyShape
+ public let n: Int
+}
+
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc {{i32|i64}} @"$S17struct_resilience31StructWithIndirectResilientEnumV1nSivg"(%T17struct_resilience31StructWithIndirectResilientEnumV* {{.*}})
+// CHECK: [[FIELD_PTR:%.*]] = getelementptr inbounds %T17struct_resilience31StructWithIndirectResilientEnumV, %T17struct_resilience31StructWithIndirectResilientEnumV* %0, i32 0, i32 1
+// CHECK-NEXT: [[FIELD_PAYLOAD_PTR:%.*]] = getelementptr inbounds %TSi, %TSi* [[FIELD_PTR]], i32 0, i32 0
+// CHECK-NEXT: [[FIELD_PAYLOAD:%.*]] = load [[INT]], [[INT]]* [[FIELD_PAYLOAD_PTR]]
+// CHECK-NEXT: ret [[INT]] [[FIELD_PAYLOAD]]
+
+
+// Partial application of methods on resilient value types
+
+public struct ResilientStructWithMethod {
+ public func method() {}
+}
+
+// Corner case -- type is address-only in SIL, but empty in IRGen
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S17struct_resilience29partialApplyOfResilientMethod1ryAA0f10StructWithG0V_tF"(%T17struct_resilience25ResilientStructWithMethodV* noalias nocapture)
+public func partialApplyOfResilientMethod(r: ResilientStructWithMethod) {
+ _ = r.method
+}
+
+// Type is address-only in SIL, and resilient in IRGen
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @"$S17struct_resilience29partialApplyOfResilientMethod1sy010resilient_A04SizeV_tF"(%swift.opaque* noalias nocapture)
+public func partialApplyOfResilientMethod(s: Size) {
+ _ = s.method
+}
+
+// Public metadata accessor for our resilient struct
+
+// CHECK-LABEL: define{{( protected)?}} %swift.type* @"$S17struct_resilience6MySizeVMa"()
+// CHECK: ret %swift.type* bitcast ([[INT]]* getelementptr inbounds {{.*}} @"$S17struct_resilience6MySizeVMf", i32 0, i32 1) to %swift.type*)
+
+
+// CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_StructWithResilientStorage(i8*)
+// CHECK: [[FIELDS:%.*]] = alloca [4 x i8**]
+
+// CHECK: [[FIELDS_ADDR:%.*]] = getelementptr inbounds [4 x i8**], [4 x i8**]* [[FIELDS]], i32 0, i32 0
+
+// public let s: Size
+
+// CHECK: [[FIELD_1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
+// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_1]]
+
+// public let ss: (Size, Size)
+
+// CHECK: [[FIELD_2:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 1
+// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_2]]
+
+// Fixed-layout aggregate -- we can reference a static value witness table
+// public let n: Int
+
+// CHECK: [[FIELD_3:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 2
+// CHECK: store i8** getelementptr inbounds (i8*, i8** @"$SBi{{32|64}}_WV", i32 {{.*}}), i8*** [[FIELD_3]]
+
+// Resilient aggregate with one field -- make sure we don't look inside it
+// public let i: ResilientInt
+// CHECK: [[FIELD_4:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 3
+// CHECK: store i8** [[SIZE_AND_ALIGNMENT:%.*]], i8*** [[FIELD_4]]
+
+// CHECK: call void @swift_initStructMetadata(%swift.type* {{.*}}, [[INT]] 256, [[INT]] 4, i8*** [[FIELDS_ADDR]], [[INT]]* {{.*}})
+// CHECK: store atomic %swift.type* {{.*}} @"$S17struct_resilience26StructWithResilientStorageVMf{{.*}}, %swift.type** @"$S17struct_resilience26StructWithResilientStorageVML" release,
+// CHECK: ret void
diff --git a/test/IRGen/runtime_calling_conventions.swift b/test/IRGen/runtime_calling_conventions.swift
index e7d0d97..74ca835 100644
--- a/test/IRGen/runtime_calling_conventions.swift
+++ b/test/IRGen/runtime_calling_conventions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-as-library -emit-ir %s | %FileCheck %s
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -parse-as-library -O -emit-ir %s | %FileCheck --check-prefix=OPT-CHECK %s
diff --git a/test/IRGen/struct_resilience.swift b/test/IRGen/struct_resilience.swift
index 1151eb1..2118662 100644
--- a/test/IRGen/struct_resilience.swift
+++ b/test/IRGen/struct_resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
diff --git a/test/Interpreter/SDK/Foundation_test.swift b/test/Interpreter/SDK/Foundation_test.swift
index 50dfc96..f41b2a3 100644
--- a/test/Interpreter/SDK/Foundation_test.swift
+++ b/test/Interpreter/SDK/Foundation_test.swift
@@ -252,7 +252,7 @@
let _: CFArrayEqualCallBack = { DarwinBoolean($0 == $1) }
}
-#if os(OSX)
+#if os(macOS)
FoundationTestSuite.test("NSRectEdge/constants") {
// Check that the following constants have the correct type and value.
//
diff --git a/test/Interpreter/SDK/c_pointers.swift b/test/Interpreter/SDK/c_pointers.swift
index f7f3657..c295c14 100644
--- a/test/Interpreter/SDK/c_pointers.swift
+++ b/test/Interpreter/SDK/c_pointers.swift
@@ -6,7 +6,7 @@
// REQUIRES: objc_interop
import Foundation
-#if os(OSX)
+#if os(macOS)
import AppKit
typealias XXColor = NSColor
#endif
@@ -28,7 +28,7 @@
let nsRed = XXColor(cgColor: cgRed)
var r: CGFloat = 0.5, g: CGFloat = 0.5, b: CGFloat = 0.5, a: CGFloat = 0.5
-#if os(OSX)
+#if os(macOS)
nsRed!.getRed(&r, green: &g, blue: &b, alpha: &a)
#else
nsRed.getRed(&r, green: &g, blue: &b, alpha: &a)
diff --git a/test/Interpreter/SDK/cf_extensions.swift b/test/Interpreter/SDK/cf_extensions.swift
index 57aa920..9dcc3cb 100644
--- a/test/Interpreter/SDK/cf_extensions.swift
+++ b/test/Interpreter/SDK/cf_extensions.swift
@@ -6,7 +6,7 @@
import Foundation
import StdlibUnittest
-#if os(OSX)
+#if os(macOS)
import AppKit
#endif
diff --git a/test/Interpreter/SDK/cf_type_bridging.swift b/test/Interpreter/SDK/cf_type_bridging.swift
index e755645..23dfa86 100644
--- a/test/Interpreter/SDK/cf_type_bridging.swift
+++ b/test/Interpreter/SDK/cf_type_bridging.swift
@@ -3,7 +3,7 @@
// REQUIRES: objc_interop
-#if os(OSX)
+#if os(macOS)
import AppKit
#endif
#if os(iOS) || os(tvOS) || os(watchOS)
diff --git a/test/Interpreter/SDK/libc.swift b/test/Interpreter/SDK/libc.swift
index 13a0e17..0e1dd7d 100644
--- a/test/Interpreter/SDK/libc.swift
+++ b/test/Interpreter/SDK/libc.swift
@@ -9,7 +9,7 @@
// TODO: rdar://problem/33388782
// REQUIRES: CPU=x86_64
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
import Glibc
diff --git a/test/Interpreter/SDK/objc_ns_enum.swift b/test/Interpreter/SDK/objc_ns_enum.swift
index e125436..b2c5d1d 100644
--- a/test/Interpreter/SDK/objc_ns_enum.swift
+++ b/test/Interpreter/SDK/objc_ns_enum.swift
@@ -8,7 +8,7 @@
// strict checking if we get a guarantee that certain types don't have
// hidden or future enumeration values.)
-#if os(OSX)
+#if os(macOS)
import AppKit
print(NSButtonType(rawValue: 20721)!.rawValue)
diff --git a/test/Migrator/no_duplicate_aarch64_use_tbi.swift b/test/Migrator/no_duplicate_aarch64_use_tbi.swift
index b2c648c..af356a1 100644
--- a/test/Migrator/no_duplicate_aarch64_use_tbi.swift
+++ b/test/Migrator/no_duplicate_aarch64_use_tbi.swift
@@ -2,14 +2,14 @@
// REQUIRES: CPU=arm64
// RUN: %target-swift-frontend -typecheck %s -swift-version 3
// RUN: %empty-directory(%t)
-// RUN: cd %t && %swiftc_driver -c -update-code -target arm64-apple-ios10.3 -output-file-map %S/Inputs/no_duplicate_aarch64_use_tbi_ofm.json -swift-version 3 %s -v
-// RUN: cd %t && %swiftc_driver -c -update-code -target arm64-apple-ios10.3 -output-file-map %S/Inputs/no_duplicate_aarch64_use_tbi_ofm.json -swift-version 3 %s -### > %t/driver_actions.txt
+// RUN: cd %t && %target-swiftc_driver -c -update-code -output-file-map %S/Inputs/no_duplicate_aarch64_use_tbi_ofm.json -swift-version 3 %s -v
+// RUN: cd %t && %target-swiftc_driver -c -update-code -output-file-map %S/Inputs/no_duplicate_aarch64_use_tbi_ofm.json -swift-version 3 %s -### > %t/driver_actions.txt
// RUN: %FileCheck --check-prefix=CHECK-REMAP %s < %t/no_duplicate_aarch64_use_tbi.remap
// RUN: %FileCheck --check-prefix=CHECK-ACTIONS %s < %t/driver_actions.txt
public func foo(_ f: (Void) -> ()) {}
-// CHECK-REMAP: "offset": 673,
+// CHECK-REMAP: "offset": 632,
// CHECK-REMAP: "remove": 5,
// CHECK-REMAP: "text": "("
diff --git a/test/Parse/ConditionalCompilation/basicIdentity.swift b/test/Parse/ConditionalCompilation/basicIdentity.swift
index 14072e7..a067063 100644
--- a/test/Parse/ConditionalCompilation/basicIdentity.swift
+++ b/test/Parse/ConditionalCompilation/basicIdentity.swift
@@ -63,3 +63,9 @@
var w = Foo()
#endif
var x = w
+
+// Test os(macOS) as well
+#if os(macOS)
+var y = Foo()
+#endif
+var z = y
diff --git a/test/PrintAsObjC/accessibility.swift b/test/PrintAsObjC/accessibility.swift
index bbe7d07..e509860 100644
--- a/test/PrintAsObjC/accessibility.swift
+++ b/test/PrintAsObjC/accessibility.swift
@@ -37,7 +37,7 @@
#if MAIN
-#if os(OSX)
+#if os(macOS)
import AppKit
@NSApplicationMain
diff --git a/test/Reflection/capture_descriptors.sil b/test/Reflection/capture_descriptors.sil
index 19580f8..5630624 100644
--- a/test/Reflection/capture_descriptors.sil
+++ b/test/Reflection/capture_descriptors.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// REQUIRES: no_asan
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -emit-module -emit-library -module-name capture_descriptors -o %t/capture_descriptors.%target-dylib-extension
diff --git a/test/Reflection/plus_zero_capture_descriptors.sil b/test/Reflection/plus_zero_capture_descriptors.sil
new file mode 100644
index 0000000..dab2c61
--- /dev/null
+++ b/test/Reflection/plus_zero_capture_descriptors.sil
@@ -0,0 +1,290 @@
+// REQUIRES: plus_zero_runtime
+// REQUIRES: no_asan
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift %s -emit-module -emit-library -module-name capture_descriptors -o %t/capture_descriptors.%target-dylib-extension
+// RUN: %target-swift-reflection-dump -binary-filename %t/capture_descriptors.%target-dylib-extension | %FileCheck %s
+
+sil_stage canonical
+
+import Builtin
+import Swift
+import SwiftShims
+
+// CHECK: CAPTURE DESCRIPTORS:
+// CHECK-NEXT: ====================
+
+// Concrete caller and callee -- nothing interesting going on
+
+protocol P {}
+extension Int: P {}
+
+sil @concrete_callee1 : $@convention(thin) (Int, @owned <τ_0_0> { var τ_0_0 } <Int>, @thin Int.Type, @thick P.Type) -> () {
+bb0(%i: $Int, %b: $<τ_0_0> { var τ_0_0 } <Int>, %m: $@thin Int.Type, %p: $@thick P.Type):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @concrete_caller1 : $@convention(thin) (Int, @thick P.Type) -> @owned @callee_guaranteed () -> () {
+bb0(%i: $Int, %p: $@thick P.Type):
+ %f = function_ref @concrete_callee1 : $@convention(thin) (Int, @owned <τ_0_0> { var τ_0_0 } <Int>, @thin Int.Type, @thick P.Type) -> ()
+ %b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ %m = metatype $@thin Int.Type
+ %c = partial_apply [callee_guaranteed] %f(%i, %b, %m, %p) : $@convention(thin) (Int, @owned <τ_0_0> { var τ_0_0 } <Int>, @thin Int.Type, @thick P.Type) -> ()
+ return %c : $@callee_guaranteed () -> ()
+}
+
+// This is the descriptor for '<τ_0_0> { var τ_0_0 } <Int>' above
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (struct Swift.Int)
+// CHECK-NEXT: - Metadata sources:
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (struct Swift.Int)
+// CHECK-NEXT: (sil_box
+// CHECK-NEXT: (struct Swift.Int))
+// CHECK-NEXT: (existential_metatype
+// CHECK-NEXT: (protocol_composition
+// CHECK-NEXT: (protocol capture_descriptors.P)))
+// CHECK-NEXT: - Metadata sources:
+
+
+// Concrete caller and generic callee -- capture types are fully substituted,
+// and there are no metadata bindings
+
+sil @generic_callee2 : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> () {
+bb0(%i: $*T, %b: $<τ_0_0> { var τ_0_0 } <U>):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @concrete_caller2 : $@convention(thin) () -> @owned @callee_guaranteed () -> () {
+bb0:
+ %f = function_ref @generic_callee2 : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> ()
+ %i = alloc_stack $Int
+ %b = alloc_box $<τ_0_0> { var τ_0_0 } <String>
+ %c = partial_apply [callee_guaranteed] %f<Int, String>(%i, %b) : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> ()
+ dealloc_stack %i : $*Int
+ return %c : $@callee_guaranteed () -> ()
+}
+
+// This is the descriptor for '<τ_0_0> { var τ_0_0 } <String>' above
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (struct Swift.String)
+// CHECK-NEXT: - Metadata sources:
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (struct Swift.Int)
+// CHECK-NEXT: (sil_box
+// CHECK-NEXT: (struct Swift.String))
+// CHECK-NEXT: - Metadata sources:
+
+
+// Generic caller and generic callee -- capture types are written in terms of
+// the caller's generic parameters, and metadata bindings are present for
+// structural sub-terms of the callee's substituted generic parameters that
+// contain the caller's generic parameters.
+
+sil @generic_callee3 : $@convention(thin) <T, U> (@in_guaranteed T) -> () {
+bb0(%t: $*T):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @generic_caller3 : $@convention(thin) <A, B, C> () -> @owned @callee_guaranteed () -> () {
+bb0:
+ %f = function_ref @generic_callee3 : $@convention(thin) <T, U> (@in_guaranteed T) -> ()
+ %t = alloc_stack $Optional<@callee_guaranteed (@in_guaranteed A) -> @out B>
+ %c = partial_apply [callee_guaranteed] %f<Optional<(A) -> B>, (B, (C) -> Int)>(%t) : $@convention(thin) <T, U> (@in_guaranteed T) -> ()
+ dealloc_stack %t : $*Optional<@callee_guaranteed (@in_guaranteed A) -> @out B>
+ return %c : $@callee_guaranteed () -> ()
+}
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (bound_generic_enum Swift.Optional
+// CHECK-NEXT: (function
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple)))
+// CHECK-NEXT: - Metadata sources:
+// CHECK-NEXT: (bound_generic_enum Swift.Optional
+// CHECK-NEXT: (function
+// CHECK-NEXT: (parameters
+// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1)))
+// CHECK-NEXT: (closure_binding index=0)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
+// CHECK-NEXT: (closure_binding index=1)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=2)
+// CHECK-NEXT: (closure_binding index=2)
+
+
+// Generic caller and generic callee -- and one of the type parameters is
+// fulfilled by a thick metatype value.
+
+sil @generic_callee4 : $@convention(thin) <T, U> (@thick Optional<T>.Type) -> () {
+bb0(%t: $@thick Optional<T>.Type):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @generic_caller4 : $@convention(thin) <A, B, C> () -> @owned @callee_guaranteed () -> () {
+bb0:
+ %f = function_ref @generic_callee4 : $@convention(thin) <T, U> (@thick Optional<T>.Type) -> ()
+ %t = metatype $@thick Optional<(B) -> C>.Type
+ %c = partial_apply [callee_guaranteed] %f<(B) -> C, Int>(%t) : $@convention(thin) <T, U> (@thick Optional<T>.Type) -> ()
+ return %c : $@callee_guaranteed () -> ()
+}
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (metatype was_abstract
+// CHECK-NEXT: (bound_generic_enum Swift.Optional
+// CHECK-NEXT: (function
+// CHECK-NEXT: (parameters
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (generic_type_parameter depth=0 index=2))))
+// CHECK-NEXT: - Metadata sources:
+// CHECK-NEXT: (function
+// CHECK-NEXT: (parameters
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (generic_type_parameter depth=0 index=2))
+// CHECK-NEXT: (generic_argument index=0
+// CHECK-NEXT: (metadata_capture index=0))
+
+
+// Generic caller and generic callee -- and one of the type parameters is
+// fulfilled by the isa pointer of a class instance.
+
+class GenericClass<T, U> {}
+
+sil @generic_callee5 : $@convention(thin) <T, U, V> (@owned GenericClass<T, U>) -> () {
+bb0(%t: $GenericClass<T, U>):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @generic_caller5 : $@convention(thin) <A, B, C> (@owned GenericClass<(A, B), (B, C)>) -> @owned @callee_guaranteed () -> () {
+bb0(%g: $GenericClass<(A, B), (B, C)>):
+ %f = function_ref @generic_callee5 : $@convention(thin) <T, U, V> (@owned GenericClass<T, U>) -> ()
+ %c = partial_apply [callee_guaranteed] %f<(A, B), (B, C), (C, A)>(%g) : $@convention(thin) <T, U, V> (@owned GenericClass<T, U>) -> ()
+ return %c : $@callee_guaranteed () -> ()
+}
+
+sil_vtable GenericClass {}
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (bound_generic_class capture_descriptors.GenericClass
+// CHECK-NEXT: (tuple
+// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1))
+// CHECK-NEXT: (tuple
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=2)))
+// CHECK-NEXT: - Metadata sources:
+// CHECK-NEXT: (generic_type_parameter depth=0 index=2)
+// CHECK-NEXT: (closure_binding index=0)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
+// CHECK-NEXT: (closure_binding index=1)
+// CHECK-NEXT: (tuple
+// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1))
+// CHECK-NEXT: (generic_argument index=0
+// CHECK-NEXT: (reference_capture index=0))
+// CHECK-NEXT: (tuple
+// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
+// CHECK-NEXT: (generic_type_parameter depth=0 index=2))
+// CHECK-NEXT: (generic_argument index=1
+// CHECK-NEXT: (reference_capture index=0))
+
+
+// Pseudogeneric caller and pseudogeneric callee -- type parameters are
+// erased at runtime.
+
+sil @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> () {
+bb0(%t: $T, %u: $U):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @pseudogeneric_caller : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject, C : AnyObject> (@owned A, @owned B) -> @owned @pseudogeneric @callee_guaranteed () -> () {
+bb0(%a: $A, %b: $B):
+ %f = function_ref @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> ()
+ %c = partial_apply [callee_guaranteed] %f<A, B>(%a, %b) : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject> (@owned A, @owned B) -> ()
+ return %c : $@pseudogeneric @callee_guaranteed () -> ()
+}
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (protocol_composition any_object)
+// CHECK-NEXT: (protocol_composition any_object)
+// CHECK-NEXT: - Metadata sources:
+
+
+// Capturing lowered function types
+
+sil @function_callee : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> () {
+bb0(%thin: $@convention(thin) () -> (), %c: $@convention(c) () -> (), %block: $@convention(block) () -> (), %thick: $@convention(thick) () -> (), %method: $@convention(method) () -> (), %witness_method: $@convention(witness_method: P) (Int) -> ()):
+ %12 = tuple ()
+ return %12 : $()
+}
+
+sil @function_caller : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> @owned @callee_guaranteed () -> () {
+bb0(%thin: $@convention(thin) () -> (), %c: $@convention(c) () -> (), %block: $@convention(block) () -> (), %thick: $@convention(thick) () -> (), %method: $@convention(method) () -> (), %witness_method: $@convention(witness_method: P) (Int) -> ()):
+ %f = function_ref @function_callee : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> ()
+ %result = partial_apply [callee_guaranteed] %f(%thin, %c, %block, %thick, %method, %witness_method) : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> ()
+ return %result : $@callee_guaranteed () -> ()
+}
+
+// CHECK: - Capture types:
+// CHECK-NEXT: (function convention=thin
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple))
+// CHECK-NEXT: (function convention=c
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple))
+// CHECK-NEXT: (function convention=block
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple))
+// CHECK-NEXT: (function
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple))
+// CHECK-NEXT: (function convention=thin
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple))
+// CHECK-NEXT: (function convention=thin
+// CHECK-NEXT: (parameters)
+// CHECK-NEXT: (result
+// CHECK-NEXT: (tuple))
+// CHECK-NEXT: - Metadata sources:
+
+// Capturing opened existentials
+//
+// Not supported yet -- make sure we bail out instead of crashing.
+//
+// FIXME: Eventually, we should emit a useful capture descriptor
+// for this case.
+
+sil @existential_callee : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P {
+bb0(%0 : $*P):
+ unreachable
+}
+
+
+sil @existential_caller : $@convention(thin) (@in P) -> () {
+bb0(%0 : $*P):
+ %payload = open_existential_addr immutable_access %0 : $*P to $*@opened("2D7A8F84-2973-11E7-838D-34363BD08DA0") P
+ %f = function_ref @existential_callee : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P
+ %result = partial_apply [callee_guaranteed] %f<@opened("2D7A8F84-2973-11E7-838D-34363BD08DA0") P>() : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P
+ destroy_value %result : $@callee_guaranteed () -> @out P
+ destroy_addr %0 : $*P
+ %tuple = tuple ()
+ return %tuple : $()
+}
diff --git a/test/Runtime/linux-fatal-backtrace.swift b/test/Runtime/linux-fatal-backtrace.swift
index 6df5ec3..202983c 100644
--- a/test/Runtime/linux-fatal-backtrace.swift
+++ b/test/Runtime/linux-fatal-backtrace.swift
@@ -4,6 +4,7 @@
// REQUIRES: executable_test
// REQUIRES: OS=linux-gnu
// REQUIRES: lldb
+// REQUIRES: rdar38181372
// Backtraces are not emitted when optimizations are enabled. This test can not
// run when optimizations are enabled.
diff --git a/test/SIL/Parser/apply_with_substitution.sil b/test/SIL/Parser/apply_with_substitution.sil
index 2991489..bce0544 100644
--- a/test/SIL/Parser/apply_with_substitution.sil
+++ b/test/SIL/Parser/apply_with_substitution.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
// rdar://14443287
diff --git a/test/SIL/Parser/bound_generic.sil b/test/SIL/Parser/bound_generic.sil
index 87c0895..73e681b 100644
--- a/test/SIL/Parser/bound_generic.sil
+++ b/test/SIL/Parser/bound_generic.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
// rdar://14443287
diff --git a/test/SIL/Parser/generic_signature_with_depth.swift b/test/SIL/Parser/generic_signature_with_depth.swift
index d1ba566..6dc1e51 100644
--- a/test/SIL/Parser/generic_signature_with_depth.swift
+++ b/test/SIL/Parser/generic_signature_with_depth.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend %s -emit-silgen | %target-sil-opt | %FileCheck %s
protocol mmGeneratorType {
diff --git a/test/SIL/Parser/keypath.sil b/test/SIL/Parser/keypath.sil
index aeae6b2..f2dad3d 100644
--- a/test/SIL/Parser/keypath.sil
+++ b/test/SIL/Parser/keypath.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-sil-opt %s | %target-sil-opt | %FileCheck %s
sil_stage canonical
diff --git a/test/SIL/Parser/plus_zero_apply_with_substitution.sil b/test/SIL/Parser/plus_zero_apply_with_substitution.sil
new file mode 100644
index 0000000..a63e3c0
--- /dev/null
+++ b/test/SIL/Parser/plus_zero_apply_with_substitution.sil
@@ -0,0 +1,52 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
+
+// rdar://14443287
+sil_stage raw
+
+import Builtin
+import Swift
+
+// CHECK-LABEL: sil @_TF4test3fooFT1fGSqFT_T___T_ : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>) -> ()
+sil @_TF4test3fooFT1fGSqFT_T___T_ : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>) -> () {
+bb0(%0 : $Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>):
+ %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>> // var f // users: %2, %6, %32
+ %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>>, 0
+ store %0 to [init] %1a : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()> // id: %2
+ %3 = alloc_stack $Optional<()> // users: %22, %28, %30, %31
+ %4 = alloc_stack $() // users: %12, %22, %25
+ %5 = alloc_stack $Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()> // users: %6, %8, %10, %11, %16, %24
+ copy_addr %1a to [initialization] %5 : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()> // id: %6
+ %7 = function_ref @_TFs22_doesOptionalHaveValueU__FT1vRGSqQ___Bi1_ : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1 // user: %8
+ %8 = apply %7<() -> ()>(%5) : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1 // user: %9
+ br bb2 // id: %13
+
+bb2: // Preds: bb0
+ %14 = function_ref @_TFs17_getOptionalValueU__FT1vGSqQ___Q_ : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>) -> @out τ_0_0 // user: %16
+ %15 = alloc_stack $@callee_guaranteed (@in_guaranteed ()) -> @out () // users: %16, %17, %23
+ // CHECK: apply %{{[0-9]+}}<() -> ()>(%{{[0-9]+}}, %{{[0-9]+}}) : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>) -> @out τ_0_0
+ %16 = apply %14<() -> ()>(%15, %5) : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>) -> @out τ_0_0
+ %17 = load [take] %15 : $*@callee_guaranteed (@in_guaranteed ()) -> @out () // user: %19
+ %18 = function_ref @_TTRXFo_iT__iT__XFo__dT__ : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out ()) -> () // user: %19
+ %19 = partial_apply [callee_guaranteed] %18(%17) : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out ()) -> () // user: %20
+ %20 = apply %19() : $@callee_guaranteed () -> ()
+ %21 = function_ref @_TFs24_injectValueIntoOptionalU__FT1vQ__GSqQ__ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0> // user: %22
+ // CHECK: apply %{{[0-9]+}}<()>(%{{[0-9]+}}, %{{[0-9]+}}) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
+ %22 = apply %21<()>(%3, %4) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
+ dealloc_stack %15 : $*@callee_guaranteed (@in_guaranteed ()) -> @out () // id: %23
+ dealloc_stack %5 : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()> // id: %24
+ dealloc_stack %4 : $*() // id: %25
+ br bb4 // id: %26
+
+bb4: // Preds: bb2 bb3
+ %30 = load [trivial] %3 : $*Optional<()>
+ dealloc_stack %3 : $*Optional<()> // id: %31
+ destroy_value %1 : $<τ_0_0> { var τ_0_0 } <Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>>
+ %33 = tuple () // user: %34
+ return %33 : $() // id: %34
+}
+
+sil [transparent] @_TFs22_doesOptionalHaveValueU__FT1vRGSqQ___Bi1_ : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1
+sil [transparent] @_TFs17_getOptionalValueU__FT1vGSqQ___Q_ : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>) -> @out τ_0_0
+sil [transparent] @_TTRXFo_iT__iT__XFo__dT__ : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out ()) -> ()
+sil [transparent] @_TFs24_injectValueIntoOptionalU__FT1vQ__GSqQ__ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out Optional<τ_0_0>
diff --git a/test/SIL/Parser/plus_zero_bound_generic.sil b/test/SIL/Parser/plus_zero_bound_generic.sil
new file mode 100644
index 0000000..c535ee7
--- /dev/null
+++ b/test/SIL/Parser/plus_zero_bound_generic.sil
@@ -0,0 +1,47 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
+
+// rdar://14443287
+sil_stage raw
+
+import Builtin
+import Swift
+
+// CHECK-LABEL: sil @_TF9optional3fooFT1fGSqFT_T___T_ : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>) -> ()
+sil @_TF9optional3fooFT1fGSqFT_T___T_ : $@convention(thin) (@guaranteed Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>) -> () {
+bb0(%0 : $Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>):
+ %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>>
+ %1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>>, 0
+ store %0 to [init] %1a : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>
+ %3 = alloc_stack $Optional<()>
+ %4 = alloc_stack $()
+ %5 = alloc_stack $Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>
+ copy_addr %1a to [initialization] %5 : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>
+ // function_ref Swift._doesOptionalHaveValue <A>(v : @inout Swift.Optional<A>) -> Builtin.Int1
+ %7 = function_ref @_TFs22_doesOptionalHaveValueU__FT1vRGSqQ___Bi1_ : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1
+ // CHECK: apply %{{[0-9]+}}<() -> ()>(%{{[0-9]+}}) : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1
+ %8 = apply %7<() -> ()>(%5) : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1
+ br bb1
+
+bb1:
+ destroy_addr %5 : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>
+ dealloc_stack %5 : $*Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>
+ dealloc_stack %4 : $*()
+ br bb3
+
+bb3:
+ %27 = function_ref @_TFs26_injectNothingIntoOptionalU__FT_GSqQ__ : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
+ // CHECK: apply %{{[0-9]+}}<()>(%{{[0-9]+}}) : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
+ %28 = apply %27<()>(%3) : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
+ br bb4
+
+bb4:
+ %30 = load [trivial] %3 : $*Optional<()>
+ dealloc_stack %3 : $*Optional<()>
+ destroy_value %1 : $<τ_0_0> { var τ_0_0 } <Optional<@callee_guaranteed (@in_guaranteed ()) -> (@out ())>>
+ %33 = tuple ()
+ return %33 : $()
+}
+
+sil [transparent] @_TFs22_doesOptionalHaveValueU__FT1vRGSqQ___Bi1_ : $@convention(thin) <τ_0_0> (@inout Optional<τ_0_0>) -> Builtin.Int1
+sil [transparent] @_TFs26_injectNothingIntoOptionalU__FT_GSqQ__ : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
diff --git a/test/SIL/Parser/plus_zero_generic_signature_with_depth.swift b/test/SIL/Parser/plus_zero_generic_signature_with_depth.swift
new file mode 100644
index 0000000..f25a2a4
--- /dev/null
+++ b/test/SIL/Parser/plus_zero_generic_signature_with_depth.swift
@@ -0,0 +1,35 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend %s -emit-silgen | %target-sil-opt | %FileCheck %s
+
+protocol mmGeneratorType {
+ associatedtype Element
+}
+
+protocol mmSequenceType {
+ associatedtype Generator : mmGeneratorType
+}
+
+protocol mmCollectionType : mmSequenceType {
+}
+
+protocol mmExt : mmCollectionType {
+ mutating func extend<
+ S : mmSequenceType
+ where S.Generator.Element == Self.Generator.Element
+ > (_ seq: S)
+}
+
+// CHECK-LABEL: @$S28generic_signature_with_depth4testyxx_q_tAA5mmExtRzAaCR_9Generator_7ElementQY_AD_AERTzr0_lF : $@convention(thin) <EC1, EC2 where EC1 : mmExt, EC2 : mmExt, EC1.Generator.Element == EC2.Generator.Element> (@in_guaranteed EC1, @in_guaranteed EC2) -> @out EC1 {
+// CHECK: witness_method $EC1, #mmExt.extend!1 : {{.*}} : $@convention(witness_method: mmExt) <τ_0_0 where τ_0_0 : mmExt><τ_1_0 where τ_1_0 : mmSequenceType, τ_0_0.Generator.Element == τ_1_0.Generator.Element> (@in_guaranteed τ_1_0, @inout τ_0_0) -> ()
+// CHECK: apply {{%[0-9]+}}<EC1, EC2>({{%[0-9]+}}, {{%[0-9]+}}) : $@convention(witness_method: mmExt) <τ_0_0 where τ_0_0 : mmExt><τ_1_0 where τ_1_0 : mmSequenceType, τ_0_0.Generator.Element == τ_1_0.Generator.Element> (@in_guaranteed τ_1_0, @inout τ_0_0) -> ()
+
+func test<
+ EC1 : mmExt,
+ EC2 : mmExt
+ where EC1.Generator.Element == EC2.Generator.Element
+>
+(_ lhs: EC1, _ rhs: EC2) -> EC1 {
+ var lhs = lhs
+ lhs.extend(rhs)
+ return lhs
+}
diff --git a/test/SIL/Parser/plus_zero_keypath.sil b/test/SIL/Parser/plus_zero_keypath.sil
new file mode 100644
index 0000000..7c9b0a0
--- /dev/null
+++ b/test/SIL/Parser/plus_zero_keypath.sil
@@ -0,0 +1,184 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-sil-opt %s | %target-sil-opt | %FileCheck %s
+
+sil_stage canonical
+
+import Swift
+
+struct S: Hashable {
+ var x: Int
+ let y: String
+ var z: C
+
+ var hashValue: Int { get }
+ static func ==(x: S, y: S) -> Bool
+}
+class C: Hashable {
+ final var x: Int
+ final let y: String
+ final var z: S
+
+ init()
+ var overridable: Int {
+ get set
+ }
+
+ var hashValue: Int { get }
+ static func ==(x: C, y: C) -> Bool
+}
+
+protocol P {}
+protocol Q {}
+protocol R {}
+
+struct Gen<A: P, B: Q, C: R> {
+ var x: A
+ let y: B
+ var z: C
+}
+
+public struct External<T> {
+ var ro: T
+
+ subscript<U: Hashable>(ro _: U) -> T { get }
+}
+
+// CHECK-LABEL: sil shared @stored_properties
+sil shared @stored_properties : $@convention(thin) () -> () {
+entry:
+ // CHECK: keypath $WritableKeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
+ %a = keypath $WritableKeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
+ // CHECK: keypath $ReferenceWritableKeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
+ %b = keypath $ReferenceWritableKeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
+ // CHECK: keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
+ %c = keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
+ // CHECK: keypath $ReferenceWritableKeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
+ %d = keypath $ReferenceWritableKeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil shared @stored_properties_generic
+sil shared @stored_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> () {
+entry:
+ // CHECK: keypath $WritableKeyPath<Gen<D, E, F>, D>, <τ_0_0, τ_0_1, τ_0_2 where {{.*}}> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; stored_property #Gen.x : $τ_0_0) <D, E, F>
+ %a = keypath $WritableKeyPath<Gen<D,E,F>, D>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; stored_property #Gen.x : $G) <D, E, F>
+ // CHECK: keypath $KeyPath<Gen<D, E, F>, E>, <τ_0_0, τ_0_1, τ_0_2 where {{.*}}> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; stored_property #Gen.y : $τ_0_1) <D, E, F>
+ %b = keypath $KeyPath<Gen<D,E,F>, E>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; stored_property #Gen.y : $H) <D, E, F>
+
+ return undef : $()
+}
+
+sil @id_a : $@convention(thin) () -> ()
+sil @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int
+sil @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ()
+sil @get_c_int : $@convention(thin) (@in_guaranteed C) -> @out Int
+sil @set_c_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ()
+sil @get_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> @out @callee_guaranteed (@in_guaranteed C) -> @out C
+sil @set_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed C) -> @out C, @in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> ()
+sil @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int
+sil @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> ()
+sil @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int
+sil @get_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed A, UnsafeRawPointer) -> @out C
+sil @set_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed C, @in_guaranteed A, UnsafeRawPointer) -> ()
+sil @gen_subs_eq : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @gen_subs_hash : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer) -> Int
+
+
+// CHECK-LABEL: sil shared @computed_properties
+sil shared @computed_properties : $@convention(thin) () -> () {
+entry:
+ // CHECK: keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int)
+ %a = keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int)
+ // CHECK: keypath $WritableKeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int, setter @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ())
+ %b = keypath $WritableKeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int, setter @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ())
+ // CHECK: keypath $WritableKeyPath<(S) -> S, (C) -> C>, (root $(S) -> S; settable_property $(C) -> C, id @id_a : $@convention(thin) () -> (), getter @get_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> @out @callee_guaranteed (@in_guaranteed C) -> @out C, setter @set_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed C) -> @out C, @in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> ())
+ %c = keypath $WritableKeyPath<(S) -> S, (C) -> C>, (root $(S) -> S; settable_property $(C) -> C, id @id_a : $@convention(thin) () -> (), getter @get_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> @out @callee_guaranteed (@in_guaranteed C) -> @out C, setter @set_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed C) -> @out C, @in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> ())
+ // CHECK: keypath $WritableKeyPath<C, Int>, (root $C; settable_property $Int, id #C.overridable!getter.1 : (C) -> () -> Int, getter @get_c_int : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @set_c_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+ %d = keypath $WritableKeyPath<C, Int>, (root $C; settable_property $Int, id #C.overridable!getter.1 : (C) -> () -> Int, getter @get_c_int : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @set_c_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+
+ return undef : $()
+}
+
+sil @get_gen_a : $@convention(thin) <X1: P, Y1: Q, Z1: R> (@in_guaranteed Gen<X1, Y1, Z1>) -> @out X1
+sil @set_gen_a : $@convention(thin) <X2: P, Y2: Q, Z2: R> (@in_guaranteed X2, @in_guaranteed Gen<X2, Y2, Z2>) -> ()
+
+// CHECK-LABEL: sil shared @computed_properties_generic
+sil shared @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> () {
+entry:
+ // CHECK: keypath $KeyPath<Gen<D, E, F>, D>, <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; settable_property $τ_0_0, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> @out τ_0_0, setter @set_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed τ_0_0, @in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> ()) <D, E, F>
+ %a = keypath $KeyPath<Gen<D, E, F>, D>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; settable_property $G, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <X3: P, Y3: Q, Z3: R> (@in_guaranteed Gen<X3, Y3, Z3>) -> @out X3, setter @set_gen_a : $@convention(thin) <X4: P, Y4: Q, Z4: R> (@in_guaranteed X4, @in_guaranteed Gen<X4, Y4, Z4>) -> ()) <D, E, F>
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil @optional
+sil @optional : $@convention(thin) () -> () {
+entry:
+ // CHECK: keypath $KeyPath<Optional<Int>, Optional<Int>>, (root $Optional<Int>; optional_chain : $Int; optional_wrap : $Optional<Int>)
+ %a = keypath $KeyPath<Optional<Int>, Optional<Int>>, (root $Optional<Int>; optional_chain : $Int; optional_wrap : $Optional<Int>)
+ // CHECK: keypath $KeyPath<Optional<Int>, Int>, (root $Optional<Int>; optional_force : $Int)
+ %b = keypath $KeyPath<Optional<Int>, Int>, (root $Optional<Int>; optional_force : $Int)
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil @indexes
+sil @indexes : $@convention(thin) (S, C) -> () {
+// CHECK: bb0([[S:%.*]] : $S, [[C:%.*]] : $C):
+entry(%s : $S, %c : $C):
+ // CHECK: keypath $KeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int, setter @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> (), indices [%$0 : $S : $S, %$1 : $C : $C], indices_equals @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int) ([[S]], [[C]])
+ %a = keypath $KeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int, setter @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> (), indices [%$0 : $S : $S, %$1 : $C : $C], indices_equals @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int) (%s, %c)
+ // CHECK: [[T:%.*]] = alloc_stack
+ %t = alloc_stack $S
+ // CHECK: [[D:%.*]] = alloc_stack
+ %d = alloc_stack $C
+ // CHECK: keypath $KeyPath<S, Int>, <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (root $τ_0_0; settable_property $τ_0_2, id @id_a : $@convention(thin) () -> (), getter @get_gen_int_subs : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (@in_guaranteed τ_0_0, UnsafeRawPointer) -> @out τ_0_2, setter @set_gen_int_subs : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (@in_guaranteed τ_0_2, @in_guaranteed τ_0_0, UnsafeRawPointer) -> (), indices [%$0 : $τ_0_0 : $*τ_0_0, %$1 : $τ_0_1 : $*τ_0_1], indices_equals @gen_subs_eq : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @gen_subs_hash : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (UnsafeRawPointer) -> Int) <S, C, Int> ([[T]], [[D]])
+ %b = keypath $KeyPath<S, Int>, <τ_0_0: Hashable, Y: Hashable, Z: Hashable> (root $τ_0_0; settable_property $Z, id @id_a : $@convention(thin) () -> (), getter @get_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed A, UnsafeRawPointer) -> @out C, setter @set_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed C, @in_guaranteed A, UnsafeRawPointer) -> (), indices [%$0 : $τ_0_0 : $*τ_0_0, %$1 : $Y : $*Y], indices_equals @gen_subs_eq : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @gen_subs_hash : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer) -> Int) <S, C, Int> (%t, %d)
+
+ dealloc_stack %d : $*C
+ dealloc_stack %t : $*S
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil @external
+sil @external : $@convention(thin) <A, B: Hashable> (@in_guaranteed B) -> () {
+entry(%z : $*B):
+ // CHECK: %1 = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
+ %a = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
+
+ // CHECK: %2 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1, τ_0_2> (root $External<τ_0_2>; external #External.ro<τ_0_2> : $τ_0_2) <A, A, A>
+ %b = keypath $KeyPath<External<A>, A>, <C, D, E> (root $External<E>; external #External.ro <E> : $E) <A, A, A>
+
+ // CHECK: %3 = keypath $KeyPath<External<Int>, Int>, <τ_0_0> (root $External<τ_0_0>; external #External.ro<τ_0_0> : $τ_0_0) <Int>
+ %c = keypath $KeyPath<External<Int>, Int>, <F> (root $External<F>; external #External.ro <F> : $F) <Int>
+
+ // CHECK: %4 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; external #External.subscript<τ_0_1, τ_0_0>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_1) <B, A> (%0)
+ %d = keypath $KeyPath<External<A>, A>, <G: Hashable, H> (root $External<H>; external #External.subscript <H, G> [%$0 : $G : $*G] : $H) <B, A> (%z)
+
+ return undef : $()
+}
+
+sil @get_external_subscript : $@convention(thin) <T, U: Hashable> (@in_guaranteed External<T>, UnsafeRawPointer) -> @out T
+sil @equals_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @hash_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer) -> Int
+
+// CHECK-LABEL: sil_property #External.ro<τ_0_0> (stored_property #External.ro : $τ_0_0)
+sil_property #External.ro <T> (stored_property #External.ro : $T)
+
+// CHECK-LABEL: sil_property #External.subscript<τ_0_0><τ_1_0 where τ_1_0 : Hashable> (gettable_property $τ_0_0,
+// CHECK-SAME: id @id_a : $@convention(thin) () -> (),
+// CHECK-SAME: getter @get_external_subscript : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : Hashable> (@in_guaranteed External<τ_0_0>, UnsafeRawPointer) -> @out τ_0_0,
+// CHECK-SAME: indices [%$0 : $τ_1_0 : $*τ_1_0],
+// CHECK-SAME: indices_equals @equals_external_subscript : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+// CHECK-SAME: indices_hash @hash_external_subscript : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : Hashable> (UnsafeRawPointer) -> Int)
+sil_property #External.subscript <T><U: Hashable> (gettable_property $T,
+ id @id_a : $@convention(thin) () -> (),
+ getter @get_external_subscript : $@convention(thin) <T, U: Hashable> (@in_guaranteed External<T>, UnsafeRawPointer) -> @out T,
+ indices [%$0 : $U : $*U],
+ indices_equals @equals_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @hash_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer) -> Int)
+
+
diff --git a/test/SIL/Serialization/deserialize_generic.sil b/test/SIL/Serialization/deserialize_generic.sil
index bbd1533..4d22ac5 100644
--- a/test/SIL/Serialization/deserialize_generic.sil
+++ b/test/SIL/Serialization/deserialize_generic.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_generic.swift
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -linker -I %t %s | %FileCheck %s
diff --git a/test/SIL/Serialization/deserialize_generic_marker.sil b/test/SIL/Serialization/deserialize_generic_marker.sil
index eebbde4..b63ef5c 100644
--- a/test/SIL/Serialization/deserialize_generic_marker.sil
+++ b/test/SIL/Serialization/deserialize_generic_marker.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_generic_marker.swift
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -linker -I %t %s | %FileCheck %s
diff --git a/test/SIL/Serialization/keypath.sil b/test/SIL/Serialization/keypath.sil
index 684f57d..73a927d 100644
--- a/test/SIL/Serialization/keypath.sil
+++ b/test/SIL/Serialization/keypath.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
// RUN: %empty-directory(%t)
// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name boxes
diff --git a/test/SIL/Serialization/plus_zero_deserialize_generic.sil b/test/SIL/Serialization/plus_zero_deserialize_generic.sil
new file mode 100644
index 0000000..d8aa071
--- /dev/null
+++ b/test/SIL/Serialization/plus_zero_deserialize_generic.sil
@@ -0,0 +1,26 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_generic.swift
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -linker -I %t %s | %FileCheck %s
+
+// Make sure that SILFunctionType with GenericSignature can match up with
+// SILFunctionType deserialized from module.
+
+sil_stage raw
+
+import def_generic
+import Builtin
+import Swift
+
+// CHECK-LABEL: sil @top_level_code
+// CHECK: function_ref @$S11def_generic1AC23convertFromArrayLiteralyACyxGxd_tF
+sil @top_level_code : $@convention(thin) () -> () {
+bb0:
+ %3 = function_ref @$S11def_generic1AC23convertFromArrayLiteralyACyxGxd_tF : $@convention(method) <T> (@guaranteed Array<T>, @guaranteed A<T>) -> @owned A<T>
+ %0 = tuple () // user: %1
+ return %0 : $() // id: %1
+}
+
+// Make sure the function body is deserialized.
+// CHECK-LABEL: sil public_external [serialized] [canonical] @$S11def_generic1AC23convertFromArrayLiteralyACyxGxd_tF : $@convention(method) <T> (@guaranteed Array<T>, @guaranteed A<T>) -> @owned A<T> {
+sil @$S11def_generic1AC23convertFromArrayLiteralyACyxGxd_tF : $@convention(method) <T> (@guaranteed Array<T>, @guaranteed A<T>) -> @owned A<T>
diff --git a/test/SIL/Serialization/plus_zero_deserialize_generic_marker.sil b/test/SIL/Serialization/plus_zero_deserialize_generic_marker.sil
new file mode 100644
index 0000000..bb3984d
--- /dev/null
+++ b/test/SIL/Serialization/plus_zero_deserialize_generic_marker.sil
@@ -0,0 +1,24 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_generic_marker.swift
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -linker -I %t %s | %FileCheck %s
+
+// Make sure that SILFunctionType with GenericSignature can match up with
+// SILFunctionType deserialized from module.
+
+import def_generic_marker
+import Builtin
+import Swift
+
+// CHECK-LABEL: sil @top_level_code
+// CHECK: function_ref @$S18def_generic_marker4testyxx_q_tAA16mmCollectionTypeRzAaCR_9Generator_7ElementQY_AD_AERTzr0_lF : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : mmCollectionType, τ_0_1 : mmCollectionType, τ_0_0.Generator.Element == τ_0_1.Generator.Element> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> @out τ_0_0
+sil @top_level_code : $@convention(thin) () -> () {
+bb0:
+ %43 = function_ref @$S18def_generic_marker4testyxx_q_tAA16mmCollectionTypeRzAaCR_9Generator_7ElementQY_AD_AERTzr0_lF : $@convention(thin) <EC1, EC2 where EC1 : mmCollectionType, EC2 : mmCollectionType, EC1.Generator.Element == EC2.Generator.Element> (@in_guaranteed EC1, @in_guaranteed EC2) -> @out EC1
+ %0 = tuple ()
+ return %0 : $()
+}
+
+// Make sure the function body is deserialized.
+// CHECK-LABEL: @$S18def_generic_marker4testyxx_q_tAA16mmCollectionTypeRzAaCR_9Generator_7ElementQY_AD_AERTzr0_lF : $@convention(thin) <EC1, EC2 where EC1 : mmCollectionType, EC2 : mmCollectionType, EC1.Generator.Element == EC2.Generator.Element> (@in_guaranteed EC1, @in_guaranteed EC2) -> @out EC1 {
+sil @$S18def_generic_marker4testyxx_q_tAA16mmCollectionTypeRzAaCR_9Generator_7ElementQY_AD_AERTzr0_lF : $@convention(thin) <EC1, EC2 where EC1 : mmCollectionType, EC2 : mmCollectionType, EC1.Generator.Element == EC2.Generator.Element> (@in_guaranteed EC1, @in_guaranteed EC2) -> @out EC1
diff --git a/test/SIL/Serialization/plus_zero_keypath.sil b/test/SIL/Serialization/plus_zero_keypath.sil
new file mode 100644
index 0000000..00a9747
--- /dev/null
+++ b/test/SIL/Serialization/plus_zero_keypath.sil
@@ -0,0 +1,200 @@
+// REQUIRES: plus_zero_runtime
+// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
+// RUN: %empty-directory(%t)
+// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name boxes
+// RUN: %target-sil-opt %t/tmp.sib -o %t/tmp.2.sib -module-name boxes
+// RUN: %target-sil-opt %t/tmp.2.sib -module-name boxes | %FileCheck %s
+
+sil_stage canonical
+
+import Swift
+
+struct S: Hashable {
+ var x: Int
+ let y: String
+ var z: C
+
+ var hashValue: Int { get }
+ static func ==(x: S, y: S) -> Bool
+}
+class C: Hashable {
+ final var x: Int
+ final let y: String
+ final var z: S
+
+ init()
+ var overridable: Int {
+ get set
+ }
+
+ var hashValue: Int { get }
+ static func ==(x: C, y: C) -> Bool
+}
+
+protocol P {}
+protocol Q {}
+protocol R {}
+
+struct Gen<A: P, B: Q, C: R> {
+ var x: A
+ let y: B
+ var z: C
+}
+
+public struct External<T> {
+ var ro: T { get }
+
+ subscript<U: Hashable>(ro _: U) -> T { get }
+}
+
+// CHECK-LABEL: sil shared [serialized] @stored_properties
+sil shared [serialized] @stored_properties : $@convention(thin) () -> () {
+entry:
+ // CHECK: keypath $WritableKeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
+ %a = keypath $WritableKeyPath<S, Int>, (root $S; stored_property #S.x : $Int)
+ // CHECK: keypath $ReferenceWritableKeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
+ %b = keypath $ReferenceWritableKeyPath<C, Int>, (root $C; stored_property #C.x : $Int)
+ // CHECK: keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
+ %c = keypath $KeyPath<S, String>, (root $S; stored_property #S.y : $String)
+ // CHECK: keypath $ReferenceWritableKeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
+ %d = keypath $ReferenceWritableKeyPath<S, Int>, (root $S; stored_property #S.z : $C; stored_property #C.x : $Int)
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil shared [serialized] @stored_properties_generic
+sil shared [serialized] @stored_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> () {
+entry:
+ // CHECK: keypath $WritableKeyPath<Gen<D, E, F>, D>, <τ_0_0, τ_0_1, τ_0_2 where {{.*}}> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; stored_property #Gen.x : $τ_0_0) <D, E, F>
+ %a = keypath $WritableKeyPath<Gen<D,E,F>, D>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; stored_property #Gen.x : $G) <D, E, F>
+ // CHECK: keypath $KeyPath<Gen<D, E, F>, E>, <τ_0_0, τ_0_1, τ_0_2 where {{.*}}> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; stored_property #Gen.y : $τ_0_1) <D, E, F>
+ %b = keypath $KeyPath<Gen<D,E,F>, E>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; stored_property #Gen.y : $H) <D, E, F>
+
+ return undef : $()
+}
+
+sil @id_a : $@convention(thin) () -> ()
+sil @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int
+sil @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ()
+sil @get_c_int : $@convention(thin) (@in_guaranteed C) -> @out Int
+sil @set_c_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ()
+sil @get_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> @out @callee_guaranteed (@in_guaranteed C) -> @out C
+sil @set_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed C) -> @out C, @in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> ()
+sil @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int
+sil @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> ()
+sil @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int
+sil @get_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed A, UnsafeRawPointer) -> @out C
+sil @set_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed C, @in_guaranteed A, UnsafeRawPointer) -> ()
+sil @gen_subs_eq : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil @gen_subs_hash : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer) -> Int
+
+// CHECK-LABEL: sil shared [serialized] @computed_properties
+sil shared [serialized] @computed_properties : $@convention(thin) () -> () {
+entry:
+ // CHECK: keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int)
+ %a = keypath $KeyPath<S, Int>, (root $S; gettable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int)
+ // CHECK: keypath $WritableKeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int, setter @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ())
+ %b = keypath $WritableKeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int : $@convention(thin) (@in_guaranteed S) -> @out Int, setter @set_s_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S) -> ())
+ // CHECK: keypath $WritableKeyPath<(S) -> S, (C) -> C>, (root $(S) -> S; settable_property $(C) -> C, id @id_a : $@convention(thin) () -> (), getter @get_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> @out @callee_guaranteed (@in_guaranteed C) -> @out C, setter @set_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed C) -> @out C, @in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> ())
+ %c = keypath $WritableKeyPath<(S) -> S, (C) -> C>, (root $(S) -> S; settable_property $(C) -> C, id @id_a : $@convention(thin) () -> (), getter @get_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> @out @callee_guaranteed (@in_guaranteed C) -> @out C, setter @set_fns_fnc : $@convention(thin) (@in_guaranteed @callee_guaranteed (@in_guaranteed C) -> @out C, @in_guaranteed @callee_guaranteed (@in_guaranteed S) -> @out S) -> ())
+ // CHECK: keypath $WritableKeyPath<C, Int>, (root $C; settable_property $Int, id #C.overridable!getter.1 : (C) -> () -> Int, getter @get_c_int : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @set_c_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+ %d = keypath $WritableKeyPath<C, Int>, (root $C; settable_property $Int, id #C.overridable!getter.1 : (C) -> () -> Int, getter @get_c_int : $@convention(thin) (@in_guaranteed C) -> @out Int, setter @set_c_int : $@convention(thin) (@in_guaranteed Int, @in_guaranteed C) -> ())
+
+ return undef : $()
+}
+
+sil @get_gen_a : $@convention(thin) <X1: P, Y1: Q, Z1: R> (@in_guaranteed Gen<X1, Y1, Z1>) -> @out X1
+sil @set_gen_a : $@convention(thin) <X2: P, Y2: Q, Z2: R> (@in_guaranteed X2, @in_guaranteed Gen<X2, Y2, Z2>) -> ()
+
+// CHECK-LABEL: sil shared [serialized] @computed_properties_generic
+sil shared [serialized] @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> () {
+entry:
+ // CHECK: keypath $KeyPath<Gen<D, E, F>, D>, <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (root $Gen<τ_0_0, τ_0_1, τ_0_2>; settable_property $τ_0_0, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> @out τ_0_0, setter @set_gen_a : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P, τ_0_1 : Q, τ_0_2 : R> (@in_guaranteed τ_0_0, @in_guaranteed Gen<τ_0_0, τ_0_1, τ_0_2>) -> ()) <D, E, F>
+ %a = keypath $KeyPath<Gen<D, E, F>, D>, <G: P, H: Q, I: R> (root $Gen<G, H, I>; settable_property $G, id @id_a : $@convention(thin) () -> (), getter @get_gen_a : $@convention(thin) <X3: P, Y3: Q, Z3: R> (@in_guaranteed Gen<X3, Y3, Z3>) -> @out X3, setter @set_gen_a : $@convention(thin) <X4: P, Y4: Q, Z4: R> (@in_guaranteed X4, @in_guaranteed Gen<X4, Y4, Z4>) -> ()) <D, E, F>
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil shared [serialized] @optional
+sil shared [serialized] @optional : $@convention(thin) () -> () {
+entry:
+ // CHECK: keypath $KeyPath<Optional<Int>, Optional<Int>>, (root $Optional<Int>; optional_chain : $Int; optional_wrap : $Optional<Int>)
+ %a = keypath $KeyPath<Optional<Int>, Optional<Int>>, (root $Optional<Int>; optional_chain : $Int; optional_wrap : $Optional<Int>)
+ // CHECK: keypath $KeyPath<Optional<Int>, Int>, (root $Optional<Int>; optional_force : $Int)
+ %b = keypath $KeyPath<Optional<Int>, Int>, (root $Optional<Int>; optional_force : $Int)
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil shared [serialized] @indexes
+sil shared [serialized] @indexes : $@convention(thin) (S, C) -> () {
+// CHECK: bb0([[S:%.*]] : $S, [[C:%.*]] : $C):
+entry(%s : $S, %c : $C):
+ // CHECK: keypath $KeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int, setter @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> (), indices [%$0 : $S : $S, %$1 : $C : $C], indices_equals @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int) ([[S]], [[C]])
+ %a = keypath $KeyPath<S, Int>, (root $S; settable_property $Int, id @id_a : $@convention(thin) () -> (), getter @get_s_int_subs : $@convention(thin) (@in_guaranteed S, UnsafeRawPointer) -> @out Int, setter @set_s_int_subs : $@convention(thin) (@in_guaranteed Int, @in_guaranteed S, UnsafeRawPointer) -> (), indices [%$0 : $S : $S, %$1 : $C : $C], indices_equals @subs_eq : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @subs_hash : $@convention(thin) (UnsafeRawPointer) -> Int) (%s, %c)
+ // CHECK: [[T:%.*]] = alloc_stack
+ %t = alloc_stack $S
+ // CHECK: [[D:%.*]] = alloc_stack
+ %d = alloc_stack $C
+ // CHECK: keypath $KeyPath<S, Int>, <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (root $τ_0_0; settable_property $τ_0_2, id @id_a : $@convention(thin) () -> (), getter @get_gen_int_subs : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (@in_guaranteed τ_0_0, UnsafeRawPointer) -> @out τ_0_2, setter @set_gen_int_subs : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (@in_guaranteed τ_0_2, @in_guaranteed τ_0_0, UnsafeRawPointer) -> (), indices [%$0 : $τ_0_0 : $*τ_0_0, %$1 : $τ_0_1 : $*τ_0_1], indices_equals @gen_subs_eq : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @gen_subs_hash : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : Hashable, τ_0_1 : Hashable, τ_0_2 : Hashable> (UnsafeRawPointer) -> Int) <S, C, Int> ([[T]], [[D]])
+ %b = keypath $KeyPath<S, Int>, <τ_0_0: Hashable, Y: Hashable, Z: Hashable> (root $τ_0_0; settable_property $Z, id @id_a : $@convention(thin) () -> (), getter @get_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed A, UnsafeRawPointer) -> @out C, setter @set_gen_int_subs : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (@in_guaranteed C, @in_guaranteed A, UnsafeRawPointer) -> (), indices [%$0 : $τ_0_0 : $*τ_0_0, %$1 : $Y : $*Y], indices_equals @gen_subs_eq : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @gen_subs_hash : $@convention(thin) <A: Hashable, B: Hashable, C: Hashable> (UnsafeRawPointer) -> Int) <S, C, Int> (%t, %d)
+
+ dealloc_stack %d : $*C
+ dealloc_stack %t : $*S
+
+ return undef : $()
+}
+
+// CHECK-LABEL: sil shared [serialized] @external
+sil shared [serialized] @external : $@convention(thin) <A, B: Hashable> (@in_guaranteed B) -> () {
+entry(%z : $*B):
+ // CHECK: %1 = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
+ %a = keypath $KeyPath<External<Int>, Int>, (root $External<Int>; external #External.ro<Int> : $Int)
+
+ // CHECK: %2 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1, τ_0_2> (root $External<τ_0_2>; external #External.ro<τ_0_2> : $τ_0_2) <A, A, A>
+ %b = keypath $KeyPath<External<A>, A>, <C, D, E> (root $External<E>; external #External.ro <E> : $E) <A, A, A>
+
+ // CHECK: %3 = keypath $KeyPath<External<Int>, Int>, <τ_0_0> (root $External<τ_0_0>; external #External.ro<τ_0_0> : $τ_0_0) <Int>
+ %c = keypath $KeyPath<External<Int>, Int>, <F> (root $External<F>; external #External.ro <F> : $F) <Int>
+
+ // CHECK: %4 = keypath $KeyPath<External<A>, A>, <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (root $External<τ_0_1>; external #External.subscript<τ_0_1, τ_0_0>[%$0 : $τ_0_0 : $*τ_0_0] : $τ_0_1) <B, A> (%0)
+ %d = keypath $KeyPath<External<A>, A>, <G: Hashable, H> (root $External<H>; external #External.subscript <H, G> [%$0 : $G : $*G] : $H) <B, A> (%z)
+
+ return undef : $()
+}
+
+sil [serialized] @serialize_all : $@convention(thin) () -> () {
+entry:
+ %0 = function_ref @stored_properties : $@convention(thin) () -> ()
+ %1 = function_ref @stored_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
+ %2 = function_ref @computed_properties : $@convention(thin) () -> ()
+ %3 = function_ref @computed_properties_generic : $@convention(thin) <D: P, E: Q, F: R> () -> ()
+ %4 = function_ref @optional : $@convention(thin) () -> ()
+ %5 = function_ref @indexes : $@convention(thin) (S, C) -> ()
+ %6 = function_ref @external : $@convention(thin) <A, B: Hashable> (@in_guaranteed B) -> ()
+
+ unreachable
+}
+
+sil [serialized] @get_external_subscript : $@convention(thin) <T, U: Hashable> (@in_guaranteed External<T>, UnsafeRawPointer) -> @out T
+sil [serialized] @equals_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool
+sil [serialized] @hash_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer) -> Int
+
+// CHECK-LABEL: sil_property [serialized] #External.ro<τ_0_0> (stored_property #External.ro : $τ_0_0)
+sil_property [serialized] #External.ro <T> (stored_property #External.ro : $T)
+
+// CHECK-LABEL: sil_property [serialized] #External.subscript<τ_0_0><τ_1_0 where τ_1_0 : Hashable> (gettable_property $τ_0_0,
+// CHECK-SAME: id @id_a : $@convention(thin) () -> (),
+// CHECK-SAME: getter @get_external_subscript : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : Hashable> (@in_guaranteed External<τ_0_0>, UnsafeRawPointer) -> @out τ_0_0,
+// CHECK-SAME: indices [%$0 : $τ_1_0 : $*τ_1_0],
+// CHECK-SAME: indices_equals @equals_external_subscript : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+// CHECK-SAME: indices_hash @hash_external_subscript : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_1 : Hashable> (UnsafeRawPointer) -> Int)
+sil_property [serialized] #External.subscript <T><U: Hashable> (gettable_property $T,
+ id @id_a : $@convention(thin) () -> (),
+ getter @get_external_subscript : $@convention(thin) <T, U: Hashable> (@in_guaranteed External<T>, UnsafeRawPointer) -> @out T,
+ indices [%$0 : $U : $*U],
+ indices_equals @equals_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer, UnsafeRawPointer) -> Bool,
+ indices_hash @hash_external_subscript : $@convention(thin) <T, U: Hashable> (UnsafeRawPointer) -> Int)
+
+
diff --git a/test/SILGen/access_marker_gen.swift b/test/SILGen/access_marker_gen.swift
index fff4558..974aa66 100644
--- a/test/SILGen/access_marker_gen.swift
+++ b/test/SILGen/access_marker_gen.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-as-library -Xllvm -sil-full-demangle -enforce-exclusivity=checked -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func modify<T>(_ x: inout T) {}
diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift
index 06982c9..5a85c8d 100644
--- a/test/SILGen/accessors.swift
+++ b/test/SILGen/accessors.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// Hold a reference to do to magically become non-POD.
@@ -65,9 +66,8 @@
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
-// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> ()
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed A, @thick A.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
-// SEMANTIC SIL TODO: This is an issue caused by the callback for materializeForSet in the class case taking the value as @inout when it should really take it as @guaranteed.
// CHECK-NEXT: store_borrow [[BORROWED_ARG_LHS]] to [[TEMP2]] : $*A
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick A.Type
// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*OrdinarySub to $Builtin.RawPointer
@@ -128,7 +128,7 @@
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
-// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store_borrow [[BORROWED_ARG_RHS]] to [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
@@ -154,7 +154,7 @@
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
-// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store_borrow [[BORROWED_ARG_LHS]] to [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
diff --git a/test/SILGen/address_only_types.swift b/test/SILGen/address_only_types.swift
index 3d771a8..bc02604 100644
--- a/test/SILGen/address_only_types.swift
+++ b/test/SILGen/address_only_types.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -parse-as-library -parse-stdlib -emit-silgen %s | %FileCheck %s
precedencegroup AssignmentPrecedence { assignment: true }
diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift
index 76fe58a..a1186cd 100644
--- a/test/SILGen/addressors.swift
+++ b/test/SILGen/addressors.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-sil %s | %FileCheck %s
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-silgen %s | %FileCheck %s -check-prefix=SILGEN
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-ir %s
@@ -354,7 +355,7 @@
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
// materializeForSet callback for G.value
-// CHECK-LABEL: sil private [transparent] @$S10addressors1GC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () {
+// CHECK-LABEL: sil private [transparent] @$S10addressors1GC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed G, @thick G.Type) -> () {
// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*G, [[SELFTYPE:%3]] : $@thick G.Type):
// CHECK: [[T0:%.*]] = project_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
// CHECK: [[OWNER:%.*]] = load [[T0]]
@@ -475,7 +476,7 @@
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
// materializeForSet callback for I.value
-// CHECK-LABEL: sil private [transparent] @$S10addressors1IC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () {
+// CHECK-LABEL: sil private [transparent] @$S10addressors1IC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed I, @thick I.Type) -> () {
// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*I, [[SELFTYPE:%3]] : $@thick I.Type):
// CHECK: [[T0:%.*]] = project_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
// CHECK: [[OWNER:%.*]] = load [[T0]]
diff --git a/test/SILGen/apply_abstraction_nested.swift b/test/SILGen/apply_abstraction_nested.swift
index df737ad..6ea71bd 100644
--- a/test/SILGen/apply_abstraction_nested.swift
+++ b/test/SILGen/apply_abstraction_nested.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen %s | %FileCheck %s
infix operator ~> { precedence 255 associativity left }
diff --git a/test/SILGen/argument_labels.swift b/test/SILGen/argument_labels.swift
index 629cb93..4702392 100644
--- a/test/SILGen/argument_labels.swift
+++ b/test/SILGen/argument_labels.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
public struct X { }
diff --git a/test/SILGen/argument_shuffle_swift3.swift b/test/SILGen/argument_shuffle_swift3.swift
index 9a671c8..d28323c 100644
--- a/test/SILGen/argument_shuffle_swift3.swift
+++ b/test/SILGen/argument_shuffle_swift3.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s -swift-version 3 | %FileCheck %s
func fn(_: Any) {}
diff --git a/test/SILGen/array_literal_abstraction.swift b/test/SILGen/array_literal_abstraction.swift
index 5a72c8f..074cf18 100644
--- a/test/SILGen/array_literal_abstraction.swift
+++ b/test/SILGen/array_literal_abstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
// Verify that reabstraction happens when forming container literals.
diff --git a/test/SILGen/auto_closures.swift b/test/SILGen/auto_closures.swift
index ae73d29..f87040c 100644
--- a/test/SILGen/auto_closures.swift
+++ b/test/SILGen/auto_closures.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-stdlib -emit-silgen %s | %FileCheck %s
struct Bool {}
diff --git a/test/SILGen/borrow.swift b/test/SILGen/borrow.swift
index 12789f0..35c3c73 100644
--- a/test/SILGen/borrow.swift
+++ b/test/SILGen/borrow.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-silgen %s | %FileCheck %s
import Swift
diff --git a/test/SILGen/boxed_existentials.swift b/test/SILGen/boxed_existentials.swift
index ae640f1..92210e8 100644
--- a/test/SILGen/boxed_existentials.swift
+++ b/test/SILGen/boxed_existentials.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen %s | %FileCheck %s
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen %s | %FileCheck %s --check-prefix=GUARANTEED
diff --git a/test/SILGen/call_chain_reabstraction.swift b/test/SILGen/call_chain_reabstraction.swift
index 22b8a82..bca5a66 100644
--- a/test/SILGen/call_chain_reabstraction.swift
+++ b/test/SILGen/call_chain_reabstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
struct A {
diff --git a/test/SILGen/capture_typed_boxes.swift b/test/SILGen/capture_typed_boxes.swift
index b19759f..50a806e 100644
--- a/test/SILGen/capture_typed_boxes.swift
+++ b/test/SILGen/capture_typed_boxes.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func foo(_ x: Int) -> () -> Int {
diff --git a/test/SILGen/casts.swift b/test/SILGen/casts.swift
index 8a429ea..74e7718 100644
--- a/test/SILGen/casts.swift
+++ b/test/SILGen/casts.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class B { }
diff --git a/test/SILGen/cf.swift b/test/SILGen/cf.swift
index aa4cb6a..ebc2c23 100644
--- a/test/SILGen/cf.swift
+++ b/test/SILGen/cf.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -import-cf-types -sdk %S/Inputs %s -emit-silgen -o - | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift
index bf9df67..b190ced 100644
--- a/test/SILGen/class_bound_protocols.swift
+++ b/test/SILGen/class_bound_protocols.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -module-name Swift -emit-silgen %s | %FileCheck %s
enum Optional<T> {
diff --git a/test/SILGen/class_resilience.swift b/test/SILGen/class_resilience.swift
index 8b91e2e..e821bc5 100644
--- a/test/SILGen/class_resilience.swift
+++ b/test/SILGen/class_resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class -I %t %S/../Inputs/resilient_class.swift
diff --git a/test/SILGen/closures.swift b/test/SILGen/closures.swift
index c90d81d..ca0d033 100644
--- a/test/SILGen/closures.swift
+++ b/test/SILGen/closures.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -parse-as-library -emit-silgen %s | %FileCheck %s
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -parse-as-library -emit-silgen %s | %FileCheck %s --check-prefix=GUARANTEED
diff --git a/test/SILGen/collection_downcast.swift b/test/SILGen/collection_downcast.swift
index a6633f0..b3768d4 100644
--- a/test/SILGen/collection_downcast.swift
+++ b/test/SILGen/collection_downcast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/collection_subtype_downcast.swift b/test/SILGen/collection_subtype_downcast.swift
index ce47645..821115f 100644
--- a/test/SILGen/collection_subtype_downcast.swift
+++ b/test/SILGen/collection_subtype_downcast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -sdk %S/Inputs %s | %FileCheck %s
struct S { var x, y: Int }
diff --git a/test/SILGen/collection_subtype_upcast.swift b/test/SILGen/collection_subtype_upcast.swift
index 6081663..d6d4ad9 100644
--- a/test/SILGen/collection_subtype_upcast.swift
+++ b/test/SILGen/collection_subtype_upcast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -sdk %S/Inputs %s | %FileCheck %s
struct S { var x, y: Int }
diff --git a/test/SILGen/collection_upcast.swift b/test/SILGen/collection_upcast.swift
index ac73520..faecb5b 100644
--- a/test/SILGen/collection_upcast.swift
+++ b/test/SILGen/collection_upcast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
// FIXME: rdar://problem/19648117 Needs splitting objc parts out
diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift
index 2d1fd81..f6e8418 100644
--- a/test/SILGen/constrained_extensions.swift
+++ b/test/SILGen/constrained_extensions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -primary-file %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-sil -O -primary-file %s > /dev/null
// RUN: %target-swift-frontend -emit-ir -primary-file %s > /dev/null
@@ -137,7 +138,7 @@
extension GenericClass where Y == () {
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvs : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var value: X {
get { while true {} }
@@ -146,7 +147,7 @@
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvs : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var empty: Y {
get { return () }
@@ -155,7 +156,7 @@
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcig : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcis : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcim : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public subscript(_: Y) -> X {
get { while true {} }
@@ -164,7 +165,7 @@
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcig : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcis : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
- // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcim : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in X, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public subscript(_: X) -> Y {
get { while true {} }
diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift
index 0059519..ad11d44 100644
--- a/test/SILGen/default_arguments.swift
+++ b/test/SILGen/default_arguments.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 3 %s | %FileCheck %s
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 3 %s | %FileCheck %s --check-prefix=NEGATIVE
diff --git a/test/SILGen/default_arguments_generic.swift b/test/SILGen/default_arguments_generic.swift
index 61297aa..4755f22 100644
--- a/test/SILGen/default_arguments_generic.swift
+++ b/test/SILGen/default_arguments_generic.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -swift-version 3 %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -swift-version 4 %s | %FileCheck %s
diff --git a/test/SILGen/default_arguments_serialized.swift b/test/SILGen/default_arguments_serialized.swift
index 0172a9c..2308dcd 100644
--- a/test/SILGen/default_arguments_serialized.swift
+++ b/test/SILGen/default_arguments_serialized.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module-path %t/default_arguments_other.swiftmodule -emit-module -swift-version 4 -primary-file %S/Inputs/default_arguments_other.swift
diff --git a/test/SILGen/dependent_member_lowering.swift b/test/SILGen/dependent_member_lowering.swift
index 218c589..86aad55 100644
--- a/test/SILGen/dependent_member_lowering.swift
+++ b/test/SILGen/dependent_member_lowering.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
protocol P {
diff --git a/test/SILGen/downcast_reabstraction.swift b/test/SILGen/downcast_reabstraction.swift
index 191a90e..3a07b17 100644
--- a/test/SILGen/downcast_reabstraction.swift
+++ b/test/SILGen/downcast_reabstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// CHECK-LABEL: sil hidden @$S22downcast_reabstraction19condFunctionFromAnyyyypF
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index 7d85d4e..49806ca 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
diff --git a/test/SILGen/dynamic_lookup.swift b/test/SILGen/dynamic_lookup.swift
index a0d85b3..b55f1f0 100644
--- a/test/SILGen/dynamic_lookup.swift
+++ b/test/SILGen/dynamic_lookup.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s --check-prefix=GUARANTEED
diff --git a/test/SILGen/dynamic_lookup_throws.swift b/test/SILGen/dynamic_lookup_throws.swift
index 67ac9b4..178909d 100644
--- a/test/SILGen/dynamic_lookup_throws.swift
+++ b/test/SILGen/dynamic_lookup_throws.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-clang-importer-objc-overlays
diff --git a/test/SILGen/dynamic_self.swift b/test/SILGen/dynamic_self.swift
index a08e377..fc284ae 100644
--- a/test/SILGen/dynamic_self.swift
+++ b/test/SILGen/dynamic_self.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
// RUN: %target-swift-frontend -emit-sil -O %s -disable-objc-attr-requires-foundation-module
// RUN: %target-swift-frontend -emit-ir %s -disable-objc-attr-requires-foundation-module
diff --git a/test/SILGen/enum.swift b/test/SILGen/enum.swift
index af87a52..f16ea12 100644
--- a/test/SILGen/enum.swift
+++ b/test/SILGen/enum.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -emit-silgen -enable-sil-ownership -module-name Swift %s | %FileCheck %s
precedencegroup AssignmentPrecedence { assignment: true }
diff --git a/test/SILGen/enum_resilience.swift b/test/SILGen/enum_resilience.swift
index dbebe9c..d2f2145 100644
--- a/test/SILGen/enum_resilience.swift
+++ b/test/SILGen/enum_resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
diff --git a/test/SILGen/erasure_reabstraction.swift b/test/SILGen/erasure_reabstraction.swift
index a63f65b..10c6e39 100644
--- a/test/SILGen/erasure_reabstraction.swift
+++ b/test/SILGen/erasure_reabstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
struct Foo {}
diff --git a/test/SILGen/existential_erasure.swift b/test/SILGen/existential_erasure.swift
index ead4724..15bf015 100644
--- a/test/SILGen/existential_erasure.swift
+++ b/test/SILGen/existential_erasure.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
protocol P {
diff --git a/test/SILGen/expressions.swift b/test/SILGen/expressions.swift
index 5f91200..6de0dea 100644
--- a/test/SILGen/expressions.swift
+++ b/test/SILGen/expressions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: echo "public var x = Int()" | %target-swift-frontend -module-name FooBar -emit-module -o %t -
// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -enable-sil-ownership %s -I%t -disable-access-control | %FileCheck %s
diff --git a/test/SILGen/extensions_objc.swift b/test/SILGen/extensions_objc.swift
index 36fce74..7015fa7 100644
--- a/test/SILGen/extensions_objc.swift
+++ b/test/SILGen/extensions_objc.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-source-import -emit-silgen -enable-sil-ownership | %FileCheck %s
//
// REQUIRES: objc_interop
diff --git a/test/SILGen/external_definitions.swift b/test/SILGen/external_definitions.swift
index 6cff400..e7a1090 100644
--- a/test/SILGen/external_definitions.swift
+++ b/test/SILGen/external_definitions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs %s -emit-silgen -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/final.swift b/test/SILGen/final.swift
index 1538d5e..dd24729 100644
--- a/test/SILGen/final.swift
+++ b/test/SILGen/final.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class TestClass {
diff --git a/test/SILGen/force_cast_chained_optional.swift b/test/SILGen/force_cast_chained_optional.swift
index e84b241..2eae970 100644
--- a/test/SILGen/force_cast_chained_optional.swift
+++ b/test/SILGen/force_cast_chained_optional.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class Foo {
diff --git a/test/SILGen/foreach.swift b/test/SILGen/foreach.swift
index 745cb95..6dd219b 100644
--- a/test/SILGen/foreach.swift
+++ b/test/SILGen/foreach.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
//////////////////
diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift
index e3c45fe..65bc729 100644
--- a/test/SILGen/foreign_errors.swift
+++ b/test/SILGen/foreign_errors.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-clang-importer-objc-overlays
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-silgen -parse-as-library %s | %FileCheck %s
diff --git a/test/SILGen/function_conversion.swift b/test/SILGen/function_conversion.swift
index 0fac5bc..2266959 100644
--- a/test/SILGen/function_conversion.swift
+++ b/test/SILGen/function_conversion.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -primary-file %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-ir -enable-sil-ownership -primary-file %s
diff --git a/test/SILGen/function_conversion_objc.swift b/test/SILGen/function_conversion_objc.swift
index 0af62ed..fcd20ec 100644
--- a/test/SILGen/function_conversion_objc.swift
+++ b/test/SILGen/function_conversion_objc.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-sil-ownership -enable-source-import -emit-silgen -verify | %FileCheck %s
import Foundation
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index 36e943a..bc02381 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-stdlib -parse-as-library -emit-silgen -enable-sil-ownership %s | %FileCheck %s
import Swift // just for Optional
diff --git a/test/SILGen/generic_casts.swift b/test/SILGen/generic_casts.swift
index 6fe1f40..56d6d8d 100644
--- a/test/SILGen/generic_casts.swift
+++ b/test/SILGen/generic_casts.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-runtime %s
protocol ClassBound : class {}
diff --git a/test/SILGen/generic_closures.swift b/test/SILGen/generic_closures.swift
index b3bddf9..7cabd10 100644
--- a/test/SILGen/generic_closures.swift
+++ b/test/SILGen/generic_closures.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -enable-sil-ownership %s | %FileCheck %s
import Swift
diff --git a/test/SILGen/generic_property_base_lifetime.swift b/test/SILGen/generic_property_base_lifetime.swift
index 9ccc903..7338fee 100644
--- a/test/SILGen/generic_property_base_lifetime.swift
+++ b/test/SILGen/generic_property_base_lifetime.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
protocol ProtocolA: class {
diff --git a/test/SILGen/generic_tuples.swift b/test/SILGen/generic_tuples.swift
index 137bd18..c2330dd 100644
--- a/test/SILGen/generic_tuples.swift
+++ b/test/SILGen/generic_tuples.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -parse-as-library -enable-sil-ownership %s | %FileCheck %s
diff --git a/test/SILGen/generic_witness.swift b/test/SILGen/generic_witness.swift
index 3b4a719..98dfffe 100644
--- a/test/SILGen/generic_witness.swift
+++ b/test/SILGen/generic_witness.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-ir -enable-sil-ownership %s
diff --git a/test/SILGen/guaranteed_normal_args.swift b/test/SILGen/guaranteed_normal_args.swift
index a072527..250a763 100644
--- a/test/SILGen/guaranteed_normal_args.swift
+++ b/test/SILGen/guaranteed_normal_args.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-as-library -module-name Swift -parse-stdlib -emit-silgen -enable-sil-ownership -enable-guaranteed-normal-arguments %s | %FileCheck %s
// This test checks specific codegen related to normal arguments being passed at
diff --git a/test/SILGen/guaranteed_self.swift b/test/SILGen/guaranteed_self.swift
index b285f62..02e4524 100644
--- a/test/SILGen/guaranteed_self.swift
+++ b/test/SILGen/guaranteed_self.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
protocol Fooable {
diff --git a/test/SILGen/if_while_binding.swift b/test/SILGen/if_while_binding.swift
index c921e3e..9564b01 100644
--- a/test/SILGen/if_while_binding.swift
+++ b/test/SILGen/if_while_binding.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func foo() -> String? { return "" }
diff --git a/test/SILGen/implicitly_unwrapped_optional.swift b/test/SILGen/implicitly_unwrapped_optional.swift
index 3273c3b..5307d7f 100644
--- a/test/SILGen/implicitly_unwrapped_optional.swift
+++ b/test/SILGen/implicitly_unwrapped_optional.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func foo(f f: (() -> ())!) {
diff --git a/test/SILGen/indirect_enum.swift b/test/SILGen/indirect_enum.swift
index bae2be1..b384995 100644
--- a/test/SILGen/indirect_enum.swift
+++ b/test/SILGen/indirect_enum.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-print-debuginfo -emit-silgen %s | %FileCheck %s
indirect enum TreeA<T> {
diff --git a/test/SILGen/inlineable_attribute.swift b/test/SILGen/inlineable_attribute.swift
index 564b5b5..747abcc 100644
--- a/test/SILGen/inlineable_attribute.swift
+++ b/test/SILGen/inlineable_attribute.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
// CHECK-LABEL: sil [serialized] @$S20inlineable_attribute15fragileFunctionyyF : $@convention(thin) () -> ()
diff --git a/test/SILGen/inlineable_attribute_objc.swift b/test/SILGen/inlineable_attribute_objc.swift
index 8e36109..a7ff8d5 100644
--- a/test/SILGen/inlineable_attribute_objc.swift
+++ b/test/SILGen/inlineable_attribute_objc.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
diff --git a/test/SILGen/keypath_application.swift b/test/SILGen/keypath_application.swift
index 88cd272..66a8fb7 100644
--- a/test/SILGen/keypath_application.swift
+++ b/test/SILGen/keypath_application.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class A {}
diff --git a/test/SILGen/keypaths.swift b/test/SILGen/keypaths.swift
index d028842..55fc6ab 100644
--- a/test/SILGen/keypaths.swift
+++ b/test/SILGen/keypaths.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
struct S<T> {
diff --git a/test/SILGen/let_decls.swift b/test/SILGen/let_decls.swift
index 43e68654..493c2db 100644
--- a/test/SILGen/let_decls.swift
+++ b/test/SILGen/let_decls.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func takeClosure(_ a : () -> Int) {}
diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift
index 751f386..1700a7f 100644
--- a/test/SILGen/lifetime.swift
+++ b/test/SILGen/lifetime.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-silgen -primary-file %s | %FileCheck %s
struct Buh<T> {
@@ -389,7 +390,7 @@
// CHECK: [[ADDR:%.*]] = pointer_to_address [[PTR]]
// CHECK: [[MARKED_ADDR:%.*]] = mark_dependence [[ADDR]] : $*Aleph on [[R2]]
// CHECK: {{.*}}([[CALLBACK_ADDR:%.*]] :
- // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> ()
+ // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed RefWithProp, @thick RefWithProp.Type) -> ()
// CHECK: [[TEMP:%.*]] = alloc_stack $RefWithProp
// CHECK: store [[R2]] to [init] [[TEMP]]
// CHECK: apply [[CALLBACK]]({{.*}}, [[STORAGE]], [[TEMP]], {{%.*}})
diff --git a/test/SILGen/mangling.swift b/test/SILGen/mangling.swift
index 0cb1dd2..6fffed4 100644
--- a/test/SILGen/mangling.swift
+++ b/test/SILGen/mangling.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index 97adf6f..be4c1a4 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
// RUN: %target-swift-frontend -emit-silgen -enforce-exclusivity=unchecked %s | %FileCheck --check-prefix=UNCHECKED %s
@@ -22,7 +23,7 @@
// UNCHECKED: return [[T3]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
// UNCHECKED: }
-// CHECK-LABEL: sil private [transparent] @$S17materializeForSet4BaseC8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () {
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet4BaseC8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed Base, @thick Base.Type) -> () {
// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Base, [[SELFTYPE:%.*]] : $@thick Base.Type):
// CHECK: [[T0:%.*]] = load_borrow [[SELF]]
// CHECK: [[T1:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
@@ -37,7 +38,7 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[ADDR]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[ADDR]]
-// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet4BaseC8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> ()
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet4BaseC8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed Base, @thick Base.Type) -> ()
// CHECK: [[T2:%.*]] = thin_function_to_pointer [[T0]]
// CHECK: [[T3:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T2]] : $Builtin.RawPointer
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[T3]] : $Optional<Builtin.RawPointer>)
@@ -76,7 +77,7 @@
extension Derived : Abstractable {}
-// CHECK-LABEL: sil private [transparent] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14storedFunction6ResultQzycvmytfU_TW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> ()
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14storedFunction6ResultQzycvmytfU_TW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed Derived, @thick Derived.Type) -> ()
// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
@@ -217,8 +218,8 @@
// CHECK-NEXT: destroy_addr [[OUT]] : $*@callee_guaranteed () -> Int
// CHECK-NEXT: store [[NEWVALUE]] to [init] [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int
// CHECK-NEXT: [[ADDR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14staticFunction6ResultQzycvmZytfU_TW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> ()
-// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14staticFunction6ResultQzycvmZytfU_TW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed @thick Derived.Type, @thick Derived.Type.Type) -> ()
+// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer
// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] : $Builtin.RawPointer
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ADDR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
// CHECK-NEXT: dealloc_stack [[OUT]] : $*@callee_guaranteed () -> Int
@@ -263,7 +264,7 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet06HasDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet06HasDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasDidSet, @thick HasDidSet.Type) -> ()
// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
@@ -282,7 +283,7 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet06HasDidC0C8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet06HasDidC0C8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasDidSet, @thick HasDidSet.Type) -> ()
// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
@@ -295,7 +296,7 @@
didSet {}
}
-// CHECK-LABEL: sil private [transparent] @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () {
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasStoredDidSet, @thick HasStoredDidSet.Type) -> () {
// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*HasStoredDidSet, [[METATYPE:%.*]] : $@thick HasStoredDidSet.Type):
// CHECK: [[SELF_VALUE:%.*]] = load_borrow [[SELF]] : $*HasStoredDidSet
// CHECK: [[BUFFER_ADDR:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
@@ -312,7 +313,7 @@
// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
@@ -332,7 +333,7 @@
// CHECK: end_access [[READ]] : $*@sil_weak Optional<HasWeak>
// CHECK: store [[T1]] to [init] [[T2]] : $*Optional<HasWeak>
// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet7HasWeakC7weakvarACSgXwvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> ()
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet7HasWeakC7weakvarACSgXwvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasWeak, @thick HasWeak.Type) -> ()
// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, {{.*}} : $Optional<Builtin.RawPointer>)
// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
// CHECK: }
@@ -344,7 +345,7 @@
// UNCHECKED: [[T1:%.*]] = load_weak [[T0]] : $*@sil_weak Optional<HasWeak>
// UNCHECKED: store [[T1]] to [init] [[T2]] : $*Optional<HasWeak>
// UNCHECKED: [[BUFFER:%.*]] = address_to_pointer [[T2]]
-// UNCHECKED: [[T0:%.*]] = function_ref @$S17materializeForSet7HasWeakC7weakvarACSgXwvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> ()
+// UNCHECKED: [[T0:%.*]] = function_ref @$S17materializeForSet7HasWeakC7weakvarACSgXwvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed HasWeak, @thick HasWeak.Type) -> ()
// UNCHECKED: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, {{.*}} : $Optional<Builtin.RawPointer>)
// UNCHECKED: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
// UNCHECKED: }
@@ -660,6 +661,25 @@
f.computed = f.computed
}
+// Odd corner case -- mutating getter, non-mutating setter
+protocol BackwardMutationProtocol {
+ var value: Int {
+ mutating get
+ nonmutating set
+ }
+}
+
+struct BackwardMutation : BackwardMutationProtocol {
+ var value: Int {
+ mutating get { return 0 }
+ nonmutating set { }
+ }
+}
+
+func doBackwardMutation(m: inout BackwardMutationProtocol) {
+ m.value += 1
+}
+
// CHECK-LABEL: sil_vtable DerivedForOverride {
// CHECK: #BaseForOverride.valueStored!getter.1: (BaseForOverride) -> () -> Int : @$S17materializeForSet07DerivedB8OverrideC11valueStoredSivg
// CHECK: #BaseForOverride.valueStored!setter.1: (BaseForOverride) -> (Int) -> () : @$S17materializeForSet07DerivedB8OverrideC11valueStoredSivs
diff --git a/test/SILGen/metatype_abstraction.swift b/test/SILGen/metatype_abstraction.swift
index 7b701ec..1ee4e9d 100644
--- a/test/SILGen/metatype_abstraction.swift
+++ b/test/SILGen/metatype_abstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -module-name Swift -parse-stdlib %s | %FileCheck %s
enum Optional<Wrapped> {
diff --git a/test/SILGen/multi_file.swift b/test/SILGen/multi_file.swift
index 9109af1..9be3c89 100644
--- a/test/SILGen/multi_file.swift
+++ b/test/SILGen/multi_file.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -primary-file %s %S/Inputs/multi_file_helper.swift | %FileCheck %s
func markUsed<T>(_ t: T) {}
diff --git a/test/SILGen/nested_generics.swift b/test/SILGen/nested_generics.swift
index d3f1460..b639d7d 100644
--- a/test/SILGen/nested_generics.swift
+++ b/test/SILGen/nested_generics.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-silgen -parse-as-library %s | %FileCheck %s
// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-sil -parse-as-library %s > /dev/null
// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-sil -O -parse-as-library %s > /dev/null
diff --git a/test/SILGen/nested_types_referencing_nested_functions.swift b/test/SILGen/nested_types_referencing_nested_functions.swift
index db22276..d6a8d6d 100644
--- a/test/SILGen/nested_types_referencing_nested_functions.swift
+++ b/test/SILGen/nested_types_referencing_nested_functions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
do {
diff --git a/test/SILGen/newtype.swift b/test/SILGen/newtype.swift
index 7b80715..1f7b6f2 100644
--- a/test/SILGen/newtype.swift
+++ b/test/SILGen/newtype.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s -check-prefix=CHECK-RAW
// RUN: %target-swift-frontend -emit-sil -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s -check-prefix=CHECK-CANONICAL
diff --git a/test/SILGen/noescape_reabstraction.swift b/test/SILGen/noescape_reabstraction.swift
index 1958efd..4bfeb40 100644
--- a/test/SILGen/noescape_reabstraction.swift
+++ b/test/SILGen/noescape_reabstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
struct S {}
diff --git a/test/SILGen/objc_attr_NSManaged.swift b/test/SILGen/objc_attr_NSManaged.swift
index 8cb5e51..0a60635 100644
--- a/test/SILGen/objc_attr_NSManaged.swift
+++ b/test/SILGen/objc_attr_NSManaged.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-source-import -emit-silgen -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
@@ -104,7 +105,7 @@
@NSManaged final var entityID: String
}
-// CHECK-LABEL: sil private @$S19objc_attr_NSManaged11FinalEntityC8entityIDSSvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout FinalEntity, @thick FinalEntity.Type) -> ()
+// CHECK-LABEL: sil private @$S19objc_attr_NSManaged11FinalEntityC8entityIDSSvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed FinalEntity, @thick FinalEntity.Type) -> ()
// CHECK: objc_method {{.*}} : $FinalEntity, #FinalEntity.entityID!setter.1.foreign
// CHECK: return
diff --git a/test/SILGen/objc_attr_NSManaged_multi.swift b/test/SILGen/objc_attr_NSManaged_multi.swift
index 5cce85e..9b4f085 100644
--- a/test/SILGen/objc_attr_NSManaged_multi.swift
+++ b/test/SILGen/objc_attr_NSManaged_multi.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs -primary-file %s %S/objc_attr_NSManaged.swift -I %S/Inputs -enable-source-import -emit-silgen -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift
index 50cc6e6..8984176 100644
--- a/test/SILGen/objc_blocks_bridging.swift
+++ b/test/SILGen/objc_blocks_bridging.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -verify -emit-silgen -I %S/Inputs -disable-objc-attr-requires-foundation-module -enable-sil-ownership %s | %FileCheck %s
diff --git a/test/SILGen/objc_bridged_results.swift b/test/SILGen/objc_bridged_results.swift
index a0aaa6b..94c6cbb 100644
--- a/test/SILGen/objc_bridged_results.swift
+++ b/test/SILGen/objc_bridged_results.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
diff --git a/test/SILGen/objc_bridging.swift b/test/SILGen/objc_bridging.swift
index 613a091..28b2ed6 100644
--- a/test/SILGen/objc_bridging.swift
+++ b/test/SILGen/objc_bridging.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -o %t -I %S/../Inputs/ObjCBridging %S/../Inputs/ObjCBridging/Appliances.swift
diff --git a/test/SILGen/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift
index aa23de2..3ca525e 100644
--- a/test/SILGen/objc_bridging_any.swift
+++ b/test/SILGen/objc_bridging_any.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -Xllvm -sil-print-debuginfo -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// REQUIRES: objc_interop
@@ -757,4 +758,5 @@
// CHECK-LABEL: sil_witness_table shared [serialized] GenericOption: Hashable module objc_generics {
// CHECK-NEXT: base_protocol Equatable: GenericOption: Equatable module objc_generics
// CHECK-NEXT: method #Hashable.hashValue!getter.1: {{.*}} : @$SSo13GenericOptionas8HashableSCsACP9hashValueSivgTW
+// CHECK-NEXT: method #Hashable._hash!1: {{.*}} : @$SSo13GenericOptionas8HashableSCsACP5_hash4intoys7_HasherVz_tFTW
// CHECK-NEXT: }
diff --git a/test/SILGen/objc_bridging_peephole.swift b/test/SILGen/objc_bridging_peephole.swift
index 317aba5..09954bb 100644
--- a/test/SILGen/objc_bridging_peephole.swift
+++ b/test/SILGen/objc_bridging_peephole.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_currying.swift b/test/SILGen/objc_currying.swift
index a22f54e..036ca8c 100644
--- a/test/SILGen/objc_currying.swift
+++ b/test/SILGen/objc_currying.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -enable-sil-ownership -emit-silgen %s | %FileCheck %s
diff --git a/test/SILGen/objc_dictionary_bridging.swift b/test/SILGen/objc_dictionary_bridging.swift
index 421fc90..74dd95e 100644
--- a/test/SILGen/objc_dictionary_bridging.swift
+++ b/test/SILGen/objc_dictionary_bridging.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
diff --git a/test/SILGen/objc_error.swift b/test/SILGen/objc_error.swift
index 1a40901..b9ee4d3 100644
--- a/test/SILGen/objc_error.swift
+++ b/test/SILGen/objc_error.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-clang-importer-objc-overlays
diff --git a/test/SILGen/objc_extensions.swift b/test/SILGen/objc_extensions.swift
index b3f34bf..639b8aa 100644
--- a/test/SILGen/objc_extensions.swift
+++ b/test/SILGen/objc_extensions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -sdk %S/Inputs/ -I %S/Inputs -enable-source-import %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_imported_generic.swift b/test/SILGen/objc_imported_generic.swift
index 165e8dd..586aea6 100644
--- a/test/SILGen/objc_imported_generic.swift
+++ b/test/SILGen/objc_imported_generic.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %s -enable-sil-ownership | %FileCheck %s
// For integration testing, ensure we get through IRGen too.
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -verify -DIRGEN_INTEGRATION_TEST %s
diff --git a/test/SILGen/objc_ownership_conventions.swift b/test/SILGen/objc_ownership_conventions.swift
index adc562a..ec991b6 100644
--- a/test/SILGen/objc_ownership_conventions.swift
+++ b/test/SILGen/objc_ownership_conventions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_protocol_native_thunk.swift b/test/SILGen/objc_protocol_native_thunk.swift
index f5540bd..bde4e32 100644
--- a/test/SILGen/objc_protocol_native_thunk.swift
+++ b/test/SILGen/objc_protocol_native_thunk.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift
index 2b91662..15a0ed2 100644
--- a/test/SILGen/objc_protocols.swift
+++ b/test/SILGen/objc_protocols.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_set_bridging.swift b/test/SILGen/objc_set_bridging.swift
index 617d9e8..5e79cfd 100644
--- a/test/SILGen/objc_set_bridging.swift
+++ b/test/SILGen/objc_set_bridging.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %build-silgen-test-overlays
diff --git a/test/SILGen/objc_thunks.swift b/test/SILGen/objc_thunks.swift
index c0adf9d..f6f8d3f 100644
--- a/test/SILGen/objc_thunks.swift
+++ b/test/SILGen/objc_thunks.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -emit-verbose-sil -enable-sil-ownership | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/objc_witnesses.swift b/test/SILGen/objc_witnesses.swift
index 9d754fc..333edae 100644
--- a/test/SILGen/objc_witnesses.swift
+++ b/test/SILGen/objc_witnesses.swift
@@ -100,7 +100,7 @@
var valence: Int { get { return 1 } set { } }
}
-// CHECK-LABEL: sil private @$SSo8NSObjectC14objc_witnessesE7valenceSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout NSObject, @thick NSObject.Type) -> () {
+// CHECK-LABEL: sil private @$SSo8NSObjectC14objc_witnessesE7valenceSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed NSObject, @thick NSObject.Type) -> () {
// CHECK: objc_method %4 : $NSObject, #NSObject.valence!setter.1.foreign
// CHECK: }
diff --git a/test/SILGen/opaque_ownership.swift b/test/SILGen/opaque_ownership.swift
index d56c998..5fa51ce 100644
--- a/test/SILGen/opaque_ownership.swift
+++ b/test/SILGen/opaque_ownership.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-opaque-values -enable-sil-ownership -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.9 -enable-sil-opaque-values -enable-sil-ownership -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck --check-prefix=CHECK-OSX %s
@@ -170,7 +171,7 @@
case minus
}
-#if os(OSX)
+#if os(macOS)
// Test open_existential_value used in a conversion context.
// (the actual bridging call is dropped because we don't import Swift).
// ---
@@ -195,7 +196,7 @@
public protocol Error {}
-#if os(OSX)
+#if os(macOS)
// Test open_existential_box_value in a conversion context.
// ---
// CHECK-OSX-LABEL: sil @$Ss3foo1eys5Error_pSg_tF : $@convention(thin) (@owned Optional<Error>) -> () {
diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift
index 1154d02..6c9931b 100644
--- a/test/SILGen/opaque_values_silgen.swift
+++ b/test/SILGen/opaque_values_silgen.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-opaque-values -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
// UNSUPPORTED: resilient_stdlib
diff --git a/test/SILGen/opaque_values_silgen_lib.swift b/test/SILGen/opaque_values_silgen_lib.swift
index c7064d7..3d69099 100644
--- a/test/SILGen/opaque_values_silgen_lib.swift
+++ b/test/SILGen/opaque_values_silgen_lib.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -enable-sil-opaque-values -emit-sorted-sil -Xllvm -sil-full-demangle -parse-stdlib -parse-as-library -emit-silgen -module-name Swift %s | %FileCheck %s
// UNSUPPORTED: resilient_stdlib
diff --git a/test/SILGen/optional-cast.swift b/test/SILGen/optional-cast.swift
index e5501cb..6a1c2f7 100644
--- a/test/SILGen/optional-cast.swift
+++ b/test/SILGen/optional-cast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class A {}
diff --git a/test/SILGen/optional.swift b/test/SILGen/optional.swift
index 68b6c8a..3cc67b5 100644
--- a/test/SILGen/optional.swift
+++ b/test/SILGen/optional.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func testCall(_ f: (() -> ())?) {
diff --git a/test/SILGen/optional_lvalue.swift b/test/SILGen/optional_lvalue.swift
index a735e2c..153200f 100644
--- a/test/SILGen/optional_lvalue.swift
+++ b/test/SILGen/optional_lvalue.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// CHECK-LABEL: sil hidden @$S15optional_lvalue07assign_a1_B0yySiSgz_SitF
diff --git a/test/SILGen/partial_apply_generic.swift b/test/SILGen/partial_apply_generic.swift
index 9b1e736..94c032c 100644
--- a/test/SILGen/partial_apply_generic.swift
+++ b/test/SILGen/partial_apply_generic.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
protocol Panda {
diff --git a/test/SILGen/partial_apply_protocol.swift b/test/SILGen/partial_apply_protocol.swift
index 902ce27..60e3e0d 100644
--- a/test/SILGen/partial_apply_protocol.swift
+++ b/test/SILGen/partial_apply_protocol.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -primary-file %s | %FileCheck %s
// RUN: %target-swift-frontend -enable-sil-ownership -emit-ir -primary-file %s
diff --git a/test/SILGen/partial_apply_protocol_class_refinement_method.swift b/test/SILGen/partial_apply_protocol_class_refinement_method.swift
index f69af05..ca2450c 100644
--- a/test/SILGen/partial_apply_protocol_class_refinement_method.swift
+++ b/test/SILGen/partial_apply_protocol_class_refinement_method.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
protocol P { func foo() }
diff --git a/test/SILGen/partial_apply_super.swift b/test/SILGen/partial_apply_super.swift
index ae315df..685ee8c 100644
--- a/test/SILGen/partial_apply_super.swift
+++ b/test/SILGen/partial_apply_super.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -I %t -emit-module -emit-module-path=%t/resilient_struct.swiftmodule -module-name resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -I %t -emit-module -emit-module-path=%t/resilient_class.swiftmodule -module-name resilient_class %S/../Inputs/resilient_class.swift
diff --git a/test/SILGen/pgo_checked_cast.swift b/test/SILGen/pgo_checked_cast.swift
index f8ae4f9..41db5fd 100644
--- a/test/SILGen/pgo_checked_cast.swift
+++ b/test/SILGen/pgo_checked_cast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_checked_cast -o %t/main
// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
diff --git a/test/SILGen/pgo_switchenum.swift b/test/SILGen/pgo_switchenum.swift
index 6b9d940..9978fa6 100644
--- a/test/SILGen/pgo_switchenum.swift
+++ b/test/SILGen/pgo_switchenum.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_switchenum -o %t/main
// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
diff --git a/test/SILGen/plus_zero_access_marker_gen.swift b/test/SILGen/plus_zero_access_marker_gen.swift
new file mode 100644
index 0000000..6781648
--- /dev/null
+++ b/test/SILGen/plus_zero_access_marker_gen.swift
@@ -0,0 +1,139 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-as-library -Xllvm -sil-full-demangle -enforce-exclusivity=checked -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func modify<T>(_ x: inout T) {}
+
+public struct S {
+ var i: Int
+ var o: AnyObject?
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S17access_marker_gen5initSyAA1SVyXlSgF : $@convention(thin) (@guaranteed Optional<AnyObject>) -> @owned S {
+// CHECK: bb0(%0 : @guaranteed $Optional<AnyObject>):
+// CHECK: [[BOX:%.*]] = alloc_box ${ var S }, var, name "s"
+// CHECK: [[MARKED_BOX:%.*]] = mark_uninitialized [var] [[BOX]] : ${ var S }
+// CHECK: [[ADDR:%.*]] = project_box [[MARKED_BOX]] : ${ var S }, 0
+// CHECK: cond_br %{{.*}}, bb1, bb2
+// CHECK: bb1:
+// CHECK: [[ACCESS1:%.*]] = begin_access [modify] [unknown] [[ADDR]] : $*S
+// CHECK: assign %{{.*}} to [[ACCESS1]] : $*S
+// CHECK: end_access [[ACCESS1]] : $*S
+// CHECK: bb2:
+// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [unknown] [[ADDR]] : $*S
+// CHECK: assign %{{.*}} to [[ACCESS2]] : $*S
+// CHECK: end_access [[ACCESS2]] : $*S
+// CHECK: bb3:
+// CHECK: [[ACCESS3:%.*]] = begin_access [read] [unknown] [[ADDR]] : $*S
+// CHECK: [[RET:%.*]] = load [copy] [[ACCESS3]] : $*S
+// CHECK: end_access [[ACCESS3]] : $*S
+// CHECK: return [[RET]] : $S
+// CHECK-LABEL: } // end sil function '$S17access_marker_gen5initSyAA1SVyXlSgF'
+@inline(never)
+func initS(_ o: AnyObject?) -> S {
+ var s: S
+ if o == nil {
+ s = S(i: 0, o: nil)
+ } else {
+ s = S(i: 1, o: o)
+ }
+ return s
+}
+
+@inline(never)
+func takeS(_ s: S) {}
+
+// CHECK-LABEL: sil @$S17access_marker_gen14modifyAndReadSyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: %[[BOX:.*]] = alloc_box ${ var S }, var, name "s"
+// CHECK: %[[ADDRS:.*]] = project_box %[[BOX]] : ${ var S }, 0
+// CHECK: %[[ACCESS1:.*]] = begin_access [modify] [unknown] %[[ADDRS]] : $*S
+// CHECK: %[[ADDRI:.*]] = struct_element_addr %[[ACCESS1]] : $*S, #S.i
+// CHECK: assign %{{.*}} to %[[ADDRI]] : $*Int
+// CHECK: end_access %[[ACCESS1]] : $*S
+// CHECK: %[[ACCESS2:.*]] = begin_access [read] [unknown] %[[ADDRS]] : $*S
+// CHECK: %{{.*}} = load [copy] %[[ACCESS2]] : $*S
+// CHECK: end_access %[[ACCESS2]] : $*S
+// CHECK-LABEL: } // end sil function '$S17access_marker_gen14modifyAndReadSyyF'
+public func modifyAndReadS() {
+ var s = initS(nil)
+ s.i = 42
+ takeS(s)
+}
+
+var global = S(i: 0, o: nil)
+
+func readGlobal() -> AnyObject? {
+ return global.o
+}
+
+// CHECK-LABEL: sil hidden @$S17access_marker_gen10readGlobalyXlSgyF
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S17access_marker_gen6globalAA1SVvau :
+// CHECK-NEXT: [[T0:%.*]] = apply [[ADDRESSOR]]()
+// CHECK-NEXT: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*S
+// CHECK-NEXT: [[T2:%.*]] = begin_access [read] [dynamic] [[T1]]
+// CHECK-NEXT: [[T3:%.*]] = struct_element_addr [[T2]] : $*S, #S.o
+// CHECK-NEXT: [[T4:%.*]] = load [copy] [[T3]]
+// CHECK-NEXT: end_access [[T2]]
+// CHECK-NEXT: return [[T4]]
+
+
+public struct HasTwoStoredProperties {
+ var f: Int = 7
+ var g: Int = 9
+
+// CHECK-LABEL: sil hidden @$S17access_marker_gen22HasTwoStoredPropertiesV027noOverlapOnAssignFromPropToM0yyF : $@convention(method) (@inout HasTwoStoredProperties) -> ()
+// CHECK: [[ACCESS1:%.*]] = begin_access [read] [unknown] [[SELF_ADDR:%.*]] : $*HasTwoStoredProperties
+// CHECK-NEXT: [[G_ADDR:%.*]] = struct_element_addr [[ACCESS1]] : $*HasTwoStoredProperties, #HasTwoStoredProperties.g
+// CHECK-NEXT: [[G_VAL:%.*]] = load [trivial] [[G_ADDR]] : $*Int
+// CHECK-NEXT: end_access [[ACCESS1]] : $*HasTwoStoredProperties
+// CHECK-NEXT: [[ACCESS2:%.*]] = begin_access [modify] [unknown] [[SELF_ADDR]] : $*HasTwoStoredProperties
+// CHECK-NEXT: [[F_ADDR:%.*]] = struct_element_addr [[ACCESS2]] : $*HasTwoStoredProperties, #HasTwoStoredProperties.f
+// CHECK-NEXT: assign [[G_VAL]] to [[F_ADDR]] : $*Int
+// CHECK-NEXT: end_access [[ACCESS2]] : $*HasTwoStoredProperties
+ mutating func noOverlapOnAssignFromPropToProp() {
+ f = g
+ }
+}
+
+class C {
+ final var x: Int = 0
+}
+
+func testClassInstanceProperties(c: C) {
+ let y = c.x
+ c.x = y
+}
+// CHECK-LABEL: sil hidden @$S17access_marker_gen27testClassInstanceProperties1cyAA1CC_tF :
+// CHECK: bb0([[C:%.*]] : @guaranteed $C
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: [[CX:%.*]] = ref_element_addr [[C]] : $C, #C.x
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[CX]] : $*Int
+// CHECK-NEXT: [[Y:%.*]] = load [trivial] [[ACCESS]]
+// CHECK-NEXT: end_access [[ACCESS]]
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: [[CX:%.*]] = ref_element_addr [[C]] : $C, #C.x
+// CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[CX]] : $*Int
+// CHECK-NEXT: assign [[Y]] to [[ACCESS]]
+// CHECK-NEXT: end_access [[ACCESS]]
+
+class D {
+ var x: Int = 0
+}
+// materializeForSet callback
+// CHECK-LABEL: sil private [transparent] @$S17access_marker_gen1DC1xSivmytfU_
+// CHECK: end_unpaired_access [dynamic] %1 : $*Builtin.UnsafeValueBuffer
+
+// materializeForSet
+// CHECK-LABEL: sil hidden [transparent] @$S17access_marker_gen1DC1xSivm
+// CHECK: [[T0:%.*]] = ref_element_addr %2 : $D, #D.x
+// CHECK-NEXT: begin_unpaired_access [modify] [dynamic] [[T0]] : $*Int
+
+func testDispatchedClassInstanceProperty(d: D) {
+ modify(&d.x)
+}
+// CHECK-LABEL: sil hidden @$S17access_marker_gen35testDispatchedClassInstanceProperty1dyAA1DC_tF
+// CHECK: bb0([[D:%.*]] : @guaranteed $D
+// CHECK: [[METHOD:%.*]] = class_method [[D]] : $D, #D.x!materializeForSet.1
+// CHECK: apply [[METHOD]]({{.*}}, [[D]])
+// CHECK-NOT: begin_access
+
diff --git a/test/SILGen/plus_zero_accessors.swift b/test/SILGen/plus_zero_accessors.swift
new file mode 100644
index 0000000..47ebf94
--- /dev/null
+++ b/test/SILGen/plus_zero_accessors.swift
@@ -0,0 +1,235 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+// Hold a reference to do to magically become non-POD.
+class Reference {}
+
+// A struct with a non-mutating getter and a mutating setter.
+struct OrdinarySub {
+ var ptr = Reference()
+ subscript(value: Int) -> Int {
+ get { return value }
+ set {}
+ }
+}
+
+class A { var array = OrdinarySub() }
+
+func index0() -> Int { return 0 }
+func index1() -> Int { return 1 }
+
+func someValidPointer<T>() -> UnsafePointer<T> { fatalError() }
+func someValidPointer<T>() -> UnsafeMutablePointer<T> { fatalError() }
+
+// Verify that there is no unnecessary extra copy_value of ref.array.
+// rdar://19002913
+func test0(_ ref: A) {
+ ref.array[index0()] = ref.array[index1()]
+}
+// CHECK: sil hidden @$S9accessors5test0yyAA1ACF : $@convention(thin) (@guaranteed A) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $A):
+// CHECK-NEXT: debug_value
+// Formal evaluation of LHS.
+// CHECK-NEXT: // function_ref accessors.index0() -> Swift.Int
+// CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors6index0SiyF
+// CHECK-NEXT: [[INDEX0:%.*]] = apply [[T0]]()
+// Formal evaluation of RHS.
+// CHECK-NEXT: // function_ref accessors.index1() -> Swift.Int
+// CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors6index1SiyF
+// CHECK-NEXT: [[INDEX1:%.*]] = apply [[T0]]()
+// Formal access to RHS.
+// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $OrdinarySub
+// CHECK-NEXT: [[T0:%.*]] = class_method [[ARG]] : $A, #A.array!getter.1
+// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[ARG]])
+// CHECK-NEXT: store [[T1]] to [init] [[TEMP]]
+// CHECK-NEXT: [[T0:%.*]] = load_borrow [[TEMP]]
+// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.getter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[T1:%.*]] = function_ref @$S9accessors11OrdinarySubVyS2icig
+// CHECK-NEXT: [[VALUE:%.*]] = apply [[T1]]([[INDEX1]], [[T0]])
+// CHECK-NEXT: end_borrow [[T0]] from [[TEMP]]
+// CHECK-NEXT: destroy_addr [[TEMP]]
+// Formal access to LHS.
+// CHECK-NEXT: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[BUFFER:%.*]] = alloc_stack $OrdinarySub
+// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER]]
+// CHECK-NEXT: [[T1:%.*]] = class_method [[ARG]] : $A, #A.array!materializeForSet.1
+// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE]], [[ARG]])
+// CHECK-NEXT: [[T3:%.*]] = tuple_extract [[T2]] {{.*}}, 0
+// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
+// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
+// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on [[ARG]] : $A
+// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[SETTER:%.*]] = function_ref @$S9accessors11OrdinarySubVyS2icis
+// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
+// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
+
+// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> ()
+// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
+// SEMANTIC SIL TODO: This is an issue caused by the callback for materializeForSet in the class case taking the value as @inout when it should really take it as @guaranteed.
+// CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*A
+// CHECK-NEXT: [[T0:%.*]] = metatype $@thick A.Type
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*OrdinarySub to $Builtin.RawPointer
+// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
+// CHECK-NEXT: dealloc_stack [[TEMP2]]
+// CHECK-NEXT: br [[CONT]]
+
+// CHECK: [[CONT]]:
+// CHECK-NEXT: dealloc_stack [[BUFFER]]
+// CHECK-NEXT: dealloc_stack [[STORAGE]]
+// CHECK-NEXT: dealloc_stack [[TEMP]]
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// A struct with a mutating getter and a mutating setter.
+struct MutatingSub {
+ var ptr = Reference()
+ subscript(value: Int) -> Int {
+ mutating get { return value }
+ set {}
+ }
+}
+class B { var array = MutatingSub() }
+
+func test1(_ ref: B) {
+ ref.array[index0()] = ref.array[index1()]
+}
+// CHECK-LABEL: sil hidden @$S9accessors5test1yyAA1BCF : $@convention(thin) (@guaranteed B) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $B):
+// CHECK-NEXT: debug_value
+// Formal evaluation of LHS.
+// CHECK-NEXT: // function_ref accessors.index0() -> Swift.Int
+// CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors6index0SiyF
+// CHECK-NEXT: [[INDEX0:%.*]] = apply [[T0]]()
+// Formal evaluation of RHS.
+// CHECK-NEXT: // function_ref accessors.index1() -> Swift.Int
+// CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors6index1SiyF
+// CHECK-NEXT: [[INDEX1:%.*]] = apply [[T0]]()
+// Formal access to RHS.
+// CHECK-NEXT: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[BUFFER:%.*]] = alloc_stack $MutatingSub
+// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER]]
+// CHECK-NEXT: [[T1:%.*]] = class_method [[ARG]] : $B, #B.array!materializeForSet.1
+// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE]], [[ARG]])
+// CHECK-NEXT: [[T3:%.*]] = tuple_extract [[T2]] {{.*}}, 0
+// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
+// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
+// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[ARG]] : $B
+// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.getter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[T0:%.*]] = function_ref @$S9accessors11MutatingSubVyS2icig : $@convention(method) (Int, @inout MutatingSub) -> Int
+// CHECK-NEXT: [[VALUE:%.*]] = apply [[T0]]([[INDEX1]], [[ADDR]])
+// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
+//
+// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
+// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
+// CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*B
+// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
+// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
+// CHECK-NEXT: dealloc_stack [[TEMP2]]
+// CHECK-NEXT: br [[CONT]]
+//
+// CHECK: [[CONT]]:
+// Formal access to LHS.
+// CHECK-NEXT: [[STORAGE2:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[BUFFER2:%.*]] = alloc_stack $MutatingSub
+// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER2]]
+// CHECK-NEXT: [[T1:%.*]] = class_method [[ARG]] : $B, #B.array!materializeForSet.1
+// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE2]], [[ARG]])
+// CHECK-NEXT: [[T3:%.*]] = tuple_extract [[T2]] {{.*}}, 0
+// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
+// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
+// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[ARG]] : $B
+// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[SETTER:%.*]] = function_ref @$S9accessors11MutatingSubVyS2icis : $@convention(method) (Int, Int, @inout MutatingSub) -> ()
+// CHECK-NEXT: apply [[SETTER]]([[VALUE]], [[INDEX0]], [[ADDR]])
+// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
+//
+// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
+// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
+// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
+// CHECK-NEXT: store_borrow [[ARG]] to [[TEMP2]] : $*B
+// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
+// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
+// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE2]], [[TEMP2]], [[T0]])
+// CHECK-NEXT: dealloc_stack [[TEMP2]]
+// CHECK-NEXT: br [[CONT]]
+//
+// CHECK: [[CONT]]:
+// CHECK-NEXT: dealloc_stack [[BUFFER2]]
+// CHECK-NEXT: dealloc_stack [[STORAGE2]]
+// CHECK-NEXT: dealloc_stack [[BUFFER]]
+// CHECK-NEXT: dealloc_stack [[STORAGE]]
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+struct RecInner {
+ subscript(i: Int) -> Int {
+ get { return i }
+ }
+}
+struct RecOuter {
+ var inner : RecInner {
+ unsafeAddress { return someValidPointer() }
+ unsafeMutableAddress { return someValidPointer() }
+ }
+}
+func test_rec(_ outer: inout RecOuter) -> Int {
+ return outer.inner[0]
+}
+// This uses the immutable addressor.
+// CHECK: sil hidden @$S9accessors8test_recySiAA8RecOuterVzF : $@convention(thin) (@inout RecOuter) -> Int {
+// CHECK: function_ref @$S9accessors8RecOuterV5innerAA0B5InnerVvlu : $@convention(method) (RecOuter) -> UnsafePointer<RecInner>
+
+struct Rec2Inner {
+ subscript(i: Int) -> Int {
+ mutating get { return i }
+ }
+}
+struct Rec2Outer {
+ var inner : Rec2Inner {
+ unsafeAddress { return someValidPointer() }
+ unsafeMutableAddress { return someValidPointer() }
+ }
+}
+func test_rec2(_ outer: inout Rec2Outer) -> Int {
+ return outer.inner[0]
+}
+// This uses the mutable addressor.
+// CHECK: sil hidden @$S9accessors9test_rec2ySiAA9Rec2OuterVzF : $@convention(thin) (@inout Rec2Outer) -> Int {
+// CHECK: function_ref @$S9accessors9Rec2OuterV5innerAA0B5InnerVvau : $@convention(method) (@inout Rec2Outer) -> UnsafeMutablePointer<Rec2Inner>
+
+struct Foo {
+ private subscript(privateSubscript x: Void) -> Void {
+ // CHECK-DAG: sil private @$S9accessors3FooV16privateSubscriptyyt_tc33_D7F31B09EE737C687DC580B2014D759CLlig : $@convention(method) (Foo) -> () {
+ get {}
+ }
+ private(set) subscript(withPrivateSet x: Void) -> Void {
+ // CHECK-DAG: sil hidden @$S9accessors3FooV14withPrivateSetyyt_tcig : $@convention(method) (Foo) -> () {
+ get {}
+ // CHECK-DAG: sil private @$S9accessors3FooV14withPrivateSetyyt_tcis : $@convention(method) (@inout Foo) -> () {
+ set {}
+ }
+ subscript(withNestedClass x: Void) -> Void {
+ // Check for initializer of NestedClass
+ // CHECK-DAG: sil private @$S9accessors3FooV15withNestedClassyyt_tcig0dE0L_CAFycfc : $@convention(method) (@owned NestedClass) -> @owned NestedClass {
+ class NestedClass {}
+ }
+
+ // CHECK-DAG: sil private @$S9accessors3FooV15privateVariable33_D7F31B09EE737C687DC580B2014D759CLLytvg : $@convention(method) (Foo) -> () {
+ private var privateVariable: Void {
+ return
+ }
+ private(set) var variableWithPrivateSet: Void {
+ // CHECK-DAG: sil hidden @$S9accessors3FooV22variableWithPrivateSetytvg : $@convention(method) (Foo) -> () {
+ get {}
+ // CHECK-DAG: sil private @$S9accessors3FooV22variableWithPrivateSetytvs : $@convention(method) (@inout Foo) -> () {
+ set {}
+ }
+ var propertyWithNestedClass: Void {
+ // Check for initializer of NestedClass
+ // CHECK-DAG: sil private @$S9accessors3FooV23propertyWithNestedClassytvg0eF0L_CAFycfc : $@convention(method) (@owned NestedClass) -> @owned NestedClass {
+ class NestedClass {}
+ }
+}
diff --git a/test/SILGen/plus_zero_address_only_types.swift b/test/SILGen/plus_zero_address_only_types.swift
new file mode 100644
index 0000000..e270074
--- /dev/null
+++ b/test/SILGen/plus_zero_address_only_types.swift
@@ -0,0 +1,229 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-as-library -parse-stdlib -emit-silgen %s | %FileCheck %s
+
+precedencegroup AssignmentPrecedence { assignment: true }
+
+typealias Int = Builtin.Int64
+
+enum Bool { case true_, false_ }
+
+protocol Unloadable {
+ func foo() -> Int
+ var address_only_prop : Unloadable { get }
+ var loadable_prop : Int { get }
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B9_argument{{[_0-9a-zA-Z]*}}F
+func address_only_argument(_ x: Unloadable) {
+ // CHECK: bb0([[XARG:%[0-9]+]] : @trivial $*Unloadable):
+ // CHECK: debug_value_addr [[XARG]]
+ // CHECK-NEXT: tuple
+ // CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B17_ignored_argument{{[_0-9a-zA-Z]*}}F
+func address_only_ignored_argument(_: Unloadable) {
+ // CHECK: bb0([[XARG:%[0-9]+]] : @trivial $*Unloadable):
+ // CHECK-NOT: dealloc_stack {{.*}} [[XARG]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B7_return{{[_0-9a-zA-Z]*}}F
+func address_only_return(_ x: Unloadable, y: Int) -> Unloadable {
+ // CHECK: bb0([[RET:%[0-9]+]] : @trivial $*Unloadable, [[XARG:%[0-9]+]] : @trivial $*Unloadable, [[YARG:%[0-9]+]] : @trivial $Builtin.Int64):
+ // CHECK-NEXT: debug_value_addr [[XARG]] : $*Unloadable, let, name "x"
+ // CHECK-NEXT: debug_value [[YARG]] : $Builtin.Int64, let, name "y"
+ // CHECK-NEXT: copy_addr [[XARG]] to [initialization] [[RET]]
+ // CHECK-NEXT: [[VOID:%[0-9]+]] = tuple ()
+ // CHECK-NEXT: return [[VOID]]
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B15_missing_return{{[_0-9a-zA-Z]*}}F
+func address_only_missing_return() -> Unloadable {
+ // CHECK: unreachable
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B27_conditional_missing_return{{[_0-9a-zA-Z]*}}F
+func address_only_conditional_missing_return(_ x: Unloadable) -> Unloadable {
+ // CHECK: bb0({{%.*}} : @trivial $*Unloadable, {{%.*}} : @trivial $*Unloadable):
+ // CHECK: switch_enum {{%.*}}, case #Bool.true_!enumelt: [[TRUE:bb[0-9]+]], case #Bool.false_!enumelt: [[FALSE:bb[0-9]+]]
+ switch Bool.true_ {
+ case .true_:
+ // CHECK: [[TRUE]]:
+ // CHECK: copy_addr %1 to [initialization] %0 : $*Unloadable
+ // CHECK: return
+ return x
+ case .false_:
+ ()
+ }
+ // CHECK: [[FALSE]]:
+ // CHECK: unreachable
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B29_conditional_missing_return_2
+func address_only_conditional_missing_return_2(_ x: Unloadable) -> Unloadable {
+ // CHECK: bb0({{%.*}} : @trivial $*Unloadable, {{%.*}} : @trivial $*Unloadable):
+ // CHECK: switch_enum {{%.*}}, case #Bool.true_!enumelt: [[TRUE1:bb[0-9]+]], case #Bool.false_!enumelt: [[FALSE1:bb[0-9]+]]
+ switch Bool.true_ {
+ case .true_:
+ return x
+ case .false_:
+ ()
+ }
+ // CHECK: [[FALSE1]]:
+ // CHECK: switch_enum {{%.*}}, case #Bool.true_!enumelt: [[TRUE2:bb[0-9]+]], case #Bool.false_!enumelt: [[FALSE2:bb[0-9]+]]
+ switch Bool.true_ {
+ case .true_:
+ return x
+ case .false_:
+ ()
+ }
+ // CHECK: [[FALSE2]]:
+ // CHECK: unreachable
+
+ // CHECK: bb{{.*}}:
+ // CHECK: return
+}
+
+var crap : Unloadable = some_address_only_function_1()
+func some_address_only_function_1() -> Unloadable { return crap }
+func some_address_only_function_2(_ x: Unloadable) -> () {}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B7_call_1
+func address_only_call_1() -> Unloadable {
+ // CHECK: bb0([[RET:%[0-9]+]] : @trivial $*Unloadable):
+ return some_address_only_function_1()
+ // FIXME emit into
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S18address_only_types05some_a1_B11_function_1AA10Unloadable_pyF
+ // CHECK: apply [[FUNC]]([[RET]])
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B21_call_1_ignore_returnyyF
+func address_only_call_1_ignore_return() {
+ // CHECK: bb0:
+ some_address_only_function_1()
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S18address_only_types05some_a1_B11_function_1AA10Unloadable_pyF
+ // CHECK: apply [[FUNC]]([[TEMP]])
+ // CHECK: destroy_addr [[TEMP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B7_call_2{{[_0-9a-zA-Z]*}}F
+func address_only_call_2(_ x: Unloadable) {
+ // CHECK: bb0([[XARG:%[0-9]+]] : @trivial $*Unloadable):
+ // CHECK: debug_value_addr [[XARG]] : $*Unloadable
+ some_address_only_function_2(x)
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S18address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC]]([[XARG]])
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B12_call_1_in_2{{[_0-9a-zA-Z]*}}F
+func address_only_call_1_in_2() {
+ // CHECK: bb0:
+ some_address_only_function_2(some_address_only_function_1())
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[FUNC1:%[0-9]+]] = function_ref @$S18address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC1]]([[TEMP]])
+ // CHECK: [[FUNC2:%[0-9]+]] = function_ref @$S18address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC2]]([[TEMP]])
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B12_materialize{{[_0-9a-zA-Z]*}}F
+func address_only_materialize() -> Int {
+ // CHECK: bb0:
+ return some_address_only_function_1().foo()
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S18address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC]]([[TEMP]])
+ // CHECK: [[TEMP_PROJ:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*Unloadable to $*[[OPENED:@opened(.*) Unloadable]]
+ // CHECK: [[FOO_METHOD:%[0-9]+]] = witness_method $[[OPENED]], #Unloadable.foo!1
+ // CHECK: [[RET:%[0-9]+]] = apply [[FOO_METHOD]]<[[OPENED]]>([[TEMP_PROJ]])
+ // CHECK: destroy_addr [[TEMP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: return [[RET]]
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B21_assignment_from_temp{{[_0-9a-zA-Z]*}}F
+func address_only_assignment_from_temp(_ dest: inout Unloadable) {
+ // CHECK: bb0([[DEST:%[0-9]+]] : @trivial $*Unloadable):
+ dest = some_address_only_function_1()
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: %[[ACCESS:.*]] = begin_access [modify] [unknown] %0 :
+ // CHECK: copy_addr [take] [[TEMP]] to %[[ACCESS]] :
+ // CHECK-NOT: destroy_addr [[TEMP]]
+ // CHECK: dealloc_stack [[TEMP]]
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B19_assignment_from_lv{{[_0-9a-zA-Z]*}}F
+func address_only_assignment_from_lv(_ dest: inout Unloadable, v: Unloadable) {
+ var v = v
+ // CHECK: bb0([[DEST:%[0-9]+]] : @trivial $*Unloadable, [[VARG:%[0-9]+]] : @trivial $*Unloadable):
+ // CHECK: [[VBOX:%.*]] = alloc_box ${ var Unloadable }
+ // CHECK: [[PBOX:%[0-9]+]] = project_box [[VBOX]]
+ // CHECK: copy_addr [[VARG]] to [initialization] [[PBOX]] : $*Unloadable
+ dest = v
+ // CHECK: [[READBOX:%.*]] = begin_access [read] [unknown] [[PBOX]] :
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: copy_addr [[READBOX]] to [initialization] [[TEMP]] :
+ // CHECK: [[RET:%.*]] = begin_access [modify] [unknown] %0 :
+ // CHECK: copy_addr [take] [[TEMP]] to [[RET]] :
+ // CHECK: destroy_value [[VBOX]]
+}
+
+var global_prop : Unloadable {
+ get {
+ return crap
+ }
+ set {}
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B33_assignment_from_temp_to_property{{[_0-9a-zA-Z]*}}F
+func address_only_assignment_from_temp_to_property() {
+ // CHECK: bb0:
+ global_prop = some_address_only_function_1()
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[SETTER:%[0-9]+]] = function_ref @$S18address_only_types11global_propAA10Unloadable_pvs
+ // CHECK: apply [[SETTER]]([[TEMP]])
+ // CHECK: dealloc_stack [[TEMP]]
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B31_assignment_from_lv_to_property{{[_0-9a-zA-Z]*}}F
+func address_only_assignment_from_lv_to_property(_ v: Unloadable) {
+ // CHECK: bb0([[VARG:%[0-9]+]] : @trivial $*Unloadable):
+ // CHECK: debug_value_addr [[VARG]] : $*Unloadable
+ // CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: copy_addr [[VARG]] to [initialization] [[TEMP]]
+ // CHECK: [[SETTER:%[0-9]+]] = function_ref @$S18address_only_types11global_propAA10Unloadable_pvs
+ // CHECK: apply [[SETTER]]([[TEMP]])
+ // CHECK: dealloc_stack [[TEMP]]
+ global_prop = v
+}
+
+// CHECK-LABEL: sil hidden @$S18address_only_types0a1_B4_varAA10Unloadable_pyF
+func address_only_var() -> Unloadable {
+ // CHECK: bb0([[RET:%[0-9]+]] : @trivial $*Unloadable):
+ var x = some_address_only_function_1()
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Unloadable }
+ // CHECK: [[XPB:%.*]] = project_box [[XBOX]]
+ // CHECK: apply {{%.*}}([[XPB]])
+ return x
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XPB]] :
+ // CHECK: copy_addr [[ACCESS]] to [initialization] %0
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return
+}
+
+func unloadable_to_unloadable(_ x: Unloadable) -> Unloadable { return x }
+var some_address_only_nontuple_arg_function : (Unloadable) -> Unloadable = unloadable_to_unloadable
+
+// CHECK-LABEL: sil hidden @$S18address_only_types05call_a1_B22_nontuple_arg_function{{[_0-9a-zA-Z]*}}F
+func call_address_only_nontuple_arg_function(_ x: Unloadable) {
+ some_address_only_nontuple_arg_function(x)
+}
diff --git a/test/SILGen/plus_zero_addressors.swift b/test/SILGen/plus_zero_addressors.swift
new file mode 100644
index 0000000..0a02140
--- /dev/null
+++ b/test/SILGen/plus_zero_addressors.swift
@@ -0,0 +1,582 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-sil %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-silgen %s | %FileCheck %s -check-prefix=SILGEN
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-ir %s
+
+// This test includes some calls to transparent stdlib functions.
+// We pattern match for the absence of access markers in the inlined code.
+// REQUIRES: optimized_stdlib
+
+import Swift
+
+func someValidPointer<T>() -> UnsafePointer<T> { fatalError() }
+func someValidPointer<T>() -> UnsafeMutablePointer<T> { fatalError() }
+
+struct A {
+ var base: UnsafeMutablePointer<Int32> = someValidPointer()
+
+ subscript(index: Int32) -> Int32 {
+ unsafeAddress {
+ return UnsafePointer(base)
+ }
+ unsafeMutableAddress {
+ return base
+ }
+ }
+
+ static var staticProp: Int32 {
+ unsafeAddress {
+ // Just don't trip up the verifier.
+ fatalError()
+ }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10addressors1AVys5Int32VAEcilu : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
+// CHECK: bb0([[INDEX:%.*]] : $Int32, [[SELF:%.*]] : $A):
+// CHECK: [[BASE:%.*]] = struct_extract [[SELF]] : $A, #A.base
+// CHECK: [[T0:%.*]] = struct_extract [[BASE]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[T1:%.*]] = struct $UnsafePointer<Int32> ([[T0]] : $Builtin.RawPointer)
+// CHECK: return [[T1]] : $UnsafePointer<Int32>
+
+// CHECK-LABEL: sil hidden @$S10addressors1AVys5Int32VAEciau : $@convention(method) (Int32, @inout A) -> UnsafeMutablePointer<Int32>
+// CHECK: bb0([[INDEX:%.*]] : $Int32, [[SELF:%.*]] : $*A):
+// CHECK: [[READ:%.*]] = begin_access [read] [static] [[SELF]] : $*A
+// CHECK: [[T0:%.*]] = struct_element_addr [[READ]] : $*A, #A.base
+// CHECK: [[BASE:%.*]] = load [[T0]] : $*UnsafeMutablePointer<Int32>
+// CHECK: return [[BASE]] : $UnsafeMutablePointer<Int32>
+
+// CHECK-LABEL: sil hidden @$S10addressors5test0yyF : $@convention(thin) () -> () {
+func test0() {
+// CHECK: [[A:%.*]] = alloc_stack $A
+// CHECK: [[T1:%.*]] = metatype $@thin A.Type
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1AV{{[_0-9a-zA-Z]*}}fC
+// CHECK: [[AVAL:%.*]] = apply [[T0]]([[T1]])
+// CHECK: store [[AVAL]] to [[A]]
+ var a = A()
+
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1AVys5Int32VAEcilu :
+// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[AVAL]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
+// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[Z:%.*]] = load [[T3]] : $*Int32
+ let z = a[10]
+
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1AVys5Int32VAEciau :
+// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: load
+// CHECK: sadd_with_overflow_Int{{32|64}}
+// CHECK: store {{%.*}} to [[T3]]
+ a[5] += z
+
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[A]] : $*A
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1AVys5Int32VAEciau :
+// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: store {{%.*}} to [[T3]]
+ a[3] = 6
+}
+
+// CHECK-LABEL: sil hidden @$S10addressors5test1s5Int32VyF : $@convention(thin) () -> Int32
+func test1() -> Int32 {
+// CHECK: [[T0:%.*]] = metatype $@thin A.Type
+// CHECK: [[CTOR:%.*]] = function_ref @$S10addressors1AV{{[_0-9a-zA-Z]*}}fC
+// CHECK: [[A:%.*]] = apply [[CTOR]]([[T0]]) : $@convention(method) (@thin A.Type) -> A
+// CHECK: [[ACCESSOR:%.*]] = function_ref @$S10addressors1AVys5Int32VAEcilu : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
+// CHECK: [[PTR:%.*]] = apply [[ACCESSOR]]({{%.*}}, [[A]]) : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = load [[T1]] : $*Int32
+// CHECK: return [[T2]] : $Int32
+ return A()[0]
+}
+
+let uninitAddr = UnsafeMutablePointer<Int32>.allocate(capacity: 1)
+var global: Int32 {
+ unsafeAddress {
+ return UnsafePointer(uninitAddr)
+ }
+// CHECK: sil hidden @$S10addressors6globals5Int32Vvlu : $@convention(thin) () -> UnsafePointer<Int32> {
+// CHECK: [[T0:%.*]] = global_addr @$S10addressors10uninitAddrSpys5Int32VGvp : $*UnsafeMutablePointer<Int32>
+// CHECK: [[T1:%.*]] = load [[T0]] : $*UnsafeMutablePointer<Int32>
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[T3:%.*]] = struct $UnsafePointer<Int32> ([[T2]] : $Builtin.RawPointer)
+// CHECK: return [[T3]] : $UnsafePointer<Int32>
+}
+
+func test_global() -> Int32 {
+ return global
+}
+// CHECK-LABEL: sil hidden @$S10addressors11test_globals5Int32VyF : $@convention(thin) () -> Int32 {
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors6globals5Int32Vvlu : $@convention(thin) () -> UnsafePointer<Int32>
+// CHECK: [[T1:%.*]] = apply [[T0]]() : $@convention(thin) () -> UnsafePointer<Int32>
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafePointer<Int32>, #UnsafePointer._rawValue
+// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T4:%.*]] = load [[T3]] : $*Int32
+// CHECK: return [[T4]] : $Int32
+
+// Test that having generated trivial accessors for something because
+// of protocol conformance doesn't force us down inefficient access paths.
+protocol Subscriptable {
+ subscript(i: Int32) -> Int32 { get set }
+}
+
+struct B : Subscriptable {
+ subscript(i: Int32) -> Int32 {
+ unsafeAddress { return someValidPointer() }
+ unsafeMutableAddress { return someValidPointer() }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10addressors6test_ByyAA1BVzF : $@convention(thin) (@inout B) -> () {
+// CHECK: bb0([[B:%.*]] : $*B):
+// CHECK: [[T0:%.*]] = integer_literal $Builtin.Int32, 0
+// CHECK: [[INDEX:%.*]] = struct $Int32 ([[T0]] : $Builtin.Int32)
+// CHECK: [[RHS:%.*]] = integer_literal $Builtin.Int32, 7
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[B]] : $*B
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1BVys5Int32VAEciau
+// CHECK: [[PTR:%.*]] = apply [[T0]]([[INDEX]], [[WRITE]])
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
+// CHECK: [[ADDR:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// Accept either of struct_extract+load or load+struct_element_addr.
+// CHECK: load
+// CHECK: [[T1:%.*]] = builtin "or_Int32"
+// CHECK: [[T2:%.*]] = struct $Int32 ([[T1]] : $Builtin.Int32)
+// CHECK: store [[T2]] to [[ADDR]] : $*Int32
+func test_B(_ b: inout B) {
+ b[0] |= 7
+}
+
+// Test that we handle abstraction difference.
+struct CArray<T> {
+ var storage: UnsafeMutablePointer<T>
+ subscript(index: Int) -> T {
+ unsafeAddress { return UnsafePointer(storage) + index }
+ unsafeMutableAddress { return storage + index }
+ }
+}
+
+func id_int(_ i: Int32) -> Int32 { return i }
+
+// CHECK-LABEL: sil hidden @$S10addressors11test_carrayys5Int32VAA6CArrayVyA2DcGzF : $@convention(thin) (@inout CArray<(Int32) -> Int32>) -> Int32 {
+// CHECK: bb0([[ARRAY:%.*]] : $*CArray<(Int32) -> Int32>):
+func test_carray(_ array: inout CArray<(Int32) -> Int32>) -> Int32 {
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*CArray<(Int32) -> Int32>
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors6CArrayVyxSiciau :
+// CHECK: [[T1:%.*]] = apply [[T0]]<(Int32) -> Int32>({{%.*}}, [[WRITE]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<(Int32) -> Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
+// CHECK: store {{%.*}} to [[T3]] :
+ array[0] = id_int
+
+// CHECK: [[READ:%.*]] = begin_access [read] [static] [[ARRAY]] : $*CArray<(Int32) -> Int32>
+// CHECK: [[T0:%.*]] = load [[READ]]
+// CHECK: [[T1:%.*]] = function_ref @$S10addressors6CArrayVyxSicilu :
+// CHECK: [[T2:%.*]] = apply [[T1]]<(Int32) -> Int32>({{%.*}}, [[T0]])
+// CHECK: [[T3:%.*]] = struct_extract [[T2]] : $UnsafePointer<(Int32) -> Int32>, #UnsafePointer._rawValue
+// CHECK: [[T4:%.*]] = pointer_to_address [[T3]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed (@in_guaranteed Int32) -> @out Int32
+// CHECK: [[T5:%.*]] = load [[T4]]
+ return array[1](5)
+}
+
+// rdar://17270560, redux
+struct D : Subscriptable {
+ subscript(i: Int32) -> Int32 {
+ get { return i }
+ unsafeMutableAddress { return someValidPointer() }
+ }
+}
+// Setter.
+// SILGEN-LABEL: sil hidden [transparent] @$S10addressors1DVys5Int32VAEcis
+// SILGEN: bb0([[VALUE:%.*]] : @trivial $Int32, [[I:%.*]] : @trivial $Int32, [[SELF:%.*]] : @trivial $*D):
+// SILGEN: debug_value [[VALUE]] : $Int32
+// SILGEN: debug_value [[I]] : $Int32
+// SILGEN: debug_value_addr [[SELF]]
+// SILGEN: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF]] : $*D // users: %12, %8
+// SILGEN: [[T0:%.*]] = function_ref @$S10addressors1DVys5Int32VAEciau{{.*}}
+// SILGEN: [[PTR:%.*]] = apply [[T0]]([[I]], [[ACCESS]])
+// SILGEN: [[T0:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
+// SILGEN: [[ADDR:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// SILGEN: assign [[VALUE]] to [[ADDR]] : $*Int32
+
+// materializeForSet.
+// SILGEN-LABEL: sil hidden [transparent] @$S10addressors1DVys5Int32VAEcim
+// SILGEN: bb0([[BUFFER:%.*]] : @trivial $Builtin.RawPointer, [[STORAGE:%.*]] : @trivial $*Builtin.UnsafeValueBuffer, [[I:%.*]] : @trivial $Int32, [[SELF:%.*]] : @trivial $*D):
+// SILGEN: [[T0:%.*]] = function_ref @$S10addressors1DVys5Int32VAEciau
+// SILGEN: [[PTR:%.*]] = apply [[T0]]([[I]], [[SELF]])
+// SILGEN: [[ADDR_TMP:%.*]] = struct_extract [[PTR]] : $UnsafeMutablePointer<Int32>,
+// SILGEN: [[ADDR:%.*]] = pointer_to_address [[ADDR_TMP]]
+// SILGEN: [[PTR:%.*]] = address_to_pointer [[ADDR]]
+// SILGEN: [[OPT:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.none!enumelt
+// SILGEN: [[T2:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[OPT]] : $Optional<Builtin.RawPointer>)
+// SILGEN: return [[T2]] :
+
+func make_int() -> Int32 { return 0 }
+func take_int_inout(_ value: inout Int32) {}
+
+// CHECK-LABEL: sil hidden @$S10addressors6test_dys5Int32VAA1DVzF : $@convention(thin) (@inout D) -> Int32
+// CHECK: bb0([[ARRAY:%.*]] : $*D):
+func test_d(_ array: inout D) -> Int32 {
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors8make_ints5Int32VyF
+// CHECK: [[V:%.*]] = apply [[T0]]()
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*D
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1DVys5Int32VAEciau
+// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
+// CHECK: [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: store [[V]] to [[ADDR]] : $*Int32
+ array[0] = make_int()
+
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*D
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1DVys5Int32VAEciau
+// CHECK: [[T1:%.*]] = apply [[T0]]({{%.*}}, [[WRITE]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>,
+// CHECK: [[ADDR:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[FN:%.*]] = function_ref @$S10addressors14take_int_inoutyys5Int32VzF
+// CHECK: apply [[FN]]([[ADDR]])
+ take_int_inout(&array[1])
+
+// CHECK: [[READ:%.*]] = begin_access [read] [static] [[ARRAY]] : $*D
+// CHECK: [[T0:%.*]] = load [[READ]]
+// CHECK: [[T1:%.*]] = function_ref @$S10addressors1DVys5Int32VAEcig
+// CHECK: [[T2:%.*]] = apply [[T1]]({{%.*}}, [[T0]])
+// CHECK: return [[T2]]
+ return array[2]
+}
+
+struct E {
+ var value: Int32 {
+ unsafeAddress { return someValidPointer() }
+ nonmutating unsafeMutableAddress { return someValidPointer() }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10addressors6test_eyyAA1EVF
+// CHECK: bb0([[E:%.*]] : $E):
+// CHECK: [[T0:%.*]] = function_ref @$S10addressors1EV5values5Int32Vvau
+// CHECK: [[T1:%.*]] = apply [[T0]]([[E]])
+// CHECK: [[T2:%.*]] = struct_extract [[T1]]
+// CHECK: [[T3:%.*]] = pointer_to_address [[T2]]
+// CHECK: store {{%.*}} to [[T3]] : $*Int32
+func test_e(_ e: E) {
+ e.value = 0
+}
+
+class F {
+ var data: UnsafeMutablePointer<Int32> = UnsafeMutablePointer.allocate(capacity: 100)
+
+ final var value: Int32 {
+ addressWithNativeOwner {
+ return (UnsafePointer(data), Builtin.castToNativeObject(self))
+ }
+ mutableAddressWithNativeOwner {
+ return (data, Builtin.castToNativeObject(self))
+ }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10addressors1FC5values5Int32Vvlo : $@convention(method) (@guaranteed F) -> (UnsafePointer<Int32>, @owned Builtin.NativeObject) {
+// CHECK-LABEL: sil hidden @$S10addressors1FC5values5Int32Vvao : $@convention(method) (@guaranteed F) -> (UnsafeMutablePointer<Int32>, @owned Builtin.NativeObject) {
+
+func test_f0(_ f: F) -> Int32 {
+ return f.value
+}
+// CHECK-LABEL: sil hidden @$S10addressors7test_f0ys5Int32VAA1FCF : $@convention(thin) (@guaranteed F) -> Int32 {
+// CHECK: bb0([[SELF:%0]] : $F):
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1FC5values5Int32Vvlo : $@convention(method) (@guaranteed F) -> (UnsafePointer<Int32>, @owned Builtin.NativeObject)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Builtin.NativeObject), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Builtin.NativeObject), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
+// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+// CHECK-NOT: strong_release [[SELF]] : $F
+// CHECK: return [[VALUE]] : $Int32
+
+func test_f1(_ f: F) {
+ f.value = 14
+}
+// CHECK-LABEL: sil hidden @$S10addressors7test_f1yyAA1FCF : $@convention(thin) (@guaranteed F) -> () {
+// CHECK: bb0([[SELF:%0]] : $F):
+// CHECK: [[T0:%.*]] = integer_literal $Builtin.Int32, 14
+// CHECK: [[VALUE:%.*]] = struct $Int32 ([[T0]] : $Builtin.Int32)
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1FC5values5Int32Vvao : $@convention(method) (@guaranteed F) -> (UnsafeMutablePointer<Int32>, @owned Builtin.NativeObject)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Builtin.NativeObject), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Builtin.NativeObject), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
+// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+// CHECK-NOT: strong_release [[SELF]] : $F
+
+class G {
+ var data: UnsafeMutablePointer<Int32> = UnsafeMutablePointer.allocate(capacity: 100)
+
+ var value: Int32 {
+ addressWithNativeOwner {
+ return (UnsafePointer(data), Builtin.castToNativeObject(self))
+ }
+ mutableAddressWithNativeOwner {
+ return (data, Builtin.castToNativeObject(self))
+ }
+ }
+}
+// CHECK-LABEL: sil hidden [transparent] @$S10addressors1GC5values5Int32Vvg : $@convention(method) (@guaranteed G) -> Int32 {
+// CHECK: bb0([[SELF:%0]] : $G):
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1GC5values5Int32Vvlo : $@convention(method) (@guaranteed G) -> (UnsafePointer<Int32>, @owned Builtin.NativeObject)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Builtin.NativeObject), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Builtin.NativeObject), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
+// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+// CHECK: return [[VALUE]] : $Int32
+
+// CHECK-LABEL: sil hidden [transparent] @$S10addressors1GC5values5Int32Vvs : $@convention(method) (Int32, @guaranteed G) -> () {
+// CHECK: bb0([[VALUE:%0]] : $Int32, [[SELF:%1]] : $G):
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1GC5values5Int32Vvao : $@convention(method) (@guaranteed G) -> (UnsafeMutablePointer<Int32>, @owned Builtin.NativeObject)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Builtin.NativeObject), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Builtin.NativeObject), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Builtin.NativeObject
+// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+
+// materializeForSet callback for G.value
+// CHECK-LABEL: sil private [transparent] @$S10addressors1GC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () {
+// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*G, [[SELFTYPE:%3]] : $@thick G.Type):
+// CHECK: [[T0:%.*]] = project_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[OWNER:%.*]] = load [[T0]]
+// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject
+// CHECK: dealloc_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+
+// materializeForSet for G.value
+// CHECK-LABEL: sil hidden [transparent] @$S10addressors1GC5values5Int32Vvm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed G) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $G):
+// Call the addressor.
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1GC5values5Int32Vvao : $@convention(method) (@guaranteed G) -> (UnsafeMutablePointer<Int32>, @owned Builtin.NativeObject)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[T1:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Builtin.NativeObject), 0
+// CHECK: [[T2:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Builtin.NativeObject), 1
+// Get the address.
+// CHECK: [[PTR:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[ADDR_TMP:%.*]] = pointer_to_address [[PTR]]
+// CHECK: [[ADDR:%.*]] = mark_dependence [[ADDR_TMP]] : $*Int32 on [[T2]]
+// Initialize the callback storage with the owner.
+// CHECK: [[T0:%.*]] = alloc_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+// CHECK: store [[T2]] to [[T0]] : $*Builtin.NativeObject
+// CHECK: [[PTR:%.*]] = address_to_pointer [[ADDR]]
+// Set up the callback.
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S10addressors1GC5values5Int32VvmytfU_ :
+// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
+// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
+// Epilogue.
+// CHECK: [[RESULT:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[RESULT]]
+
+class H {
+ var data: UnsafeMutablePointer<Int32> = UnsafeMutablePointer.allocate(capacity: 100)
+
+ final var value: Int32 {
+ addressWithPinnedNativeOwner {
+ return (UnsafePointer(data), Builtin.tryPin(Builtin.castToNativeObject(self)))
+ }
+ mutableAddressWithPinnedNativeOwner {
+ return (data, Builtin.tryPin(Builtin.castToNativeObject(self)))
+ }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10addressors1HC5values5Int32Vvlp : $@convention(method) (@guaranteed H) -> (UnsafePointer<Int32>, @owned Optional<Builtin.NativeObject>) {
+// CHECK-LABEL: sil hidden @$S10addressors1HC5values5Int32VvaP : $@convention(method) (@guaranteed H) -> (UnsafeMutablePointer<Int32>, @owned Optional<Builtin.NativeObject>) {
+
+func test_h0(_ f: H) -> Int32 {
+ return f.value
+}
+// CHECK-LABEL: sil hidden @$S10addressors7test_h0ys5Int32VAA1HCF : $@convention(thin) (@guaranteed H) -> Int32 {
+// CHECK: bb0([[SELF:%0]] : $H):
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1HC5values5Int32Vvlp : $@convention(method) (@guaranteed H) -> (UnsafePointer<Int32>, @owned Optional<Builtin.NativeObject>)
+
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Optional<Builtin.NativeObject>), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Optional<Builtin.NativeObject>), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK-NOT: strong_release [[SELF]] : $H
+// CHECK: return [[VALUE]] : $Int32
+
+func test_h1(_ f: H) {
+ f.value = 14
+}
+// CHECK-LABEL: sil hidden @$S10addressors7test_h1yyAA1HCF : $@convention(thin) (@guaranteed H) -> () {
+// CHECK: bb0([[SELF:%0]] : $H):
+// CHECK: [[T0:%.*]] = integer_literal $Builtin.Int32, 14
+// CHECK: [[VALUE:%.*]] = struct $Int32 ([[T0]] : $Builtin.Int32)
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1HC5values5Int32VvaP : $@convention(method) (@guaranteed H) -> (UnsafeMutablePointer<Int32>, @owned Optional<Builtin.NativeObject>)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Optional<Builtin.NativeObject>), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Optional<Builtin.NativeObject>), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK-NOT: strong_release [[SELF]] : $H
+
+class I {
+ var data: UnsafeMutablePointer<Int32> = UnsafeMutablePointer.allocate(capacity: 100)
+
+ var value: Int32 {
+ addressWithPinnedNativeOwner {
+ return (UnsafePointer(data), Builtin.tryPin(Builtin.castToNativeObject(self)))
+ }
+ mutableAddressWithPinnedNativeOwner {
+ return (data, Builtin.tryPin(Builtin.castToNativeObject(self)))
+ }
+ }
+}
+// CHECK-LABEL: sil hidden [transparent] @$S10addressors1IC5values5Int32Vvg : $@convention(method) (@guaranteed I) -> Int32 {
+// CHECK: bb0([[SELF:%0]] : $I):
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1IC5values5Int32Vvlp : $@convention(method) (@guaranteed I) -> (UnsafePointer<Int32>, @owned Optional<Builtin.NativeObject>)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Optional<Builtin.NativeObject>), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafePointer<Int32>, Optional<Builtin.NativeObject>), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: [[VALUE:%.*]] = load [[T2]] : $*Int32
+// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: return [[VALUE]] : $Int32
+
+// CHECK-LABEL: sil hidden [transparent] @$S10addressors1IC5values5Int32Vvs : $@convention(method) (Int32, @guaranteed I) -> () {
+// CHECK: bb0([[VALUE:%0]] : $Int32, [[SELF:%1]] : $I):
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1IC5values5Int32VvaP : $@convention(method) (@guaranteed I) -> (UnsafeMutablePointer<Int32>, @owned Optional<Builtin.NativeObject>)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[PTR:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Optional<Builtin.NativeObject>), 0
+// CHECK: [[OWNER:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Optional<Builtin.NativeObject>), 1
+// CHECK: [[T0:%.*]] = struct_extract [[PTR]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Int32
+// CHECK: [[T2:%.*]] = mark_dependence [[T1]] : $*Int32 on [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: store [[VALUE]] to [[T2]] : $*Int32
+// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+
+// materializeForSet callback for I.value
+// CHECK-LABEL: sil private [transparent] @$S10addressors1IC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () {
+// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*I, [[SELFTYPE:%3]] : $@thick I.Type):
+// CHECK: [[T0:%.*]] = project_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[OWNER:%.*]] = load [[T0]]
+// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
+// CHECK: dealloc_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+
+// CHECK-LABEL: sil hidden [transparent] @$S10addressors1IC5values5Int32Vvm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed I) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $I):
+// Call the addressor.
+// CHECK: [[ADDRESSOR:%.*]] = function_ref @$S10addressors1IC5values5Int32VvaP : $@convention(method) (@guaranteed I) -> (UnsafeMutablePointer<Int32>, @owned Optional<Builtin.NativeObject>)
+// CHECK: [[T0:%.*]] = apply [[ADDRESSOR]]([[SELF]])
+// CHECK: [[T1:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Optional<Builtin.NativeObject>), 0
+// CHECK: [[T2:%.*]] = tuple_extract [[T0]] : $(UnsafeMutablePointer<Int32>, Optional<Builtin.NativeObject>), 1
+// Pull out the address.
+// CHECK: [[PTR:%.*]] = struct_extract [[T1]] : $UnsafeMutablePointer<Int32>, #UnsafeMutablePointer._rawValue
+// CHECK: [[ADDR_TMP:%.*]] = pointer_to_address [[PTR]]
+// CHECK: [[ADDR:%.*]] = mark_dependence [[ADDR_TMP]] : $*Int32 on [[T2]]
+// Initialize the callback storage with the owner.
+// CHECK: [[T0:%.*]] = alloc_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
+// CHECK: store [[T2]] to [[T0]] : $*Optional<Builtin.NativeObject>
+// CHECK: [[PTR:%.*]] = address_to_pointer [[ADDR]]
+// Set up the callback.
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S10addressors1IC5values5Int32VvmytfU_ :
+// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
+// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
+// Epilogue.
+// CHECK: [[RESULT:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[RESULT]]
+
+struct RecInner {
+ subscript(i: Int32) -> Int32 {
+ mutating get { return i }
+ }
+}
+struct RecMiddle {
+ var inner: RecInner
+}
+class RecOuter {
+ var data: UnsafeMutablePointer<RecMiddle> = UnsafeMutablePointer.allocate(capacity: 100)
+ final var middle: RecMiddle {
+ addressWithPinnedNativeOwner {
+ return (UnsafePointer(data), Builtin.tryPin(Builtin.castToNativeObject(self)))
+ }
+ mutableAddressWithPinnedNativeOwner {
+ return (data, Builtin.tryPin(Builtin.castToNativeObject(self)))
+ }
+ }
+}
+func test_rec(_ outer: RecOuter) -> Int32 {
+ return outer.middle.inner[0]
+}
+// This uses the mutable addressor.
+// CHECK-LABEL: sil hidden @$S10addressors8test_recys5Int32VAA8RecOuterCF : $@convention(thin) (@guaranteed RecOuter) -> Int32 {
+// CHECK: function_ref @$S10addressors8RecOuterC6middleAA0B6MiddleVvaP
+// CHECK: struct_element_addr {{.*}} : $*RecMiddle, #RecMiddle.inner
+// CHECK: function_ref @$S10addressors8RecInnerVys5Int32VAEcig
+
+class Base {
+ var data: UnsafeMutablePointer<Int32> = UnsafeMutablePointer.allocate(capacity: 100)
+
+ var value: Int32 {
+ addressWithNativeOwner {
+ return (UnsafePointer(data), Builtin.castToNativeObject(self))
+ }
+ mutableAddressWithNativeOwner {
+ return (data, Builtin.castToNativeObject(self))
+ }
+ }
+}
+
+class Sub : Base {
+ override var value: Int32 {
+ addressWithNativeOwner {
+ return (UnsafePointer(data), Builtin.castToNativeObject(self))
+ }
+ mutableAddressWithNativeOwner {
+ return (data, Builtin.castToNativeObject(self))
+ }
+ }
+}
+
+// Make sure addressors don't get vtable entries.
+// CHECK-LABEL: sil_vtable Base {
+// CHECK-NEXT: #Base.data!getter.1: (Base) -> () -> UnsafeMutablePointer<Int32> : @$S10addressors4BaseC4dataSpys5Int32VGvg
+// CHECK-NEXT: #Base.data!setter.1: (Base) -> (UnsafeMutablePointer<Int32>) -> () : @$S10addressors4BaseC4dataSpys5Int32VGvs
+// CHECK-NEXT: #Base.data!materializeForSet.1: (Base) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : @$S10addressors4BaseC4dataSpys5Int32VGvm
+// CHECK-NEXT: #Base.value!getter.1: (Base) -> () -> Int32 : @$S10addressors4BaseC5values5Int32Vvg
+// CHECK-NEXT: #Base.value!setter.1: (Base) -> (Int32) -> () : @$S10addressors4BaseC5values5Int32Vvs
+// CHECK-NEXT: #Base.value!materializeForSet.1: (Base) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : @$S10addressors4BaseC5values5Int32Vvm
+// CHECK-NEXT: #Base.init!initializer.1: (Base.Type) -> () -> Base : @$S10addressors4BaseCACycfc
+// CHECK-NEXT: #Base.deinit!deallocator: @$S10addressors4BaseCfD
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_vtable Sub {
+// CHECK-NEXT: #Base.data!getter.1: (Base) -> () -> UnsafeMutablePointer<Int32> : @$S10addressors4BaseC4dataSpys5Int32VGvg
+// CHECK-NEXT: #Base.data!setter.1: (Base) -> (UnsafeMutablePointer<Int32>) -> () : @$S10addressors4BaseC4dataSpys5Int32VGvs
+// CHECK-NEXT: #Base.data!materializeForSet.1: (Base) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : @$S10addressors4BaseC4dataSpys5Int32VGvm
+// CHECK-NEXT: #Base.value!getter.1: (Base) -> () -> Int32 : @$S10addressors3SubC5values5Int32Vvg
+// CHECK-NEXT: #Base.value!setter.1: (Base) -> (Int32) -> () : @$S10addressors3SubC5values5Int32Vvs
+// CHECK-NEXT: #Base.value!materializeForSet.1: (Base) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : @$S10addressors3SubC5values5Int32Vvm
+// CHECK-NEXT: #Base.init!initializer.1: (Base.Type) -> () -> Base : @$S10addressors3SubCACycfc
+// CHECK-NEXT: #Sub.deinit!deallocator: @$S10addressors3SubCfD
+// CHECK-NEXT: }
diff --git a/test/SILGen/plus_zero_apply_abstraction_nested.swift b/test/SILGen/plus_zero_apply_abstraction_nested.swift
new file mode 100644
index 0000000..f1143d9
--- /dev/null
+++ b/test/SILGen/plus_zero_apply_abstraction_nested.swift
@@ -0,0 +1,27 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen %s | %FileCheck %s
+
+infix operator ~> { precedence 255 associativity left }
+
+protocol P { }
+
+func bar<T:P>(_: inout T) -> () -> () { return {_ in ()} }
+func baz<T:P>(_: inout T) -> (Int) -> () { return {_ in ()} }
+
+func ~> <T: P, Args, Result>(
+ x: inout T,
+ m: (_ x: inout T) -> ((Args) -> Result)
+) -> ((Args) -> Result) {
+ return m(&x)
+}
+
+struct X : P {}
+
+var a = X()
+(a~>bar)()
+
+// CHECK: [[CHAINED_FUNC:%.*]] = apply {{%.*}}<X, (), ()>({{%.*}}, {{%.*}}) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2 where τ_0_0 : P> (@inout τ_0_0, @noescape @callee_guaranteed (@inout τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed τ_0_1) -> @out τ_0_2) -> @owned @callee_guaranteed (@in_guaranteed τ_0_1) -> @out τ_0_2
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$SytytIegnr_Ieg_TR
+// CHECK: [[CHAINED_FUNC_REABSTRACTED:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[CHAINED_FUNC]])
+// CHECK: [[BORROW:%.*]] = begin_borrow [[CHAINED_FUNC_REABSTRACTED]]
+// CHECK: apply [[BORROW]]() : $@callee_guaranteed () -> ()
diff --git a/test/SILGen/plus_zero_argument_labels.swift b/test/SILGen/plus_zero_argument_labels.swift
new file mode 100644
index 0000000..95bb1d6
--- /dev/null
+++ b/test/SILGen/plus_zero_argument_labels.swift
@@ -0,0 +1,21 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+public struct X { }
+public struct Y { }
+
+public class Foo {
+ func doSomething(x: X, y: Y) { }
+ func doSomethingElse(x: X) { }
+}
+
+// CHECK-LABEL: sil hidden @$S15argument_labels7testFoo{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Foo,
+func testFoo(foo: Foo, x: X, y: Y) {
+ // CHECK: class_method [[ARG0]] : $Foo, #Foo.doSomething!1 : (Foo) -> (X, Y) -> ()
+ foo.doSomething(x: x, y: y)
+
+ // CHECK: class_method [[ARG0]] : $Foo, #Foo.doSomethingElse!1 : (Foo) -> (X) -> ()
+ foo.doSomethingElse(x: x)
+}
+
diff --git a/test/SILGen/plus_zero_argument_shuffle_swift3.swift b/test/SILGen/plus_zero_argument_shuffle_swift3.swift
new file mode 100644
index 0000000..d76bb29
--- /dev/null
+++ b/test/SILGen/plus_zero_argument_shuffle_swift3.swift
@@ -0,0 +1,26 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s -swift-version 3 | %FileCheck %s
+
+func fn(_: Any) {}
+
+enum HasAnyCase {
+ case any(_: Any)
+}
+
+// CHECK-LABEL: sil hidden @$S23argument_shuffle_swift31g1xyyp_tF : $@convention(thin) (@in_guaranteed Any) -> () {
+func g(x: Any) {
+ // CHECK: [[FN:%.*]] = function_ref @$S23argument_shuffle_swift32fnyyypF : $@convention(thin) (@in_guaranteed Any) -> ()
+ // CHECK: apply [[FN:%.*]]({{.*}}) : $@convention(thin) (@in_guaranteed Any) -> ()
+ fn(data: 123)
+ // CHECK: [[FN:%.*]] = function_ref @$S23argument_shuffle_swift32fnyyypF : $@convention(thin) (@in_guaranteed Any) -> ()
+ // CHECK: apply [[FN:%.*]]({{.*}}) : $@convention(thin) (@in_guaranteed Any) -> ()
+ fn(data: x)
+
+ // CHECK: inject_enum_addr {{.*}} : $*HasAnyCase, #HasAnyCase.any!enumelt.1
+ _ = HasAnyCase.any(123)
+
+ // CHECK: inject_enum_addr {{.*}} : $*HasAnyCase, #HasAnyCase.any!enumelt.1
+ _ = HasAnyCase.any(data: 123)
+
+ // CHECK: return
+}
diff --git a/test/SILGen/plus_zero_array_literal_abstraction.swift b/test/SILGen/plus_zero_array_literal_abstraction.swift
new file mode 100644
index 0000000..d7f1e36
--- /dev/null
+++ b/test/SILGen/plus_zero_array_literal_abstraction.swift
@@ -0,0 +1,25 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+// Verify that reabstraction happens when forming container literals.
+// <rdar://problem/16039286>
+
+// CHECK-LABEL: sil hidden @$S25array_literal_abstraction0A9_of_funcsSayyycGyF
+// CHECK: pointer_to_address {{.*}} $*@callee_guaranteed (@in_guaranteed ()) -> @out ()
+func array_of_funcs() -> [(() -> ())] {
+ return [{}, {}]
+}
+
+// CHECK-LABEL: sil hidden @$S25array_literal_abstraction13dict_of_funcss10DictionaryVySiyycGyF
+// CHECK: pointer_to_address {{.*}} $*(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+func dict_of_funcs() -> Dictionary<Int, () -> ()> {
+ return [0: {}, 1: {}]
+}
+
+func vararg_funcs(_ fs: (() -> ())...) {}
+
+// CHECK-LABEL: sil hidden @$S25array_literal_abstraction17call_vararg_funcsyyF
+// CHECK: pointer_to_address {{.*}} $*@callee_guaranteed (@in_guaranteed ()) -> @out ()
+func call_vararg_funcs() {
+ vararg_funcs({}, {})
+}
diff --git a/test/SILGen/plus_zero_auto_closures.swift b/test/SILGen/plus_zero_auto_closures.swift
new file mode 100644
index 0000000..0adc57e
--- /dev/null
+++ b/test/SILGen/plus_zero_auto_closures.swift
@@ -0,0 +1,73 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct Bool {}
+var false_ = Bool()
+
+// CHECK-LABEL: sil hidden @$S13auto_closures05call_A8_closureyAA4BoolVADyXKF : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> Bool
+func call_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
+ // CHECK: bb0([[CLOSURE:%.*]] : @trivial $@noescape @callee_guaranteed () -> Bool):
+ // CHECK: [[RET:%.*]] = apply [[CLOSURE]]()
+ // CHECK: return [[RET]]
+ return x()
+}
+
+// CHECK-LABEL: sil hidden @$S13auto_closures05test_A21_closure_with_capture{{[_0-9a-zA-Z]*}}F
+func test_auto_closure_with_capture(_ x: Bool) -> Bool {
+ // CHECK: [[CLOSURE:%.*]] = function_ref @$S13auto_closures05test_A21_closure_with_capture
+ // CHECK: [[WITHCAPTURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE]](
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[WITHCAPTURE]]
+ // CHECK: [[RET:%.*]] = apply {{%.*}}([[CVT]])
+ // CHECK: return [[RET]]
+ return call_auto_closure(x)
+}
+
+// CHECK-LABEL: sil hidden @$S13auto_closures05test_A24_closure_without_capture{{[_0-9a-zA-Z]*}}F
+func test_auto_closure_without_capture() -> Bool {
+ // CHECK: [[CLOSURE:%.*]] = function_ref @$S13auto_closures05test_A24_closure_without_capture
+ // CHECK: [[CVT:%.*]] = convert_function [[CLOSURE]]
+ // CHECK: [[THICK:%.*]] = thin_to_thick_function [[CVT]] : $@convention(thin) @noescape () -> Bool to $@noescape @callee_guaranteed () -> Bool
+ // CHECK: [[RET:%.*]] = apply {{%.*}}([[THICK]])
+ // CHECK: return [[RET]]
+ return call_auto_closure(false_)
+}
+
+public class Base {
+ var x: Bool { return false_ }
+}
+
+public class Sub : Base {
+ // CHECK-LABEL: sil hidden @$S13auto_closures3SubC1xAA4BoolVvg : $@convention(method) (@guaranteed Sub) -> Bool {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $Sub):
+ // CHECK: [[AUTOCLOSURE_FUNC:%.*]] = function_ref @$S13auto_closures3SubC1xAA4BoolVvgAFyXKfu_ : $@convention(thin) (@guaranteed Sub) -> Bool
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[AUTOCLOSURE:%.*]] = partial_apply [callee_guaranteed] [[AUTOCLOSURE_FUNC]]([[SELF_COPY]])
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[AUTOCLOSURE]]
+ // CHECK: [[AUTOCLOSURE_CONSUMER:%.*]] = function_ref @$S13auto_closures05call_A8_closureyAA4BoolVADyXKF : $@convention(thin)
+ // CHECK: [[RET:%.*]] = apply [[AUTOCLOSURE_CONSUMER]]([[CVT]])
+ // CHECK: return [[RET]] : $Bool
+ // CHECK: }
+
+ // CHECK-LABEL: sil private [transparent] @$S13auto_closures3SubC1xAA4BoolVvgAFyXKfu_ : $@convention(thin) (@guaranteed Sub) -> Bool {
+ // CHECK: [[SUPER:%[0-9]+]] = function_ref @$S13auto_closures4BaseC1xAA4BoolVvg : $@convention(method) (@guaranteed Base) -> Bool
+ // CHECK: [[RET:%.*]] = apply [[SUPER]]({{%.*}})
+ // CHECK: return [[RET]]
+ override var x: Bool { return call_auto_closure(super.x) }
+}
+
+// CHECK-LABEL: sil hidden @$S13auto_closures20closureInAutoclosureyAA4BoolVAD_ADtF : $@convention(thin) (Bool, Bool) -> Bool {
+// CHECK: }
+// CHECK-LABEL: sil private [transparent] @$S13auto_closures20closureInAutoclosureyAA4BoolVAD_ADtFADyXKfu_ : $@convention(thin) (Bool, Bool) -> Bool {
+// CHECK: }
+// CHECK-LABEL: sil private @$S13auto_closures20closureInAutoclosureyAA4BoolVAD_ADtFADyXKfu_A2DXEfU_ : $@convention(thin) (Bool, Bool) -> Bool {
+// CHECK: }
+func compareBool(_ lhs: Bool, _ rhs: Bool) -> Bool { return false_ }
+func testBool(_ x: Bool, _ pred: (Bool) -> Bool) -> Bool {
+ return pred(x)
+}
+func delayBool(_ fn: @autoclosure () -> Bool) -> Bool {
+ return fn()
+}
+func closureInAutoclosure(_ lhs: Bool, _ rhs: Bool) -> Bool {
+ return delayBool(testBool(lhs, { compareBool($0, rhs) }))
+}
diff --git a/test/SILGen/plus_zero_borrow.swift b/test/SILGen/plus_zero_borrow.swift
new file mode 100644
index 0000000..5dcec6f
--- /dev/null
+++ b/test/SILGen/plus_zero_borrow.swift
@@ -0,0 +1,36 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -emit-silgen %s | %FileCheck %s
+
+import Swift
+
+final class D {}
+
+// Make sure that we insert the borrow for a ref_element_addr lvalue in the
+// proper place.
+final class C {
+ var d: D = D()
+}
+
+func useD(_ d: D) {}
+
+// CHECK-LABEL: sil hidden @$S6borrow44lvalueBorrowShouldBeAtEndOfFormalAccessScope{{.*}} : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[BOX:%.*]] = alloc_box ${ var C }, var, name "c"
+// CHECK: [[PB_BOX:%.*]] = project_box [[BOX]]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB_BOX]] : $*C
+// CHECK: [[CLASS:%.*]] = load [copy] [[ACCESS]]
+// CHECK: [[BORROWED_CLASS:%.*]] = begin_borrow [[CLASS]]
+// CHECK: [[OFFSET:%.*]] = ref_element_addr [[BORROWED_CLASS]]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[OFFSET]] : $*D
+// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[ACCESS]]
+// CHECK: end_borrow [[BORROWED_CLASS]] from [[CLASS]]
+// CHECK: destroy_value [[CLASS]]
+// CHECK: [[BORROWED_LOADED_VALUE:%.*]] = begin_borrow [[LOADED_VALUE]]
+// CHECK: [[FUNC:%.*]] = function_ref @$S6borrow4useD{{.*}} : $@convention(thin) (@guaranteed D) -> ()
+// CHECK: apply [[FUNC]]([[BORROWED_LOADED_VALUE]])
+// CHECK: destroy_value [[BOX]]
+// CHECK: } // end sil function '$S6borrow44lvalueBorrowShouldBeAtEndOfFormalAccessScope{{.*}}'
+func lvalueBorrowShouldBeAtEndOfFormalAccessScope() {
+ var c = C()
+ useD(c.d)
+}
diff --git a/test/SILGen/plus_zero_boxed_existentials.swift b/test/SILGen/plus_zero_boxed_existentials.swift
new file mode 100644
index 0000000..70b4197
--- /dev/null
+++ b/test/SILGen/plus_zero_boxed_existentials.swift
@@ -0,0 +1,217 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen %s | %FileCheck %s --check-prefix=GUARANTEED
+
+func test_type_lowering(_ x: Error) { }
+// CHECK-LABEL: sil hidden @$S18boxed_existentials18test_type_loweringyys5Error_pF : $@convention(thin) (@guaranteed Error) -> () {
+// CHECK-NOT: destroy_value %0 : $Error
+
+class Document {}
+
+enum ClericalError: Error {
+ case MisplacedDocument(Document)
+
+ var _domain: String { return "" }
+ var _code: Int { return 0 }
+}
+
+func test_concrete_erasure(_ x: ClericalError) -> Error {
+ return x
+}
+// CHECK-LABEL: sil hidden @$S18boxed_existentials21test_concrete_erasureys5Error_pAA08ClericalF0OF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $ClericalError):
+// CHECK: [[EXISTENTIAL:%.*]] = alloc_existential_box $Error, $ClericalError
+// CHECK: [[ADDR:%.*]] = project_existential_box $ClericalError in [[EXISTENTIAL]] : $Error
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: store [[ARG_COPY]] to [init] [[ADDR]] : $*ClericalError
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[EXISTENTIAL]] : $Error
+
+protocol HairType {}
+
+func test_composition_erasure(_ x: HairType & Error) -> Error {
+ return x
+}
+// CHECK-LABEL: sil hidden @$S18boxed_existentials24test_composition_erasureys5Error_psAC_AA8HairTypepF
+// CHECK: [[VALUE_ADDR:%.*]] = open_existential_addr immutable_access [[OLD_EXISTENTIAL:%.*]] : $*Error & HairType to $*[[VALUE_TYPE:@opened\(.*\) Error & HairType]]
+// CHECK: [[NEW_EXISTENTIAL:%.*]] = alloc_existential_box $Error, $[[VALUE_TYPE]]
+// CHECK: [[ADDR:%.*]] = project_existential_box $[[VALUE_TYPE]] in [[NEW_EXISTENTIAL]] : $Error
+// CHECK: copy_addr [[VALUE_ADDR]] to [initialization] [[ADDR]]
+// CHECK-NOT: destroy_addr [[OLD_EXISTENTIAL]]
+// CHECK: return [[NEW_EXISTENTIAL]]
+
+protocol HairClass: class {}
+
+func test_class_composition_erasure(_ x: HairClass & Error) -> Error {
+ return x
+}
+// CHECK-LABEL: sil hidden @$S18boxed_existentials30test_class_composition_erasureys5Error_psAC_AA9HairClasspF
+// CHECK: [[VALUE:%.*]] = open_existential_ref [[OLD_EXISTENTIAL:%.*]] : $Error & HairClass to $[[VALUE_TYPE:@opened\(.*\) Error & HairClass]]
+// CHECK: [[NEW_EXISTENTIAL:%.*]] = alloc_existential_box $Error, $[[VALUE_TYPE]]
+// CHECK: [[ADDR:%.*]] = project_existential_box $[[VALUE_TYPE]] in [[NEW_EXISTENTIAL]] : $Error
+// CHECK: [[COPIED_VALUE:%.*]] = copy_value [[VALUE]]
+// CHECK: store [[COPIED_VALUE]] to [init] [[ADDR]]
+// CHECK: return [[NEW_EXISTENTIAL]]
+
+func test_property(_ x: Error) -> String {
+ return x._domain
+}
+// CHECK-LABEL: sil hidden @$S18boxed_existentials13test_propertyySSs5Error_pF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error):
+// CHECK: [[VALUE:%.*]] = open_existential_box [[ARG]] : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
+// FIXME: Extraneous copy here
+// CHECK-NEXT: [[COPY:%[0-9]+]] = alloc_stack $[[VALUE_TYPE]]
+// CHECK-NEXT: copy_addr [[VALUE]] to [initialization] [[COPY]] : $*[[VALUE_TYPE]]
+// CHECK: [[METHOD:%.*]] = witness_method $[[VALUE_TYPE]], #Error._domain!getter.1
+// -- self parameter of witness is @in_guaranteed; no need to copy since
+// value in box is immutable and box is guaranteed
+// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[COPY]])
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[RESULT]]
+
+func test_property_of_lvalue(_ x: Error) -> String {
+ var x = x
+ return x._domain
+}
+
+// CHECK-LABEL: sil hidden @$S18boxed_existentials23test_property_of_lvalueySSs5Error_pF :
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error):
+// CHECK: [[VAR:%.*]] = alloc_box ${ var Error }
+// CHECK: [[PVAR:%.*]] = project_box [[VAR]]
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $Error
+// CHECK: store [[ARG_COPY]] to [init] [[PVAR]]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PVAR]] : $*Error
+// CHECK: [[VALUE_BOX:%.*]] = load [copy] [[ACCESS]]
+// CHECK: [[VALUE:%.*]] = open_existential_box [[VALUE_BOX]] : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
+// CHECK: [[COPY:%.*]] = alloc_stack $[[VALUE_TYPE]]
+// CHECK: copy_addr [[VALUE]] to [initialization] [[COPY]]
+// CHECK: [[METHOD:%.*]] = witness_method $[[VALUE_TYPE]], #Error._domain!getter.1
+// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[COPY]])
+// CHECK: destroy_addr [[COPY]]
+// CHECK: dealloc_stack [[COPY]]
+// CHECK: destroy_value [[VALUE_BOX]]
+// CHECK: destroy_value [[VAR]]
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function '$S18boxed_existentials23test_property_of_lvalueySSs5Error_pF'
+extension Error {
+ func extensionMethod() { }
+}
+
+// CHECK-LABEL: sil hidden @$S18boxed_existentials21test_extension_methodyys5Error_pF
+func test_extension_method(_ error: Error) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Error):
+ // CHECK: [[VALUE:%.*]] = open_existential_box [[ARG]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK-NOT: copy_addr
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK-NOT: destroy_addr [[COPY]]
+ // CHECK-NOT: destroy_addr [[VALUE]]
+ // CHECK-NOT: destroy_addr [[VALUE]]
+ // -- destroy_value the owned argument
+ // CHECK-NOT: destroy_value %0
+ error.extensionMethod()
+}
+
+func plusOneError() -> Error { }
+
+// CHECK-LABEL: sil hidden @$S18boxed_existentials31test_open_existential_semanticsyys5Error_p_sAC_ptF
+// GUARANTEED-LABEL: sil hidden @$S18boxed_existentials31test_open_existential_semanticsyys5Error_p_sAC_ptF
+// CHECK: bb0([[ARG0:%.*]]: @guaranteed $Error,
+// GUARANTEED: bb0([[ARG0:%.*]]: @guaranteed $Error,
+func test_open_existential_semantics(_ guaranteed: Error,
+ _ immediate: Error) {
+ var immediate = immediate
+ // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
+ // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
+ // GUARANTEED: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
+ // GUARANTEED: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
+
+ // CHECK-NOT: copy_value [[ARG0]]
+ // CHECK: [[VALUE:%.*]] = open_existential_box [[ARG0]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK-NOT: copy_addr
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK-NOT: destroy_value [[ARG0]]
+
+ // GUARANTEED-NOT: copy_value [[ARG0]]
+ // GUARANTEED: [[VALUE:%.*]] = open_existential_box [[ARG0]]
+ // GUARANTEED: [[METHOD:%.*]] = function_ref
+ // GUARANTEED: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // GUARANTEED-NOT: destroy_addr [[VALUE]]
+ // GUARANTEED-NOT: destroy_value [[ARG0]]
+ guaranteed.extensionMethod()
+
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*Error
+ // CHECK: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]]
+ // -- need a copy_value to guarantee
+ // CHECK: [[VALUE:%.*]] = open_existential_box [[IMMEDIATE]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK-NOT: copy_addr
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // -- end the guarantee
+ // -- TODO: could in theory do this sooner, after the value's been copied
+ // out.
+ // CHECK: destroy_value [[IMMEDIATE]]
+
+ // GUARANTEED: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]] : $*Error
+ // GUARANTEED: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]]
+ // -- need a copy_value to guarantee
+ // GUARANTEED: [[VALUE:%.*]] = open_existential_box [[IMMEDIATE]]
+ // GUARANTEED: [[METHOD:%.*]] = function_ref
+ // GUARANTEED: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // GUARANTEED-NOT: destroy_addr [[VALUE]]
+ // -- end the guarantee
+ // GUARANTEED: destroy_value [[IMMEDIATE]]
+ immediate.extensionMethod()
+
+ // CHECK: [[F:%.*]] = function_ref {{.*}}plusOneError
+ // CHECK: [[PLUS_ONE:%.*]] = apply [[F]]()
+ // CHECK: [[VALUE:%.*]] = open_existential_box [[PLUS_ONE]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK-NOT: copy_addr
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK: destroy_value [[PLUS_ONE]]
+
+ // GUARANTEED: [[F:%.*]] = function_ref {{.*}}plusOneError
+ // GUARANTEED: [[PLUS_ONE:%.*]] = apply [[F]]()
+ // GUARANTEED: [[VALUE:%.*]] = open_existential_box [[PLUS_ONE]]
+ // GUARANTEED: [[METHOD:%.*]] = function_ref
+ // GUARANTEED: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // GUARANTEED-NOT: destroy_addr [[VALUE]]
+ // GUARANTEED: destroy_value [[PLUS_ONE]]
+ plusOneError().extensionMethod()
+}
+
+// CHECK-LABEL: sil hidden @$S18boxed_existentials14erasure_to_anyyyps5Error_p_sAC_ptF
+// CHECK: bb0([[OUT:%.*]] : @trivial $*Any, [[GUAR:%.*]] : @guaranteed $Error,
+func erasure_to_any(_ guaranteed: Error, _ immediate: Error) -> Any {
+ var immediate = immediate
+ // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
+ // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
+ if true {
+ // CHECK-NOT: copy_value [[GUAR]]
+ // CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[GUAR:%.*]]
+ // CHECK: [[TO_VALUE:%.*]] = init_existential_addr [[OUT]]
+ // CHECK: copy_addr [[FROM_VALUE]] to [initialization] [[TO_VALUE]]
+ // CHECK-NOT: destroy_value [[GUAR]]
+ return guaranteed
+ } else if true {
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: [[IMMEDIATE:%.*]] = load [copy] [[ACCESS]]
+ // CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[IMMEDIATE]]
+ // CHECK: [[TO_VALUE:%.*]] = init_existential_addr [[OUT]]
+ // CHECK: copy_addr [[FROM_VALUE]] to [initialization] [[TO_VALUE]]
+ // CHECK: destroy_value [[IMMEDIATE]]
+ return immediate
+ } else if true {
+ // CHECK: function_ref boxed_existentials.plusOneError
+ // CHECK: [[PLUS_ONE:%.*]] = apply
+ // CHECK: [[FROM_VALUE:%.*]] = open_existential_box [[PLUS_ONE]]
+ // CHECK: [[TO_VALUE:%.*]] = init_existential_addr [[OUT]]
+ // CHECK: copy_addr [[FROM_VALUE]] to [initialization] [[TO_VALUE]]
+ // CHECK: destroy_value [[PLUS_ONE]]
+
+ return plusOneError()
+ }
+}
diff --git a/test/SILGen/plus_zero_call_chain_reabstraction.swift b/test/SILGen/plus_zero_call_chain_reabstraction.swift
new file mode 100644
index 0000000..123c453
--- /dev/null
+++ b/test/SILGen/plus_zero_call_chain_reabstraction.swift
@@ -0,0 +1,20 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct A {
+ func g<U>(_ recur: (A, U) -> U) -> (A, U) -> U {
+ return { _, x in return x }
+ }
+ // CHECK-LABEL: sil hidden @$S24call_chain_reabstraction1AV1f{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[G:%.*]] = function_ref @$S24call_chain_reabstraction1AV1g{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[G2:%.*]] = apply [[G]]<A>
+ // CHECK: [[REABSTRACT_THUNK:%.*]] = function_ref @$S24call_chain_reabstraction1AVA2CIegynr_A3CIegyyd_TR
+ // CHECK: [[REABSTRACT:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT_THUNK]]([[G2]])
+ // CHECK: [[BORROW:%.*]] = begin_borrow [[REABSTRACT]]
+ // CHECK: apply [[BORROW]]([[SELF:%.*]], [[SELF]])
+ // CHECK: destroy_value [[REABSTRACT]]
+ func f() {
+ let recur: (A, A) -> A = { c, x in x }
+ let b = g(recur)(self, self)
+ }
+}
diff --git a/test/SILGen/plus_zero_capture_typed_boxes.swift b/test/SILGen/plus_zero_capture_typed_boxes.swift
new file mode 100644
index 0000000..c33dad1
--- /dev/null
+++ b/test/SILGen/plus_zero_capture_typed_boxes.swift
@@ -0,0 +1,32 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func foo(_ x: Int) -> () -> Int {
+ var x = x
+ return { x }
+}
+// CHECK-LABEL: sil private @$S19capture_typed_boxes3fooySiycSiFSiycfU_ : $@convention(thin) (@guaranteed { var Int }) -> Int {
+// CHECK: bb0(%0 : @guaranteed ${ var Int }):
+
+func closure(_ f: @escaping (Int) -> Int) -> Int {
+ var f = f
+ func bar(_ x: Int) -> Int {
+ return f(x)
+ }
+
+ return bar(0)
+}
+// CHECK-LABEL: sil private @$S19capture_typed_boxes7closureyS3icF3barL_yS2iF : $@convention(thin) (Int, @guaranteed { var @callee_guaranteed (Int) -> Int }) -> Int {
+// CHECK: bb0(%0 : @trivial $Int, %1 : @guaranteed ${ var @callee_guaranteed (Int) -> Int }):
+
+func closure_generic<T>(_ f: @escaping (T) -> T, x: T) -> T {
+ var f = f
+ func bar(_ x: T) -> T {
+ return f(x)
+ }
+
+ return bar(x)
+}
+// CHECK-LABEL: sil private @$S19capture_typed_boxes15closure_generic{{.*}} : $@convention(thin) <T> (@in_guaranteed T, @guaranteed <τ_0_0> { var @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_0_0 } <T>) -> @out T {
+// CHECK-LABEL: bb0(%0 : @trivial $*T, %1 : @trivial $*T, %2 : @guaranteed $<τ_0_0> { var @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_0_0 } <T>):
+
diff --git a/test/SILGen/plus_zero_casts.swift b/test/SILGen/plus_zero_casts.swift
new file mode 100644
index 0000000..6944bbd
--- /dev/null
+++ b/test/SILGen/plus_zero_casts.swift
@@ -0,0 +1,103 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class B { }
+class D : B { }
+
+// CHECK-LABEL: sil hidden @$S5casts6upcast{{[_0-9a-zA-Z]*}}F
+func upcast(d: D) -> B {
+ // CHECK: {{%.*}} = upcast
+ return d
+}
+// CHECK-LABEL: sil hidden @$S5casts8downcast{{[_0-9a-zA-Z]*}}F
+func downcast(b: B) -> D {
+ // CHECK: {{%.*}} = unconditional_checked_cast
+ return b as! D
+}
+
+// CHECK-LABEL: sil hidden @$S5casts3isa{{[_0-9a-zA-Z]*}}F
+func isa(b: B) -> Bool {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $B):
+ // CHECK: [[COPIED_BORROWED_ARG:%.*]] = copy_value [[ARG]]
+ // CHECK: checked_cast_br [[COPIED_BORROWED_ARG]] : $B to $D, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+ //
+ // CHECK: [[YES]]([[CASTED_VALUE:%.*]] : @owned $D):
+ // CHECK: integer_literal {{.*}} -1
+ // CHECK: destroy_value [[CASTED_VALUE]]
+ //
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : @owned $B):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: integer_literal {{.*}} 0
+ return b is D
+}
+
+// CHECK-LABEL: sil hidden @$S5casts16upcast_archetype{{[_0-9a-zA-Z]*}}F
+func upcast_archetype<T : B>(t: T) -> B {
+ // CHECK: {{%.*}} = upcast
+ return t
+}
+
+// CHECK-LABEL: sil hidden @$S5casts25upcast_archetype_metatype{{[_0-9a-zA-Z]*}}F
+func upcast_archetype_metatype<T : B>(t: T.Type) -> B.Type {
+ // CHECK: {{%.*}} = upcast
+ return t
+}
+
+// CHECK-LABEL: sil hidden @$S5casts18downcast_archetype{{[_0-9a-zA-Z]*}}F
+func downcast_archetype<T : B>(b: B) -> T {
+ // CHECK: {{%.*}} = unconditional_checked_cast
+ return b as! T
+}
+
+// This is making sure that we do not have the default propagating behavior in
+// the address case.
+//
+// CHECK-LABEL: sil hidden @$S5casts12is_archetype{{[_0-9a-zA-Z]*}}F
+func is_archetype<T : B>(b: B, _: T) -> Bool {
+ // CHECK: bb0([[ARG1:%.*]] : @guaranteed $B, [[ARG2:%.*]] : @guaranteed $T):
+ // CHECK: checked_cast_br {{%.*}}, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+ // CHECK: [[YES]]([[CASTED_ARG:%.*]] : @owned $T):
+ // CHECK: integer_literal {{.*}} -1
+ // CHECK: destroy_value [[CASTED_ARG]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : @owned $B):
+ // CHCEK: destroy_value [[CASTED_ARG]]
+ // CHECK: integer_literal {{.*}} 0
+ return b is T
+}
+// CHECK: } // end sil function '$S5casts12is_archetype{{[_0-9a-zA-Z]*}}F'
+
+// CHECK: sil hidden @$S5casts20downcast_conditional{{[_0-9a-zA-Z]*}}F
+// CHECK: checked_cast_br {{%.*}} : $B to $D
+// CHECK: bb{{[0-9]+}}({{.*}} : $Optional<D>)
+func downcast_conditional(b: B) -> D? {
+ return b as? D
+}
+
+protocol P {}
+struct S : P {}
+
+// CHECK: sil hidden @$S5casts32downcast_existential_conditional{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[IN:%.*]] : @trivial $*P):
+// CHECK: [[COPY:%.*]] = alloc_stack $P
+// CHECK: copy_addr [[IN]] to [initialization] [[COPY]]
+// CHECK: [[TMP:%.*]] = alloc_stack $S
+// CHECK: checked_cast_addr_br take_always P in [[COPY]] : $*P to S in [[TMP]] : $*S, bb1, bb2
+// Success block.
+// CHECK: bb1:
+// CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*S
+// CHECK: [[T1:%.*]] = enum $Optional<S>, #Optional.some!enumelt.1, [[T0]] : $S
+// CHECK: dealloc_stack [[TMP]]
+// CHECK: br bb3([[T1]] : $Optional<S>)
+// Failure block.
+// CHECK: bb2:
+// CHECK: [[T0:%.*]] = enum $Optional<S>, #Optional.none!enumelt
+// CHECK: dealloc_stack [[TMP]]
+// CHECK: br bb3([[T0]] : $Optional<S>)
+// Continuation block.
+// CHECK: bb3([[RESULT:%.*]] : @trivial $Optional<S>):
+// CHECK: dealloc_stack [[COPY]]
+// CHECK: return [[RESULT]]
+func downcast_existential_conditional(p: P) -> S? {
+ return p as? S
+}
+
diff --git a/test/SILGen/plus_zero_cf.swift b/test/SILGen/plus_zero_cf.swift
new file mode 100644
index 0000000..ac4e227
--- /dev/null
+++ b/test/SILGen/plus_zero_cf.swift
@@ -0,0 +1,83 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -import-cf-types -sdk %S/Inputs %s -emit-silgen -o - | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import CoreCooling
+
+// CHECK: sil hidden @$S2cf8useEmAllyySo16CCMagnetismModelCF :
+// CHECK: bb0([[ARG:%.*]] : $CCMagnetismModel):
+func useEmAll(_ model: CCMagnetismModel) {
+// CHECK: function_ref @CCPowerSupplyGetDefault : $@convention(c) () -> @autoreleased Optional<CCPowerSupply>
+ let power = CCPowerSupplyGetDefault()
+
+// CHECK: function_ref @CCRefrigeratorCreate : $@convention(c) (Optional<CCPowerSupply>) -> Optional<Unmanaged<CCRefrigerator>>
+ let unmanagedFridge = CCRefrigeratorCreate(power)
+
+// CHECK: function_ref @CCRefrigeratorSpawn : $@convention(c) (Optional<CCPowerSupply>) -> @owned Optional<CCRefrigerator>
+ let managedFridge = CCRefrigeratorSpawn(power)
+
+// CHECK: function_ref @CCRefrigeratorOpen : $@convention(c) (Optional<CCRefrigerator>) -> ()
+ CCRefrigeratorOpen(managedFridge)
+
+// CHECK: function_ref @CCRefrigeratorCopy : $@convention(c) (Optional<CCRefrigerator>) -> @owned Optional<CCRefrigerator>
+ let copy = CCRefrigeratorCopy(managedFridge)
+
+// CHECK: function_ref @CCRefrigeratorClone : $@convention(c) (Optional<CCRefrigerator>) -> @autoreleased Optional<CCRefrigerator>
+ let clone = CCRefrigeratorClone(managedFridge)
+
+// CHECK: function_ref @CCRefrigeratorDestroy : $@convention(c) (@owned Optional<CCRefrigerator>) -> ()
+ CCRefrigeratorDestroy(clone)
+
+// CHECK: objc_method [[ARG]] : $CCMagnetismModel, #CCMagnetismModel.refrigerator!1.foreign : (CCMagnetismModel) -> () -> Unmanaged<CCRefrigerator>?, $@convention(objc_method) (CCMagnetismModel) -> Optional<Unmanaged<CCRefrigerator>>
+ let f0 = model.refrigerator()
+
+// CHECK: objc_method [[ARG]] : $CCMagnetismModel, #CCMagnetismModel.getRefrigerator!1.foreign : (CCMagnetismModel) -> () -> CCRefrigerator?, $@convention(objc_method) (CCMagnetismModel) -> @autoreleased Optional<CCRefrigerator>
+ let f1 = model.getRefrigerator()
+
+// CHECK: objc_method [[ARG]] : $CCMagnetismModel, #CCMagnetismModel.takeRefrigerator!1.foreign : (CCMagnetismModel) -> () -> CCRefrigerator?, $@convention(objc_method) (CCMagnetismModel) -> @owned Optional<CCRefrigerator>
+ let f2 = model.takeRefrigerator()
+
+// CHECK: objc_method [[ARG]] : $CCMagnetismModel, #CCMagnetismModel.borrowRefrigerator!1.foreign : (CCMagnetismModel) -> () -> CCRefrigerator?, $@convention(objc_method) (CCMagnetismModel) -> @autoreleased Optional<CCRefrigerator>
+ let f3 = model.borrowRefrigerator()
+
+// CHECK: objc_method [[ARG]] : $CCMagnetismModel, #CCMagnetismModel.setRefrigerator!1.foreign : (CCMagnetismModel) -> (CCRefrigerator?) -> (), $@convention(objc_method) (Optional<CCRefrigerator>, CCMagnetismModel) -> ()
+ model.setRefrigerator(copy)
+
+// CHECK: objc_method [[ARG]] : $CCMagnetismModel, #CCMagnetismModel.giveRefrigerator!1.foreign : (CCMagnetismModel) -> (CCRefrigerator?) -> (), $@convention(objc_method) (@owned Optional<CCRefrigerator>, CCMagnetismModel) -> ()
+ model.giveRefrigerator(copy)
+
+ // rdar://16846555
+ let prop: CCRefrigerator = model.fridgeProp
+}
+
+// Ensure that accessors are emitted for fields used as protocol witnesses.
+protocol Impedance {
+ associatedtype Component
+ var real: Component { get }
+ var imag: Component { get }
+}
+
+extension CCImpedance: Impedance {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$SSo11CCImpedanceV2cf9ImpedanceA2cDP4real9ComponentQzvgTW
+// CHECK-LABEL: sil shared [transparent] [serializable] @$SSo11CCImpedanceV4realSdvg
+// CHECK-LABEL: sil private [transparent] [thunk] @$SSo11CCImpedanceV2cf9ImpedanceA2cDP4imag9ComponentQzvgTW
+// CHECK-LABEL: sil shared [transparent] [serializable] @$SSo11CCImpedanceV4imagSdvg
+
+class MyMagnetism : CCMagnetismModel {
+ // CHECK-LABEL: sil hidden [thunk] @$S2cf11MyMagnetismC15getRefrigerator{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (MyMagnetism) -> @autoreleased CCRefrigerator
+ override func getRefrigerator() -> CCRefrigerator {
+ return super.getRefrigerator()
+ }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S2cf11MyMagnetismC16takeRefrigerator{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (MyMagnetism) -> @owned CCRefrigerator
+ override func takeRefrigerator() -> CCRefrigerator {
+ return super.takeRefrigerator()
+ }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S2cf11MyMagnetismC18borrowRefrigerator{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (MyMagnetism) -> @autoreleased CCRefrigerator
+ override func borrowRefrigerator() -> CCRefrigerator {
+ return super.borrowRefrigerator()
+ }
+}
diff --git a/test/SILGen/plus_zero_class_bound_protocols.swift b/test/SILGen/plus_zero_class_bound_protocols.swift
new file mode 100644
index 0000000..a6b66b8
--- /dev/null
+++ b/test/SILGen/plus_zero_class_bound_protocols.swift
@@ -0,0 +1,219 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -module-name Swift -emit-silgen %s | %FileCheck %s
+
+enum Optional<T> {
+ case some(T)
+ case none
+}
+
+precedencegroup AssignmentPrecedence {}
+
+typealias AnyObject = Builtin.AnyObject
+
+// -- Class-bound archetypes and existentials are *not* address-only and can
+// be manipulated using normal reference type value semantics.
+
+protocol NotClassBound {
+ func notClassBoundMethod()
+}
+protocol ClassBound : class {
+ func classBoundMethod()
+}
+
+protocol ClassBound2 : class {
+ func classBound2Method()
+}
+
+class ConcreteClass : NotClassBound, ClassBound, ClassBound2 {
+ func notClassBoundMethod() {}
+ func classBoundMethod() {}
+ func classBound2Method() {}
+}
+
+class ConcreteSubclass : ConcreteClass { }
+
+// CHECK-LABEL: sil hidden @$Ss19class_bound_generic{{[_0-9a-zA-Z]*}}F
+func class_bound_generic<T : ClassBound>(x: T) -> T {
+ var x = x
+ // CHECK: bb0([[X:%.*]] : $T):
+ // CHECK: [[X_ADDR:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : ClassBound> { var τ_0_0 } <T>
+ // CHECK: [[PB:%.*]] = project_box [[X_ADDR]]
+ // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
+ // CHECK: store [[X_COPY]] to [init] [[PB]]
+ return x
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
+ // CHECK: [[X1:%.*]] = load [copy] [[READ]]
+ // CHECK: destroy_value [[X_ADDR]]
+ // CHECK: return [[X1]]
+}
+
+// CHECK-LABEL: sil hidden @$Ss21class_bound_generic_2{{[_0-9a-zA-Z]*}}F
+func class_bound_generic_2<T : ClassBound & NotClassBound>(x: T) -> T {
+ var x = x
+ // CHECK: bb0([[X:%.*]] : $T):
+ // CHECK: [[X_ADDR:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : ClassBound, τ_0_0 : NotClassBound> { var τ_0_0 } <T>
+ // CHECK: [[PB:%.*]] = project_box [[X_ADDR]]
+ // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
+ // CHECK: store [[X_COPY]] to [init] [[PB]]
+ return x
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
+ // CHECK: [[X1:%.*]] = load [copy] [[READ]]
+ // CHECK: return [[X1]]
+}
+
+// CHECK-LABEL: sil hidden @$Ss20class_bound_protocol{{[_0-9a-zA-Z]*}}F
+func class_bound_protocol(x: ClassBound) -> ClassBound {
+ var x = x
+ // CHECK: bb0([[X:%.*]] : $ClassBound):
+ // CHECK: [[X_ADDR:%.*]] = alloc_box ${ var ClassBound }
+ // CHECK: [[PB:%.*]] = project_box [[X_ADDR]]
+ // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
+ // CHECK: store [[X_COPY]] to [init] [[PB]]
+ return x
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*ClassBound
+ // CHECK: [[X1:%.*]] = load [copy] [[READ]]
+ // CHECK: return [[X1]]
+}
+
+// CHECK-LABEL: sil hidden @$Ss32class_bound_protocol_composition{{[_0-9a-zA-Z]*}}F
+func class_bound_protocol_composition(x: ClassBound & NotClassBound)
+-> ClassBound & NotClassBound {
+ var x = x
+ // CHECK: bb0([[X:%.*]] : $ClassBound & NotClassBound):
+ // CHECK: [[X_ADDR:%.*]] = alloc_box ${ var ClassBound & NotClassBound }
+ // CHECK: [[PB:%.*]] = project_box [[X_ADDR]]
+ // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
+ // CHECK: store [[X_COPY]] to [init] [[PB]]
+ return x
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*ClassBound & NotClassBound
+ // CHECK: [[X1:%.*]] = load [copy] [[READ]]
+ // CHECK: return [[X1]]
+}
+
+// CHECK-LABEL: sil hidden @$Ss19class_bound_erasure{{[_0-9a-zA-Z]*}}F
+func class_bound_erasure(x: ConcreteClass) -> ClassBound {
+ return x
+ // CHECK: [[PROTO:%.*]] = init_existential_ref {{%.*}} : $ConcreteClass, $ClassBound
+ // CHECK: return [[PROTO]]
+}
+
+// CHECK-LABEL: sil hidden @$Ss30class_bound_existential_upcast1xs10ClassBound_psAC_s0E6Bound2p_tF :
+func class_bound_existential_upcast(x: ClassBound & ClassBound2)
+-> ClassBound {
+ return x
+ // CHECK: bb0([[ARG:%.*]] : $ClassBound & ClassBound2):
+ // CHECK: [[OPENED:%.*]] = open_existential_ref [[ARG]] : $ClassBound & ClassBound2 to [[OPENED_TYPE:\$@opened(.*) ClassBound & ClassBound2]]
+ // CHECK: [[OPENED_COPY:%.*]] = copy_value [[OPENED]]
+ // CHECK: [[PROTO:%.*]] = init_existential_ref [[OPENED_COPY]] : [[OPENED_TYPE]] : [[OPENED_TYPE]], $ClassBound
+ // CHECK: return [[PROTO]]
+}
+// CHECK: } // end sil function '$Ss30class_bound_existential_upcast1xs10ClassBound_psAC_s0E6Bound2p_tF'
+
+// CHECK-LABEL: sil hidden @$Ss41class_bound_to_unbound_existential_upcast1xs13NotClassBound_ps0hI0_sACp_tF :
+// CHECK: bb0([[ARG0:%.*]] : $*NotClassBound, [[ARG1:%.*]] : $ClassBound & NotClassBound):
+// CHECK: [[X_OPENED:%.*]] = open_existential_ref [[ARG1]] : $ClassBound & NotClassBound to [[OPENED_TYPE:\$@opened(.*) ClassBound & NotClassBound]]
+// CHECK: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[ARG0]] : $*NotClassBound, [[OPENED_TYPE]]
+// CHECK: [[X_OPENED_COPY:%.*]] = copy_value [[X_OPENED]]
+// CHECK: store [[X_OPENED_COPY]] to [init] [[PAYLOAD_ADDR]]
+func class_bound_to_unbound_existential_upcast
+(x: ClassBound & NotClassBound) -> NotClassBound {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$Ss18class_bound_method1xys10ClassBound_p_tF :
+// CHECK: bb0([[ARG:%.*]] : $ClassBound):
+func class_bound_method(x: ClassBound) {
+ var x = x
+ x.classBoundMethod()
+ // CHECK: [[XBOX:%.*]] = alloc_box ${ var ClassBound }, var, name "x"
+ // CHECK: [[XBOX_PB:%.*]] = project_box [[XBOX]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: store [[ARG_COPY]] to [init] [[XBOX_PB]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*ClassBound
+ // CHECK: [[X:%.*]] = load [copy] [[READ]] : $*ClassBound
+ // CHECK: [[PROJ:%.*]] = open_existential_ref [[X]] : $ClassBound to $[[OPENED:@opened(.*) ClassBound]]
+ // CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #ClassBound.classBoundMethod!1
+ // CHECK: apply [[METHOD]]<[[OPENED]]>([[PROJ]])
+ // CHECK: destroy_value [[PROJ]]
+ // CHECK: destroy_value [[XBOX]]
+}
+// CHECK: } // end sil function '$Ss18class_bound_method1xys10ClassBound_p_tF'
+
+// rdar://problem/31858378
+struct Value {}
+
+protocol HasMutatingMethod {
+ mutating func mutateMe()
+ var mutatingCounter: Value { get set }
+ var nonMutatingCounter: Value { get nonmutating set }
+}
+
+protocol InheritsMutatingMethod : class, HasMutatingMethod {}
+
+func takesInOut<T>(_: inout T) {}
+
+// CHECK-LABEL: sil hidden @$Ss27takesInheritsMutatingMethod1x1yys0bcD0_pz_s5ValueVtF : $@convention(thin) (@inout InheritsMutatingMethod, Value) -> () {
+func takesInheritsMutatingMethod(x: inout InheritsMutatingMethod,
+ y: Value) {
+ // CHECK: [[X_ADDR:%.*]] = begin_access [modify] [unknown] %0 : $*InheritsMutatingMethod
+ // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $InheritsMutatingMethod to $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") InheritsMutatingMethod, #HasMutatingMethod.mutateMe!1 : <Self where Self : HasMutatingMethod> (inout Self) -> () -> (), [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@inout τ_0_0) -> ()
+ // CHECK-NEXT: apply [[METHOD]]<@opened("{{.*}}") InheritsMutatingMethod>([[TEMPORARY]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@inout τ_0_0) -> ()
+ // CHECK-NEXT: [[X_PAYLOAD:%.*]] = load [take] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[X_VALUE:%.*]] = init_existential_ref [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@opened("{{.*}}") InheritsMutatingMethod, $InheritsMutatingMethod
+ // CHECK-NEXT: assign [[X_VALUE]] to [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: end_access [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ x.mutateMe()
+
+ // CHECK-NEXT: [[RESULT_BOX:%.*]] = alloc_stack $Value
+ // CHECK-NEXT: [[RESULT:%.*]] = mark_uninitialized [var] [[RESULT_BOX]] : $*Value
+ // CHECK-NEXT: [[X_ADDR:%.*]] = begin_access [read] [unknown] %0 : $*InheritsMutatingMethod
+ // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $InheritsMutatingMethod to $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[X_PAYLOAD_RELOADED:%.*]] = load_borrow [[TEMPORARY]]
+ //
+ // ** *NOTE* This extra copy is here since RValue invariants enforce that all
+ // ** loadable objects are actually loaded. So we form the RValue and
+ // ** load... only to then need to store the value back in a stack location to
+ // ** pass to an in_guaranteed method. PredictableMemOpts is able to handle this
+ // ** type of temporary codegen successfully.
+ // CHECK-NEXT: [[TEMPORARY_2:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: store_borrow [[X_PAYLOAD_RELOADED:%.*]] to [[TEMPORARY_2]]
+ //
+ // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") InheritsMutatingMethod, #HasMutatingMethod.mutatingCounter!getter.1 : <Self where Self : HasMutatingMethod> (Self) -> () -> Value, [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
+ // CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[METHOD]]<@opened("{{.*}}") InheritsMutatingMethod>([[TEMPORARY_2]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (@in_guaranteed τ_0_0) -> Value
+ // CHECK-NEXT: dealloc_stack [[TEMPORARY_2]]
+ // CHECK-NEXT: end_borrow [[X_PAYLOAD_RELOADED]]
+ // CHECK-NEXT: assign [[RESULT_VALUE]] to [[RESULT]] : $*Value
+ // CHECK-NEXT: destroy_addr [[TEMPORARY]]
+ // CHECK-NEXT: end_access [[X_ADDR]]
+ // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: dealloc_stack [[RESULT_BOX]] : $*Value
+ _ = x.mutatingCounter
+
+ // CHECK-NEXT: [[X_ADDR:%.*]] = begin_access [modify] [unknown] %0 : $*InheritsMutatingMethod
+ // CHECK-NEXT: [[X_VALUE:%.*]] = load [copy] [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: [[X_PAYLOAD:%.*]] = open_existential_ref [[X_VALUE]] : $InheritsMutatingMethod to $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") InheritsMutatingMethod, #HasMutatingMethod.mutatingCounter!setter.1 : <Self where Self : HasMutatingMethod> (inout Self) -> (Value) -> (), [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (Value, @inout τ_0_0) -> ()
+ // CHECK-NEXT: apply [[METHOD]]<@opened("{{.*}}") InheritsMutatingMethod>(%1, [[TEMPORARY]]) : $@convention(witness_method: HasMutatingMethod) <τ_0_0 where τ_0_0 : HasMutatingMethod> (Value, @inout τ_0_0) -> ()
+ // CHECK-NEXT: [[X_PAYLOAD:%.*]] = load [take] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ // CHECK-NEXT: [[X_VALUE:%.*]] = init_existential_ref [[X_PAYLOAD]] : $@opened("{{.*}}") InheritsMutatingMethod : $@opened("{{.*}}") InheritsMutatingMethod, $InheritsMutatingMethod
+ // CHECK-NEXT: assign [[X_VALUE]] to [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: end_access [[X_ADDR]] : $*InheritsMutatingMethod
+ // CHECK-NEXT: dealloc_stack [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
+ x.mutatingCounter = y
+
+ takesInOut(&x.mutatingCounter)
+
+ _ = x.nonMutatingCounter
+ x.nonMutatingCounter = y
+ takesInOut(&x.nonMutatingCounter)
+}
diff --git a/test/SILGen/plus_zero_class_resilience.swift b/test/SILGen/plus_zero_class_resilience.swift
new file mode 100644
index 0000000..5421688
--- /dev/null
+++ b/test/SILGen/plus_zero_class_resilience.swift
@@ -0,0 +1,48 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_class.swiftmodule -module-name=resilient_class -I %t %S/../Inputs/resilient_class.swift
+// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -enable-resilience %s | %FileCheck %s
+
+import resilient_class
+
+// Accessing final property of resilient class from different resilience domain
+// through accessor
+
+// CHECK-LABEL: sil @$S16class_resilience20finalPropertyOfOtheryy010resilient_A022ResilientOutsideParentCF
+// CHECK: function_ref @$S15resilient_class22ResilientOutsideParentC13finalPropertySSvg
+
+public func finalPropertyOfOther(_ other: ResilientOutsideParent) {
+ _ = other.finalProperty
+}
+
+public class MyResilientClass {
+ public final var finalProperty: String = "MyResilientClass.finalProperty"
+}
+
+// Accessing final property of resilient class from my resilience domain
+// directly
+
+// CHECK-LABEL: sil @$S16class_resilience19finalPropertyOfMineyyAA16MyResilientClassCF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $MyResilientClass):
+// CHECK: ref_element_addr [[ARG]] : $MyResilientClass, #MyResilientClass.finalProperty
+// CHECK: } // end sil function '$S16class_resilience19finalPropertyOfMineyyAA16MyResilientClassCF'
+
+public func finalPropertyOfMine(_ other: MyResilientClass) {
+ _ = other.finalProperty
+}
+
+class SubclassOfOutsideChild : ResilientOutsideChild {
+ override func method() {}
+
+ func newMethod() {}
+}
+
+// Note: no entries for [inherited] methods
+
+// CHECK-LABEL: sil_vtable SubclassOfOutsideChild {
+// CHECK-NEXT: #ResilientOutsideParent.init!initializer.1: (ResilientOutsideParent.Type) -> () -> ResilientOutsideParent : @$S16class_resilience22SubclassOfOutsideChildCACycfc [override]
+// CHECK-NEXT: #ResilientOutsideParent.method!1: (ResilientOutsideParent) -> () -> () : @$S16class_resilience22SubclassOfOutsideChildC6methodyyF [override]
+// CHECK-NEXT: #SubclassOfOutsideChild.newMethod!1: (SubclassOfOutsideChild) -> () -> () : @$S16class_resilience22SubclassOfOutsideChildC9newMethodyyF
+// CHECK-NEXT: #SubclassOfOutsideChild.deinit!deallocator: @$S16class_resilience22SubclassOfOutsideChildCfD
+// CHECK-NEXT: }
diff --git a/test/SILGen/plus_zero_closures.swift b/test/SILGen/plus_zero_closures.swift
new file mode 100644
index 0000000..2442f4b
--- /dev/null
+++ b/test/SILGen/plus_zero_closures.swift
@@ -0,0 +1,792 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -parse-as-library -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -parse-as-library -emit-silgen %s | %FileCheck %s --check-prefix=GUARANTEED
+
+import Swift
+
+var zero = 0
+
+// <rdar://problem/15921334>
+// CHECK-LABEL: sil hidden @$S8closures46return_local_generic_function_without_captures{{[_0-9a-zA-Z]*}}F : $@convention(thin) <A, R> () -> @owned @callee_guaranteed (@in_guaranteed A) -> @out R {
+func return_local_generic_function_without_captures<A, R>() -> (A) -> R {
+ func f(_: A) -> R {
+ Builtin.int_trap()
+ }
+ // CHECK: [[FN:%.*]] = function_ref @$S8closures46return_local_generic_function_without_captures{{[_0-9a-zA-Z]*}} : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1
+ // CHECK: [[FN_WITH_GENERIC_PARAMS:%.*]] = partial_apply [callee_guaranteed] [[FN]]<A, R>() : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1
+ // CHECK: return [[FN_WITH_GENERIC_PARAMS]] : $@callee_guaranteed (@in_guaranteed A) -> @out R
+ return f
+}
+
+func return_local_generic_function_with_captures<A, R>(_ a: A) -> (A) -> R {
+ func f(_: A) -> R {
+ _ = a
+ }
+
+ return f
+}
+
+// CHECK-LABEL: sil hidden @$S8closures17read_only_captureyS2iF : $@convention(thin) (Int) -> Int {
+func read_only_capture(_ x: Int) -> Int {
+ var x = x
+ // CHECK: bb0([[X:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+ // SEMANTIC ARC TODO: This is incorrect. We need to do the project_box on the copy.
+ // CHECK: [[PROJECT:%.*]] = project_box [[XBOX]]
+ // CHECK: store [[X]] to [trivial] [[PROJECT]]
+
+ func cap() -> Int {
+ return x
+ }
+
+ return cap()
+ // CHECK: [[XBOX_BORROW:%.*]] = begin_borrow [[XBOX]]
+ // SEMANTIC ARC TODO: See above. This needs to happen on the copy_valued box.
+ // CHECK: mark_function_escape [[PROJECT]]
+ // CHECK: [[CAP:%[0-9]+]] = function_ref @[[CAP_NAME:\$S8closures17read_only_capture.*]] : $@convention(thin) (@guaranteed { var Int }) -> Int
+ // CHECK: [[RET:%[0-9]+]] = apply [[CAP]]([[XBOX_BORROW]])
+ // CHECK: end_borrow [[XBOX_BORROW]]
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return [[RET]]
+}
+// CHECK: } // end sil function '$S8closures17read_only_captureyS2iF'
+
+// CHECK: sil private @[[CAP_NAME]]
+// CHECK: bb0([[XBOX:%[0-9]+]] : @guaranteed ${ var Int }):
+// CHECK: [[XADDR:%[0-9]+]] = project_box [[XBOX]]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XADDR]] : $*Int
+// CHECK: [[X:%[0-9]+]] = load [trivial] [[ACCESS]]
+// CHECK: return [[X]]
+// } // end sil function '[[CAP_NAME]]'
+
+// SEMANTIC ARC TODO: This is a place where we have again project_box too early.
+// CHECK-LABEL: sil hidden @$S8closures16write_to_captureyS2iF : $@convention(thin) (Int) -> Int {
+func write_to_capture(_ x: Int) -> Int {
+ var x = x
+ // CHECK: bb0([[X:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[XBOX_PB:%.*]] = project_box [[XBOX]]
+ // CHECK: store [[X]] to [trivial] [[XBOX_PB]]
+ // CHECK: [[X2BOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[X2BOX_PB:%.*]] = project_box [[X2BOX]]
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XBOX_PB]] : $*Int
+ // CHECK: copy_addr [[ACCESS]] to [initialization] [[X2BOX_PB]]
+ // CHECK: [[X2BOX_BORROW:%.*]] = begin_borrow [[X2BOX]]
+ // SEMANTIC ARC TODO: This next mark_function_escape should be on a projection from X2BOX_BORROW.
+ // CHECK: mark_function_escape [[X2BOX_PB]]
+ var x2 = x
+
+ func scribble() {
+ x2 = zero
+ }
+
+ scribble()
+ // CHECK: [[SCRIB:%[0-9]+]] = function_ref @[[SCRIB_NAME:\$S8closures16write_to_capture.*]] : $@convention(thin) (@guaranteed { var Int }) -> ()
+ // CHECK: apply [[SCRIB]]([[X2BOX_BORROW]])
+ // SEMANTIC ARC TODO: This should load from X2BOX_BORROW project. There is an
+ // issue here where after a copy_value, we need to reassign a projection in
+ // some way.
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[X2BOX_PB]] : $*Int
+ // CHECK: [[RET:%[0-9]+]] = load [trivial] [[ACCESS]]
+ // CHECK: destroy_value [[X2BOX]]
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return [[RET]]
+ return x2
+}
+// CHECK: } // end sil function '$S8closures16write_to_captureyS2iF'
+
+// CHECK: sil private @[[SCRIB_NAME]]
+// CHECK: bb0([[XBOX:%[0-9]+]] : @guaranteed ${ var Int }):
+// CHECK: [[XADDR:%[0-9]+]] = project_box [[XBOX]]
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[XADDR]] : $*Int
+// CHECK: assign {{%[0-9]+}} to [[ACCESS]]
+// CHECK: return
+// CHECK: } // end sil function '[[SCRIB_NAME]]'
+
+// CHECK-LABEL: sil hidden @$S8closures21multiple_closure_refs{{[_0-9a-zA-Z]*}}F
+func multiple_closure_refs(_ x: Int) -> (() -> Int, () -> Int) {
+ var x = x
+ func cap() -> Int {
+ return x
+ }
+
+ return (cap, cap)
+ // CHECK: [[CAP:%[0-9]+]] = function_ref @[[CAP_NAME:\$S8closures21multiple_closure_refs.*]] : $@convention(thin) (@guaranteed { var Int }) -> Int
+ // CHECK: [[CAP_CLOSURE_1:%[0-9]+]] = partial_apply [callee_guaranteed] [[CAP]]
+ // CHECK: [[CAP:%[0-9]+]] = function_ref @[[CAP_NAME:\$S8closures21multiple_closure_refs.*]] : $@convention(thin) (@guaranteed { var Int }) -> Int
+ // CHECK: [[CAP_CLOSURE_2:%[0-9]+]] = partial_apply [callee_guaranteed] [[CAP]]
+ // CHECK: [[RET:%[0-9]+]] = tuple ([[CAP_CLOSURE_1]] : {{.*}}, [[CAP_CLOSURE_2]] : {{.*}})
+ // CHECK: return [[RET]]
+}
+
+// CHECK-LABEL: sil hidden @$S8closures18capture_local_funcySiycycSiF : $@convention(thin) (Int) -> @owned @callee_guaranteed () -> @owned @callee_guaranteed () -> Int {
+func capture_local_func(_ x: Int) -> () -> () -> Int {
+ // CHECK: bb0([[ARG:%.*]] : @trivial $Int):
+ var x = x
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[XBOX_PB:%.*]] = project_box [[XBOX]]
+ // CHECK: store [[ARG]] to [trivial] [[XBOX_PB]]
+
+ func aleph() -> Int { return x }
+
+ func beth() -> () -> Int { return aleph }
+ // CHECK: [[BETH_REF:%.*]] = function_ref @[[BETH_NAME:\$S8closures18capture_local_funcySiycycSiF4bethL_SiycyF]] : $@convention(thin) (@guaranteed { var Int }) -> @owned @callee_guaranteed () -> Int
+ // CHECK: [[XBOX_COPY:%.*]] = copy_value [[XBOX]]
+ // SEMANTIC ARC TODO: This is incorrect. This should be a project_box from XBOX_COPY.
+ // CHECK: mark_function_escape [[XBOX_PB]]
+ // CHECK: [[BETH_CLOSURE:%[0-9]+]] = partial_apply [callee_guaranteed] [[BETH_REF]]([[XBOX_COPY]])
+
+ return beth
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return [[BETH_CLOSURE]]
+}
+// CHECK: } // end sil function '$S8closures18capture_local_funcySiycycSiF'
+
+// CHECK: sil private @[[ALEPH_NAME:\$S8closures18capture_local_funcySiycycSiF5alephL_SiyF]] : $@convention(thin) (@guaranteed { var Int }) -> Int {
+// CHECK: bb0([[XBOX:%[0-9]+]] : @guaranteed ${ var Int }):
+
+// CHECK: sil private @[[BETH_NAME]] : $@convention(thin) (@guaranteed { var Int }) -> @owned @callee_guaranteed () -> Int {
+// CHECK: bb0([[XBOX:%[0-9]+]] : @guaranteed ${ var Int }):
+// CHECK: [[XBOX_PB:%.*]] = project_box [[XBOX]]
+// CHECK: [[ALEPH_REF:%[0-9]+]] = function_ref @[[ALEPH_NAME]] : $@convention(thin) (@guaranteed { var Int }) -> Int
+// CHECK: [[XBOX_COPY:%.*]] = copy_value [[XBOX]]
+// SEMANTIC ARC TODO: This should be on a PB from XBOX_COPY.
+// CHECK: mark_function_escape [[XBOX_PB]]
+// CHECK: [[ALEPH_CLOSURE:%[0-9]+]] = partial_apply [callee_guaranteed] [[ALEPH_REF]]([[XBOX_COPY]])
+// CHECK: return [[ALEPH_CLOSURE]]
+// CHECK: } // end sil function '[[BETH_NAME]]'
+
+// CHECK-LABEL: sil hidden @$S8closures22anon_read_only_capture{{[_0-9a-zA-Z]*}}F
+func anon_read_only_capture(_ x: Int) -> Int {
+ var x = x
+ // CHECK: bb0([[X:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PB:%.*]] = project_box [[XBOX]]
+
+ return ({ x })()
+ // -- func expression
+ // CHECK: [[ANON:%[0-9]+]] = function_ref @[[CLOSURE_NAME:\$S8closures22anon_read_only_capture[_0-9a-zA-Z]*]] : $@convention(thin) (@inout_aliasable Int) -> Int
+ // -- apply expression
+ // CHECK: [[RET:%[0-9]+]] = apply [[ANON]]([[PB]])
+ // -- cleanup
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return [[RET]]
+}
+// CHECK: sil private @[[CLOSURE_NAME]]
+// CHECK: bb0([[XADDR:%[0-9]+]] : @trivial $*Int):
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XADDR]] : $*Int
+// CHECK: [[X:%[0-9]+]] = load [trivial] [[ACCESS]]
+// CHECK: return [[X]]
+
+// CHECK-LABEL: sil hidden @$S8closures21small_closure_capture{{[_0-9a-zA-Z]*}}F
+func small_closure_capture(_ x: Int) -> Int {
+ var x = x
+ // CHECK: bb0([[X:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PB:%.*]] = project_box [[XBOX]]
+
+ return { x }()
+ // -- func expression
+ // CHECK: [[ANON:%[0-9]+]] = function_ref @[[CLOSURE_NAME:\$S8closures21small_closure_capture[_0-9a-zA-Z]*]] : $@convention(thin) (@inout_aliasable Int) -> Int
+ // -- apply expression
+ // CHECK: [[RET:%[0-9]+]] = apply [[ANON]]([[PB]])
+ // -- cleanup
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return [[RET]]
+}
+// CHECK: sil private @[[CLOSURE_NAME]]
+// CHECK: bb0([[XADDR:%[0-9]+]] : @trivial $*Int):
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[XADDR]] : $*Int
+// CHECK: [[X:%[0-9]+]] = load [trivial] [[ACCESS]]
+// CHECK: return [[X]]
+
+
+// CHECK-LABEL: sil hidden @$S8closures35small_closure_capture_with_argument{{[_0-9a-zA-Z]*}}F
+func small_closure_capture_with_argument(_ x: Int) -> (_ y: Int) -> Int {
+ var x = x
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+
+ return { x + $0 }
+ // -- func expression
+ // CHECK: [[ANON:%[0-9]+]] = function_ref @[[CLOSURE_NAME:\$S8closures35small_closure_capture_with_argument.*]] : $@convention(thin) (Int, @guaranteed { var Int }) -> Int
+ // CHECK: [[XBOX_COPY:%.*]] = copy_value [[XBOX]]
+ // CHECK: [[ANON_CLOSURE_APP:%[0-9]+]] = partial_apply [callee_guaranteed] [[ANON]]([[XBOX_COPY]])
+ // -- return
+ // CHECK: destroy_value [[XBOX]]
+ // CHECK: return [[ANON_CLOSURE_APP]]
+}
+// FIXME(integers): the following checks should be updated for the new way +
+// gets invoked. <rdar://problem/29939484>
+// XCHECK: sil private @[[CLOSURE_NAME]] : $@convention(thin) (Int, @guaranteed { var Int }) -> Int
+// XCHECK: bb0([[DOLLAR0:%[0-9]+]] : $Int, [[XBOX:%[0-9]+]] : ${ var Int }):
+// XCHECK: [[XADDR:%[0-9]+]] = project_box [[XBOX]]
+// XCHECK: [[PLUS:%[0-9]+]] = function_ref @$Ss1poiS2i_SitF{{.*}}
+// XCHECK: [[LHS:%[0-9]+]] = load [trivial] [[XADDR]]
+// XCHECK: [[RET:%[0-9]+]] = apply [[PLUS]]([[LHS]], [[DOLLAR0]])
+// XCHECK: destroy_value [[XBOX]]
+// XCHECK: return [[RET]]
+
+// CHECK-LABEL: sil hidden @$S8closures24small_closure_no_capture{{[_0-9a-zA-Z]*}}F
+func small_closure_no_capture() -> (_ y: Int) -> Int {
+ // CHECK: [[ANON:%[0-9]+]] = function_ref @[[CLOSURE_NAME:\$S8closures24small_closure_no_captureS2icyFS2icfU_]] : $@convention(thin) (Int) -> Int
+ // CHECK: [[ANON_THICK:%[0-9]+]] = thin_to_thick_function [[ANON]] : ${{.*}} to $@callee_guaranteed (Int) -> Int
+ // CHECK: return [[ANON_THICK]]
+ return { $0 }
+}
+// CHECK: sil private @[[CLOSURE_NAME]] : $@convention(thin) (Int) -> Int
+// CHECK: bb0([[YARG:%[0-9]+]] : @trivial $Int):
+
+// CHECK-LABEL: sil hidden @$S8closures17uncaptured_locals{{[_0-9a-zA-Z]*}}F :
+func uncaptured_locals(_ x: Int) -> (Int, Int) {
+ var x = x
+ // -- locals without captures are stack-allocated
+ // CHECK: bb0([[XARG:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PB:%.*]] = project_box [[XADDR]]
+ // CHECK: store [[XARG]] to [trivial] [[PB]]
+
+ var y = zero
+ // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int }
+ return (x, y)
+
+}
+
+class SomeClass {
+ var x : Int = zero
+
+ init() {
+ x = { self.x }() // Closing over self.
+ }
+}
+
+// Closures within destructors <rdar://problem/15883734>
+class SomeGenericClass<T> {
+ deinit {
+ var i: Int = zero
+ // CHECK: [[C1REF:%[0-9]+]] = function_ref @$S8closures16SomeGenericClassCfdSiyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> Int
+ // CHECK: apply [[C1REF]]([[IBOX:%[0-9]+]]) : $@convention(thin) (@inout_aliasable Int) -> Int
+ var x = { i + zero } ()
+
+ // CHECK: [[C2REF:%[0-9]+]] = function_ref @$S8closures16SomeGenericClassCfdSiyXEfU0_ : $@convention(thin) () -> Int
+ // CHECK: apply [[C2REF]]() : $@convention(thin) () -> Int
+ var y = { zero } ()
+
+ // CHECK: [[C3REF:%[0-9]+]] = function_ref @$S8closures16SomeGenericClassCfdyyXEfU1_ : $@convention(thin) <τ_0_0> () -> ()
+ // CHECK: apply [[C3REF]]<T>() : $@convention(thin) <τ_0_0> () -> ()
+ var z = { _ = T.self } ()
+ }
+
+ // CHECK-LABEL: sil private @$S8closures16SomeGenericClassCfdSiyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> Int
+
+ // CHECK-LABEL: sil private @$S8closures16SomeGenericClassCfdSiyXEfU0_ : $@convention(thin) () -> Int
+
+ // CHECK-LABEL: sil private @$S8closures16SomeGenericClassCfdyyXEfU1_ : $@convention(thin) <T> () -> ()
+}
+
+// This is basically testing that the constraint system ranking
+// function conversions as worse than others, and therefore performs
+// the conversion within closures when possible.
+class SomeSpecificClass : SomeClass {}
+func takesSomeClassGenerator(_ fn : () -> SomeClass) {}
+func generateWithConstant(_ x : SomeSpecificClass) {
+ takesSomeClassGenerator({ x })
+}
+
+// CHECK-LABEL: sil private @$S8closures20generateWithConstantyyAA17SomeSpecificClassCFAA0eG0CyXEfU_ : $@convention(thin) (@guaranteed SomeSpecificClass) -> @owned SomeClass {
+// CHECK: bb0([[T0:%.*]] : @guaranteed $SomeSpecificClass):
+// CHECK: debug_value [[T0]] : $SomeSpecificClass, let, name "x", argno 1
+// CHECK: [[T0_COPY:%.*]] = copy_value [[T0]]
+// CHECK: [[T0_COPY_CASTED:%.*]] = upcast [[T0_COPY]] : $SomeSpecificClass to $SomeClass
+// CHECK: return [[T0_COPY_CASTED]]
+// CHECK: } // end sil function '$S8closures20generateWithConstantyyAA17SomeSpecificClassCFAA0eG0CyXEfU_'
+
+
+// Check the annoying case of capturing 'self' in a derived class 'init'
+// method. We allocate a mutable box to deal with 'self' potentially being
+// rebound by super.init, but 'self' is formally immutable and so is captured
+// by value. <rdar://problem/15599464>
+class Base {}
+
+class SelfCapturedInInit : Base {
+ var foo : () -> SelfCapturedInInit
+
+ // CHECK-LABEL: sil hidden @$S8closures18SelfCapturedInInitC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (@owned SelfCapturedInInit) -> @owned SelfCapturedInInit {
+ // CHECK: bb0([[SELF:%.*]] : @owned $SelfCapturedInInit):
+ //
+ // First create our initial value for self.
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var SelfCapturedInInit }, let, name "self"
+ // CHECK: [[UNINIT_SELF:%.*]] = mark_uninitialized [derivedself] [[SELF_BOX]]
+ // CHECK: [[PB_SELF_BOX:%.*]] = project_box [[UNINIT_SELF]]
+ // CHECK: store [[SELF]] to [init] [[PB_SELF_BOX]]
+ //
+ // Then perform the super init sequence.
+ // CHECK: [[TAKEN_SELF:%.*]] = load [take] [[PB_SELF_BOX]]
+ // CHECK: [[UPCAST_TAKEN_SELF:%.*]] = upcast [[TAKEN_SELF]]
+ // CHECK: [[NEW_SELF:%.*]] = apply {{.*}}([[UPCAST_TAKEN_SELF]]) : $@convention(method) (@owned Base) -> @owned Base
+ // CHECK: [[DOWNCAST_NEW_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]] : $Base to $SelfCapturedInInit
+ // CHECK: store [[DOWNCAST_NEW_SELF]] to [init] [[PB_SELF_BOX]]
+ //
+ // Finally put self in the closure.
+ // CHECK: [[BORROWED_SELF:%.*]] = load_borrow [[PB_SELF_BOX]]
+ // CHECK: [[COPIED_SELF:%.*]] = load [copy] [[PB_SELF_BOX]]
+ // CHECK: [[FOO_VALUE:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[COPIED_SELF]]) : $@convention(thin) (@guaranteed SelfCapturedInInit) -> @owned SelfCapturedInInit
+ // CHECK: [[FOO_LOCATION:%.*]] = ref_element_addr [[BORROWED_SELF]]
+ // CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[FOO_LOCATION]] : $*@callee_guaranteed () -> @owned SelfCapturedInInit
+ // CHECK: assign [[FOO_VALUE]] to [[ACCESS]]
+ override init() {
+ super.init()
+ foo = { self }
+ }
+}
+
+func takeClosure(_ fn: () -> Int) -> Int { return fn() }
+
+class TestCaptureList {
+ var x = zero
+
+ func testUnowned() {
+ let aLet = self
+ takeClosure { aLet.x }
+ takeClosure { [unowned aLet] in aLet.x }
+ takeClosure { [weak aLet] in aLet!.x }
+
+ var aVar = self
+ takeClosure { aVar.x }
+ takeClosure { [unowned aVar] in aVar.x }
+ takeClosure { [weak aVar] in aVar!.x }
+
+ takeClosure { self.x }
+ takeClosure { [unowned self] in self.x }
+ takeClosure { [weak self] in self!.x }
+
+ takeClosure { [unowned newVal = TestCaptureList()] in newVal.x }
+ takeClosure { [weak newVal = TestCaptureList()] in newVal!.x }
+ }
+}
+
+class ClassWithIntProperty { final var x = 42 }
+
+func closeOverLetLValue() {
+ let a : ClassWithIntProperty
+ a = ClassWithIntProperty()
+
+ takeClosure { a.x }
+}
+
+// The let property needs to be captured into a temporary stack slot so that it
+// is loadable even though we capture the value.
+// CHECK-LABEL: sil private @$S8closures18closeOverLetLValueyyFSiyXEfU_ : $@convention(thin) (@guaranteed ClassWithIntProperty) -> Int {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassWithIntProperty):
+// CHECK: [[TMP_CLASS_ADDR:%.*]] = alloc_stack $ClassWithIntProperty, let, name "a", argno 1
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: store [[COPY_ARG]] to [init] [[TMP_CLASS_ADDR]] : $*ClassWithIntProperty
+// CHECK: [[LOADED_CLASS:%.*]] = load [copy] [[TMP_CLASS_ADDR]] : $*ClassWithIntProperty
+// CHECK: [[BORROWED_LOADED_CLASS:%.*]] = begin_borrow [[LOADED_CLASS]]
+// CHECK: [[INT_IN_CLASS_ADDR:%.*]] = ref_element_addr [[BORROWED_LOADED_CLASS]] : $ClassWithIntProperty, #ClassWithIntProperty.x
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[INT_IN_CLASS_ADDR]] : $*Int
+// CHECK: [[INT_IN_CLASS:%.*]] = load [trivial] [[ACCESS]] : $*Int
+// CHECK: end_borrow [[BORROWED_LOADED_CLASS]] from [[LOADED_CLASS]]
+// CHECK: destroy_value [[LOADED_CLASS]]
+// CHECK: destroy_addr [[TMP_CLASS_ADDR]] : $*ClassWithIntProperty
+// CHECK: dealloc_stack %1 : $*ClassWithIntProperty
+// CHECK: return [[INT_IN_CLASS]]
+// CHECK: } // end sil function '$S8closures18closeOverLetLValueyyFSiyXEfU_'
+
+// GUARANTEED-LABEL: sil private @$S8closures18closeOverLetLValueyyFSiyXEfU_ : $@convention(thin) (@guaranteed ClassWithIntProperty) -> Int {
+// GUARANTEED: bb0(%0 : @guaranteed $ClassWithIntProperty):
+// GUARANTEED: [[TMP:%.*]] = alloc_stack $ClassWithIntProperty
+// GUARANTEED: [[COPY:%.*]] = copy_value %0 : $ClassWithIntProperty
+// GUARANTEED: store [[COPY]] to [init] [[TMP]] : $*ClassWithIntProperty
+// GUARANTEED: [[LOADED_COPY:%.*]] = load [copy] [[TMP]]
+// GUARANTEED: [[BORROWED:%.*]] = begin_borrow [[LOADED_COPY]]
+// GUARANTEED: end_borrow [[BORROWED]] from [[LOADED_COPY]]
+// GUARANTEED: destroy_value [[LOADED_COPY]]
+// GUARANTEED: destroy_addr [[TMP]]
+// GUARANTEED: } // end sil function '$S8closures18closeOverLetLValueyyFSiyXEfU_'
+
+
+// Use an external function so inout deshadowing cannot see its body.
+@_silgen_name("takesNoEscapeClosure")
+func takesNoEscapeClosure(fn : () -> Int)
+
+struct StructWithMutatingMethod {
+ var x = 42
+
+ mutating func mutatingMethod() {
+ // This should not capture the refcount of the self shadow.
+ takesNoEscapeClosure { x = 42; return x }
+ }
+}
+
+// Check that the address of self is passed in, but not the refcount pointer.
+
+// CHECK-LABEL: sil hidden @$S8closures24StructWithMutatingMethodV08mutatingE0{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0(%0 : @trivial $*StructWithMutatingMethod):
+// CHECK: [[CLOSURE:%[0-9]+]] = function_ref @$S8closures24StructWithMutatingMethodV08mutatingE0{{.*}} : $@convention(thin) (@inout_aliasable StructWithMutatingMethod) -> Int
+// CHECK: partial_apply [callee_guaranteed] [[CLOSURE]](%0) : $@convention(thin) (@inout_aliasable StructWithMutatingMethod) -> Int
+
+// Check that the closure body only takes the pointer.
+// CHECK-LABEL: sil private @$S8closures24StructWithMutatingMethodV08mutatingE0{{.*}} : $@convention(thin) (@inout_aliasable StructWithMutatingMethod) -> Int {
+// CHECK: bb0(%0 : @trivial $*StructWithMutatingMethod):
+
+class SuperBase {
+ func boom() {}
+}
+class SuperSub : SuperBase {
+ override func boom() {}
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1ayyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_1:\$S8closures8SuperSubC1a[_0-9a-zA-Z]*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: apply [[INNER]]([[SELF]])
+ // CHECK: } // end sil function '$S8closures8SuperSubC1ayyF'
+ func a() {
+ // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[CLASS_METHOD:%.*]] = class_method [[ARG]] : $SuperSub, #SuperSub.boom!1
+ // CHECK: = apply [[CLASS_METHOD]]([[ARG]])
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
+ // CHECK: destroy_value [[ARG_COPY_SUPER]]
+ // CHECK: } // end sil function '[[INNER_FUNC_1]]'
+ func a1() {
+ self.boom()
+ super.boom()
+ }
+ a1()
+ }
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1byyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_1:\$S8closures8SuperSubC1b[_0-9a-zA-Z]*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: = apply [[INNER]]([[SELF]])
+ // CHECK: } // end sil function '$S8closures8SuperSubC1byyF'
+ func b() {
+ // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:\$S8closures8SuperSubC1b.*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: = apply [[INNER]]([[ARG]])
+ // CHECK: } // end sil function '[[INNER_FUNC_1]]'
+ func b1() {
+ // CHECK: sil private @[[INNER_FUNC_2]] : $@convention(thin) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[CLASS_METHOD:%.*]] = class_method [[ARG]] : $SuperSub, #SuperSub.boom!1
+ // CHECK: = apply [[CLASS_METHOD]]([[ARG]]) : $@convention(method) (@guaranteed SuperSub) -> ()
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase)
+ // CHECK: destroy_value [[ARG_COPY_SUPER]]
+ // CHECK: } // end sil function '[[INNER_FUNC_2]]'
+ func b2() {
+ self.boom()
+ super.boom()
+ }
+ b2()
+ }
+ b1()
+ }
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1cyyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_1:\$S8closures8SuperSubC1c[_0-9a-zA-Z]*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[SELF_COPY]])
+ // CHECK: [[BORROWED_PA:%.*]] = begin_borrow [[PA]]
+ // CHECK: [[PA_COPY:%.*]] = copy_value [[BORROWED_PA]]
+ // CHECK: [[B:%.*]] = begin_borrow [[PA_COPY]]
+ // CHECK: apply [[B]]()
+ // CHECK: end_borrow [[B]]
+ // CHECK: destroy_value [[PA_COPY]]
+ // CHECK: end_borrow [[BORROWED_PA]] from [[PA]]
+ // CHECK: destroy_value [[PA]]
+ // CHECK: } // end sil function '$S8closures8SuperSubC1cyyF'
+ func c() {
+ // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[CLASS_METHOD:%.*]] = class_method [[ARG]] : $SuperSub, #SuperSub.boom!1
+ // CHECK: = apply [[CLASS_METHOD]]([[ARG]]) : $@convention(method) (@guaranteed SuperSub) -> ()
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
+ // CHECK: destroy_value [[ARG_COPY_SUPER]]
+ // CHECK: } // end sil function '[[INNER_FUNC_1]]'
+ let c1 = { () -> Void in
+ self.boom()
+ super.boom()
+ }
+ c1()
+ }
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1dyyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_1:\$S8closures8SuperSubC1d[_0-9a-zA-Z]*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[SELF_COPY]])
+ // CHECK: [[BORROWED_PA:%.*]] = begin_borrow [[PA]]
+ // CHECK: [[PA_COPY:%.*]] = copy_value [[BORROWED_PA]]
+ // CHECK: [[B:%.*]] = begin_borrow [[PA_COPY]]
+ // CHECK: apply [[B]]()
+ // CHECK: end_borrow [[B]]
+ // CHECK: destroy_value [[PA_COPY]]
+ // CHECK: end_borrow [[BORROWED_PA]] from [[PA]]
+ // CHECK: destroy_value [[PA]]
+ // CHECK: } // end sil function '$S8closures8SuperSubC1dyyF'
+ func d() {
+ // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:\$S8closures8SuperSubC1d.*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: = apply [[INNER]]([[ARG]])
+ // CHECK: } // end sil function '[[INNER_FUNC_1]]'
+ let d1 = { () -> Void in
+ // CHECK: sil private @[[INNER_FUNC_2]] : $@convention(thin) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
+ // CHECK: destroy_value [[ARG_COPY_SUPER]]
+ // CHECK: } // end sil function '[[INNER_FUNC_2]]'
+ func d2() {
+ super.boom()
+ }
+ d2()
+ }
+ d1()
+ }
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1eyyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_NAME1:\$S8closures8SuperSubC1e[_0-9a-zA-Z]*]] : $@convention(thin)
+ // CHECK: = apply [[INNER]]([[SELF]])
+ // CHECK: } // end sil function '$S8closures8SuperSubC1eyyF'
+ func e() {
+ // CHECK: sil private @[[INNER_FUNC_NAME1]] : $@convention(thin)
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_NAME2:\$S8closures8SuperSubC1e.*]] : $@convention(thin)
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[ARG_COPY]])
+ // CHECK: [[BORROWED_PA:%.*]] = begin_borrow [[PA]]
+ // CHECK: [[PA_COPY:%.*]] = copy_value [[BORROWED_PA]]
+ // CHECK: [[B:%.*]] = begin_borrow [[PA_COPY]]
+ // CHECK: apply [[B]]() : $@callee_guaranteed () -> ()
+ // CHECK: end_borrow [[B]]
+ // CHECK: destroy_value [[PA_COPY]]
+ // CHECK: end_borrow [[BORROWED_PA]] from [[PA]]
+ // CHECK: destroy_value [[PA]]
+ // CHECK: } // end sil function '[[INNER_FUNC_NAME1]]'
+ func e1() {
+ // CHECK: sil private @[[INNER_FUNC_NAME2]] : $@convention(thin)
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPERCAST:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPERCAST:%.*]] = begin_borrow [[ARG_COPY_SUPERCAST]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPERCAST]])
+ // CHECK: destroy_value [[ARG_COPY_SUPERCAST]]
+ // CHECK: return
+ // CHECK: } // end sil function '[[INNER_FUNC_NAME2]]'
+ let e2 = {
+ super.boom()
+ }
+ e2()
+ }
+ e1()
+ }
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1fyyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_1:\$S8closures8SuperSubC1fyyFyycfU_]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[SELF_COPY]])
+ // CHECK: destroy_value [[PA]]
+ // CHECK: } // end sil function '$S8closures8SuperSubC1fyyF'
+ func f() {
+ // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:\$S8closures8SuperSubC1fyyFyycfU_yyKXKfu_]] : $@convention(thin) (@guaranteed SuperSub) -> @error Error
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[ARG_COPY]])
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]]
+ // CHECK: [[REABSTRACT_PA:%.*]] = partial_apply [callee_guaranteed] {{.*}}([[CVT]])
+ // CHECK: [[REABSTRACT_CVT:%.*]] = convert_escape_to_noescape [[REABSTRACT_PA]]
+ // CHECK: [[TRY_APPLY_AUTOCLOSURE:%.*]] = function_ref @$Ss2qqoiyxxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
+ // CHECK: try_apply [[TRY_APPLY_AUTOCLOSURE]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
+ // CHECK: [[NORMAL_BB]]{{.*}}
+ // CHECK: } // end sil function '[[INNER_FUNC_1]]'
+ let f1 = {
+ // CHECK: sil private [transparent] @[[INNER_FUNC_2]]
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: destroy_value [[ARG_COPY_SUPER]]
+ // CHECK: } // end sil function '[[INNER_FUNC_2]]'
+ nil ?? super.boom()
+ }
+ }
+
+ // CHECK-LABEL: sil hidden @$S8closures8SuperSubC1gyyF : $@convention(method) (@guaranteed SuperSub) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_1:\$S8closures8SuperSubC1g[_0-9a-zA-Z]*]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: = apply [[INNER]]([[SELF]])
+ // CHECK: } // end sil function '$S8closures8SuperSubC1gyyF'
+ func g() {
+ // CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@guaranteed SuperSub) -> ()
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:\$S8closures8SuperSubC1g.*]] : $@convention(thin) (@guaranteed SuperSub) -> @error Error
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[INNER]]([[ARG_COPY]])
+ // CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> @error Error to $@noescape @callee_guaranteed () -> @error Error
+ // CHECK: [[REABSTRACT_PA:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> @error Error) -> (@out (), @error Error)
+ // CHECK: [[REABSTRACT_CVT:%.*]] = convert_escape_to_noescape [[REABSTRACT_PA]]
+ // CHECK: [[TRY_APPLY_FUNC:%.*]] = function_ref @$Ss2qqoiyxxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
+ // CHECK: try_apply [[TRY_APPLY_FUNC]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, @noescape @callee_guaranteed () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
+ // CHECK: [[NORMAL_BB]]{{.*}}
+ // CHECK: } // end sil function '[[INNER_FUNC_1]]'
+ func g1() {
+ // CHECK: sil private [transparent] @[[INNER_FUNC_2]] : $@convention(thin) (@guaranteed SuperSub) -> @error Error {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $SuperSub):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
+ // CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S8closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
+ // CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
+ // CHECK: destroy_value [[ARG_COPY_SUPER]]
+ // CHECK: } // end sil function '[[INNER_FUNC_2]]'
+ nil ?? super.boom()
+ }
+ g1()
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S8closures24UnownedSelfNestedCaptureC06nestedE0{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed UnownedSelfNestedCapture) -> ()
+// -- We enter with an assumed strong +1.
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $UnownedSelfNestedCapture):
+// CHECK: [[OUTER_SELF_CAPTURE:%.*]] = alloc_box ${ var @sil_unowned UnownedSelfNestedCapture }
+// CHECK: [[PB:%.*]] = project_box [[OUTER_SELF_CAPTURE]]
+// -- strong +2
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: [[UNOWNED_SELF:%.*]] = ref_to_unowned [[SELF_COPY]] :
+// -- TODO: A lot of fussy r/r traffic and owned/unowned conversions here.
+// -- strong +2, unowned +1
+// CHECK: [[UNOWNED_SELF_COPY:%.*]] = copy_value [[UNOWNED_SELF]]
+// CHECK: store [[UNOWNED_SELF_COPY]] to [init] [[PB]]
+// SEMANTIC ARC TODO: This destroy_value should probably be /after/ the load from PB on the next line.
+// CHECK: destroy_value [[SELF_COPY]]
+// CHECK: [[UNOWNED_SELF:%.*]] = load_borrow [[PB]]
+// -- strong +2, unowned +1
+// CHECK: [[SELF:%.*]] = copy_unowned_value [[UNOWNED_SELF]]
+// CHECK: end_borrow [[UNOWNED_SELF]] from [[PB]]
+// CHECK: [[UNOWNED_SELF2:%.*]] = ref_to_unowned [[SELF]]
+// -- strong +2, unowned +2
+// CHECK: [[UNOWNED_SELF2_COPY:%.*]] = copy_value [[UNOWNED_SELF2]]
+// -- strong +1, unowned +2
+// CHECK: destroy_value [[SELF]]
+// -- closure takes unowned ownership
+// CHECK: [[OUTER_CLOSURE:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[UNOWNED_SELF2_COPY]])
+// CHECK: [[OUTER_CONVERT:%.*]] = convert_escape_to_noescape [[OUTER_CLOSURE]]
+// -- call consumes closure
+// -- strong +1, unowned +1
+// CHECK: [[INNER_CLOSURE:%.*]] = apply [[OUTER_CONVERT]]
+// CHECK: [[B:%.*]] = begin_borrow [[INNER_CLOSURE]]
+// CHECK: [[CONSUMED_RESULT:%.*]] = apply [[B]]()
+// CHECK: destroy_value [[CONSUMED_RESULT]]
+// CHECK: destroy_value [[INNER_CLOSURE]]
+// -- destroy_values unowned self in box
+// -- strong +1, unowned +0
+// CHECK: destroy_value [[OUTER_SELF_CAPTURE]]
+// -- strong +0, unowned +0
+// CHECK: } // end sil function '$S8closures24UnownedSelfNestedCaptureC06nestedE0{{[_0-9a-zA-Z]*}}F'
+
+// -- outer closure
+// -- strong +0, unowned +1
+// CHECK: sil private @[[OUTER_CLOSURE_FUN:\$S8closures24UnownedSelfNestedCaptureC06nestedE0yyFACycyXEfU_]] : $@convention(thin) (@guaranteed @sil_unowned UnownedSelfNestedCapture) -> @owned @callee_guaranteed () -> @owned UnownedSelfNestedCapture {
+// CHECK: bb0([[CAPTURED_SELF:%.*]] : @guaranteed $@sil_unowned UnownedSelfNestedCapture):
+// -- strong +0, unowned +2
+// CHECK: [[CAPTURED_SELF_COPY:%.*]] = copy_value [[CAPTURED_SELF]] :
+// -- closure takes ownership of unowned ref
+// CHECK: [[INNER_CLOSURE:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[CAPTURED_SELF_COPY]])
+// -- strong +0, unowned +1 (claimed by closure)
+// CHECK: return [[INNER_CLOSURE]]
+// CHECK: } // end sil function '[[OUTER_CLOSURE_FUN]]'
+
+// -- inner closure
+// -- strong +0, unowned +1
+// CHECK: sil private @[[INNER_CLOSURE_FUN:\$S8closures24UnownedSelfNestedCaptureC06nestedE0yyFACycyXEfU_ACycfU_]] : $@convention(thin) (@guaranteed @sil_unowned UnownedSelfNestedCapture) -> @owned UnownedSelfNestedCapture {
+// CHECK: bb0([[CAPTURED_SELF:%.*]] : @guaranteed $@sil_unowned UnownedSelfNestedCapture):
+// -- strong +1, unowned +1
+// CHECK: [[SELF:%.*]] = copy_unowned_value [[CAPTURED_SELF:%.*]] :
+// -- strong +1, unowned +0 (claimed by return)
+// CHECK: return [[SELF]]
+// CHECK: } // end sil function '[[INNER_CLOSURE_FUN]]'
+class UnownedSelfNestedCapture {
+ func nestedCapture() {
+ {[unowned self] in { self } }()()
+ }
+}
+
+// Check that capturing 'self' via a 'super' call also captures the generic
+// signature if the base class is concrete and the derived class is generic
+
+class ConcreteBase {
+ func swim() {}
+}
+
+// CHECK-LABEL: sil private @$S8closures14GenericDerivedC4swimyyFyyXEfU_ : $@convention(thin) <Ocean> (@guaranteed GenericDerived<Ocean>) -> ()
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $GenericDerived<Ocean>):
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $GenericDerived<Ocean> to $ConcreteBase
+// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+// CHECK: [[METHOD:%.*]] = function_ref @$S8closures12ConcreteBaseC4swimyyF
+// CHECK: apply [[METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed ConcreteBase) -> ()
+// CHECK: destroy_value [[ARG_COPY_SUPER]]
+// CHECK: } // end sil function '$S8closures14GenericDerivedC4swimyyFyyXEfU_'
+
+class GenericDerived<Ocean> : ConcreteBase {
+ override func swim() {
+ withFlotationAid {
+ super.swim()
+ }
+ }
+
+ func withFlotationAid(_ fn: () -> ()) {}
+}
+
+// Don't crash on this
+func r25993258_helper(_ fn: (inout Int, Int) -> ()) {}
+func r25993258() {
+ r25993258_helper { _ in () }
+}
+
+// rdar://29810997
+//
+// Using a let from a closure in an init was causing the type-checker
+// to produce invalid AST: 'self.fn' was an l-value, but 'self' was already
+// loaded to make an r-value. This was ultimately because CSApply was
+// building the member reference correctly in the context of the closure,
+// where 'fn' is not settable, but CSGen / CSSimplify was processing it
+// in the general DC of the constraint system, i.e. the init, where
+// 'fn' *is* settable.
+func r29810997_helper(_ fn: (Int) -> Int) -> Int { return fn(0) }
+struct r29810997 {
+ private let fn: (Int) -> Int
+ private var x: Int
+
+ init(function: @escaping (Int) -> Int) {
+ fn = function
+ x = r29810997_helper { fn($0) }
+ }
+}
+
+// DI will turn this into a direct capture of the specific stored property.
+// CHECK-LABEL: sil hidden @$S8closures16r29810997_helperyS3iXEF : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int) -> Int
diff --git a/test/SILGen/plus_zero_collection_downcast.swift b/test/SILGen/plus_zero_collection_downcast.swift
new file mode 100644
index 0000000..30f16af
--- /dev/null
+++ b/test/SILGen/plus_zero_collection_downcast.swift
@@ -0,0 +1,241 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+// FIXME: Should go into the standard library.
+public extension _ObjectiveCBridgeable {
+ static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
+ -> Self {
+ var result: Self?
+ _forceBridgeFromObjectiveC(source!, result: &result)
+ return result!
+ }
+}
+
+class BridgedObjC : NSObject { }
+
+func == (x: BridgedObjC, y: BridgedObjC) -> Bool { return true }
+
+struct BridgedSwift : Hashable, _ObjectiveCBridgeable {
+ var hashValue: Int { return 0 }
+
+ func _bridgeToObjectiveC() -> BridgedObjC {
+ return BridgedObjC()
+ }
+
+ static func _forceBridgeFromObjectiveC(
+ _ x: BridgedObjC,
+ result: inout BridgedSwift?
+ ) {
+ }
+ static func _conditionallyBridgeFromObjectiveC(
+ _ x: BridgedObjC,
+ result: inout BridgedSwift?
+ ) -> Bool {
+ return true
+ }
+}
+
+func == (x: BridgedSwift, y: BridgedSwift) -> Bool { return true }
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast17testArrayDowncast{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<AnyObject>):
+func testArrayDowncast(_ array: [AnyObject]) -> [BridgedObjC] {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss15_arrayForceCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<AnyObject, BridgedObjC>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ return array as! [BridgedObjC]
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast27testArrayDowncastFromObject{{.*}}F
+// CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+func testArrayDowncastFromObject(_ obj: AnyObject) -> [BridgedObjC] {
+ // CHECK: unconditional_checked_cast_addr AnyObject in [[OBJECT_ALLOC:%[0-9]+]] : $*AnyObject to Array<BridgedObjC> in [[VALUE_ALLOC:%[0-9]+]] : $*Array<BridgedObjC>
+ return obj as! [BridgedObjC]
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast28testArrayDowncastFromNSArray{{.*}}F
+// CHECK: bb0([[NSARRAY_OBJ:%[0-9]+]] : $NSArray):
+func testArrayDowncastFromNSArray(_ obj: NSArray) -> [BridgedObjC] {
+ // CHECK: unconditional_checked_cast_addr NSArray in [[OBJECT_ALLOC:%[0-9]+]] : $*NSArray to Array<BridgedObjC> in [[VALUE_ALLOC:%[0-9]+]] : $*Array<BridgedObjC>
+ return obj as! [BridgedObjC]
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast28testArrayDowncastConditional{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<AnyObject>):
+func testArrayDowncastConditional(_ array: [AnyObject]) -> [BridgedObjC]? {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss21_arrayConditionalCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<AnyObject, BridgedObjC>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
+ return array as? [BridgedObjC]
+}
+// CHECK: } // end sil function '$S19collection_downcast28testArrayDowncastConditional{{.*}}F'
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast12testArrayIsa{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<AnyObject>)
+func testArrayIsa(_ array: [AnyObject]) -> Bool {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss21_arrayConditionalCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<AnyObject, BridgedObjC>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
+ // CHECK-NOT: destroy_value [[ARRAY]]
+ return array is [BridgedObjC] ? true : false
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast24testArrayDowncastBridged{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<AnyObject>):
+func testArrayDowncastBridged(_ array: [AnyObject]) -> [BridgedSwift] {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss15_arrayForceCast{{.*}}F
+ // CHECK: apply [[BRIDGE_FN]]<AnyObject, BridgedSwift>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ // CHECK-NOT: destroy_value [[ARRAY]]
+ return array as! [BridgedSwift]
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast35testArrayDowncastBridgedConditional{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<AnyObject>):
+func testArrayDowncastBridgedConditional(_ array: [AnyObject]) -> [BridgedSwift]?{
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss21_arrayConditionalCast{{.*}}F
+ // CHECK: apply [[BRIDGE_FN]]<AnyObject, BridgedSwift>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
+ // CHECK-NOT: destroy_value [[ARRAY]]
+ return array as? [BridgedSwift]
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast19testArrayIsaBridged{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<AnyObject>)
+func testArrayIsaBridged(_ array: [AnyObject]) -> Bool {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss21_arrayConditionalCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<AnyObject, BridgedSwift>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
+ // CHECK-NOT: destroy_value [[ARRAY]]
+ return array is [BridgedSwift] ? true : false
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast32testDictionaryDowncastFromObject{{.*}}F
+// CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+func testDictionaryDowncastFromObject(_ obj: AnyObject)
+ -> Dictionary<BridgedObjC, BridgedObjC> {
+ // CHECK: unconditional_checked_cast_addr AnyObject in [[OBJECT_ALLOC:%[0-9]+]] : $*AnyObject to Dictionary<BridgedObjC, BridgedObjC> in [[VALUE_ALLOC:%[0-9]+]] : $*Dictionary<BridgedObjC, BridgedObjC>
+ return obj as! Dictionary<BridgedObjC, BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast22testDictionaryDowncast{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<NSObject, AnyObject>)
+func testDictionaryDowncast(_ dict: Dictionary<NSObject, AnyObject>)
+ -> Dictionary<BridgedObjC, BridgedObjC> {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss19_dictionaryDownCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<NSObject, AnyObject, BridgedObjC, BridgedObjC>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK-NOT: destroy_value [[DICT]]
+ return dict as! Dictionary<BridgedObjC, BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast33testDictionaryDowncastConditional{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<NSObject, AnyObject>)
+func testDictionaryDowncastConditional(_ dict: Dictionary<NSObject, AnyObject>)
+-> Dictionary<BridgedObjC, BridgedObjC>? {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss30_dictionaryDownCastConditional{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<NSObject, AnyObject, BridgedObjC, BridgedObjC>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>
+ // CHECK-NOT: destroy_value [[DICT]]
+ return dict as? Dictionary<BridgedObjC, BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast41testDictionaryDowncastBridgedVConditional{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<NSObject, AnyObject>)
+func testDictionaryDowncastBridgedVConditional(_ dict: Dictionary<NSObject, AnyObject>)
+ -> Dictionary<BridgedObjC, BridgedSwift>? {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss30_dictionaryDownCastConditional{{.*}}F
+ // CHECK: apply [[BRIDGE_FN]]<NSObject, AnyObject, BridgedObjC, BridgedSwift>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>{{.*}}
+ // CHECK-NOT: destroy_value [[DICT]]
+ return dict as? Dictionary<BridgedObjC, BridgedSwift>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast41testDictionaryDowncastBridgedKConditional{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<NSObject, AnyObject>)
+func testDictionaryDowncastBridgedKConditional(_ dict: Dictionary<NSObject, AnyObject>)
+-> Dictionary<BridgedSwift, BridgedObjC>? {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss30_dictionaryDownCastConditional{{.*}}F
+ // CHECK: apply [[BRIDGE_FN]]<NSObject, AnyObject, BridgedSwift, BridgedObjC>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>
+ // CHECK-NOT: destroy_value [[DICT]]
+ return dict as? Dictionary<BridgedSwift, BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast31testDictionaryDowncastBridgedKV{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<NSObject, AnyObject>)
+func testDictionaryDowncastBridgedKV(_ dict: Dictionary<NSObject, AnyObject>)
+-> Dictionary<BridgedSwift, BridgedSwift> {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss19_dictionaryDownCast{{.*}}F
+ // CHECK: apply [[BRIDGE_FN]]<NSObject, AnyObject, BridgedSwift, BridgedSwift>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK-NOT: destroy_value [[DICT]]
+ return dict as! Dictionary<BridgedSwift, BridgedSwift>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast42testDictionaryDowncastBridgedKVConditional{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<NSObject, AnyObject>)
+func testDictionaryDowncastBridgedKVConditional(_ dict: Dictionary<NSObject, AnyObject>)
+ -> Dictionary<BridgedSwift, BridgedSwift>? {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss30_dictionaryDownCastConditional{{.*}}F
+ // CHECK: apply [[BRIDGE_FN]]<NSObject, AnyObject, BridgedSwift, BridgedSwift>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>
+ // CHECK-NOT: destroy_value [[DICT]]
+ return dict as? Dictionary<BridgedSwift, BridgedSwift>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast25testSetDowncastFromObject{{.*}}F
+// CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+func testSetDowncastFromObject(_ obj: AnyObject)
+ -> Set<BridgedObjC> {
+ // CHECK: unconditional_checked_cast_addr AnyObject in [[OBJECT_ALLOC:%[0-9]+]] : $*AnyObject to Set<BridgedObjC> in [[VALUE_ALLOC:%[0-9]+]] : $*Set<BridgedObjC>
+ return obj as! Set<BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast15testSetDowncast{{.*}}F
+// CHECK: bb0([[SET:%[0-9]+]] : $Set<NSObject>)
+func testSetDowncast(_ dict: Set<NSObject>)
+ -> Set<BridgedObjC> {
+ // CHECK: [[SET_COPY:%.*]] = copy_value [[SET]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss12_setDownCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<NSObject, BridgedObjC>([[SET_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Set<τ_0_1>
+ // CHECK-NOT: destroy_value [[SET]]
+ return dict as! Set<BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast26testSetDowncastConditional{{.*}}F
+// CHECK: bb0([[SET:%[0-9]+]] : $Set<NSObject>)
+func testSetDowncastConditional(_ dict: Set<NSObject>)
+ -> Set<BridgedObjC>? {
+ // CHECK: [[SET_COPY:%.*]] = copy_value [[SET]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss23_setDownCastConditional{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<NSObject, BridgedObjC>([[SET_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Optional<Set<τ_0_1>>
+ // CHECK-NOT: destroy_value [[SET]]
+ return dict as? Set<BridgedObjC>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast22testSetDowncastBridged{{.*}}F
+// CHECK: bb0([[SET:%[0-9]+]] : $Set<NSObject>)
+func testSetDowncastBridged(_ dict: Set<NSObject>)
+ -> Set<BridgedSwift> {
+ // CHECK: [[SET_COPY:%.*]] = copy_value [[SET]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss12_setDownCast{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<NSObject, BridgedSwift>([[SET_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Set<τ_0_1>
+ // CHECK-NOT: destroy_value [[SET]]
+ return dict as! Set<BridgedSwift>
+}
+
+// CHECK-LABEL: sil hidden @$S19collection_downcast33testSetDowncastBridgedConditional{{.*}}F
+// CHECK: bb0([[SET:%[0-9]+]] : $Set<NSObject>)
+func testSetDowncastBridgedConditional(_ dict: Set<NSObject>)
+ -> Set<BridgedSwift>? {
+ // CHECK: [[SET_COPY:%.*]] = copy_value [[SET]]
+ // CHECK: [[DOWNCAST_FN:%[0-9]+]] = function_ref @$Ss23_setDownCastConditional{{.*}}F
+ // CHECK: apply [[DOWNCAST_FN]]<NSObject, BridgedSwift>([[SET_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Optional<Set<τ_0_1>>
+ // CHECK-NOT: destroy_value [[SET]]
+ return dict as? Set<BridgedSwift>
+}
diff --git a/test/SILGen/plus_zero_collection_subtype_downcast.swift b/test/SILGen/plus_zero_collection_subtype_downcast.swift
new file mode 100644
index 0000000..251eb9e
--- /dev/null
+++ b/test/SILGen/plus_zero_collection_subtype_downcast.swift
@@ -0,0 +1,47 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -sdk %S/Inputs %s | %FileCheck %s
+
+struct S { var x, y: Int }
+
+// CHECK-LABEL: sil hidden @$S27collection_subtype_downcast06array_C00D0SayAA1SVGSgSayypG_tF :
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Array<Any>):
+// CHECK-NEXT: debug_value [[ARG]]
+// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[FN:%.*]] = function_ref @$Ss21_arrayConditionalCastySayq_GSgSayxGr0_lF
+// CHECK-NEXT: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Any, S>([[BORROWED_ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Optional<Array<τ_0_1>>
+// CHECK-NEXT: end_borrow
+// CHECK-NEXT: destroy_value [[ARG_COPY]]
+// CHECK-NEXT: return [[RESULT]]
+func array_downcast(array: [Any]) -> [S]? {
+ return array as? [S]
+}
+
+extension S : Hashable {
+ var hashValue : Int {
+ return x + y
+ }
+}
+func ==(lhs: S, rhs: S) -> Bool {
+ return true
+}
+
+// FIXME: This entrypoint name should not be bridging-specific
+// CHECK-LABEL: sil hidden @$S27collection_subtype_downcast05dict_C00D0s10DictionaryVyAA1SVSiGSgAEyAGypG_tF :
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Dictionary<S, Any>):
+// CHECK: debug_value [[ARG]]
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: // function_ref
+// CHECK: [[FN:%.*]] = function_ref @$Ss30_dictionaryDownCastConditionalys10DictionaryVyq0_q1_GSgACyxq_Gs8HashableRzsAGR0_r2_lF
+// CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
+// CHECK: [[RESULT:%.*]] = apply [[FN]]<S, Any, S, Int>([[BORROWED_ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Optional<Dictionary<τ_0_2, τ_0_3>>
+// CHECK: end_borrow [[BORROWED_ARG_COPY]] from [[ARG_COPY]]
+// CHECK: destroy_value [[ARG_COPY]]
+// CHECK: return [[RESULT]]
+func dict_downcast(dict: [S: Any]) -> [S: Int]? {
+ return dict as? [S: Int]
+}
+
+// It's not actually possible to test this for Sets independent of
+// the bridging rules.
diff --git a/test/SILGen/plus_zero_collection_subtype_upcast.swift b/test/SILGen/plus_zero_collection_subtype_upcast.swift
new file mode 100644
index 0000000..a0d1a13
--- /dev/null
+++ b/test/SILGen/plus_zero_collection_subtype_upcast.swift
@@ -0,0 +1,46 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -sdk %S/Inputs %s | %FileCheck %s
+
+struct S { var x, y: Int }
+
+// CHECK-LABEL: sil hidden @$S25collection_subtype_upcast06array_C00D0SayypGSayAA1SVG_tF :
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Array<S>):
+// CHECK: debug_value [[ARG]]
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: // function_ref
+// CHECK: [[FN:%.*]] = function_ref @$Ss15_arrayForceCastySayq_GSayxGr0_lF
+// CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
+// CHECK: [[RESULT:%.*]] = apply [[FN]]<S, Any>([[BORROWED_ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+// CHECK: end_borrow [[BORROWED_ARG_COPY]] from [[ARG_COPY]]
+// CHECK: destroy_value [[ARG_COPY]]
+// CHECK: return [[RESULT]]
+func array_upcast(array: [S]) -> [Any] {
+ return array
+}
+
+extension S : Hashable {
+ var hashValue : Int {
+ return x + y
+ }
+}
+func ==(lhs: S, rhs: S) -> Bool {
+ return true
+}
+
+// FIXME: This entrypoint name should not be bridging-specific
+// CHECK-LABEL: sil hidden @$S25collection_subtype_upcast05dict_C00D0s10DictionaryVyAA1SVypGAEyAGSiG_tF :
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Dictionary<S, Int>):
+// CHECK: debug_value [[ARG]]
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: // function_ref
+// CHECK: [[FN:%.*]] = function_ref @$Ss17_dictionaryUpCastys10DictionaryVyq0_q1_GACyxq_Gs8HashableRzsAFR0_r2_lF
+// CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[ARG_COPY]]
+// CHECK: [[RESULT:%.*]] = apply [[FN]]<S, Int, S, Any>([[BORROWED_ARG_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+// CHECK: destroy_value [[ARG_COPY]]
+// CHECK: return [[RESULT]]
+func dict_upcast(dict: [S: Int]) -> [S: Any] {
+ return dict
+}
+
+// It's not actually possible to test this for Sets independent of
+// the bridging rules.
diff --git a/test/SILGen/plus_zero_collection_upcast.swift b/test/SILGen/plus_zero_collection_upcast.swift
new file mode 100644
index 0000000..c0bb574
--- /dev/null
+++ b/test/SILGen/plus_zero_collection_upcast.swift
@@ -0,0 +1,111 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
+
+// FIXME: rdar://problem/19648117 Needs splitting objc parts out
+// XFAIL: linux
+
+import Foundation
+
+// FIXME: Should go into the standard library.
+public extension _ObjectiveCBridgeable {
+ static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
+ -> Self {
+ var result: Self?
+ _forceBridgeFromObjectiveC(source!, result: &result)
+ return result!
+ }
+}
+
+class BridgedObjC : NSObject { }
+
+func == (x: BridgedObjC, y: BridgedObjC) -> Bool { return true }
+
+struct BridgedSwift : Hashable, _ObjectiveCBridgeable {
+ var hashValue: Int { return 0 }
+
+ func _bridgeToObjectiveC() -> BridgedObjC {
+ return BridgedObjC()
+ }
+
+ static func _forceBridgeFromObjectiveC(
+ _ x: BridgedObjC,
+ result: inout BridgedSwift?
+ ) {
+ }
+ static func _conditionallyBridgeFromObjectiveC(
+ _ x: BridgedObjC,
+ result: inout BridgedSwift?
+ ) -> Bool {
+ return true
+ }
+}
+
+func == (x: BridgedSwift, y: BridgedSwift) -> Bool { return true }
+
+// CHECK-LABEL: sil hidden @$S17collection_upcast15testArrayUpcast{{.*}}F :
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<BridgedObjC>):
+func testArrayUpcast(_ array: [BridgedObjC]) {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[UPCAST_FN:%[0-9]+]] = function_ref @$Ss15_arrayForceCast{{.*}}F : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ // CHECK: [[RESULT:%.*]] = apply [[UPCAST_FN]]<BridgedObjC, AnyObject>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[ARRAY]]
+ let anyObjectArr: [AnyObject] = array
+}
+// CHECK: } // end sil function '$S17collection_upcast15testArrayUpcast{{.*}}F'
+
+// CHECK-LABEL: sil hidden @$S17collection_upcast22testArrayUpcastBridged{{.*}}F
+// CHECK: bb0([[ARRAY:%[0-9]+]] : $Array<BridgedSwift>):
+func testArrayUpcastBridged(_ array: [BridgedSwift]) {
+ // CHECK: [[ARRAY_COPY:%.*]] = copy_value [[ARRAY]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss15_arrayForceCast{{.*}}F : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ // CHECK: [[RESULT:%.*]] = apply [[BRIDGE_FN]]<BridgedSwift, AnyObject>([[ARRAY_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[ARRAY]]
+ let anyObjectArr = array as [AnyObject]
+}
+// CHECK: } // end sil function '$S17collection_upcast22testArrayUpcastBridged{{.*}}F'
+
+// CHECK-LABEL: sil hidden @$S17collection_upcast20testDictionaryUpcast{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<BridgedObjC, BridgedObjC>):
+func testDictionaryUpcast(_ dict: Dictionary<BridgedObjC, BridgedObjC>) {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[UPCAST_FN:%[0-9]+]] = function_ref @$Ss17_dictionaryUpCast{{.*}}F : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK: [[RESULT:%.*]] = apply [[UPCAST_FN]]<BridgedObjC, BridgedObjC, NSObject, AnyObject>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[DICT]]
+ let anyObjectDict: Dictionary<NSObject, AnyObject> = dict
+}
+
+// CHECK-LABEL: sil hidden @$S17collection_upcast27testDictionaryUpcastBridged{{.*}}F
+// CHECK: bb0([[DICT:%[0-9]+]] : $Dictionary<BridgedSwift, BridgedSwift>):
+func testDictionaryUpcastBridged(_ dict: Dictionary<BridgedSwift, BridgedSwift>) {
+ // CHECK: [[DICT_COPY:%.*]] = copy_value [[DICT]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss17_dictionaryUpCast{{.*}}F
+ // CHECK: [[RESULT:%.*]] = apply [[BRIDGE_FN]]<BridgedSwift, BridgedSwift, NSObject, AnyObject>([[DICT_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[DICT]]
+ let anyObjectDict = dict as Dictionary<NSObject, AnyObject>
+}
+
+// CHECK-LABEL: sil hidden @$S17collection_upcast13testSetUpcast{{.*}}F
+// CHECK: bb0([[SET:%[0-9]+]] : $Set<BridgedObjC>):
+func testSetUpcast(_ dict: Set<BridgedObjC>) {
+ // CHECK: [[SET_COPY:%.*]] = copy_value [[SET]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss10_setUpCast{{.*}}F : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Set<τ_0_1>
+ // CHECK: [[RESULT:%.*]] = apply [[BRIDGE_FN]]<BridgedObjC, NSObject>([[SET_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Set<τ_0_1>
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[SET]]
+ let anyObjectSet: Set<NSObject> = dict
+}
+
+// CHECK-LABEL: sil hidden @$S17collection_upcast20testSetUpcastBridged{{.*}}F
+// CHECK: bb0([[SET:%.*]] : $Set<BridgedSwift>):
+func testSetUpcastBridged(_ set: Set<BridgedSwift>) {
+ // CHECK: [[SET_COPY:%.*]] = copy_value [[SET]]
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$Ss10_setUpCast{{.*}}F
+ // CHECK: [[RESULT:%.*]] = apply [[BRIDGE_FN]]<BridgedSwift, NSObject>([[SET_COPY]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Hashable, τ_0_1 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned Set<τ_0_1>
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[SET]]
+ let anyObjectSet = set as Set<NSObject>
+}
diff --git a/test/SILGen/plus_zero_constrained_extensions.swift b/test/SILGen/plus_zero_constrained_extensions.swift
new file mode 100644
index 0000000..c925a1e
--- /dev/null
+++ b/test/SILGen/plus_zero_constrained_extensions.swift
@@ -0,0 +1,226 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -primary-file %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-sil -O -primary-file %s > /dev/null
+// RUN: %target-swift-frontend -emit-ir -primary-file %s > /dev/null
+
+extension Array where Element == Int {
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE1xSaySiGyt_tcfC : $@convention(method) (@thin Array<Int>.Type) -> @owned Array<Int>
+ public init(x: ()) {
+ self.init()
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE16instancePropertySivg : $@convention(method) (@guaranteed Array<Int>) -> Int
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE16instancePropertySivs : $@convention(method) (Int, @inout Array<Int>) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$SSa22constrained_extensionsSiRszlE16instancePropertySivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>, @thick Array<Int>.Type) -> ()
+ // CHECK-LABEL: sil [transparent] [serialized] @$SSa22constrained_extensionsSiRszlE16instancePropertySivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array<Int>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+
+ public var instanceProperty: Element {
+ get {
+ return self[0]
+ }
+ set {
+ self[0] = newValue
+ }
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE14instanceMethodSiyF : $@convention(method) (@guaranteed Array<Int>) -> Int
+ public func instanceMethod() -> Element {
+ return instanceProperty
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE14instanceMethod1eS2i_tF : $@convention(method) (Int, @guaranteed Array<Int>) -> Int
+ public func instanceMethod(e: Element) -> Element {
+ return e
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE14staticPropertySivgZ : $@convention(method) (@thin Array<Int>.Type) -> Int
+ public static var staticProperty: Element {
+ return Array(x: ()).instanceProperty
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE12staticMethodSiyFZ : $@convention(method) (@thin Array<Int>.Type) -> Int
+ public static func staticMethod() -> Element {
+ return staticProperty
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE12staticMethod1eS2iSg_tFZfA_ : $@convention(thin) () -> Optional<Int>
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE12staticMethod1eS2iSg_tFZ : $@convention(method) (Optional<Int>, @thin Array<Int>.Type) -> Int
+ public static func staticMethod(e: Element? = nil) -> Element {
+ return e!
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlEySiyt_tcig : $@convention(method) (@guaranteed Array<Int>) -> Int
+ public subscript(i: ()) -> Element {
+ return self[0]
+ }
+
+ // CHECK-LABEL: sil @$SSa22constrained_extensionsSiRszlE21inoutAccessOfPropertyyyF : $@convention(method) (@inout Array<Int>) -> ()
+ public mutating func inoutAccessOfProperty() {
+ func increment(x: inout Element) {
+ x += 1
+ }
+
+ increment(x: &instanceProperty)
+ }
+}
+
+extension Dictionary where Key == Int {
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE1xABySiq_Gyt_tcfC : $@convention(method) <Key, Value where Key == Int> (@thin Dictionary<Int, Value>.Type) -> @owned Dictionary<Int, Value> {
+ public init(x: ()) {
+ self.init()
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE16instancePropertyq_vg : $@convention(method) <Key, Value where Key == Int> (@guaranteed Dictionary<Int, Value>) -> @out Value
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE16instancePropertyq_vs : $@convention(method) <Key, Value where Key == Int> (@in Value, @inout Dictionary<Int, Value>) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$Ss10DictionaryV22constrained_extensionsSiRszrlE16instancePropertyq_vmytfU_ : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>, @thick Dictionary<Int, Value>.Type) -> ()
+ // CHECK-LABEL: sil [transparent] [serialized] @$Ss10DictionaryV22constrained_extensionsSiRszrlE16instancePropertyq_vm : $@convention(method) <Key, Value where Key == Int> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Int, Value>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public var instanceProperty: Value {
+ get {
+ return self[0]!
+ }
+ set {
+ self[0] = newValue
+ }
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE14instanceMethodq_yF : $@convention(method) <Key, Value where Key == Int> (@guaranteed Dictionary<Int, Value>) -> @out Value
+ public func instanceMethod() -> Value {
+ return instanceProperty
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE14instanceMethod1vq_q__tF : $@convention(method) <Key, Value where Key == Int> (@in_guaranteed Value, @guaranteed Dictionary<Int, Value>) -> @out Value
+ public func instanceMethod(v: Value) -> Value {
+ return v
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE12staticMethodSiyFZ : $@convention(method) <Key, Value where Key == Int> (@thin Dictionary<Int, Value>.Type) -> Int
+ public static func staticMethod() -> Key {
+ return staticProperty
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE14staticPropertySivgZ : $@convention(method) <Key, Value where Key == Int> (@thin Dictionary<Int, Value>.Type) -> Int
+ public static var staticProperty: Key {
+ return 0
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE12staticMethod1k1vq_SiSg_q_SgtFZfA_ : $@convention(thin) <Key, Value where Key == Int> () -> Optional<Int>
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE12staticMethod1k1vq_SiSg_q_SgtFZfA0_ : $@convention(thin) <Key, Value where Key == Int> () -> @out Optional<Value>
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE12staticMethod1k1vq_SiSg_q_SgtFZ : $@convention(method) <Key, Value where Key == Int> (Optional<Int>, @in_guaranteed Optional<Value>, @thin Dictionary<Int, Value>.Type) -> @out Value
+ public static func staticMethod(k: Key? = nil, v: Value? = nil) -> Value {
+ return v!
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE17callsStaticMethodq_yFZ : $@convention(method) <Key, Value where Key == Int> (@thin Dictionary<Int, Value>.Type) -> @out Value
+ public static func callsStaticMethod() -> Value {
+ return staticMethod()
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE16callsConstructorq_yFZ : $@convention(method) <Key, Value where Key == Int> (@thin Dictionary<Int, Value>.Type) -> @out Value
+ public static func callsConstructor() -> Value {
+ return Dictionary(x: ()).instanceMethod()
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlEyq_yt_tcig : $@convention(method) <Key, Value where Key == Int> (@guaranteed Dictionary<Int, Value>) -> @out Value
+ public subscript(i: ()) -> Value {
+ return self[0]!
+ }
+
+ // CHECK-LABEL: sil @$Ss10DictionaryV22constrained_extensionsSiRszrlE21inoutAccessOfPropertyyyF : $@convention(method) <Key, Value where Key == Int> (@inout Dictionary<Int, Value>) -> ()
+ public mutating func inoutAccessOfProperty() {
+ func increment(x: inout Value) { }
+
+ increment(x: &instanceProperty)
+ }
+}
+
+public class GenericClass<X, Y> {}
+
+extension GenericClass where Y == () {
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvs : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public var value: X {
+ get { while true {} }
+ set {}
+ }
+
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvs : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public var empty: Y {
+ get { return () }
+ set {}
+ }
+
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcig : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcis : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcim : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public subscript(_: Y) -> X {
+ get { while true {} }
+ set {}
+ }
+
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcig : $@convention(method) <X, Y where Y == ()> (@in_guaranteed X, @guaranteed GenericClass<X, ()>) -> ()
+ // CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcis : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
+ // CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
+ // CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcim : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed X, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public subscript(_: X) -> Y {
+ get { while true {} }
+ set {}
+ }
+}
+
+protocol VeryConstrained {}
+
+struct AnythingGoes<T> {
+ // CHECK-LABEL: sil hidden [transparent] @$S22constrained_extensions12AnythingGoesV13meaningOfLifexSgvpfi : $@convention(thin) <T> () -> @out Optional<T>
+ var meaningOfLife: T? = nil
+}
+
+extension AnythingGoes where T : VeryConstrained {
+ // CHECK-LABEL: sil hidden @$S22constrained_extensions12AnythingGoesVA2A15VeryConstrainedRzlE13fromExtensionACyxGyt_tcfC : $@convention(method) <T where T : VeryConstrained> (@thin AnythingGoes<T>.Type) -> @out AnythingGoes<T> {
+
+ // CHECK: [[INIT:%.*]] = function_ref @$S22constrained_extensions12AnythingGoesV13meaningOfLifexSgvpfi : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
+ // CHECK: [[RESULT:%.*]] = alloc_stack $Optional<T>
+ // CHECK: apply [[INIT]]<T>([[RESULT]]) : $@convention(thin) <τ_0_0> () -> @out Optional<τ_0_0>
+ // CHECK: return
+ init(fromExtension: ()) {}
+}
+
+extension Array where Element == Int {
+ struct Nested {
+ // CHECK-LABEL: sil hidden [transparent] @$SSa22constrained_extensionsSiRszlE6NestedV1eSiSgvpfi : $@convention(thin) () -> Optional<Int>
+ var e: Element? = nil
+
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsSiRszlE6NestedV10hasDefault1eySiSg_tFfA_ : $@convention(thin) () -> Optional<Int>
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsSiRszlE6NestedV10hasDefault1eySiSg_tF : $@convention(method) (Optional<Int>, @inout Array<Int>.Nested) -> ()
+ mutating func hasDefault(e: Element? = nil) {
+ self.e = e
+ }
+ }
+}
+
+extension Array where Element == AnyObject {
+ class NestedClass {
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsyXlRszlE11NestedClassCfd : $@convention(method) (@guaranteed Array<AnyObject>.NestedClass) -> @owned Builtin.NativeObject
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsyXlRszlE11NestedClassCfD : $@convention(method) (@owned Array<AnyObject>.NestedClass) -> ()
+ deinit { }
+
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsyXlRszlE11NestedClassCACyyXl_GycfC : $@convention(method) (@thick Array<AnyObject>.NestedClass.Type) -> @owned Array<AnyObject>.NestedClass
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsyXlRszlE11NestedClassCACyyXl_Gycfc : $@convention(method) (@owned Array<AnyObject>.NestedClass) -> @owned Array<AnyObject>.NestedClass
+ }
+
+ class DerivedClass : NestedClass {
+ // CHECK-LABEL: sil hidden [transparent] @$SSa22constrained_extensionsyXlRszlE12DerivedClassC1eyXlSgvpfi : $@convention(thin) () -> @owned Optional<AnyObject>
+ // CHECK-LABEL: sil hidden @$SSa22constrained_extensionsyXlRszlE12DerivedClassCfE : $@convention(method) (@guaranteed Array<AnyObject>.DerivedClass) -> ()
+ var e: Element? = nil
+ }
+}
+
+func referenceNestedTypes() {
+ _ = Array<AnyObject>.NestedClass()
+ _ = Array<AnyObject>.DerivedClass()
+}
diff --git a/test/SILGen/plus_zero_default_arguments.swift b/test/SILGen/plus_zero_default_arguments.swift
new file mode 100644
index 0000000..ad5ff0e
--- /dev/null
+++ b/test/SILGen/plus_zero_default_arguments.swift
@@ -0,0 +1,378 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 3 %s | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 3 %s | %FileCheck %s --check-prefix=NEGATIVE
+
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 4 %s | %FileCheck %s
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 4 %s | %FileCheck %s --check-prefix=NEGATIVE
+
+// __FUNCTION__ used as top-level parameter produces the module name.
+// CHECK-LABEL: sil @main
+// CHECK: string_literal utf16 "default_arguments"
+
+// Default argument for first parameter.
+// CHECK-LABEL: sil hidden @$S17default_arguments7defarg11i1d1sySi_SdSStFfA_ : $@convention(thin) () -> Int
+// CHECK: [[INT:%[0-9]+]] = metatype $@thin Int.Type
+// CHECK: [[LIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 17
+// CHECK: [[CVT:%[0-9]+]] = function_ref @$SSi22_builtinIntegerLiteralSiBi{{[_0-9]*}}__tcfC
+// CHECK: [[RESULT:%[0-9]+]] = apply [[CVT]]([[LIT]], [[INT]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+// CHECK: return [[RESULT]] : $Int
+
+// Default argument for third parameter.
+// CHECK-LABEL: sil hidden @$S17default_arguments7defarg11i1d1sySi_SdSStFfA1_ : $@convention(thin) () -> @owned String
+// CHECK: [[LIT:%[0-9]+]] = string_literal utf8 "Hello"
+// CHECK: [[LEN:%[0-9]+]] = integer_literal $Builtin.Word, 5
+// CHECK: [[STRING:%[0-9]+]] = metatype $@thin String.Type
+// CHECK: [[CVT:%[0-9]+]] = function_ref @$SSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC
+// CHECK: [[RESULT:%[0-9]+]] = apply [[CVT]]([[LIT]], [[LEN]], {{[^,]+}}, [[STRING]]) : $@convention(method)
+// CHECK: return [[RESULT]] : $String
+func defarg1(i: Int = 17, d: Double, s: String = "Hello") { }
+
+// CHECK-LABEL: sil hidden @$S17default_arguments15testDefaultArg1yyF
+func testDefaultArg1() {
+ // CHECK: [[FLOAT64:%[0-9]+]] = metatype $@thin Double.Type
+ // CHECK: [[FLOATLIT:%[0-9]+]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x4009000000000000|0x4000C800000000000000}}
+ // CHECK: [[LITFN:%[0-9]+]] = function_ref @$SSd20_builtinFloatLiteralSdBf{{[_0-9]*}}__tcfC
+ // CHECK: [[FLOATVAL:%[0-9]+]] = apply [[LITFN]]([[FLOATLIT]], [[FLOAT64]])
+ // CHECK: [[DEF0FN:%[0-9]+]] = function_ref @$S17default_arguments7defarg1{{.*}}A_
+ // CHECK: [[DEF0:%[0-9]+]] = apply [[DEF0FN]]()
+ // CHECK: [[DEF2FN:%[0-9]+]] = function_ref @$S17default_arguments7defarg1{{.*}}A1_
+ // CHECK: [[DEF2:%[0-9]+]] = apply [[DEF2FN]]()
+ // CHECK: [[BORROWED_DEF2:%.*]] = begin_borrow [[DEF2]]
+ // CHECK: [[FNREF:%[0-9]+]] = function_ref @$S17default_arguments7defarg1{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FNREF]]([[DEF0]], [[FLOATVAL]], [[BORROWED_DEF2]])
+ defarg1(d:3.125)
+}
+
+func defarg2(_ i: Int, d: Double = 3.125, s: String = "Hello") { }
+
+// CHECK-LABEL: sil hidden @$S17default_arguments15testDefaultArg2{{[_0-9a-zA-Z]*}}F
+func testDefaultArg2() {
+// CHECK: [[INT64:%[0-9]+]] = metatype $@thin Int.Type
+// CHECK: [[INTLIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 5
+// CHECK: [[LITFN:%[0-9]+]] = function_ref @$SSi22_builtinIntegerLiteralSiBi{{[_0-9]*}}__tcfC
+// CHECK: [[I:%[0-9]+]] = apply [[LITFN]]([[INTLIT]], [[INT64]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+// CHECK: [[DFN:%[0-9]+]] = function_ref @$S17default_arguments7defarg2{{.*}}A0_ : $@convention(thin) () -> Double
+// CHECK: [[D:%[0-9]+]] = apply [[DFN]]() : $@convention(thin) () -> Double
+// CHECK: [[SFN:%[0-9]+]] = function_ref @$S17default_arguments7defarg2{{.*}}A1_ : $@convention(thin) () -> @owned String
+// CHECK: [[S:%[0-9]+]] = apply [[SFN]]() : $@convention(thin) () -> @owned String
+// CHECK: [[BORROWED_S:%.*]] = begin_borrow [[S]]
+// CHECK: [[FNREF:%[0-9]+]] = function_ref @$S17default_arguments7defarg2{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Double, @guaranteed String) -> ()
+// CHECK: apply [[FNREF]]([[I]], [[D]], [[BORROWED_S]]) : $@convention(thin) (Int, Double, @guaranteed String) -> ()
+ defarg2(5)
+}
+
+func autocloseFile(x: @autoclosure () -> String = #file,
+ y: @autoclosure () -> Int = #line) { }
+// CHECK-LABEL: sil hidden @$S17default_arguments17testAutocloseFileyyF
+func testAutocloseFile() {
+ // CHECK-LABEL: sil private [transparent] @$S17default_arguments17testAutocloseFileyyFSSyXKfu_ : $@convention(thin) () -> @owned String
+ // CHECK: string_literal utf16{{.*}}default_arguments.swift
+
+ // CHECK-LABEL: sil private [transparent] @$S17default_arguments17testAutocloseFileyyFSiyXKfu0_ : $@convention(thin) () -> Int
+ // CHECK: integer_literal $Builtin.Int2048, [[@LINE+1]]
+ autocloseFile()
+}
+
+func testMagicLiterals(file: String = #file,
+ function: String = #function,
+ line: Int = #line,
+ column: Int = #column) {}
+
+// Check that default argument generator functions don't leak information about
+// user's source.
+//
+// NEGATIVE-NOT: sil hidden @$S17default_arguments17testMagicLiteralsySS4file_SS8functionSi4lineSi6columntFfA_
+//
+// NEGATIVE-NOT: sil hidden @$S17default_arguments17testMagicLiteralsySS4file_SS8functionSi4lineSi6columntFfA0_
+//
+// NEGATIVE-NOT: sil hidden @$S17default_arguments17testMagicLiteralsySS4file_SS8functionSi4lineSi6columntFfA1_
+//
+// NEGATIVE-NOT: sil hidden @$S17default_arguments17testMagicLiteralsySS4file_SS8functionSi4lineSi6columntFfA2_
+
+func closure(_: () -> ()) {}
+func autoclosure(_: @autoclosure () -> ()) {}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments25testCallWithMagicLiteralsyyF
+// CHECK: string_literal utf16 "testCallWithMagicLiterals()"
+// CHECK: string_literal utf16 "testCallWithMagicLiterals()"
+// CHECK-LABEL: sil private @$S17default_arguments25testCallWithMagicLiteralsyyFyyXEfU_
+// CHECK: string_literal utf16 "testCallWithMagicLiterals()"
+// CHECK-LABEL: sil private [transparent] @$S17default_arguments25testCallWithMagicLiteralsyyFyyXKfu_
+// CHECK: string_literal utf16 "testCallWithMagicLiterals()"
+func testCallWithMagicLiterals() {
+ testMagicLiterals()
+ testMagicLiterals()
+ closure { testMagicLiterals() }
+ autoclosure(testMagicLiterals())
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments25testPropWithMagicLiteralsSivg
+// CHECK: string_literal utf16 "testPropWithMagicLiterals"
+var testPropWithMagicLiterals: Int {
+ testMagicLiterals()
+ closure { testMagicLiterals() }
+ autoclosure(testMagicLiterals())
+ return 0
+}
+
+class Foo {
+
+ // CHECK-LABEL: sil hidden @$S17default_arguments3FooC3int6stringACSi_SStcfc : $@convention(method) (Int, @owned String, @owned Foo) -> @owned Foo
+ // CHECK: string_literal utf16 "init(int:string:)"
+ init(int: Int, string: String = #function) {
+ testMagicLiterals()
+ closure { testMagicLiterals() }
+ autoclosure(testMagicLiterals())
+ }
+
+ // CHECK-LABEL: sil hidden @$S17default_arguments3FooCfd
+ // CHECK: string_literal utf16 "deinit"
+ deinit {
+ testMagicLiterals()
+ closure { testMagicLiterals() }
+ autoclosure(testMagicLiterals())
+ }
+
+ // CHECK-LABEL: sil hidden @$S17default_arguments3FooCyS2icig
+ // CHECK: string_literal utf16 "subscript"
+ subscript(x: Int) -> Int {
+ testMagicLiterals()
+ closure { testMagicLiterals() }
+ autoclosure(testMagicLiterals())
+ return x
+ }
+
+ // CHECK-LABEL: sil private @globalinit_33_E52D764B1F2009F2390B2B8DF62DAEB8_func0
+ // CHECK: string_literal utf16 "Foo"
+ static let x = Foo(int:0)
+
+}
+
+// Test at top level.
+testMagicLiterals()
+closure { testMagicLiterals() }
+autoclosure(testMagicLiterals())
+
+// CHECK: string_literal utf16 "default_arguments"
+let y : String = #function
+
+// CHECK-LABEL: sil hidden @$S17default_arguments16testSelectorCall_17withMagicLiteralsySi_SitF
+// CHECK: string_literal utf16 "testSelectorCall(_:withMagicLiterals:)"
+func testSelectorCall(_ x: Int, withMagicLiterals y: Int) {
+ testMagicLiterals()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments32testSelectorCallWithUnnamedPieceyySi_SitF
+// CHECK: string_literal utf16 "testSelectorCallWithUnnamedPiece"
+func testSelectorCallWithUnnamedPiece(_ x: Int, _ y: Int) {
+ testMagicLiterals()
+}
+
+// Test default arguments in an inherited subobject initializer
+class SuperDefArg {
+ init(int i: Int = 10) { }
+}
+
+// CHECK: sil hidden @$S17default_arguments11SuperDefArgC3intACSi_tcfcfA_ : $@convention(thin) () -> Int
+
+// CHECK-NOT: sil hidden @$S17default_arguments9SubDefArgCAC3intSi_tcfcfA_ : $@convention(thin) () -> Int
+
+class SubDefArg : SuperDefArg { }
+
+// CHECK: sil hidden @$S17default_arguments13testSubDefArgAA0deF0CyF : $@convention(thin) () -> @owned SubDefArg
+func testSubDefArg() -> SubDefArg {
+ // CHECK: function_ref @$S17default_arguments11SuperDefArgC3intACSi_tcfcfA_
+ // CHECK: function_ref @$S17default_arguments9SubDefArgC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: return
+ return SubDefArg()
+}
+
+// CHECK-NOT: sil hidden @$S17default_arguments9SubDefArgCACSi3int_tcfcfA_ : $@convention(thin) () -> Int
+
+// <rdar://problem/17379550>
+func takeDefaultArgUnnamed(_ x: Int = 5) { }
+
+// CHECK-LABEL: sil hidden @$S17default_arguments25testTakeDefaultArgUnnamed{{[_0-9a-zA-Z]*}}F
+func testTakeDefaultArgUnnamed(_ i: Int) {
+ // CHECK: bb0([[I:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[FN:%[0-9]+]] = function_ref @$S17default_arguments21takeDefaultArgUnnamedyySiF : $@convention(thin) (Int) -> ()
+ // CHECK: apply [[FN]]([[I]]) : $@convention(thin) (Int) -> ()
+ takeDefaultArgUnnamed(i)
+}
+
+func takeDSOHandle(_ handle: UnsafeRawPointer = #dsohandle) { }
+
+// CHECK-LABEL: sil hidden @$S17default_arguments13testDSOHandleyyF
+func testDSOHandle() {
+ // CHECK: [[DSO_HANDLE:%[0-9]+]] = global_addr @__dso_handle : $*Builtin.RawPointer
+ takeDSOHandle()
+}
+
+// Test __FUNCTION__ in an extension initializer. rdar://problem/19792181
+extension SuperDefArg {
+ static let extensionInitializerWithClosure: Int = { return 22 }()
+}
+
+
+// <rdar://problem/19086357> SILGen crashes reabstracting default argument closure in members
+class ReabstractDefaultArgument<T> {
+ init(a: (T, T) -> Bool = { _, _ in true }) {
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments32testDefaultArgumentReabstractionyyF
+// function_ref default_arguments.ReabstractDefaultArgument.__allocating_init <A>(default_arguments.ReabstractDefaultArgument<A>.Type)(a : (A, A) -> Swift.Bool) -> default_arguments.ReabstractDefaultArgument<A>
+// CHECK: [[FN:%.*]] = function_ref @$S17default_arguments25ReabstractDefaultArgument{{.*}} : $@convention(thin) <τ_0_0> () -> @owned @callee_guaranteed (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Int>() : $@convention(thin) <τ_0_0> () -> @owned @callee_guaranteed (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+// CHECK-NEXT: function_ref reabstraction thunk helper from @escaping @callee_guaranteed (@in_guaranteed Swift.Int, @in_guaranteed Swift.Int) -> (@unowned Swift.Bool) to @escaping @callee_guaranteed (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool)
+// CHECK-NEXT: [[THUNK:%.*]] = function_ref @$SS2iSbIegnnd_S2iSbIegyyd_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Int, @in_guaranteed Int) -> Bool) -> Bool
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[RESULT]]) : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Int, @in_guaranteed Int) -> Bool) -> Bool
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_escape_to_noescape [[FN]]
+// function_ref reabstraction thunk helper from @callee_guaranteed (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool) to @callee_guaranteed (@in_guaranteed Swift.Int, @in_guaranteed Swift.Int) -> (@unowned Swift.Bool)
+// CHECK: [[THUNK:%.*]] = function_ref @$SS2iSbIgyyd_S2iSbIegnnd_TR : $@convention(thin) (@in_guaranteed Int, @in_guaranteed Int, @noescape @callee_guaranteed (Int, Int) -> Bool) -> Bool
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CONV_FN]]) : $@convention(thin) (@in_guaranteed Int, @in_guaranteed Int, @noescape @callee_guaranteed (Int, Int) -> Bool) -> Bool
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_escape_to_noescape [[FN]]
+// CHECK: [[INITFN:%[0-9]+]] = function_ref @$S17default_arguments25ReabstractDefaultArgumentC{{[_0-9a-zA-Z]*}}fC
+// CHECK-NEXT: apply [[INITFN]]<Int>([[CONV_FN]],
+
+func testDefaultArgumentReabstraction() {
+ _ = ReabstractDefaultArgument<Int>()
+}
+
+// <rdar://problem/20494437> SILGen crash handling default arguments
+// CHECK-LABEL: sil hidden @$S17default_arguments18r20494437onSuccessyyAA25r20494437ExecutionContext_pF
+// CHECK: function_ref @$S17default_arguments19r20494437onCompleteyyAA25r20494437ExecutionContext_pF
+// <rdar://problem/20494437> SILGen crash handling default arguments
+protocol r20494437ExecutionContext {}
+let r20494437Default: r20494437ExecutionContext
+func r20494437onComplete(_ executionContext: r20494437ExecutionContext = r20494437Default) {}
+func r20494437onSuccess(_ a: r20494437ExecutionContext) {
+ r20494437onComplete(a)
+}
+
+// <rdar://problem/18400194> Parenthesized function expression crashes the compiler
+func r18400194(_ a: Int, x: Int = 97) {}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments9r18400194_1xySi_SitFfA0_
+// CHECK: integer_literal $Builtin.Int2048, 97
+
+// CHECK-LABEL: sil hidden @$S17default_arguments14test_r18400194yyF
+// CHECK: integer_literal $Builtin.Int2048, 1
+// CHECK: function_ref @$S17default_arguments9r18400194_1xySi_SitFfA0_ : $@convention(thin) () -> Int
+// CHECK: function_ref @$S17default_arguments9r18400194_1xySi_SitF : $@convention(thin) (Int, Int) -> (){{.*}}
+func test_r18400194() {
+ (r18400194)(1)
+}
+
+// rdar://24242783
+// Don't add capture arguments to local default argument generators.
+func localFunctionWithDefaultArg() {
+ var z = 5
+ func bar(_ x: Int? = nil) {
+ z += 1
+ }
+ bar()
+}
+// CHECK-LABEL: sil private @$S17default_arguments27localFunctionWithDefaultArgyyF3barL_yySiSgFfA_
+// CHECK-SAME: $@convention(thin) () -> Optional<Int>
+
+// CHECK-LABEL: sil hidden @$S17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+func throwingDefault(closure: () throws -> Bool = { return true }) throws {
+ try _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+func throwingAutoclosureDefault(closure: @autoclosure () throws -> Bool = true ) throws {
+ try _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments0A3Arg7closureySbyXE_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+func defaultArg(closure: () -> Bool = { return true }) {
+ _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments21autoclosureDefaultArg7closureySbyXK_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+func autoclosureDefaultArg(closure: @autoclosure () -> Bool = true ) {
+ _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments23throwingDefaultEscaping7closureySbyKc_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+func throwingDefaultEscaping(closure: @escaping () throws -> Bool = { return true }) throws {
+ try _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+func throwingAutoclosureDefaultEscaping(closure: @escaping @autoclosure () throws -> Bool = true ) throws {
+ try _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments0A8Escaping7closureySbyc_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+func defaultEscaping(closure: @escaping () -> Bool = { return true }) {
+ _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @$S17default_arguments26autoclosureDefaultEscaping7closureySbyXA_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool {
+func autoclosureDefaultEscaping(closure: @escaping @autoclosure () -> Bool = true ) {
+ _ = closure()
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}callThem{{.*}} : $@convention(thin) () -> @error Error
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments15throwingDefault7closureySbyKXE_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments15throwingDefault7closureySbyKXE_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error Error)) -> @error Error
+// CHECK: try_apply [[R]]([[E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments26throwingAutoclosureDefault7closureySbyKXK_tKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Bool, @error Error)) -> @error Error
+// CHECK: try_apply [[R]]([[E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments0A3Arg7closureySbyXE_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments0A3Arg7closureySbyXE_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
+// CHECK: apply [[R]]([[E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments21autoclosureDefaultArg7closureySbyXK_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Boo
+// CHECK: [[C:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[E:%.*]] = convert_escape_to_noescape [[C]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments21autoclosureDefaultArg7closureySbyXK_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
+// CHECK: apply [[R]]([[E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments23throwingDefaultEscaping7closureySbyKc_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[BORROWED_E:%.*]] = begin_borrow [[E]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments23throwingDefaultEscaping7closureySbyKc_tKF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Bool, @error Error)) -> @error Erro
+// CHECK: try_apply [[R]]([[BORROWED_E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> (Bool, @error Error)
+// CHECK: [[BORROWED_E:%.*]] = begin_borrow [[E]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments34throwingAutoclosureDefaultEscaping7closureySbyKXA_tKF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Bool, @error Error)) -> @error Error
+// CHECK: try_apply [[R]]([[BORROWED_E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments0A8Escaping7closureySbyc_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[BORROWED_E:%.*]] = begin_borrow [[E]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments0A8Escaping7closureySbyc_tF : $@convention(thin) (@guaranteed @callee_guaranteed () -> Bool) -> ()
+// CHECK: apply [[R]]([[BORROWED_E]])
+
+// CHECK: [[F:%.*]] = function_ref @$S17default_arguments26autoclosureDefaultEscaping7closureySbyXA_tFfA_ : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[E:%.*]] = apply [[F]]() : $@convention(thin) () -> @owned @callee_guaranteed () -> Bool
+// CHECK: [[BORROWED_E:%.*]] = begin_borrow [[E]]
+// CHECK: [[R:%.*]] = function_ref @$S17default_arguments26autoclosureDefaultEscaping7closureySbyXA_tF : $@convention(thin) (@guaranteed @callee_guaranteed () -> Bool) -> ()
+// CHECK: apply [[R]]([[BORROWED_E]])
+
+func callThem() throws {
+ try throwingDefault()
+ try throwingAutoclosureDefault()
+ defaultArg()
+ autoclosureDefaultArg()
+ try throwingDefaultEscaping()
+ try throwingAutoclosureDefaultEscaping()
+ defaultEscaping()
+ autoclosureDefaultEscaping()
+}
diff --git a/test/SILGen/plus_zero_default_arguments_generic.swift b/test/SILGen/plus_zero_default_arguments_generic.swift
new file mode 100644
index 0000000..b382f5b
--- /dev/null
+++ b/test/SILGen/plus_zero_default_arguments_generic.swift
@@ -0,0 +1,66 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -swift-version 3 %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -swift-version 4 %s | %FileCheck %s
+
+func foo<T: ExpressibleByIntegerLiteral>(_: T.Type, x: T = 0) { }
+
+struct Zim<T: ExpressibleByIntegerLiteral> {
+ init(x: T = 0) { }
+ init<U: ExpressibleByFloatLiteral>(_ x: T = 0, y: U = 0.5) { }
+
+ static func zim(x: T = 0) { }
+ static func zang<U: ExpressibleByFloatLiteral>(_: U.Type, _ x: T = 0, y: U = 0.5) { }
+}
+
+// CHECK-LABEL: sil hidden @$S25default_arguments_generic3baryyF : $@convention(thin) () -> () {
+func bar() {
+ // CHECK: [[FOO_DFLT:%.*]] = function_ref @$S25default_arguments_generic3foo
+ // CHECK: apply [[FOO_DFLT]]<Int>
+ foo(Int.self)
+ // CHECK: [[ZIM_DFLT:%.*]] = function_ref @$S25default_arguments_generic3ZimV3zim
+ // CHECK: apply [[ZIM_DFLT]]<Int>
+ Zim<Int>.zim()
+ // CHECK: [[ZANG_DFLT_0:%.*]] = function_ref @$S25default_arguments_generic3ZimV4zang{{.*}}A0_
+ // CHECK: apply [[ZANG_DFLT_0]]<Int, Double>
+ // CHECK: [[ZANG_DFLT_1:%.*]] = function_ref @$S25default_arguments_generic3ZimV4zang{{.*}}A1_
+ // CHECK: apply [[ZANG_DFLT_1]]<Int, Double>
+ Zim<Int>.zang(Double.self)
+ // CHECK: [[ZANG_DFLT_1:%.*]] = function_ref @$S25default_arguments_generic3ZimV4zang{{.*}}A1_
+ // CHECK: apply [[ZANG_DFLT_1]]<Int, Double>
+ Zim<Int>.zang(Double.self, 22)
+}
+
+protocol Initializable {
+ init()
+}
+struct Generic<T: Initializable> {
+ init(_ value: T = T()) {}
+}
+struct InitializableImpl: Initializable {
+ init() {}
+}
+// CHECK-LABEL: sil hidden @$S25default_arguments_generic17testInitializableyyF
+func testInitializable() {
+ // The ".init" is required to trigger the crash that used to happen.
+ _ = Generic<InitializableImpl>.init()
+ // CHECK: function_ref @$S25default_arguments_generic7GenericVyACyxGxcfcfA_ : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> @out τ_0_0
+ // CHECK: [[INIT:%.+]] = function_ref @$S25default_arguments_generic7GenericVyACyxGxcfC
+ // CHECK: apply [[INIT]]<InitializableImpl>({{%.+}}, {{%.+}}) : $@convention(method) <τ_0_0 where τ_0_0 : Initializable> (@in τ_0_0, @thin Generic<τ_0_0>.Type) -> Generic<τ_0_0>
+} // CHECK: end sil function '$S25default_arguments_generic17testInitializableyyF'
+
+// Local generic functions with default arguments
+
+// CHECK-LABEL: sil hidden @$S25default_arguments_generic5outer1tyx_tlF : $@convention(thin) <T> (@in_guaranteed T) -> ()
+func outer<T>(t: T) {
+ func inner1(x: Int = 0) {}
+
+ // CHECK: [[ARG_GENERATOR:%.*]] = function_ref @$S25default_arguments_generic5outer1tyx_tlF6inner1L_1xySi_tlFfA_ : $@convention(thin) () -> Int
+ // CHECK: [[ARG:%.*]] = apply [[ARG_GENERATOR]]() : $@convention(thin) () -> Int
+ _ = inner1()
+
+ func inner2(x: Int = 0) { _ = T.self }
+
+ // CHECK: [[ARG_GENERATOR:%.*]] = function_ref @$S25default_arguments_generic5outer1tyx_tlF6inner2L_1xySi_tlFfA_ : $@convention(thin) <τ_0_0> () -> Int
+ // CHECK: [[ARG:%.*]] = apply [[ARG_GENERATOR]]<T>() : $@convention(thin) <τ_0_0> () -> Int
+ _ = inner2()
+}
diff --git a/test/SILGen/plus_zero_default_arguments_serialized.swift b/test/SILGen/plus_zero_default_arguments_serialized.swift
new file mode 100644
index 0000000..1472952
--- /dev/null
+++ b/test/SILGen/plus_zero_default_arguments_serialized.swift
@@ -0,0 +1,62 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module-path %t/default_arguments_other.swiftmodule -emit-module -swift-version 4 -primary-file %S/Inputs/default_arguments_other.swift
+
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 3 -I %t %s | %FileCheck %s --check-prefix=SWIFT3 --check-prefix=CHECK
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-silgen -swift-version 4 -I %t %s | %FileCheck %s --check-prefix=SWIFT4 --check-prefix=CHECK
+
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-sil -O -swift-version 3 -I %t %s | %FileCheck %s --check-prefix=OPT
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -enable-sil-ownership -emit-sil -O -swift-version 4 -I %t %s | %FileCheck %s --check-prefix=OPT
+
+// Check that default arguments are serialized in Swift 4 mode.
+
+import default_arguments_other
+
+// CHECK-LABEL: sil @$S28default_arguments_serialized0A6StringSSyF : $@convention(thin) () -> @owned String
+public func defaultString() -> String { return "hi" }
+
+// SWIFT3-LABEL: sil @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStFfA_ : $@convention(thin) () -> Int
+// SWIFT4-LABEL: sil non_abi [serialized] @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStFfA_ : $@convention(thin) () -> Int
+
+// SWIFT3-LABEL: sil @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStFfA0_ : $@convention(thin) () -> @owned String
+// SWIFT4-LABEL: sil non_abi [serialized] @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStFfA0_ : $@convention(thin) () -> @owned String
+
+public func hasDefaultArguments(x: Int = 0, y: String = defaultString()) {}
+
+// CHECK-LABEL: sil @$S28default_arguments_serialized21callsDefaultArgumentsyyF : $@convention(thin) () -> ()
+// CHECK: function_ref @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStFfA_ : $@convention(thin) () -> Int
+// CHECK: function_ref @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStFfA0_ : $@convention(thin) () -> @owned String
+// CHECK: function_ref @$S28default_arguments_serialized19hasDefaultArguments1x1yySi_SStF : $@convention(thin) (Int, @guaranteed String) -> ()
+// CHECK: apply
+// CHECK: return
+public func callsDefaultArguments() {
+ hasDefaultArguments()
+}
+
+// When calling a default argument generator for a function in another module
+// that was built in Swift 4 mode, we should always treat it as serialized,
+// even if *this* module is built in Swift 3 mode.
+
+// CHECK-LABEL: sil @$S28default_arguments_serialized26callsOtherDefaultArgumentsyyF : $@convention(thin) () -> ()
+// CHECK: function_ref @$S23default_arguments_other0C16DefaultArguments1xySi_tFfA_ : $@convention(thin) () -> Int
+// CHECK: function_ref @$S23default_arguments_other0C16DefaultArguments1xySi_tF : $@convention(thin) (Int) -> ()
+// CHECK: apply
+// CHECK: return
+
+// Make sure the optimizer inlines the default argument generator from the
+// other module.
+
+// OPT-LABEL: sil @$S28default_arguments_serialized26callsOtherDefaultArgumentsyyF : $@convention(thin) () -> ()
+// OPT: [[INT_VAL:%.*]] = integer_literal [[INT_TYPE:\$Builtin.Int(32|64)]], 0
+// OPT: [[INT:%.*]] = struct $Int ([[INT_VAL]] : [[INT_TYPE]]
+// OPT: [[FN:%.*]] = function_ref @$S23default_arguments_other0C16DefaultArguments1xySi_tF : $@convention(thin) (Int) -> ()
+// OPT: apply [[FN]]([[INT]]) : $@convention(thin) (Int) -> ()
+// OPT: return
+public func callsOtherDefaultArguments() {
+ otherDefaultArguments()
+}
+
+// CHECK-LABEL: sil hidden_external [serialized] @$S23default_arguments_other0C16DefaultArguments1xySi_tFfA_ : $@convention(thin) () -> Int
+
+// CHECK-LABEL: sil @$S23default_arguments_other0C16DefaultArguments1xySi_tF : $@convention(thin) (Int) -> ()
+
diff --git a/test/SILGen/plus_zero_dependent_member_lowering.swift b/test/SILGen/plus_zero_dependent_member_lowering.swift
new file mode 100644
index 0000000..be5785f
--- /dev/null
+++ b/test/SILGen/plus_zero_dependent_member_lowering.swift
@@ -0,0 +1,22 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol P {
+ associatedtype A
+
+ func f(_ x: A)
+}
+struct Foo<T>: P {
+ typealias A = T.Type
+
+ func f(_ t: T.Type) {}
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S25dependent_member_lowering3FooVyxGAA1PA2aEP1fyy1AQzFTW : $@convention(witness_method: P) <τ_0_0> (@in_guaranteed @thick τ_0_0.Type, @in_guaranteed Foo<τ_0_0>) -> ()
+ // CHECK: bb0(%0 : @trivial $*@thick τ_0_0.Type, %1 : @trivial $*Foo<τ_0_0>):
+}
+struct Bar<T>: P {
+ typealias A = (Int) -> T
+
+ func f(_ t: @escaping (Int) -> T) {}
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S25dependent_member_lowering3BarVyxGAA1PA2aEP1fyy1AQzFTW : $@convention(witness_method: P) <τ_0_0> (@in_guaranteed @callee_guaranteed (@in_guaranteed Int) -> @out τ_0_0, @in_guaranteed Bar<τ_0_0>) -> ()
+ // CHECK: bb0(%0 : @trivial $*@callee_guaranteed (@in_guaranteed Int) -> @out τ_0_0, %1 : @trivial $*Bar<τ_0_0>):
+}
diff --git a/test/SILGen/plus_zero_downcast_reabstraction.swift b/test/SILGen/plus_zero_downcast_reabstraction.swift
new file mode 100644
index 0000000..52608d2
--- /dev/null
+++ b/test/SILGen/plus_zero_downcast_reabstraction.swift
@@ -0,0 +1,28 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+// CHECK-LABEL: sil hidden @$S22downcast_reabstraction19condFunctionFromAnyyyypF
+// CHECK: checked_cast_addr_br take_always Any in [[IN:%.*]] : $*Any to () -> () in [[OUT:%.*]] : $*@callee_guaranteed (@in_guaranteed ()) -> @out (), [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+// CHECK: [[YES]]:
+// CHECK: [[ORIG_VAL:%.*]] = load [take] [[OUT]]
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$SytytIegnr_Ieg_TR
+// CHECK: [[SUBST_VAL:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[ORIG_VAL]])
+
+func condFunctionFromAny(_ x: Any) {
+ if let f = x as? () -> () {
+ f()
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S22downcast_reabstraction21uncondFunctionFromAnyyyypF : $@convention(thin) (@in_guaranteed Any) -> () {
+// CHECK: unconditional_checked_cast_addr Any in [[IN:%.*]] : $*Any to () -> () in [[OUT:%.*]] : $*@callee_guaranteed (@in_guaranteed ()) -> @out ()
+// CHECK: [[ORIG_VAL:%.*]] = load [take] [[OUT]]
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$SytytIegnr_Ieg_TR
+// CHECK: [[SUBST_VAL:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[ORIG_VAL]])
+// CHECK: [[BORROW:%.*]] = begin_borrow [[SUBST_VAL]]
+// CHECK: apply [[BORROW]]()
+// CHECK: end_borrow [[BORROW]] from [[SUBST_VAL]]
+// CHECK: destroy_value [[SUBST_VAL]]
+func uncondFunctionFromAny(_ x: Any) {
+ (x as! () -> ())()
+}
diff --git a/test/SILGen/plus_zero_dynamic.swift b/test/SILGen/plus_zero_dynamic.swift
new file mode 100644
index 0000000..2376ae7
--- /dev/null
+++ b/test/SILGen/plus_zero_dynamic.swift
@@ -0,0 +1,557 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -Xllvm -sil-full-demangle -primary-file %s %S/Inputs/dynamic_other.swift -emit-silgen | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -Xllvm -sil-full-demangle -primary-file %s %S/Inputs/dynamic_other.swift -emit-sil -verify
+
+// REQUIRES: objc_interop
+
+import Foundation
+import gizmo
+
+class Foo: Proto {
+ // Not objc or dynamic, so only a vtable entry
+ init(native: Int) {}
+ func nativeMethod() {}
+ var nativeProp: Int = 0
+ subscript(native native: Int) -> Int {
+ get { return native }
+ set {}
+ }
+
+ // @objc, so it has an ObjC entry point but can also be dispatched
+ // by vtable
+ @objc init(objc: Int) {}
+ @objc func objcMethod() {}
+ @objc var objcProp: Int = 0
+ @objc subscript(objc objc: AnyObject) -> Int {
+ get { return 0 }
+ set {}
+ }
+
+ // dynamic, so it has only an ObjC entry point
+ dynamic init(dynamic: Int) {}
+ dynamic func dynamicMethod() {}
+ dynamic var dynamicProp: Int = 0
+ dynamic subscript(dynamic dynamic: Int) -> Int {
+ get { return dynamic }
+ set {}
+ }
+
+ func overriddenByDynamic() {}
+
+ @NSManaged var managedProp: Int
+}
+
+protocol Proto {
+ func nativeMethod()
+ var nativeProp: Int { get set }
+ subscript(native native: Int) -> Int { get set }
+
+ func objcMethod()
+ var objcProp: Int { get set }
+ subscript(objc objc: AnyObject) -> Int { get set }
+
+ func dynamicMethod()
+ var dynamicProp: Int { get set }
+ subscript(dynamic dynamic: Int) -> Int { get set }
+}
+
+// ObjC entry points for @objc and dynamic entry points
+
+// normal and @objc initializing ctors can be statically dispatched
+// CHECK-LABEL: sil hidden @$S7dynamic3FooC{{.*}}tcfC
+// CHECK: function_ref @$S7dynamic3FooC{{.*}}tcfc
+
+// CHECK-LABEL: sil hidden @$S7dynamic3FooC{{.*}}tcfC
+// CHECK: function_ref @$S7dynamic3FooC{{.*}}tcfc
+
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3{{[_0-9a-zA-Z]*}}fcTo
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3FooC10objcMethod{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [transparent] [thunk] @$S7dynamic3FooC8objcPropSivgTo
+// CHECK-LABEL: sil hidden [transparent] [thunk] @$S7dynamic3FooC8objcPropSivsTo
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3FooC4objcSiyXl_tcigTo
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3FooC4objcSiyXl_tcisTo
+
+// TODO: dynamic initializing ctor must be objc dispatched
+// CHECK-LABEL: sil hidden @$S7dynamic3{{[_0-9a-zA-Z]*}}fC
+// CHECK: function_ref @$S7dynamic3{{[_0-9a-zA-Z]*}}fcTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S7dynamic3{{[_0-9a-zA-Z]*}}fcTD
+// CHECK: objc_method {{%.*}} : $Foo, #Foo.init!initializer.1.foreign :
+
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3{{[_0-9a-zA-Z]*}}fcTo
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3FooC0A6Method{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [transparent] [thunk] @$S7dynamic3FooC0A4PropSivgTo
+// CHECK-LABEL: sil hidden [transparent] [thunk] @$S7dynamic3FooC0A4PropSivsTo
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3FooCAAS2i_tcigTo
+// CHECK-LABEL: sil hidden [thunk] @$S7dynamic3FooCAAS2i_tcisTo
+
+// Protocol witnesses use best appropriate dispatch
+
+// Native witnesses use vtable dispatch:
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP12nativeMethod{{[_0-9a-zA-Z]*}}FTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.nativeMethod!1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP10nativePropSivgTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.nativeProp!getter.1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP10nativePropSivsTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.nativeProp!setter.1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP6nativeS2i_tcigTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!getter.1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP6nativeS2i_tcisTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!setter.1 :
+
+// @objc witnesses use vtable dispatch:
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP10objcMethod{{[_0-9a-zA-Z]*}}FTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.objcMethod!1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP8objcPropSivgTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.objcProp!getter.1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP8objcPropSivsTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.objcProp!setter.1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP4objcSiyXl_tcigTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!getter.1 :
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP4objcSiyXl_tcisTW
+// CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!setter.1 :
+
+// Dynamic witnesses use objc dispatch:
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP0A6Method{{[_0-9a-zA-Z]*}}FTW
+// CHECK: function_ref @$S7dynamic3FooC0A6Method{{[_0-9a-zA-Z]*}}FTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S7dynamic3FooC0A6Method{{[_0-9a-zA-Z]*}}FTD
+// CHECK: objc_method {{%.*}} : $Foo, #Foo.dynamicMethod!1.foreign :
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP0A4PropSivgTW
+// CHECK: function_ref @$S7dynamic3FooC0A4PropSivgTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S7dynamic3FooC0A4PropSivgTD
+// CHECK: objc_method {{%.*}} : $Foo, #Foo.dynamicProp!getter.1.foreign :
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDP0A4PropSivsTW
+// CHECK: function_ref @$S7dynamic3FooC0A4PropSivsTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S7dynamic3FooC0A4PropSivsTD
+// CHECK: objc_method {{%.*}} : $Foo, #Foo.dynamicProp!setter.1.foreign :
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDPAAS2i_tcigTW
+// CHECK: function_ref @$S7dynamic3FooCAAS2i_tcigTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S7dynamic3FooCAAS2i_tcigTD
+// CHECK: objc_method {{%.*}} : $Foo, #Foo.subscript!getter.1.foreign :
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S7dynamic3FooCAA5ProtoA2aDPAAS2i_tcisTW
+// CHECK: function_ref @$S7dynamic3FooCAAS2i_tcisTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S7dynamic3FooCAAS2i_tcisTD
+// CHECK: objc_method {{%.*}} : $Foo, #Foo.subscript!setter.1.foreign :
+
+// Superclass dispatch
+class Subclass: Foo {
+ // Native and objc methods can directly reference super members
+ override init(native: Int) {
+ super.init(native: native)
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: function_ref @$S7dynamic8SubclassC{{[_0-9a-zA-Z]*}}fc
+
+ override func nativeMethod() {
+ super.nativeMethod()
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC12nativeMethod{{[_0-9a-zA-Z]*}}F
+ // CHECK: function_ref @$S7dynamic3FooC12nativeMethodyyF : $@convention(method) (@guaranteed Foo) -> ()
+
+ override var nativeProp: Int {
+ get { return super.nativeProp }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC10nativePropSivg
+ // CHECK: function_ref @$S7dynamic3FooC10nativePropSivg : $@convention(method) (@guaranteed Foo) -> Int
+ set { super.nativeProp = newValue }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC10nativePropSivs
+ // CHECK: function_ref @$S7dynamic3FooC10nativePropSivs : $@convention(method) (Int, @guaranteed Foo) -> ()
+ }
+
+ override subscript(native native: Int) -> Int {
+ get { return super[native: native] }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC6nativeS2i_tcig
+ // CHECK: function_ref @$S7dynamic3FooC6nativeS2i_tcig : $@convention(method) (Int, @guaranteed Foo) -> Int
+ set { super[native: native] = newValue }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC6nativeS2i_tcis
+ // CHECK: function_ref @$S7dynamic3FooC6nativeS2i_tcis : $@convention(method) (Int, Int, @guaranteed Foo) -> ()
+ }
+
+ override init(objc: Int) {
+ super.init(objc: objc)
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC4objcACSi_tcfc
+ // CHECK: function_ref @$S7dynamic3FooC4objcACSi_tcfc : $@convention(method) (Int, @owned Foo) -> @owned Foo
+
+ override func objcMethod() {
+ super.objcMethod()
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC10objcMethod{{[_0-9a-zA-Z]*}}F
+ // CHECK: function_ref @$S7dynamic3FooC10objcMethodyyF : $@convention(method) (@guaranteed Foo) -> ()
+
+ override var objcProp: Int {
+ get { return super.objcProp }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC8objcPropSivg
+ // CHECK: function_ref @$S7dynamic3FooC8objcPropSivg : $@convention(method) (@guaranteed Foo) -> Int
+ set { super.objcProp = newValue }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC8objcPropSivs
+ // CHECK: function_ref @$S7dynamic3FooC8objcPropSivs : $@convention(method) (Int, @guaranteed Foo) -> ()
+ }
+
+ override subscript(objc objc: AnyObject) -> Int {
+ get { return super[objc: objc] }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC4objcSiyXl_tcig
+ // CHECK: function_ref @$S7dynamic3FooC4objcSiyXl_tcig : $@convention(method) (@guaranteed AnyObject, @guaranteed Foo) -> Int
+ set { super[objc: objc] = newValue }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC4objcSiyXl_tcis
+ // CHECK: function_ref @$S7dynamic3FooC4objcSiyXl_tcis : $@convention(method) (Int, @owned AnyObject, @guaranteed Foo) -> ()
+ }
+
+ // Dynamic methods are super-dispatched by objc_msgSend
+ override init(dynamic: Int) {
+ super.init(dynamic: dynamic)
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: objc_super_method {{%.*}} : $Subclass, #Foo.init!initializer.1.foreign :
+
+ override func dynamicMethod() {
+ super.dynamicMethod()
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC0A6Method{{[_0-9a-zA-Z]*}}F
+ // CHECK: objc_super_method {{%.*}} : $Subclass, #Foo.dynamicMethod!1.foreign :
+
+ override var dynamicProp: Int {
+ get { return super.dynamicProp }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC0A4PropSivg
+ // CHECK: objc_super_method {{%.*}} : $Subclass, #Foo.dynamicProp!getter.1.foreign :
+ set { super.dynamicProp = newValue }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassC0A4PropSivs
+ // CHECK: objc_super_method {{%.*}} : $Subclass, #Foo.dynamicProp!setter.1.foreign :
+ }
+
+ override subscript(dynamic dynamic: Int) -> Int {
+ get { return super[dynamic: dynamic] }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassCAAS2i_tcig
+ // CHECK: objc_super_method {{%.*}} : $Subclass, #Foo.subscript!getter.1.foreign :
+ set { super[dynamic: dynamic] = newValue }
+ // CHECK-LABEL: sil hidden @$S7dynamic8SubclassCAAS2i_tcis
+ // CHECK: objc_super_method {{%.*}} : $Subclass, #Foo.subscript!setter.1.foreign :
+ }
+
+ dynamic override func overriddenByDynamic() {}
+}
+
+class SubclassWithInheritedInits: Foo {
+ // CHECK-LABEL: sil hidden @$S7dynamic26SubclassWithInheritedInitsC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: objc_super_method {{%.*}} : $SubclassWithInheritedInits, #Foo.init!initializer.1.foreign :
+}
+class GrandchildWithInheritedInits: SubclassWithInheritedInits {
+ // CHECK-LABEL: sil hidden @$S7dynamic28GrandchildWithInheritedInitsC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: objc_super_method {{%.*}} : $GrandchildWithInheritedInits, #SubclassWithInheritedInits.init!initializer.1.foreign :
+}
+class GrandchildOfInheritedInits: SubclassWithInheritedInits {
+ // Dynamic methods are super-dispatched by objc_msgSend
+ override init(dynamic: Int) {
+ super.init(dynamic: dynamic)
+ }
+ // CHECK-LABEL: sil hidden @$S7dynamic26GrandchildOfInheritedInitsC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: objc_super_method {{%.*}} : $GrandchildOfInheritedInits, #SubclassWithInheritedInits.init!initializer.1.foreign :
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic20nativeMethodDispatchyyF : $@convention(thin) () -> ()
+func nativeMethodDispatch() {
+ // CHECK: function_ref @$S7dynamic3{{[_0-9a-zA-Z]*}}fC
+ let c = Foo(native: 0)
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.nativeMethod!1 :
+ c.nativeMethod()
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.nativeProp!getter.1 :
+ let x = c.nativeProp
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.nativeProp!setter.1 :
+ c.nativeProp = x
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!getter.1 :
+ let y = c[native: 0]
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!setter.1 :
+ c[native: 0] = y
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic18objcMethodDispatchyyF : $@convention(thin) () -> ()
+func objcMethodDispatch() {
+ // CHECK: function_ref @$S7dynamic3{{[_0-9a-zA-Z]*}}fC
+ let c = Foo(objc: 0)
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.objcMethod!1 :
+ c.objcMethod()
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.objcProp!getter.1 :
+ let x = c.objcProp
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.objcProp!setter.1 :
+ c.objcProp = x
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!getter.1 :
+ let y = c[objc: 0 as NSNumber]
+ // CHECK: class_method {{%.*}} : $Foo, #Foo.subscript!setter.1 :
+ c[objc: 0 as NSNumber] = y
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic0A14MethodDispatchyyF : $@convention(thin) () -> ()
+func dynamicMethodDispatch() {
+ // CHECK: function_ref @$S7dynamic3{{[_0-9a-zA-Z]*}}fC
+ let c = Foo(dynamic: 0)
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.dynamicMethod!1.foreign
+ c.dynamicMethod()
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.dynamicProp!getter.1.foreign
+ let x = c.dynamicProp
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.dynamicProp!setter.1.foreign
+ c.dynamicProp = x
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.subscript!getter.1.foreign
+ let y = c[dynamic: 0]
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.subscript!setter.1.foreign
+ c[dynamic: 0] = y
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic15managedDispatchyyAA3FooCF
+func managedDispatch(_ c: Foo) {
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.managedProp!getter.1.foreign
+ let x = c.managedProp
+ // CHECK: objc_method {{%.*}} : $Foo, #Foo.managedProp!setter.1.foreign
+ c.managedProp = x
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic21foreignMethodDispatchyyF
+func foreignMethodDispatch() {
+ // CHECK: function_ref @$SSo9GuisemeauC{{[_0-9a-zA-Z]*}}fC
+ let g = Guisemeau()!
+ // CHECK: objc_method {{%.*}} : $Gizmo, #Gizmo.frob!1.foreign
+ g.frob()
+ // CHECK: objc_method {{%.*}} : $Gizmo, #Gizmo.count!getter.1.foreign
+ let x = g.count
+ // CHECK: objc_method {{%.*}} : $Gizmo, #Gizmo.count!setter.1.foreign
+ g.count = x
+ // CHECK: objc_method {{%.*}} : $Guisemeau, #Guisemeau.subscript!getter.1.foreign
+ let y: Any! = g[0]
+ // CHECK: objc_method {{%.*}} : $Guisemeau, #Guisemeau.subscript!setter.1.foreign
+ g[0] = y
+ // CHECK: objc_method {{%.*}} : $NSObject, #NSObject.description!getter.1.foreign
+ _ = g.description
+}
+
+extension Gizmo {
+ // CHECK-LABEL: sil hidden @$SSo5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fc
+ // CHECK: objc_method {{%.*}} : $Gizmo, #Gizmo.init!initializer.1.foreign
+ convenience init(convenienceInExtension: Int) {
+ self.init(bellsOn: convenienceInExtension)
+ }
+
+ // CHECK-LABEL: sil hidden @$SSo5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fC
+ // CHECK: objc_method {{%.*}} : $@objc_metatype Gizmo.Type, #Gizmo.init!allocator.1.foreign
+ convenience init(foreignClassFactory x: Int) {
+ self.init(stuff: x)
+ }
+
+ // CHECK-LABEL: sil hidden @$SSo5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fC
+ // CHECK: objc_method {{%.*}} : $@objc_metatype Gizmo.Type, #Gizmo.init!allocator.1.foreign
+ convenience init(foreignClassExactFactory x: Int) {
+ self.init(exactlyStuff: x)
+ }
+
+ @objc func foreignObjCExtension() { }
+ dynamic func foreignDynamicExtension() { }
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic24foreignExtensionDispatchyySo5GizmoCF
+// CHECK: bb0([[ARG:%.*]] : $Gizmo):
+func foreignExtensionDispatch(_ g: Gizmo) {
+ // CHECK: objc_method [[ARG]] : $Gizmo, #Gizmo.foreignObjCExtension!1.foreign : (Gizmo)
+ g.foreignObjCExtension()
+ // CHECK: objc_method [[ARG]] : $Gizmo, #Gizmo.foreignDynamicExtension!1.foreign
+ g.foreignDynamicExtension()
+}
+
+
+// CHECK-LABEL: sil hidden @$S7dynamic33nativeMethodDispatchFromOtherFileyyF : $@convention(thin) () -> ()
+func nativeMethodDispatchFromOtherFile() {
+ // CHECK: function_ref @$S7dynamic13FromOtherFile{{[_0-9a-zA-Z]*}}fC
+ let c = FromOtherFile(native: 0)
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.nativeMethod!1 :
+ c.nativeMethod()
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.nativeProp!getter.1 :
+ let x = c.nativeProp
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.nativeProp!setter.1 :
+ c.nativeProp = x
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.subscript!getter.1 :
+ let y = c[native: 0]
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.subscript!setter.1 :
+ c[native: 0] = y
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic31objcMethodDispatchFromOtherFileyyF : $@convention(thin) () -> ()
+func objcMethodDispatchFromOtherFile() {
+ // CHECK: function_ref @$S7dynamic13FromOtherFile{{[_0-9a-zA-Z]*}}fC
+ let c = FromOtherFile(objc: 0)
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.objcMethod!1 :
+ c.objcMethod()
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.objcProp!getter.1 :
+ let x = c.objcProp
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.objcProp!setter.1 :
+ c.objcProp = x
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.subscript!getter.1 :
+ let y = c[objc: 0]
+ // CHECK: class_method {{%.*}} : $FromOtherFile, #FromOtherFile.subscript!setter.1 :
+ c[objc: 0] = y
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic0A27MethodDispatchFromOtherFileyyF : $@convention(thin) () -> ()
+func dynamicMethodDispatchFromOtherFile() {
+ // CHECK: function_ref @$S7dynamic13FromOtherFile{{[_0-9a-zA-Z]*}}fC
+ let c = FromOtherFile(dynamic: 0)
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.dynamicMethod!1.foreign
+ c.dynamicMethod()
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.dynamicProp!getter.1.foreign
+ let x = c.dynamicProp
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.dynamicProp!setter.1.foreign
+ c.dynamicProp = x
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.subscript!getter.1.foreign
+ let y = c[dynamic: 0]
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.subscript!setter.1.foreign
+ c[dynamic: 0] = y
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic28managedDispatchFromOtherFileyyAA0deF0CF
+func managedDispatchFromOtherFile(_ c: FromOtherFile) {
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.managedProp!getter.1.foreign
+ let x = c.managedProp
+ // CHECK: objc_method {{%.*}} : $FromOtherFile, #FromOtherFile.managedProp!setter.1.foreign
+ c.managedProp = x
+}
+
+// CHECK-LABEL: sil hidden @$S7dynamic0A16ExtensionMethodsyyAA13ObjCOtherFileCF
+func dynamicExtensionMethods(_ obj: ObjCOtherFile) {
+ // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.extensionMethod!1.foreign
+ obj.extensionMethod()
+ // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.extensionProp!getter.1.foreign
+ _ = obj.extensionProp
+
+ // CHECK: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+ // CHECK-NEXT: objc_method {{%.*}} : $@objc_metatype ObjCOtherFile.Type, #ObjCOtherFile.extensionClassProp!getter.1.foreign
+ _ = type(of: obj).extensionClassProp
+
+ // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.dynExtensionMethod!1.foreign
+ obj.dynExtensionMethod()
+ // CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.dynExtensionProp!getter.1.foreign
+ _ = obj.dynExtensionProp
+
+ // CHECK: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+ // CHECK-NEXT: objc_method {{%.*}} : $@objc_metatype ObjCOtherFile.Type, #ObjCOtherFile.dynExtensionClassProp!getter.1.foreign
+ _ = type(of: obj).dynExtensionClassProp
+}
+
+public class Base {
+ dynamic var x: Bool { return false }
+}
+
+public class Sub : Base {
+ // CHECK-LABEL: sil hidden @$S7dynamic3SubC1xSbvg : $@convention(method) (@guaranteed Sub) -> Bool {
+ // CHECK: bb0([[SELF:%.*]] : $Sub):
+ // CHECK: [[AUTOCLOSURE:%.*]] = function_ref @$S7dynamic3SubC1xSbvgSbyKXKfu_ : $@convention(thin) (@guaranteed Sub) -> (Bool, @error Error)
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: = partial_apply [callee_guaranteed] [[AUTOCLOSURE]]([[SELF_COPY]])
+ // CHECK: return {{%.*}} : $Bool
+ // CHECK: } // end sil function '$S7dynamic3SubC1xSbvg'
+
+ // CHECK-LABEL: sil private [transparent] @$S7dynamic3SubC1xSbvgSbyKXKfu_ : $@convention(thin) (@guaranteed Sub) -> (Bool, @error Error) {
+ // CHECK: bb0([[VALUE:%.*]] : $Sub):
+ // CHECK: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK: [[CASTED_VALUE_COPY:%.*]] = upcast [[VALUE_COPY]]
+ // CHECK: [[BORROWED_CASTED_VALUE_COPY:%.*]] = begin_borrow [[CASTED_VALUE_COPY]]
+ // CHECK: [[DOWNCAST_FOR_SUPERMETHOD:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_VALUE_COPY]]
+ // CHECK: [[SUPER:%.*]] = objc_super_method [[DOWNCAST_FOR_SUPERMETHOD]] : $Sub, #Base.x!getter.1.foreign : (Base) -> () -> Bool, $@convention(objc_method) (Base) -> ObjCBool
+ // CHECK: end_borrow [[BORROWED_CASTED_VALUE_COPY]]
+ // CHECK: = apply [[SUPER]]([[CASTED_VALUE_COPY]])
+ // CHECK: destroy_value [[CASTED_VALUE_COPY]]
+ // CHECK: } // end sil function '$S7dynamic3SubC1xSbvgSbyKXKfu_'
+ override var x: Bool { return false || super.x }
+}
+
+public class BaseExt : NSObject {}
+
+extension BaseExt {
+ @objc public var count: Int {
+ return 0
+ }
+}
+
+public class SubExt : BaseExt {
+ public override var count: Int {
+ return 1
+ }
+}
+
+public class GenericBase<T> {
+ public func method(_: T) {}
+}
+
+public class ConcreteDerived : GenericBase<Int> {
+ public override dynamic func method(_: Int) {}
+}
+
+// The dynamic override has a different calling convention than the base,
+// so after re-abstracting the signature we must dispatch to the dynamic
+// thunk.
+
+// CHECK-LABEL: sil private @$S7dynamic15ConcreteDerivedC6methodyySiFAA11GenericBaseCADyyxFTV : $@convention(method) (@in_guaranteed Int, @guaranteed ConcreteDerived) -> ()
+// CHECK: bb0(%0 : $*Int, %1 : $ConcreteDerived):
+// CHECK-NEXT: [[VALUE:%.*]] = load [trivial] %0 : $*Int
+// CHECK: [[DYNAMIC_THUNK:%.*]] = function_ref @$S7dynamic15ConcreteDerivedC6methodyySiFTD : $@convention(method) (Int, @guaranteed ConcreteDerived) -> ()
+// CHECK-NEXT: apply [[DYNAMIC_THUNK]]([[VALUE]], %1) : $@convention(method) (Int, @guaranteed ConcreteDerived) -> ()
+// CHECK: return
+
+// Vtable contains entries for native and @objc methods, but not dynamic ones
+// CHECK-LABEL: sil_vtable Foo {
+// CHECK-NEXT: #Foo.init!initializer.1: {{.*}} : @$S7dynamic3FooC6nativeACSi_tcfc
+// CHECK-NEXT: #Foo.nativeMethod!1: {{.*}} : @$S7dynamic3FooC12nativeMethodyyF
+// CHECK-NEXT: #Foo.nativeProp!getter.1: {{.*}} : @$S7dynamic3FooC10nativePropSivg // dynamic.Foo.nativeProp.getter : Swift.Int
+// CHECK-NEXT: #Foo.nativeProp!setter.1: {{.*}} : @$S7dynamic3FooC10nativePropSivs // dynamic.Foo.nativeProp.setter : Swift.Int
+// CHECK-NEXT: #Foo.nativeProp!materializeForSet.1
+// CHECK-NEXT: #Foo.subscript!getter.1: {{.*}} : @$S7dynamic3FooC6nativeS2i_tcig // dynamic.Foo.subscript.getter : (native: Swift.Int) -> Swift.Int
+// CHECK-NEXT: #Foo.subscript!setter.1: {{.*}} : @$S7dynamic3FooC6nativeS2i_tcis // dynamic.Foo.subscript.setter : (native: Swift.Int) -> Swift.Int
+// CHECK-NEXT: #Foo.subscript!materializeForSet.1
+// CHECK-NEXT: #Foo.init!initializer.1: {{.*}} : @$S7dynamic3FooC4objcACSi_tcfc
+// CHECK-NEXT: #Foo.objcMethod!1: {{.*}} : @$S7dynamic3FooC10objcMethodyyF
+// CHECK-NEXT: #Foo.objcProp!getter.1: {{.*}} : @$S7dynamic3FooC8objcPropSivg // dynamic.Foo.objcProp.getter : Swift.Int
+// CHECK-NEXT: #Foo.objcProp!setter.1: {{.*}} : @$S7dynamic3FooC8objcPropSivs // dynamic.Foo.objcProp.setter : Swift.Int
+// CHECK-NEXT: #Foo.objcProp!materializeForSet.1
+// CHECK-NEXT: #Foo.subscript!getter.1: {{.*}} : @$S7dynamic3FooC4objcSiyXl_tcig // dynamic.Foo.subscript.getter : (objc: Swift.AnyObject) -> Swift.Int
+// CHECK-NEXT: #Foo.subscript!setter.1: {{.*}} : @$S7dynamic3FooC4objcSiyXl_tcis // dynamic.Foo.subscript.setter : (objc: Swift.AnyObject) -> Swift.Int
+// CHECK-NEXT: #Foo.subscript!materializeForSet
+// CHECK-NEXT: #Foo.overriddenByDynamic!1: {{.*}} : @$S7dynamic3FooC19overriddenByDynamic{{[_0-9a-zA-Z]*}}
+// CHECK-NEXT: #Foo.deinit!deallocator: {{.*}}
+// CHECK-NEXT: }
+
+// Vtable uses a dynamic thunk for dynamic overrides
+// CHECK-LABEL: sil_vtable Subclass {
+// CHECK: #Foo.overriddenByDynamic!1: {{.*}} : public @$S7dynamic8SubclassC19overriddenByDynamic{{[_0-9a-zA-Z]*}}FTD
+// CHECK: }
+
+// Check vtables for implicitly-inherited initializers
+// CHECK-LABEL: sil_vtable SubclassWithInheritedInits {
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : @$S7dynamic26SubclassWithInheritedInitsC6nativeACSi_tcfc
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : @$S7dynamic26SubclassWithInheritedInitsC4objcACSi_tcfc
+// CHECK-NOT: .init!
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable GrandchildWithInheritedInits {
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : @$S7dynamic28GrandchildWithInheritedInitsC6nativeACSi_tcfc
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : @$S7dynamic28GrandchildWithInheritedInitsC4objcACSi_tcfc
+// CHECK-NOT: .init!
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable GrandchildOfInheritedInits {
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : @$S7dynamic26GrandchildOfInheritedInitsC6nativeACSi_tcfc
+// CHECK: #Foo.init!initializer.1: (Foo.Type) -> (Int) -> Foo : @$S7dynamic26GrandchildOfInheritedInitsC4objcACSi_tcfc
+// CHECK-NOT: .init!
+// CHECK: }
+
+// No vtable entry for override of @objc extension property
+// CHECK-LABEL: sil_vtable [serialized] SubExt {
+// CHECK-NEXT: #BaseExt.init!initializer.1: (BaseExt.Type) -> () -> BaseExt : @$S7dynamic6SubExtCACycfc [override] // dynamic.SubExt.init() -> dynamic.SubExt
+// CHECK-NEXT: #SubExt.deinit!deallocator: @$S7dynamic6SubExtCfD // dynamic.SubExt.__deallocating_deinit
+// CHECK-NEXT: }
+
+// Dynamic thunk + vtable re-abstraction
+// CHECK-LABEL: sil_vtable [serialized] ConcreteDerived {
+// CHECK-NEXT: #GenericBase.method!1: <T> (GenericBase<T>) -> (T) -> () : public @$S7dynamic15ConcreteDerivedC6methodyySiFAA11GenericBaseCADyyxFTV [override] // vtable thunk for dynamic.GenericBase.method(A) -> () dispatching to dynamic.ConcreteDerived.method(Swift.Int) -> ()
+// CHECK-NEXT: #GenericBase.init!initializer.1: <T> (GenericBase<T>.Type) -> () -> GenericBase<T> : @$S7dynamic15ConcreteDerivedCACycfc [override] // dynamic.ConcreteDerived.init() -> dynamic.ConcreteDerived
+// CHECK-NEXT: #ConcreteDerived.deinit!deallocator: @$S7dynamic15ConcreteDerivedCfD // dynamic.ConcreteDerived.__deallocating_deinit
+// CHECK-NEXT: }
diff --git a/test/SILGen/plus_zero_dynamic_lookup.swift b/test/SILGen/plus_zero_dynamic_lookup.swift
new file mode 100644
index 0000000..64062f5
--- /dev/null
+++ b/test/SILGen/plus_zero_dynamic_lookup.swift
@@ -0,0 +1,361 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
+// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s --check-prefix=GUARANTEED
+
+// REQUIRES: objc_interop
+
+class X {
+ @objc func f() { }
+ @objc class func staticF() { }
+ @objc var value: Int {
+ return 17
+ }
+
+ @objc subscript (i: Int) -> Int {
+ get {
+ return i
+ }
+ set {}
+ }
+}
+
+@objc protocol P {
+ func g()
+}
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup15direct_to_class{{[_0-9a-zA-Z]*}}F
+func direct_to_class(_ obj: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : $AnyObject):
+ // CHECK: [[OPENED_ARG:%[0-9]+]] = open_existential_ref [[ARG]] : $AnyObject to $@opened({{.*}}) AnyObject
+ // CHECK: [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #X.f!1.foreign : (X) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // CHECK: apply [[METHOD]]([[OPENED_ARG_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // CHECK: destroy_value [[OPENED_ARG_COPY]]
+ obj.f!()
+}
+// CHECK: } // end sil function '$S14dynamic_lookup15direct_to_class{{[_0-9a-zA-Z]*}}F'
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup18direct_to_protocol{{[_0-9a-zA-Z]*}}F
+func direct_to_protocol(_ obj: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : $AnyObject):
+ // CHECK: [[OPENED_ARG:%[0-9]+]] = open_existential_ref [[ARG]] : $AnyObject to $@opened({{.*}}) AnyObject
+ // CHECK: [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #P.g!1.foreign : <Self where Self : P> (Self) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // CHECK: apply [[METHOD]]([[OPENED_ARG_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // CHECK: destroy_value [[OPENED_ARG_COPY]]
+ obj.g!()
+}
+// CHECK: } // end sil function '$S14dynamic_lookup18direct_to_protocol{{[_0-9a-zA-Z]*}}F'
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup23direct_to_static_method{{[_0-9a-zA-Z]*}}F
+func direct_to_static_method(_ obj: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : $AnyObject):
+ var obj = obj
+ // CHECK: [[OBJBOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK-NEXT: [[PBOBJ:%[0-9]+]] = project_box [[OBJBOX]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: store [[ARG_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK-NEXT: [[OBJCOPY:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: end_access [[READ]]
+ // CHECK-NEXT: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick AnyObject.Type, [[OBJCOPY]] : $AnyObject
+ // CHECK-NEXT: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick AnyObject.Type to $@thick (@opened([[UUID:".*"]]) AnyObject).Type
+ // CHECK-NEXT: [[METHOD:%[0-9]+]] = objc_method [[OPENMETA]] : $@thick (@opened([[UUID]]) AnyObject).Type, #X.staticF!1.foreign : (X.Type) -> () -> (), $@convention(objc_method) (@thick (@opened([[UUID]]) AnyObject).Type) -> ()
+ // CHECK: apply [[METHOD]]([[OPENMETA]]) : $@convention(objc_method) (@thick (@opened([[UUID]]) AnyObject).Type) -> ()
+ // CHECK: destroy_value [[OBJBOX]]
+ type(of: obj).staticF!()
+}
+// } // end sil function '_TF14dynamic_lookup23direct_to_static_method{{.*}}'
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup12opt_to_class{{[_0-9a-zA-Z]*}}F
+func opt_to_class(_ obj: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : $AnyObject):
+ var obj = obj
+ // CHECK: [[EXISTBOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK: [[PBOBJ:%[0-9]+]] = project_box [[EXISTBOX]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: store [[ARG_COPY]] to [init] [[PBOBJ]]
+ // CHECK: [[OPTBOX:%[0-9]+]] = alloc_box ${ var Optional<@callee_guaranteed () -> ()> }
+ // CHECK: [[PBOPT:%.*]] = project_box [[OPTBOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK: [[EXISTVAL:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: [[OBJ_SELF:%[0-9]*]] = open_existential_ref [[EXISTVAL]]
+ // CHECK: [[OPT_TMP:%.*]] = alloc_stack $Optional<@callee_guaranteed () -> ()>
+ // CHECK: dynamic_method_br [[OBJ_SELF]] : $@opened({{.*}}) AnyObject, #X.f!1.foreign, [[HASBB:[a-zA-z0-9]+]], [[NOBB:[a-zA-z0-9]+]]
+
+ // Has method BB:
+ // CHECK: [[HASBB]]([[UNCURRIED:%[0-9]+]] : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()):
+ // CHECK: [[OBJ_SELF_COPY:%.*]] = copy_value [[OBJ_SELF]]
+ // CHECK: [[PARTIAL:%[0-9]+]] = partial_apply [callee_guaranteed] [[UNCURRIED]]([[OBJ_SELF_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // CHECK: [[THUNK_PAYLOAD:%.*]] = init_enum_data_addr [[OPT_TMP]]
+ // CHECK: store [[PARTIAL]] to [init] [[THUNK_PAYLOAD]]
+ // CHECK: inject_enum_addr [[OPT_TMP]] : $*Optional<@callee_guaranteed () -> ()>, #Optional.some!enumelt.1
+ // CHECK: br [[CONTBB:[a-zA-Z0-9]+]]
+
+ // No method BB:
+ // CHECK: [[NOBB]]:
+ // CHECK: inject_enum_addr [[OPT_TMP]] : {{.*}}, #Optional.none!enumelt
+ // CHECK: br [[CONTBB]]
+
+ // Continuation block
+ // CHECK: [[CONTBB]]:
+ // CHECK: [[OPT:%.*]] = load [take] [[OPT_TMP]]
+ // CHECK: store [[OPT]] to [init] [[PBOPT]] : $*Optional<@callee_guaranteed () -> ()>
+ // CHECK: dealloc_stack [[OPT_TMP]]
+ var of: (() -> ())! = obj.f
+
+ // Exit
+ // CHECK: destroy_value [[OBJ_SELF]] : $@opened({{".*"}}) AnyObject
+ // CHECK: destroy_value [[OPTBOX]] : ${ var Optional<@callee_guaranteed () -> ()> }
+ // CHECK: destroy_value [[EXISTBOX]] : ${ var AnyObject }
+ // CHECK: [[RESULT:%[0-9]+]] = tuple ()
+ // CHECK: return [[RESULT]] : $()
+}
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup20forced_without_outer{{[_0-9a-zA-Z]*}}F
+func forced_without_outer(_ obj: AnyObject) {
+ // CHECK: dynamic_method_br
+ var f = obj.f!
+}
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup20opt_to_static_method{{[_0-9a-zA-Z]*}}F
+func opt_to_static_method(_ obj: AnyObject) {
+ var obj = obj
+ // CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+ // CHECK: [[OBJBOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK: [[PBOBJ:%[0-9]+]] = project_box [[OBJBOX]]
+ // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // CHECK: [[OPTBOX:%[0-9]+]] = alloc_box ${ var Optional<@callee_guaranteed () -> ()> }
+ // CHECK: [[PBO:%.*]] = project_box [[OPTBOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK: [[OBJCOPY:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: [[OBJMETA:%[0-9]+]] = existential_metatype $@thick AnyObject.Type, [[OBJCOPY]] : $AnyObject
+ // CHECK: [[OPENMETA:%[0-9]+]] = open_existential_metatype [[OBJMETA]] : $@thick AnyObject.Type to $@thick (@opened
+ // CHECK: [[OBJCMETA:%[0-9]+]] = thick_to_objc_metatype [[OPENMETA]]
+ // CHECK: [[OPTTEMP:%.*]] = alloc_stack $Optional<@callee_guaranteed () -> ()>
+ // CHECK: dynamic_method_br [[OBJCMETA]] : $@objc_metatype (@opened({{".*"}}) AnyObject).Type, #X.staticF!1.foreign, [[HASMETHOD:[A-Za-z0-9_]+]], [[NOMETHOD:[A-Za-z0-9_]+]]
+ var optF: (() -> ())! = type(of: obj).staticF
+}
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup15opt_to_property{{[_0-9a-zA-Z]*}}F
+func opt_to_property(_ obj: AnyObject) {
+ var obj = obj
+ // CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+ // CHECK: [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK: [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+ // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // CHECK: [[INT_BOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: project_box [[INT_BOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: [[RAWOBJ_SELF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject
+ // CHECK: [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+ // CHECK: dynamic_method_br [[RAWOBJ_SELF]] : $@opened({{.*}}) AnyObject, #X.value!getter.1.foreign, bb1, bb2
+
+ // CHECK: bb1([[METHOD:%[0-9]+]] : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> Int):
+ // CHECK: [[RAWOBJ_SELF_COPY:%.*]] = copy_value [[RAWOBJ_SELF]]
+ // CHECK: [[BOUND_METHOD:%[0-9]+]] = partial_apply [callee_guaranteed] [[METHOD]]([[RAWOBJ_SELF_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> Int
+ // CHECK: [[B:%.*]] = begin_borrow [[BOUND_METHOD]]
+ // CHECK: [[VALUE:%[0-9]+]] = apply [[B]]() : $@callee_guaranteed () -> Int
+ // CHECK: end_borrow [[B]]
+ // CHECK: [[VALUETEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+ // CHECK: store [[VALUE]] to [trivial] [[VALUETEMP]]
+ // CHECK: inject_enum_addr [[OPTTEMP]]{{.*}}some
+ // CHECK: destroy_value [[BOUND_METHOD]]
+ // CHECK: br bb3
+ var i: Int = obj.value!
+}
+// CHECK: } // end sil function '$S14dynamic_lookup15opt_to_property{{[_0-9a-zA-Z]*}}F'
+
+// GUARANTEED-LABEL: sil hidden @$S14dynamic_lookup15opt_to_property{{[_0-9a-zA-Z]*}}F
+ // GUARANTEED: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+ // GUARANTEED: [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // GUARANTEED: [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+ // GUARANTEED: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // GUARANTEED: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // GUARANTEED: [[INT_BOX:%[0-9]+]] = alloc_box ${ var Int }
+ // GUARANTEED: project_box [[INT_BOX]]
+ // GUARANTEED: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // GUARANTEED: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // GUARANTEED: [[RAWOBJ_SELF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject
+ // GUARANTEED: [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+ // GUARANTEED: dynamic_method_br [[RAWOBJ_SELF]] : $@opened({{.*}}) AnyObject, #X.value!getter.1.foreign, bb1, bb2
+
+ // GUARANTEED: bb1([[METHOD:%[0-9]+]] : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> Int):
+ // GUARANTEED: [[RAWOBJ_SELF_COPY:%.*]] = copy_value [[RAWOBJ_SELF]]
+ // GUARANTEED: [[BOUND_METHOD:%[0-9]+]] = partial_apply [callee_guaranteed] [[METHOD]]([[RAWOBJ_SELF_COPY]])
+ // GUARANTEED: [[BEGIN_BORROW:%.*]] = begin_borrow [[BOUND_METHOD]]
+ // GUARANTEED: [[VALUE:%[0-9]+]] = apply [[BEGIN_BORROW]]
+ // GUARANTEED: end_borrow [[BEGIN_BORROW]] from [[BOUND_METHOD]]
+ // GUARANTEED: [[VALUETEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+ // GUARANTEED: store [[VALUE]] to [trivial] [[VALUETEMP]]
+ // GUARANTEED: inject_enum_addr [[OPTTEMP]]{{.*}}some
+ // GUARANTEED: destroy_value [[BOUND_METHOD]]
+ // GUARANTEED: br bb3
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F
+func direct_to_subscript(_ obj: AnyObject, i: Int) {
+ var obj = obj
+ var i = i
+ // CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject, [[I:%[0-9]+]] : $Int):
+ // CHECK: [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK: [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+ // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // CHECK: [[I_BOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PBI:%.*]] = project_box [[I_BOX]]
+ // CHECK: store [[I]] to [trivial] [[PBI]] : $*Int
+ // CHECK: alloc_box ${ var Int }
+ // CHECK: project_box
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: [[OBJ_REF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject to $@opened({{.*}}) AnyObject
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBI]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READ]] : $*Int
+ // CHECK: [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+ // CHECK: dynamic_method_br [[OBJ_REF]] : $@opened({{.*}}) AnyObject, #X.subscript!getter.1.foreign, bb1, bb2
+
+ // CHECK: bb1([[GETTER:%[0-9]+]] : $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int):
+ // CHECK: [[OBJ_REF_COPY:%.*]] = copy_value [[OBJ_REF]]
+ // CHECK: [[GETTER_WITH_SELF:%[0-9]+]] = partial_apply [callee_guaranteed] [[GETTER]]([[OBJ_REF_COPY]]) : $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int
+ // CHECK: [[B:%.*]] = begin_borrow [[GETTER_WITH_SELF]]
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[B]]([[I]]) : $@callee_guaranteed (Int) -> Int
+ // CHECK: end_borrow [[B]]
+ // CHECK: [[RESULTTEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+ // CHECK: store [[RESULT]] to [trivial] [[RESULTTEMP]]
+ // CHECK: inject_enum_addr [[OPTTEMP]]{{.*}}some
+ // CHECK: destroy_value [[GETTER_WITH_SELF]]
+ // CHECK: br bb3
+ var x: Int = obj[i]!
+}
+// CHECK: } // end sil function '$S14dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F'
+
+// GUARANTEED-LABEL: sil hidden @$S14dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F
+ // GUARANTEED: bb0([[OBJ:%[0-9]+]] : $AnyObject, [[I:%[0-9]+]] : $Int):
+ // GUARANTEED: [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // GUARANTEED: [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+ // GUARANTEED: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // GUARANTEED: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // GUARANTEED: [[I_BOX:%[0-9]+]] = alloc_box ${ var Int }
+ // GUARANTEED: [[PBI:%.*]] = project_box [[I_BOX]]
+ // GUARANTEED: store [[I]] to [trivial] [[PBI]] : $*Int
+ // GUARANTEED: alloc_box ${ var Int }
+ // GUARANTEED: project_box
+ // GUARANTEED: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // GUARANTEED: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // GUARANTEED: [[OBJ_REF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject to $@opened({{.*}}) AnyObject
+ // GUARANTEED: [[READ:%.*]] = begin_access [read] [unknown] [[PBI]]
+ // GUARANTEED: [[I:%[0-9]+]] = load [trivial] [[READ]] : $*Int
+ // GUARANTEED: [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+ // GUARANTEED: dynamic_method_br [[OBJ_REF]] : $@opened({{.*}}) AnyObject, #X.subscript!getter.1.foreign, bb1, bb2
+
+ // GUARANTEED: bb1([[GETTER:%[0-9]+]] : $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int):
+ // GUARANTEED: [[OBJ_REF_COPY:%.*]] = copy_value [[OBJ_REF]]
+ // GUARANTEED: [[GETTER_WITH_SELF:%[0-9]+]] = partial_apply [callee_guaranteed] [[GETTER]]([[OBJ_REF_COPY]])
+ // GUARANTEED: [[BORROW:%.*]] = begin_borrow [[GETTER_WITH_SELF]]
+ // GUARANTEED: [[RESULT:%[0-9]+]] = apply [[BORROW]]([[I]])
+ // GUARANTEED: end_borrow [[BORROW]] from [[GETTER_WITH_SELF]]
+ // GUARANTEED: [[RESULTTEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+ // GUARANTEED: store [[RESULT]] to [trivial] [[RESULTTEMP]]
+ // GUARANTEED: inject_enum_addr [[OPTTEMP]]{{.*}}some
+ // GUARANTEED: destroy_value [[GETTER_WITH_SELF]]
+ // GUARANTEED: br bb3
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup16opt_to_subscript{{[_0-9a-zA-Z]*}}F
+func opt_to_subscript(_ obj: AnyObject, i: Int) {
+ var obj = obj
+ var i = i
+ // CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject, [[I:%[0-9]+]] : $Int):
+ // CHECK: [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK: [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+ // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // CHECK: [[I_BOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PBI:%.*]] = project_box [[I_BOX]]
+ // CHECK: store [[I]] to [trivial] [[PBI]] : $*Int
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: [[OBJ_REF:%[0-9]+]] = open_existential_ref [[OBJ]] : $AnyObject to $@opened({{.*}}) AnyObject
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBI]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READ]] : $*Int
+ // CHECK: [[OPTTEMP:%.*]] = alloc_stack $Optional<Int>
+ // CHECK: dynamic_method_br [[OBJ_REF]] : $@opened({{.*}}) AnyObject, #X.subscript!getter.1.foreign, bb1, bb2
+
+ // CHECK: bb1([[GETTER:%[0-9]+]] : $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int):
+ // CHECK: [[OBJ_REF_COPY:%.*]] = copy_value [[OBJ_REF]]
+ // CHECK: [[GETTER_WITH_SELF:%[0-9]+]] = partial_apply [callee_guaranteed] [[GETTER]]([[OBJ_REF_COPY]]) : $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int
+ // CHECK: [[B:%.*]] = begin_borrow [[GETTER_WITH_SELF]]
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[B]]([[I]]) : $@callee_guaranteed (Int) -> Int
+ // CHECK: end_borrow [[B]]
+ // CHECK: [[RESULTTEMP:%.*]] = init_enum_data_addr [[OPTTEMP]]
+ // CHECK: store [[RESULT]] to [trivial] [[RESULTTEMP]]
+ // CHECK: inject_enum_addr [[OPTTEMP]]
+ // CHECK: destroy_value [[GETTER_WITH_SELF]]
+ // CHECK: br bb3
+ obj[i]
+}
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup8downcast{{[_0-9a-zA-Z]*}}F
+func downcast(_ obj: AnyObject) -> X {
+ var obj = obj
+ // CHECK: bb0([[OBJ:%[0-9]+]] : $AnyObject):
+ // CHECK: [[OBJ_BOX:%[0-9]+]] = alloc_box ${ var AnyObject }
+ // CHECK: [[PBOBJ:%[0-9]+]] = project_box [[OBJ_BOX]]
+ // CHECK: [[OBJ_COPY:%.*]] = copy_value [[OBJ]]
+ // CHECK: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOBJ]]
+ // CHECK: [[OBJ:%[0-9]+]] = load [copy] [[READ]] : $*AnyObject
+ // CHECK: [[X:%[0-9]+]] = unconditional_checked_cast [[OBJ]] : $AnyObject to $X
+ // CHECK: destroy_value [[OBJ_BOX]] : ${ var AnyObject }
+ // CHECK: return [[X]] : $X
+ return obj as! X
+}
+
+@objc class Juice { }
+
+@objc protocol Fruit {
+ @objc optional var juice: Juice { get }
+}
+
+// CHECK-LABEL: sil hidden @$S14dynamic_lookup7consumeyyAA5Fruit_pF
+// CHECK: bb0(%0 : $Fruit):
+// CHECK: [[BOX:%.*]] = alloc_stack $Optional<Juice>
+// CHECK: dynamic_method_br [[SELF:%.*]] : $@opened("{{.*}}") Fruit, #Fruit.juice!getter.1.foreign, bb1, bb2
+
+// CHECK: bb1([[FN:%.*]] : $@convention(objc_method) (@opened("{{.*}}") Fruit) -> @autoreleased Juice):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]]([[SELF_COPY]]) : $@convention(objc_method) (@opened("{{.*}}") Fruit) -> @autoreleased Juice
+// CHECK: [[B:%.*]] = begin_borrow [[METHOD]]
+// CHECK: [[RESULT:%.*]] = apply [[B]]() : $@callee_guaranteed () -> @owned Juice
+// CHECK: end_borrow [[B]]
+// CHECK: [[PAYLOAD:%.*]] = init_enum_data_addr [[BOX]] : $*Optional<Juice>, #Optional.some!enumelt.1
+// CHECK: store [[RESULT]] to [init] [[PAYLOAD]]
+// CHECK: inject_enum_addr [[BOX]] : $*Optional<Juice>, #Optional.some!enumelt.1
+// CHECK: destroy_value [[METHOD]]
+// CHECK: br bb3
+
+// CHECK: bb2:
+// CHECK: inject_enum_addr [[BOX]] : $*Optional<Juice>, #Optional.none!enumelt
+// CHECK: br bb3
+
+// CHECK: bb3:
+// CHECK: return
+
+func consume(_ fruit: Fruit) {
+ _ = fruit.juice
+}
+
+// rdar://problem/29249513 -- looking up an IUO member through AnyObject
+// produces a Foo!? type. The SIL verifier did not correctly consider Optional
+// to be the lowering of IUO (which is now eliminated by SIL lowering).
+
+@objc protocol IUORequirement {
+ var iuoProperty: AnyObject! { get }
+}
+
+func getIUOPropertyDynamically(x: AnyObject) -> Any {
+ return x.iuoProperty
+}
+
diff --git a/test/SILGen/plus_zero_dynamic_lookup_throws.swift b/test/SILGen/plus_zero_dynamic_lookup_throws.swift
new file mode 100644
index 0000000..6b2a455
--- /dev/null
+++ b/test/SILGen/plus_zero_dynamic_lookup_throws.swift
@@ -0,0 +1,30 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-clang-importer-objc-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-silgen -parse-as-library %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+class Blub : NSObject {
+ func blub() throws {}
+}
+
+// CHECK-LABEL: sil hidden @$S21dynamic_lookup_throws8testBlub1ayyXl_tKF : $@convention(thin) (@guaranteed AnyObject) -> @error Error
+// CHECK: bb0([[ARG:%.*]] : $AnyObject):
+func testBlub(a: AnyObject) throws {
+ // CHECK: [[ANYOBJECT_REF:%.*]] = open_existential_ref [[ARG]] : $AnyObject to $@opened("[[OPENED:.*]]") AnyObject
+ // CHECK: [[ANYOBJECT_REF_COPY:%.*]] = copy_value [[ANYOBJECT_REF]]
+ // CHECK: objc_method [[ANYOBJECT_REF_COPY]] : $@opened("[[OPENED]]") AnyObject, #Blub.blub!1.foreign : (Blub) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @opened("[[OPENED]]") AnyObject) -> ObjCBool
+ // CHECK: cond_br {{%.*}}, bb1, bb2
+
+ // CHECK: bb1
+ // CHECK: return
+
+ // CHECK: bb2
+ // CHECK: function_ref @$S10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF
+ // CHECK: throw {{%.*}} : $Error
+ try a.blub()
+}
diff --git a/test/SILGen/plus_zero_dynamic_self.swift b/test/SILGen/plus_zero_dynamic_self.swift
new file mode 100644
index 0000000..d02f276
--- /dev/null
+++ b/test/SILGen/plus_zero_dynamic_self.swift
@@ -0,0 +1,375 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
+// RUN: %target-swift-frontend -emit-sil -O %s -disable-objc-attr-requires-foundation-module
+// RUN: %target-swift-frontend -emit-ir %s -disable-objc-attr-requires-foundation-module
+
+protocol P {
+ func f() -> Self
+}
+
+protocol CP : class {
+ func f() -> Self
+}
+
+class X : P, CP {
+ required init(int i: Int) { }
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self1XC1f{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed X) -> @owned
+ func f() -> Self { return self }
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self1XC7factory{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (Int, @thick X.Type) -> @owned X
+ // CHECK: bb0([[I:%[0-9]+]] : @trivial $Int, [[SELF:%[0-9]+]] : @trivial $@thick X.Type):
+ // CHECK: [[DYNAMIC_SELF:%[0-9]+]] = unchecked_trivial_bit_cast [[SELF]] : $@thick X.Type to $@thick @dynamic_self X.Type
+ // CHECK: [[STATIC_SELF:%[0-9]+]] = upcast [[DYNAMIC_SELF]] : $@thick @dynamic_self X.Type to $@thick X.Type
+ // CHECK: [[CTOR:%[0-9]+]] = class_method [[STATIC_SELF]] : $@thick X.Type, #X.init!allocator.1 : (X.Type) -> (Int) -> X, $@convention(method) (Int, @thick X.Type) -> @owned X
+ // CHECK: apply [[CTOR]]([[I]], [[STATIC_SELF]]) : $@convention(method) (Int, @thick X.Type) -> @owned X
+ class func factory(i: Int) -> Self { return self.init(int: i) }
+}
+
+class Y : X {
+ required init(int i: Int) {
+ super.init(int: i)
+ }
+}
+
+class GX<T> {
+ func f() -> Self { return self }
+}
+
+class GY<T> : GX<[T]> { }
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self23testDynamicSelfDispatch{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed Y) -> ()
+// CHECK: bb0([[Y:%[0-9]+]] : @guaranteed $Y):
+// CHECK: [[Y_AS_X:%[0-9]+]] = upcast [[Y]] : $Y to $X
+// CHECK: [[X_F:%[0-9]+]] = class_method [[Y_AS_X]] : $X, #X.f!1 : (X) -> () -> @dynamic_self X, $@convention(method) (@guaranteed X) -> @owned X
+// CHECK: [[X_RESULT:%[0-9]+]] = apply [[X_F]]([[Y_AS_X]]) : $@convention(method) (@guaranteed X) -> @owned X
+// CHECK: [[Y_RESULT:%[0-9]+]] = unchecked_ref_cast [[X_RESULT]] : $X to $Y
+// CHECK: destroy_value [[Y_RESULT]] : $Y
+func testDynamicSelfDispatch(y: Y) {
+ _ = y.f()
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self30testDynamicSelfDispatchGeneric{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed GY<Int>) -> ()
+func testDynamicSelfDispatchGeneric(gy: GY<Int>) {
+ // CHECK: bb0([[GY:%[0-9]+]] : @guaranteed $GY<Int>):
+ // CHECK: [[GY_AS_GX:%[0-9]+]] = upcast [[GY]] : $GY<Int> to $GX<Array<Int>>
+ // CHECK: [[GX_F:%[0-9]+]] = class_method [[GY_AS_GX]] : $GX<Array<Int>>, #GX.f!1 : <T> (GX<T>) -> () -> @dynamic_self GX<T>, $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
+ // CHECK: [[GX_RESULT:%[0-9]+]] = apply [[GX_F]]<[Int]>([[GY_AS_GX]]) : $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
+ // CHECK: [[GY_RESULT:%[0-9]+]] = unchecked_ref_cast [[GX_RESULT]] : $GX<Array<Int>> to $GY<Int>
+ // CHECK: destroy_value [[GY_RESULT]] : $GY<Int>
+ _ = gy.f()
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self21testArchetypeDispatch{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : P> (@in_guaranteed T) -> ()
+func testArchetypeDispatch<T: P>(t: T) {
+ // CHECK: bb0([[T:%[0-9]+]] : @trivial $*T):
+ // CHECK: [[T_RESULT:%[0-9]+]] = alloc_stack $T
+ // CHECK: [[ARCHETYPE_F:%[0-9]+]] = witness_method $T, #P.f!1 : {{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: [[SELF_RESULT:%[0-9]+]] = apply [[ARCHETYPE_F]]<T>([[T_RESULT]], [[T]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ _ = t.f()
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self23testExistentialDispatch{{[_0-9a-zA-Z]*}}F
+func testExistentialDispatch(p: P) {
+// CHECK: bb0([[P:%[0-9]+]] : @trivial $*P):
+// CHECK: [[PCOPY_ADDR:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P to $*@opened([[N:".*"]]) P
+// CHECK: [[P_RESULT:%[0-9]+]] = alloc_stack $P
+// CHECK: [[P_RESULT_ADDR:%[0-9]+]] = init_existential_addr [[P_RESULT]] : $*P, $@opened([[N]]) P
+// CHECK: [[P_F_METHOD:%[0-9]+]] = witness_method $@opened([[N]]) P, #P.f!1 : {{.*}}, [[PCOPY_ADDR]]{{.*}} : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: apply [[P_F_METHOD]]<@opened([[N]]) P>([[P_RESULT_ADDR]], [[PCOPY_ADDR]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK: destroy_addr [[P_RESULT]] : $*P
+// CHECK: dealloc_stack [[P_RESULT]] : $*P
+ _ = p.f()
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self28testExistentialDispatchClass{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed CP) -> ()
+// CHECK: bb0([[CP:%[0-9]+]] : @guaranteed $CP):
+// CHECK: [[CP_ADDR:%[0-9]+]] = open_existential_ref [[CP]] : $CP to $@opened([[N:".*"]]) CP
+// CHECK: [[CP_F:%[0-9]+]] = witness_method $@opened([[N]]) CP, #CP.f!1 : {{.*}}, [[CP_ADDR]]{{.*}} : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
+// CHECK: [[CP_F_RESULT:%[0-9]+]] = apply [[CP_F]]<@opened([[N]]) CP>([[CP_ADDR]]) : $@convention(witness_method: CP) <τ_0_0 where τ_0_0 : CP> (@guaranteed τ_0_0) -> @owned τ_0_0
+// CHECK: [[RESULT_EXISTENTIAL:%[0-9]+]] = init_existential_ref [[CP_F_RESULT]] : $@opened([[N]]) CP : $@opened([[N]]) CP, $CP
+// CHECK: destroy_value [[RESULT_EXISTENTIAL]]
+func testExistentialDispatchClass(cp: CP) {
+ _ = cp.f()
+}
+
+@objc class ObjC {
+ @objc func method() -> Self { return self }
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self21testAnyObjectDispatch1oyyXl_tF : $@convention(thin) (@guaranteed AnyObject) -> () {
+func testAnyObjectDispatch(o: AnyObject) {
+ // CHECK: dynamic_method_br [[O_OBJ:%[0-9]+]] : $@opened({{.*}}) AnyObject, #ObjC.method!1.foreign, bb1, bb2
+
+ // CHECK: bb1([[METHOD:%[0-9]+]] : @trivial $@convention(objc_method) (@opened({{.*}}) AnyObject) -> @autoreleased AnyObject):
+ // CHECK: [[O_OBJ_COPY:%.*]] = copy_value [[O_OBJ]]
+ // CHECK: [[VAR_9:%[0-9]+]] = partial_apply [callee_guaranteed] [[METHOD]]([[O_OBJ_COPY]]) : $@convention(objc_method) (@opened({{.*}}) AnyObject) -> @autoreleased AnyObject
+ var _ = o.method
+}
+// CHECK: } // end sil function '$S12dynamic_self21testAnyObjectDispatch1oyyXl_tF'
+
+
+// <rdar://problem/16270889> Dispatch through ObjC metatypes.
+class ObjCInit {
+ dynamic required init() { }
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self12testObjCInit{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@thick ObjCInit.Type) -> ()
+func testObjCInit(meta: ObjCInit.Type) {
+// CHECK: bb0([[THICK_META:%[0-9]+]] : @trivial $@thick ObjCInit.Type):
+// CHECK: [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[THICK_META]] : $@thick ObjCInit.Type to $@objc_metatype ObjCInit.Type
+// CHECK: [[OBJ:%[0-9]+]] = alloc_ref_dynamic [objc] [[OBJC_META]] : $@objc_metatype ObjCInit.Type, $ObjCInit
+// CHECK: [[INIT:%[0-9]+]] = objc_method [[OBJ]] : $ObjCInit, #ObjCInit.init!initializer.1.foreign : (ObjCInit.Type) -> () -> ObjCInit, $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
+// CHECK: [[RESULT_OBJ:%[0-9]+]] = apply [[INIT]]([[OBJ]]) : $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
+// CHECK: [[RESULT:%[0-9]+]] = tuple ()
+// CHECK: return [[RESULT]] : $()
+ _ = meta.init()
+}
+
+class OptionalResult {
+ func foo() -> Self? { return self }
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self14OptionalResultC3fooACXDSgyF : $@convention(method) (@guaranteed OptionalResult) -> @owned Optional<OptionalResult> {
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $OptionalResult):
+// CHECK-NEXT: debug_value [[SELF]] : $OptionalResult
+// CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK-NEXT: [[T0:%.*]] = enum $Optional<OptionalResult>, #Optional.some!enumelt.1, [[SELF_COPY]] : $OptionalResult
+// CHECK-NEXT: return [[T0]] : $Optional<OptionalResult>
+// CHECK: } // end sil function '$S12dynamic_self14OptionalResultC3fooACXDSgyF'
+
+class OptionalResultInheritor : OptionalResult {
+ func bar() {}
+}
+
+func testOptionalResult(v : OptionalResultInheritor) {
+ v.foo()?.bar()
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self18testOptionalResult1vyAA0dE9InheritorC_tF : $@convention(thin) (@guaranteed OptionalResultInheritor) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $OptionalResultInheritor):
+// CHECK: [[CAST_ARG:%.*]] = upcast [[ARG]]
+// CHECK: [[T0:%.*]] = class_method [[CAST_ARG]] : $OptionalResult, #OptionalResult.foo!1 : (OptionalResult) -> () -> @dynamic_self OptionalResult?, $@convention(method) (@guaranteed OptionalResult) -> @owned Optional<OptionalResult>
+// CHECK-NEXT: [[RES:%.*]] = apply [[T0]]([[CAST_ARG]])
+// CHECK-NEXT: [[T4:%.*]] = unchecked_ref_cast [[RES]] : $Optional<OptionalResult> to $Optional<OptionalResultInheritor>
+
+func id<T>(_ t: T) -> T { return t }
+
+class Z {
+
+ required init() {}
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tF : $@convention(method) (Int, @guaranteed Z) -> @owned Z {
+ func testDynamicSelfCaptures(x: Int) -> Self {
+ // CHECK: bb0({{.*}}, [[SELF:%.*]] : @guaranteed $Z):
+
+ // Single capture of 'self' type
+
+ // CHECK: [[FN:%.*]] = function_ref @$S12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tFyycfU_ : $@convention(thin) (@guaranteed Z) -> ()
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Z
+ // CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]]([[SELF_COPY]])
+ let fn1 = { _ = self }
+ fn1()
+
+ // Capturing 'self', but it's not the last capture. Make sure it ends
+ // up at the end of the list anyway
+
+ // CHECK: [[FN:%.*]] = function_ref @$S12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tFyycfU0_ : $@convention(thin) (Int, @guaranteed Z) -> ()
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Z
+ // CHECK-NEXT: partial_apply [callee_guaranteed] [[FN]]({{.*}}, [[SELF_COPY]])
+ let fn2 = {
+ _ = self
+ _ = x
+ }
+ fn2()
+
+ // Capturing 'self' weak, so we have to pass in a metatype explicitly
+ // so that IRGen can recover metadata.
+
+ // CHECK: [[WEAK_SELF:%.*]] = alloc_box ${ var @sil_weak Optional<Z> }
+ // CHECK: [[FN:%.*]] = function_ref @$S12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tFyycfU1_ : $@convention(thin) (@guaranteed { var @sil_weak Optional<Z> }, @thick @dynamic_self Z.Type) -> ()
+ // CHECK: [[WEAK_SELF_COPY:%.*]] = copy_value [[WEAK_SELF]] : ${ var @sil_weak Optional<Z> }
+ // CHECK-NEXT: [[DYNAMIC_SELF:%.*]] = metatype $@thick @dynamic_self Z.Type
+ // CHECK: partial_apply [callee_guaranteed] [[FN]]([[WEAK_SELF_COPY]], [[DYNAMIC_SELF]]) : $@convention(thin) (@guaranteed { var @sil_weak Optional<Z> }, @thick @dynamic_self Z.Type) -> ()
+ let fn3 = {
+ [weak self] in
+ _ = self
+ }
+ fn3()
+
+ // Capturing a value with a complex type involving self
+
+ // CHECK: [[FN:%.*]] = function_ref @$S12dynamic_self1ZC23testDynamicSelfCaptures1xACXDSi_tFyycfU2_ : $@convention(thin) (@guaranteed (Z, Z), @thick @dynamic_self Z.Type) -> ()
+ let xx = (self, self)
+ let fn4 = {
+ _ = xx
+ }
+ fn4()
+
+ return self
+ }
+
+ // Capturing metatype of dynamic self
+ static func testStaticMethodDynamicSelfCaptures() -> Self {
+ let fn0 = { _ = self; _ = { _ = self } }
+ fn0()
+
+ let x = self
+ let fn1 = { _ = x; _ = { _ = x } }
+ fn1()
+
+ let xx = (self, self)
+ let fn2 = { _ = xx; _ = { _ = xx } }
+ fn2()
+
+ return self.init()
+ }
+
+ // Make sure the actual self value has the same lowered type as the
+ // substituted result of a generic function call
+ func testDynamicSelfSubstitution(_ b: Bool) -> Self {
+ return b ? self : id(self)
+ }
+
+ // Same for metatype of self
+ static func testStaticMethodDynamicSelfSubstitution(_ b: Bool) -> Self {
+ _ = (b ? self : id(self))
+ return self.init()
+ }
+}
+
+// Unbound reference to a method returning Self.
+
+class Factory {
+ required init() {}
+
+ func newInstance() -> Self { return self }
+ class func classNewInstance() -> Self { return self.init() }
+ static func staticNewInstance() -> Self { return self.init() }
+}
+
+// CHECK-LABEL: sil hidden @$S12dynamic_self22partialApplySelfReturn1c1tyAA7FactoryC_AFmtF : $@convention(thin) (@guaranteed Factory, @thick Factory.Type) -> ()
+func partialApplySelfReturn(c: Factory, t: Factory.Type) {
+ // CHECK: function_ref @$S12dynamic_self7FactoryC11newInstanceACXDyFTc : $@convention(thin) (@guaranteed Factory) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = c.newInstance
+ // CHECK: function_ref @$S12dynamic_self7FactoryC11newInstanceACXDyFTc : $@convention(thin) (@guaranteed Factory) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = Factory.newInstance
+ // CHECK: function_ref @$S12dynamic_self7FactoryC11newInstanceACXDyFTc : $@convention(thin) (@guaranteed Factory) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = t.newInstance
+ _ = type(of: c).newInstance
+
+ // CHECK: function_ref @$S12dynamic_self7FactoryC16classNewInstanceACXDyFZTc : $@convention(thin) (@thick Factory.Type) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = t.classNewInstance
+ // CHECK: function_ref @$S12dynamic_self7FactoryC16classNewInstanceACXDyFZTc : $@convention(thin) (@thick Factory.Type) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = type(of: c).classNewInstance
+ // CHECK: function_ref @$S12dynamic_self7FactoryC16classNewInstanceACXDyFZTc : $@convention(thin) (@thick Factory.Type) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = Factory.classNewInstance
+
+ // CHECK: function_ref @$S12dynamic_self7FactoryC17staticNewInstanceACXDyFZTc : $@convention(thin) (@thick Factory.Type) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = t.staticNewInstance
+ // CHECK: function_ref @$S12dynamic_self7FactoryC17staticNewInstanceACXDyFZTc : $@convention(thin) (@thick Factory.Type) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = type(of: c).staticNewInstance
+ // CHECK: function_ref @$S12dynamic_self7FactoryC17staticNewInstanceACXDyFZTc : $@convention(thin) (@thick Factory.Type) -> @owned @callee_guaranteed () -> @owned Factory
+ _ = Factory.staticNewInstance
+}
+
+class FactoryFactory {
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self07FactoryC0C11newInstanceACXDyFZ : $@convention(method) (@thick FactoryFactory.Type) -> @owned FactoryFactory
+ static func newInstance() -> Self {
+ // CHECK: bb0(%0 : @trivial $@thick FactoryFactory.Type):
+
+ // CHECK: [[DYNAMIC_SELF:%.*]] = unchecked_trivial_bit_cast %0 : $@thick FactoryFactory.Type to $@thick @dynamic_self FactoryFactory.Type
+ // CHECK: [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self FactoryFactory.Type.Type, [[DYNAMIC_SELF]] : $@thick @dynamic_self FactoryFactory.Type
+ // CHECK: [[ANY:%.*]] = init_existential_metatype [[METATYPE]] : $@thick @dynamic_self FactoryFactory.Type.Type, $@thick Any.Type
+ let _: Any.Type = type(of: self)
+
+ while true {}
+ }
+}
+
+// Super call to a method returning Self
+class Base {
+ required init() {}
+
+ func returnsSelf() -> Self {
+ return self
+ }
+
+ static func returnsSelfStatic() -> Self {
+ return self.init()
+ }
+}
+
+class Derived : Base {
+ // CHECK-LABEL: sil hidden @$S12dynamic_self7DerivedC9superCallyyF : $@convention(method) (@guaranteed Derived) -> ()
+ // CHECK: [[SELF:%.*]] = copy_value %0
+ // CHECK: [[SUPER:%.*]] = upcast [[SELF]] : $Derived to $Base
+ // CHECK: [[BORROWED_SUPER:%.*]] = begin_borrow [[SUPER]]
+ // CHECK: [[METHOD:%.*]] = function_ref @$S12dynamic_self4BaseC11returnsSelfACXDyF
+ // CHECK: apply [[METHOD]]([[BORROWED_SUPER]])
+ // CHECK: return
+ func superCall() {
+ _ = super.returnsSelf()
+ }
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self7DerivedC15superCallStaticyyFZ : $@convention(method) (@thick Derived.Type) -> ()
+ // CHECK: [[SUPER:%.*]] = upcast %0 : $@thick Derived.Type to $@thick Base.Type
+ // CHECK: [[METHOD:%.*]] = function_ref @$S12dynamic_self4BaseC17returnsSelfStaticACXDyFZ
+ // CHECK: apply [[METHOD]]([[SUPER]])
+ // CHECK: return
+ static func superCallStatic() {
+ _ = super.returnsSelfStatic()
+ }
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self7DerivedC32superCallFromMethodReturningSelfACXDyF : $@convention(method) (@guaranteed Derived) -> @owned Derived
+ // CHECK: [[SELF:%.*]] = copy_value %0
+ // CHECK: [[SUPER:%.*]] = upcast [[SELF]] : $Derived to $Base
+ // CHEcK: [[BORROWED_SUPER:%.*]] = begin_borrow [[SUPER]]
+ // CHECK: [[METHOD:%.*]] = function_ref @$S12dynamic_self4BaseC11returnsSelfACXDyF
+ // CHECK: apply [[METHOD]]([[BORROWED_SUPER]])
+ // CHECK: return
+ func superCallFromMethodReturningSelf() -> Self {
+ _ = super.returnsSelf()
+ return self
+ }
+
+ // CHECK-LABEL: sil hidden @$S12dynamic_self7DerivedC38superCallFromMethodReturningSelfStaticACXDyFZ : $@convention(method) (@thick Derived.Type) -> @owned Derived
+ // CHECK; [[DYNAMIC_SELF:%.*]] = unchecked_trivial_bit_cast %0 : $@thick Derived.Type to $@thick @synamic_self Derived.Type
+ // CHECK: [[SUPER:%.*]] = upcast [[DYNAMIC_SELF]] : $@thick @dynamic_self Derived.Type to $@thick Base.Type
+ // CHECK: [[METHOD:%.*]] = function_ref @$S12dynamic_self4BaseC17returnsSelfStaticACXDyFZ
+ // CHECK: apply [[METHOD]]([[SUPER]])
+ // CHECK: return
+ static func superCallFromMethodReturningSelfStatic() -> Self {
+ _ = super.returnsSelfStatic()
+ return self.init()
+ }
+}
+
+class Generic<T> {
+ // Examples where we have to add a special argument to capture Self's metadata
+ func t1() -> Self {
+ // CHECK-LABEL: sil private @$S12dynamic_self7GenericC2t1ACyxGXDyFAEXDSgycfU_ : $@convention(thin) <T> (@guaranteed <τ_0_0> { var @sil_weak Optional<Generic<τ_0_0>> } <T>, @thick @dynamic_self Generic<T>.Type) -> @owned Optional<Generic<T>>
+ _ = {[weak self] in self }
+ return self
+ }
+
+ func t2() -> Self {
+ // CHECK-LABEL: sil private @$S12dynamic_self7GenericC2t2ACyxGXDyFAEXD_AEXDtycfU_ : $@convention(thin) <T> (@guaranteed (Generic<T>, Generic<T>), @thick @dynamic_self Generic<T>.Type) -> (@owned Generic<T>, @owned Generic<T>)
+ let selves = (self, self)
+ _ = { selves }
+ return self
+ }
+
+ func t3() -> Self {
+ // CHECK-LABEL: sil private @$S12dynamic_self7GenericC2t3ACyxGXDyFAEXDycfU_ : $@convention(thin) <T> (@guaranteed @sil_unowned Generic<T>, @thick @dynamic_self Generic<T>.Type) -> @owned Generic<T>
+ _ = {[unowned self] in self }
+ return self
+ }
+}
+
+// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
+// CHECK: method #P.f!1: {{.*}} : @$S12dynamic_self1XCAA1PA2aDP1f{{[_0-9a-zA-Z]*}}FTW
+
+// CHECK-LABEL: sil_witness_table hidden X: CP module dynamic_self {
+// CHECK: method #CP.f!1: {{.*}} : @$S12dynamic_self1XCAA2CPA2aDP1f{{[_0-9a-zA-Z]*}}FTW
diff --git a/test/SILGen/plus_zero_enum.swift b/test/SILGen/plus_zero_enum.swift
new file mode 100644
index 0000000..53a818c
--- /dev/null
+++ b/test/SILGen/plus_zero_enum.swift
@@ -0,0 +1,215 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -emit-silgen -enable-sil-ownership -module-name Swift %s | %FileCheck %s
+
+precedencegroup AssignmentPrecedence { assignment: true }
+
+enum Optional<Wrapped> {
+ case none
+ case some(Wrapped)
+}
+
+enum Boolish {
+ case falsy
+ case truthy
+}
+
+// CHECK-LABEL: sil hidden @$Ss13Boolish_casesyyF
+func Boolish_cases() {
+ // CHECK: [[BOOLISH:%[0-9]+]] = metatype $@thin Boolish.Type
+ // CHECK-NEXT: [[FALSY:%[0-9]+]] = enum $Boolish, #Boolish.falsy!enumelt
+ _ = Boolish.falsy
+
+ // CHECK-NEXT: [[BOOLISH:%[0-9]+]] = metatype $@thin Boolish.Type
+ // CHECK-NEXT: [[TRUTHY:%[0-9]+]] = enum $Boolish, #Boolish.truthy!enumelt
+ _ = Boolish.truthy
+}
+
+struct Int {}
+
+enum Optionable {
+ case nought
+ case mere(Int)
+}
+
+// CHECK-LABEL: sil hidden @$Ss16Optionable_casesyySiF
+func Optionable_cases(_ x: Int) {
+
+ // CHECK: [[METATYPE:%.*]] = metatype $@thin Optionable.Type
+ // CHECK: [[FN:%.*]] = function_ref @$Ss10OptionableO4mereyABSicABmF
+ // CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
+ // CHECK-NEXT: destroy_value [[CTOR]]
+ _ = Optionable.mere
+
+ // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Optionable.Type
+ // CHECK-NEXT: [[RES:%.*]] = enum $Optionable, #Optionable.mere!enumelt.1, %0 : $Int
+ _ = Optionable.mere(x)
+}
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$Ss10OptionableO4mereyABSicABmF
+// CHECK: [[FN:%.*]] = function_ref @$Ss10OptionableO4mereyABSicABmF
+// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
+// CHECK-NEXT: return [[METHOD]]
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil shared [transparent] @$Ss10OptionableO4mereyABSicABmF
+// CHECK: [[RES:%.*]] = enum $Optionable, #Optionable.mere!enumelt.1, %0 : $Int
+// CHECK-NEXT: return [[RES]] : $Optionable
+// CHECK-NEXT: }
+
+protocol P {}
+struct S : P {}
+
+enum AddressOnly {
+ case nought
+ case mere(P)
+ case phantom(S)
+}
+
+// CHECK-LABEL: sil hidden @$Ss17AddressOnly_casesyys1SVF
+func AddressOnly_cases(_ s: S) {
+
+ // CHECK: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
+ // CHECK: [[FN:%.*]] = function_ref @$Ss11AddressOnlyO4mereyABs1P_pcABmF
+ // CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
+ // CHECK-NEXT: destroy_value [[CTOR]]
+ _ = AddressOnly.mere
+
+ // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
+ // CHECK-NEXT: [[NOUGHT:%.*]] = alloc_stack $AddressOnly
+ // CHECK-NEXT: inject_enum_addr [[NOUGHT]]
+ // CHECK-NEXT: destroy_addr [[NOUGHT]]
+ // CHECK-NEXT: dealloc_stack [[NOUGHT]]
+ _ = AddressOnly.nought
+
+ // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
+ // CHECK-NEXT: [[MERE:%.*]] = alloc_stack $AddressOnly
+ // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]]
+ // CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = init_existential_addr [[PAYLOAD]]
+ // CHECK-NEXT: store %0 to [trivial] [[PAYLOAD_ADDR]]
+ // CHECK-NEXT: inject_enum_addr [[MERE]]
+ // CHECK-NEXT: destroy_addr [[MERE]]
+ // CHECK-NEXT: dealloc_stack [[MERE]]
+ _ = AddressOnly.mere(s)
+
+ // Address-only enum vs loadable payload
+
+ // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
+ // CHECK-NEXT: [[PHANTOM:%.*]] = alloc_stack $AddressOnly
+ // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[PHANTOM]] : $*AddressOnly, #AddressOnly.phantom!enumelt.1
+ // CHECK-NEXT: store %0 to [trivial] [[PAYLOAD]]
+ // CHECK-NEXT: inject_enum_addr [[PHANTOM]] : $*AddressOnly, #AddressOnly.phantom!enumelt.1
+ // CHECK-NEXT: destroy_addr [[PHANTOM]]
+ // CHECK-NEXT: dealloc_stack [[PHANTOM]]
+
+ _ = AddressOnly.phantom(s)
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$Ss11AddressOnlyO4mereyABs1P_pcABmF
+// CHECK: [[FN:%.*]] = function_ref @$Ss11AddressOnlyO4mereyABs1P_pcABmF
+// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$Ss1P_ps11AddressOnlyOIegir_sAA_pACIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in P) -> @out AddressOnly) -> @out AddressOnly
+// CHECK-NEXT: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[METHOD]])
+// CHECK-NEXT: return [[CANONICAL_THUNK]] : $@callee_guaranteed (@in_guaranteed P) -> @out AddressOnly
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil shared [transparent] @$Ss11AddressOnlyO4mereyABs1P_pcABmF : $@convention
+// CHECK: bb0([[ARG0:%.*]] : @trivial $*AddressOnly, [[ARG1:%.*]] : @trivial $*P, [[ARG2:%.*]] : @trivial $@thin AddressOnly.Type):
+// CHECK: [[RET_DATA:%.*]] = init_enum_data_addr [[ARG0]] : $*AddressOnly, #AddressOnly.mere!enumelt.1
+// CHECK-NEXT: copy_addr [take] [[ARG1]] to [initialization] [[RET_DATA]] : $*P
+// CHECK-NEXT: inject_enum_addr [[ARG0]] : $*AddressOnly, #AddressOnly.mere!enumelt.1
+// CHECK: return
+// CHECK-NEXT: } // end sil function '$Ss11AddressOnlyO4mereyABs1P_pcABmF'
+
+enum PolyOptionable<T> {
+ case nought
+ case mere(T)
+}
+
+// CHECK-LABEL: sil hidden @$Ss20PolyOptionable_casesyyxlF
+func PolyOptionable_cases<T>(_ t: T) {
+
+// CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<T>.Type
+// CHECK-NEXT: [[NOUGHT:%.*]] = alloc_stack $PolyOptionable<T>
+// CHECK-NEXT: inject_enum_addr [[NOUGHT]]
+// CHECK-NEXT: destroy_addr [[NOUGHT]]
+// CHECK-NEXT: dealloc_stack [[NOUGHT]]
+ _ = PolyOptionable<T>.nought
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<T>.Type
+// CHECK-NEXT: [[MERE:%.*]] = alloc_stack $PolyOptionable<T>
+// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[MERE]]
+// CHECK-NEXT: copy_addr %0 to [initialization] [[PAYLOAD]]
+// CHECK-NEXT: inject_enum_addr [[MERE]]
+// CHECK-NEXT: destroy_addr [[MERE]]
+// CHECK-NEXT: dealloc_stack [[MERE]]
+
+ _ = PolyOptionable<T>.mere(t)
+
+// CHECK-NOT: destroy_addr %0
+// CHECK: return
+
+}
+
+// The substituted type is loadable and trivial here
+
+// CHECK-LABEL: sil hidden @$Ss32PolyOptionable_specialized_casesyySiF
+func PolyOptionable_specialized_cases(_ t: Int) {
+
+// CHECK: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<Int>.Type
+// CHECK-NEXT: [[NOUGHT:%.*]] = enum $PolyOptionable<Int>, #PolyOptionable.nought!enumelt
+ _ = PolyOptionable<Int>.nought
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin PolyOptionable<Int>.Type
+// CHECK-NEXT: [[NOUGHT:%.*]] = enum $PolyOptionable<Int>, #PolyOptionable.mere!enumelt.1, %0
+ _ = PolyOptionable<Int>.mere(t)
+
+// CHECK: return
+
+}
+
+
+// Regression test for a bug where temporary allocations created as a result of
+// tuple implosion were not deallocated in enum constructors.
+struct String { var ptr: Builtin.NativeObject }
+
+enum Foo { case A(P, String) }
+
+// Curry Thunk for Foo.A(_:)
+//
+// CHECK-LABEL: sil shared [transparent] [thunk] @$Ss3FooO1AyABs1P_p_SStcABmF
+// CHECK: [[FN:%.*]] = function_ref @$Ss3FooO1AyABs1P_p_SStcABmF
+// CHECK-NEXT: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]](%0)
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$Ss1P_pSSs3FooOIegixr_sAA_pSSACIegngr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed String, @guaranteed @callee_guaranteed (@in P, @owned String) -> @out Foo) -> @out Foo
+// CHECK-NEXT: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[METHOD]])
+// CHECK-NEXT: return [[CANONICAL_THUNK]]
+// CHECK-NEXT: }
+
+// Foo.A(_:)
+// CHECK-LABEL: sil shared [transparent] @$Ss3FooO1AyABs1P_p_SStcABmF
+// CHECK: bb0([[ARG0:%.*]] : @trivial $*Foo, [[ARG1:%.*]] : @trivial $*P, [[ARG2:%.*]] : @owned $String, [[ARG3:%.*]] : @trivial $@thin Foo.Type):
+// CHECK: [[PAYLOAD:%.*]] = init_enum_data_addr [[ARG0]] : $*Foo, #Foo.A!enumelt.1
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PAYLOAD]] : $*(P, String), 0
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PAYLOAD]] : $*(P, String), 1
+// CHECK-NEXT: copy_addr [take] [[ARG1]] to [initialization] [[LEFT]] : $*P
+// CHECK-NEXT: store [[ARG2]] to [init] [[RIGHT]]
+// CHECK-NEXT: inject_enum_addr [[ARG0]] : $*Foo, #Foo.A!enumelt.1
+// CHECK: return
+// CHECK-NEXT: } // end sil function '$Ss3FooO1AyABs1P_p_SStcABmF'
+
+func Foo_cases() {
+ _ = Foo.A
+}
+
+enum Indirect<T> {
+ indirect case payload((T, other: T))
+ case none
+}
+// CHECK-LABEL: sil{{.*}} @{{.*}}makeIndirectEnum{{.*}} : $@convention(thin) <T> (@in_guaranteed T) -> @owned Indirect<T>
+// CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (τ_0_0, other: τ_0_0) } <T>
+// CHECK: enum $Indirect<T>, #Indirect.payload!enumelt.1, [[BOX]] : $<τ_0_0> { var (τ_0_0, other: τ_0_0) } <T>
+func makeIndirectEnum<T>(_ payload: T) -> Indirect<T> {
+ return Indirect.payload((payload, other: payload))
+}
diff --git a/test/SILGen/plus_zero_enum_resilience.swift b/test/SILGen/plus_zero_enum_resilience.swift
new file mode 100644
index 0000000..7b5ac8a
--- /dev/null
+++ b/test/SILGen/plus_zero_enum_resilience.swift
@@ -0,0 +1,83 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_enum.swiftmodule -module-name=resilient_enum -I %t %S/../Inputs/resilient_enum.swift
+// RUN: %target-swift-frontend -I %t -enable-sil-ownership -emit-silgen -enable-resilience %s | %FileCheck %s
+
+import resilient_enum
+
+// Resilient enums are always address-only, and switches must include
+// a default case
+
+// CHECK-LABEL: sil hidden @$S15enum_resilience15resilientSwitchyy0c1_A06MediumOF : $@convention(thin) (@in_guaranteed Medium) -> ()
+// CHECK: [[BOX:%.*]] = alloc_stack $Medium
+// CHECK-NEXT: copy_addr %0 to [initialization] [[BOX]]
+// CHECK-NEXT: switch_enum_addr [[BOX]] : $*Medium, case #Medium.Paper!enumelt: bb1, case #Medium.Canvas!enumelt: bb2, case #Medium.Pamphlet!enumelt.1: bb3, case #Medium.Postcard!enumelt.1: bb4, default bb5
+// CHECK: bb1:
+// CHECK-NEXT: dealloc_stack [[BOX]]
+// CHECK-NEXT: br bb6
+// CHECK: bb2:
+// CHECK-NEXT: dealloc_stack [[BOX]]
+// CHECK-NEXT: br bb6
+// CHECK: bb3:
+// CHECK-NEXT: [[INDIRECT_ADDR:%.*]] = unchecked_take_enum_data_addr [[BOX]]
+// CHECK-NEXT: [[INDIRECT:%.*]] = load [take] [[INDIRECT_ADDR]]
+// CHECK-NEXT: [[PAYLOAD:%.*]] = project_box [[INDIRECT]]
+// CHECK-NEXT: destroy_value [[INDIRECT]]
+// CHECK-NEXT: dealloc_stack [[BOX]]
+// CHECK-NEXT: br bb6
+// CHECK: bb4:
+// CHECK-NEXT: [[PAYLOAD_ADDR:%.*]] = unchecked_take_enum_data_addr [[BOX]]
+// CHECK-NEXT: destroy_addr [[PAYLOAD_ADDR]]
+// CHECK-NEXT: dealloc_stack [[BOX]]
+// CHECK-NEXT: br bb6
+// CHECK: bb5:
+// CHECK-NEXT: builtin "int_trap"()
+// CHECK-NEXT: unreachable
+// CHECK: bb6:
+// CHECK-NOT: destroy_addr %0
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]]
+
+func resilientSwitch(_ m: Medium) {
+ switch m {
+ case .Paper: ()
+ case .Canvas: ()
+ case .Pamphlet: ()
+ case .Postcard: ()
+ }
+}
+
+// Indirect enums are still address-only, because the discriminator is stored
+// as part of the value, so we cannot resiliently make assumptions about the
+// enum's size
+
+// CHECK-LABEL: sil hidden @$S15enum_resilience21indirectResilientEnumyy010resilient_A016IndirectApproachOF : $@convention(thin) (@in_guaranteed IndirectApproach) -> ()
+func indirectResilientEnum(_ ia: IndirectApproach) {}
+
+public enum MyResilientEnum {
+ case kevin
+ case loki
+}
+
+// CHECK-LABEL: sil @$S15enum_resilience15resilientSwitchyyAA15MyResilientEnumOF : $@convention(thin) (@in_guaranteed MyResilientEnum) -> ()
+// CHECK: switch_enum_addr %2 : $*MyResilientEnum, case #MyResilientEnum.kevin!enumelt: bb1, case #MyResilientEnum.loki!enumelt: bb2 //
+// CHECK: return
+public func resilientSwitch(_ e: MyResilientEnum) {
+ switch e {
+ case .kevin: ()
+ case .loki: ()
+ }
+}
+
+// Inlineable functions must lower the switch as if it came from outside the module
+
+// CHECK-LABEL: sil [serialized] @$S15enum_resilience16inlineableSwitchyyAA15MyResilientEnumOF : $@convention(thin) (@in_guaranteed MyResilientEnum) -> ()
+// CHECK: switch_enum_addr %2 : $*MyResilientEnum, case #MyResilientEnum.kevin!enumelt: bb1, case #MyResilientEnum.loki!enumelt: bb2, default bb3
+// CHECK: return
+@_inlineable public func inlineableSwitch(_ e: MyResilientEnum) {
+ switch e {
+ case .kevin: ()
+ case .loki: ()
+ }
+}
diff --git a/test/SILGen/plus_zero_erasure_reabstraction.swift b/test/SILGen/plus_zero_erasure_reabstraction.swift
new file mode 100644
index 0000000..1c2c0eb
--- /dev/null
+++ b/test/SILGen/plus_zero_erasure_reabstraction.swift
@@ -0,0 +1,20 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct Foo {}
+class Bar {}
+
+// CHECK: [[CONCRETE:%.*]] = init_existential_addr [[EXISTENTIAL:%.*]] : $*Any, $Foo.Type
+// CHECK: [[METATYPE:%.*]] = metatype $@thick Foo.Type
+// CHECK: store [[METATYPE]] to [trivial] [[CONCRETE]] : $*@thick Foo.Type
+let x: Any = Foo.self
+
+
+// CHECK: [[CONCRETE:%.*]] = init_existential_addr [[EXISTENTIAL:%.*]] : $*Any, $() -> ()
+// CHECK: [[CLOSURE:%.*]] = function_ref
+// CHECK: [[CLOSURE_THICK:%.*]] = thin_to_thick_function [[CLOSURE]]
+// CHECK: [[REABSTRACTION_THUNK:%.*]] = function_ref @$SIeg_ytytIegnr_TR
+// CHECK: [[CLOSURE_REABSTRACTED:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTION_THUNK]]([[CLOSURE_THICK]])
+// CHECK: store [[CLOSURE_REABSTRACTED]] to [init] [[CONCRETE]]
+let y: Any = {() -> () in ()}
+
diff --git a/test/SILGen/plus_zero_existential_erasure.swift b/test/SILGen/plus_zero_existential_erasure.swift
new file mode 100644
index 0000000..a60024f
--- /dev/null
+++ b/test/SILGen/plus_zero_existential_erasure.swift
@@ -0,0 +1,129 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol P {
+ func downgrade(_ m68k: Bool) -> Self
+ func upgrade() throws -> Self
+}
+protocol Q {}
+
+struct X: P, Q {
+ func downgrade(_ m68k: Bool) -> X {
+ return self
+ }
+
+ func upgrade() throws -> X {
+ return self
+ }
+}
+
+func makePQ() -> P & Q { return X() }
+
+func useP(_ x: P) { }
+
+func throwingFunc() throws -> Bool { return true }
+
+// CHECK-LABEL: sil hidden @$S19existential_erasure5PQtoPyyF : $@convention(thin) () -> () {
+func PQtoP() {
+ // CHECK: [[PQ_PAYLOAD:%.*]] = open_existential_addr immutable_access [[PQ:%.*]] : $*P & Q to $*[[OPENED_TYPE:@opened(.*) P & Q]]
+ // CHECK: [[P_PAYLOAD:%.*]] = init_existential_addr [[P:%.*]] : $*P, $[[OPENED_TYPE]]
+ // CHECK: copy_addr [[PQ_PAYLOAD]] to [initialization] [[P_PAYLOAD]]
+ // CHECK: destroy_addr [[PQ]]
+ // CHECK-NOT: destroy_addr [[P]]
+ // CHECK-NOT: destroy_addr [[P_PAYLOAD]]
+ // CHECK-NOT: deinit_existential_addr [[PQ]]
+ // CHECK-NOT: destroy_addr [[PQ_PAYLOAD]]
+ useP(makePQ())
+}
+
+// Make sure uninitialized existentials are properly deallocated when we
+// have an early return.
+
+// CHECK-LABEL: sil hidden @$S19existential_erasure19openExistentialToP1yyAA1P_pKF
+func openExistentialToP1(_ p: P) throws {
+// CHECK: bb0(%0 : @trivial $*P):
+// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*[[OPEN_TYPE:@opened\(.*\) P]]
+// CHECK: [[RESULT:%.*]] = alloc_stack $P
+// CHECK: [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*P, $[[OPEN_TYPE]]
+// CHECK: [[FUNC:%.*]] = function_ref @$S19existential_erasure12throwingFuncSbyKF
+// CHECK: try_apply [[FUNC]]()
+//
+// CHECK: bb1([[SUCCESS:%.*]] : @trivial $Bool):
+// CHECK: [[METHOD:%.*]] = witness_method $[[OPEN_TYPE]], #P.downgrade!1 : {{.*}}, [[OPEN]]
+// CHECK: apply [[METHOD]]<[[OPEN_TYPE]]>([[RESULT_ADDR]], [[SUCCESS]], [[OPEN]])
+// CHECK: dealloc_stack [[RESULT]]
+// CHECK: return
+//
+// CHECK: bb2([[FAILURE:%.*]] : @owned $Error):
+// CHECK: deinit_existential_addr [[RESULT]]
+// CHECK: dealloc_stack [[RESULT]]
+// CHECK: throw [[FAILURE]]
+//
+ try useP(p.downgrade(throwingFunc()))
+}
+
+// CHECK-LABEL: sil hidden @$S19existential_erasure19openExistentialToP2yyAA1P_pKF
+func openExistentialToP2(_ p: P) throws {
+// CHECK: bb0(%0 : @trivial $*P):
+// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access %0 : $*P to $*[[OPEN_TYPE:@opened\(.*\) P]]
+// CHECK: [[RESULT:%.*]] = alloc_stack $P
+// CHECK: [[RESULT_ADDR:%.*]] = init_existential_addr [[RESULT]] : $*P, $[[OPEN_TYPE]]
+// CHECK: [[METHOD:%.*]] = witness_method $[[OPEN_TYPE]], #P.upgrade!1 : {{.*}}, [[OPEN]]
+// CHECK: try_apply [[METHOD]]<[[OPEN_TYPE]]>([[RESULT_ADDR]], [[OPEN]])
+//
+// CHECK: bb1
+// CHECK: dealloc_stack [[RESULT]]
+// CHECK: return
+//
+// CHECK: bb2([[FAILURE:%.*]]: @owned $Error):
+// CHECK: deinit_existential_addr [[RESULT]]
+// CHECK: dealloc_stack [[RESULT]]
+// CHECK: throw [[FAILURE]]
+//
+ try useP(p.upgrade())
+}
+
+// Same as above but for boxed existentials
+
+extension Error {
+ func returnOrThrowSelf() throws -> Self {
+ throw self
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S19existential_erasure12errorHandlerys5Error_psAC_pKF
+func errorHandler(_ e: Error) throws -> Error {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Error):
+// CHECK: debug_value [[ARG]] : $Error
+// CHECK: [[OPEN:%.*]] = open_existential_box [[ARG]] : $Error to $*[[OPEN_TYPE:@opened\(.*\) Error]]
+// CHECK: [[RESULT:%.*]] = alloc_existential_box $Error, $[[OPEN_TYPE]]
+// CHECK: [[ADDR:%.*]] = project_existential_box $[[OPEN_TYPE]] in [[RESULT]] : $Error
+// CHECK: [[FUNC:%.*]] = function_ref @$Ss5ErrorP19existential_erasureE17returnOrThrowSelf{{[_0-9a-zA-Z]*}}F
+// CHECK: try_apply [[FUNC]]<[[OPEN_TYPE]]>([[ADDR]], [[OPEN]])
+//
+// CHECK: bb1
+// CHECK: return [[RESULT]] : $Error
+//
+// CHECK: bb2([[FAILURE:%.*]] : @owned $Error):
+// CHECK: dealloc_existential_box [[RESULT]]
+// CHECK: throw [[FAILURE]] : $Error
+//
+ return try e.returnOrThrowSelf()
+}
+
+
+// rdar://problem/22003864 -- SIL verifier crash when init_existential_addr
+// references dynamic Self type
+class EraseDynamicSelf {
+ required init() {}
+
+// CHECK-LABEL: sil hidden @$S19existential_erasure16EraseDynamicSelfC7factoryACXDyFZ : $@convention(method) (@thick EraseDynamicSelf.Type) -> @owned EraseDynamicSelf
+// CHECK: [[ANY:%.*]] = alloc_stack $Any
+// CHECK: init_existential_addr [[ANY]] : $*Any, $@dynamic_self EraseDynamicSelf
+//
+ class func factory() -> Self {
+ let instance = self.init()
+ let _: Any = instance
+ return instance
+ }
+}
diff --git a/test/SILGen/plus_zero_expressions.swift b/test/SILGen/plus_zero_expressions.swift
new file mode 100644
index 0000000..293c8fe
--- /dev/null
+++ b/test/SILGen/plus_zero_expressions.swift
@@ -0,0 +1,737 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: echo "public var x = Int()" | %target-swift-frontend -module-name FooBar -emit-module -o %t -
+// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -enable-sil-ownership %s -I%t -disable-access-control | %FileCheck %s
+
+import Swift
+import FooBar
+
+struct SillyString : _ExpressibleByBuiltinStringLiteral, ExpressibleByStringLiteral {
+ init(_builtinUnicodeScalarLiteral value: Builtin.Int32) {}
+
+ init(unicodeScalarLiteral value: SillyString) { }
+
+ init(
+ _builtinExtendedGraphemeClusterLiteral start: Builtin.RawPointer,
+ utf8CodeUnitCount: Builtin.Word,
+ isASCII: Builtin.Int1
+ ) {
+ }
+
+ init(extendedGraphemeClusterLiteral value: SillyString) { }
+
+ init(
+ _builtinStringLiteral start: Builtin.RawPointer,
+ utf8CodeUnitCount: Builtin.Word,
+ isASCII: Builtin.Int1) {
+ }
+
+ init(stringLiteral value: SillyString) { }
+}
+
+struct SillyUTF16String : _ExpressibleByBuiltinUTF16StringLiteral, ExpressibleByStringLiteral {
+ init(_builtinUnicodeScalarLiteral value: Builtin.Int32) { }
+
+ init(unicodeScalarLiteral value: SillyString) { }
+
+ init(
+ _builtinExtendedGraphemeClusterLiteral start: Builtin.RawPointer,
+ utf8CodeUnitCount: Builtin.Word,
+ isASCII: Builtin.Int1
+ ) {
+ }
+
+ init(extendedGraphemeClusterLiteral value: SillyString) { }
+
+ init(
+ _builtinStringLiteral start: Builtin.RawPointer,
+ utf8CodeUnitCount: Builtin.Word,
+ isASCII: Builtin.Int1
+ ) { }
+
+ init(
+ _builtinUTF16StringLiteral start: Builtin.RawPointer,
+ utf16CodeUnitCount: Builtin.Word
+ ) {
+ }
+
+ init(stringLiteral value: SillyUTF16String) { }
+}
+
+struct SillyConstUTF16String : _ExpressibleByBuiltinConstUTF16StringLiteral, ExpressibleByStringLiteral {
+ init(_builtinUnicodeScalarLiteral value: Builtin.Int32) { }
+
+ init(unicodeScalarLiteral value: SillyString) { }
+
+ init(
+ _builtinExtendedGraphemeClusterLiteral start: Builtin.RawPointer,
+ utf8CodeUnitCount: Builtin.Word,
+ isASCII: Builtin.Int1
+ ) {
+ }
+
+ init(extendedGraphemeClusterLiteral value: SillyString) { }
+
+ init( _builtinConstStringLiteral start: Builtin.RawPointer) { }
+
+ init( _builtinConstUTF16StringLiteral start: Builtin.RawPointer) { }
+
+ init(stringLiteral value: SillyUTF16String) { }
+}
+
+func literals() {
+ var a = 1
+ var b = 1.25
+ var d = "foö"
+ var e:SillyString = "foo"
+
+ var f:SillyConstUTF16String = "foobar"
+ var non_ascii:SillyConstUTF16String = "foobarö"
+}
+// CHECK-LABEL: sil hidden @$S11expressions8literalsyyF
+// CHECK: integer_literal $Builtin.Int2048, 1
+// CHECK: float_literal $Builtin.FPIEEE{{64|80}}, {{0x3FF4000000000000|0x3FFFA000000000000000}}
+// CHECK: string_literal utf16 "foö"
+// CHECK: string_literal utf8 "foo"
+// CHECK: [[CONST_STRING_LIT:%.*]] = const_string_literal utf8 "foobar"
+// CHECK: [[METATYPE:%.*]] = metatype $@thin SillyConstUTF16String.Type
+// CHECK: [[FUN:%.*]] = function_ref @$S11expressions21SillyConstUTF16StringV08_builtincE7LiteralACBp_tcfC : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
+// CHECK: apply [[FUN]]([[CONST_STRING_LIT]], [[METATYPE]]) : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
+// CHECK: [[CONST_UTF16STRING_LIT:%.*]] = const_string_literal utf16 "foobarö"
+// CHECK: [[FUN:%.*]] = function_ref @$S11expressions21SillyConstUTF16StringV08_builtincdE7LiteralACBp_tcfC : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
+// CHECK: apply [[FUN]]([[CONST_UTF16STRING_LIT]], {{.*}}) : $@convention(method) (Builtin.RawPointer, @thin SillyConstUTF16String.Type) -> SillyConstUTF16String
+
+func bar(_ x: Int) {}
+func bar(_ x: Int, _ y: Int) {}
+
+func call_one() {
+ bar(42);
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions8call_oneyyF
+// CHECK: [[FORTYTWO:%[0-9]+]] = integer_literal {{.*}} 42
+// CHECK: [[FORTYTWO_CONVERTED:%[0-9]+]] = apply {{.*}}([[FORTYTWO]], {{.*}})
+// CHECK: [[BAR:%[0-9]+]] = function_ref @$S11expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int) -> ()
+// CHECK: apply [[BAR]]([[FORTYTWO_CONVERTED]])
+
+func call_two() {
+ bar(42, 219)
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions8call_twoyyF
+// CHECK: [[FORTYTWO:%[0-9]+]] = integer_literal {{.*}} 42
+// CHECK: [[FORTYTWO_CONVERTED:%[0-9]+]] = apply {{.*}}([[FORTYTWO]], {{.*}})
+// CHECK: [[TWONINETEEN:%[0-9]+]] = integer_literal {{.*}} 219
+// CHECK: [[TWONINETEEN_CONVERTED:%[0-9]+]] = apply {{.*}}([[TWONINETEEN]], {{.*}})
+// CHECK: [[BAR:%[0-9]+]] = function_ref @$S11expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Int) -> ()
+// CHECK: apply [[BAR]]([[FORTYTWO_CONVERTED]], [[TWONINETEEN_CONVERTED]])
+
+func tuples() {
+ bar((4, 5).1)
+
+ var T1 : (a: Int16, b: Int) = (b : 42, a : 777)
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions6tuplesyyF
+
+
+class C {
+ var chi:Int
+ init() {
+ chi = 219
+ }
+ init(x:Int) {
+ chi = x
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions7classesyyF
+func classes() {
+ // CHECK: function_ref @$S11expressions1CC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick C.Type) -> @owned C
+ var a = C()
+ // CHECK: function_ref @$S11expressions1CC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Int, @thick C.Type) -> @owned C
+ var b = C(x: 0)
+}
+
+struct S {
+ var x:Int
+ init() {
+ x = 219
+ }
+ init(x: Int) {
+ self.x = x
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions7structsyyF
+func structs() {
+ // CHECK: function_ref @$S11expressions1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin S.Type) -> S
+ var a = S()
+ // CHECK: function_ref @$S11expressions1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Int, @thin S.Type) -> S
+ var b = S(x: 0)
+}
+
+
+func inoutcallee(_ x: inout Int) {}
+func address_of_expr() {
+ var x: Int = 4
+ inoutcallee(&x)
+}
+
+
+
+func identity<T>(_ x: T) -> T {}
+
+struct SomeStruct {
+ mutating
+ func a() {}
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions5callsyyF
+// CHECK: [[METHOD:%[0-9]+]] = function_ref @$S11expressions10SomeStructV1a{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout SomeStruct) -> ()
+// CHECK: apply [[METHOD]]({{.*}})
+func calls() {
+ var a : SomeStruct
+ a.a()
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions11module_path{{[_0-9a-zA-Z]*}}F
+func module_path() -> Int {
+ return FooBar.x
+ // CHECK: [[x_GET:%[0-9]+]] = function_ref @$S6FooBar1xSivau
+ // CHECK-NEXT: apply [[x_GET]]()
+}
+
+func default_args(_ x: Int, y: Int = 219, z: Int = 20721) {}
+
+// CHECK-LABEL: sil hidden @$S11expressions19call_default_args_1{{[_0-9a-zA-Z]*}}F
+func call_default_args_1(_ x: Int) {
+ default_args(x)
+ // CHECK: [[YFUNC:%[0-9]+]] = function_ref @$S11expressions12default_args{{[_0-9a-zA-Z]*}}A0_
+ // CHECK: [[Y:%[0-9]+]] = apply [[YFUNC]]()
+ // CHECK: [[ZFUNC:%[0-9]+]] = function_ref @$S11expressions12default_args{{[_0-9a-zA-Z]*}}A1_
+ // CHECK: [[Z:%[0-9]+]] = apply [[ZFUNC]]()
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S11expressions12default_args{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC]]({{.*}}, [[Y]], [[Z]])
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions19call_default_args_2{{[_0-9a-zA-Z]*}}F
+func call_default_args_2(_ x: Int, z: Int) {
+ default_args(x, z:z)
+ // CHECK: [[DEFFN:%[0-9]+]] = function_ref @$S11expressions12default_args{{[_0-9a-zA-Z]*}}A0_
+ // CHECK-NEXT: [[C219:%[0-9]+]] = apply [[DEFFN]]()
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S11expressions12default_args{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply [[FUNC]]({{.*}}, [[C219]], {{.*}})
+}
+
+struct Generic<T> {
+ var mono_member:Int
+ var typevar_member:T
+
+ // CHECK-LABEL: sil hidden @$S11expressions7GenericV13type_variable{{[_0-9a-zA-Z]*}}F
+ mutating
+ func type_variable() -> T.Type {
+ return T.self
+ // CHECK: [[METATYPE:%[0-9]+]] = metatype $@thick T.Type
+ // CHECK: return [[METATYPE]]
+ }
+
+ // CHECK-LABEL: sil hidden @$S11expressions7GenericV19copy_typevar_member{{[_0-9a-zA-Z]*}}F
+ mutating
+ func copy_typevar_member(_ x: Generic<T>) {
+ typevar_member = x.typevar_member
+ }
+
+ // CHECK-LABEL: sil hidden @$S11expressions7GenericV12class_method{{[_0-9a-zA-Z]*}}FZ
+ static func class_method() {}
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions18generic_member_ref{{[_0-9a-zA-Z]*}}F
+func generic_member_ref<T>(_ x: Generic<T>) -> Int {
+ // CHECK: bb0([[XADDR:%[0-9]+]] : @trivial $*Generic<T>):
+ return x.mono_member
+ // CHECK: [[MEMBER_ADDR:%[0-9]+]] = struct_element_addr {{.*}}, #Generic.mono_member
+ // CHECK: load [trivial] [[MEMBER_ADDR]]
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions24bound_generic_member_ref{{[_0-9a-zA-Z]*}}F
+func bound_generic_member_ref(_ x: Generic<UnicodeScalar>) -> Int {
+ var x = x
+ // CHECK: bb0([[XADDR:%[0-9]+]] : @trivial $Generic<Unicode.Scalar>):
+ return x.mono_member
+ // CHECK: [[MEMBER_ADDR:%[0-9]+]] = struct_element_addr {{.*}}, #Generic.mono_member
+ // CHECK: load [trivial] [[MEMBER_ADDR]]
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions6coerce{{[_0-9a-zA-Z]*}}F
+func coerce(_ x: Int32) -> Int64 {
+ return 0
+}
+
+class B {
+}
+
+class D : B {
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions8downcast{{[_0-9a-zA-Z]*}}F
+func downcast(_ x: B) -> D {
+ return x as! D
+ // CHECK: unconditional_checked_cast %{{[0-9]+}} : {{.*}} to $D
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions6upcast{{[_0-9a-zA-Z]*}}F
+func upcast(_ x: D) -> B {
+ return x
+ // CHECK: upcast %{{[0-9]+}} : ${{.*}} to $B
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions14generic_upcast{{[_0-9a-zA-Z]*}}F
+func generic_upcast<T : B>(_ x: T) -> B {
+ return x
+ // CHECK: upcast %{{.*}} to $B
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions16generic_downcast{{[_0-9a-zA-Z]*}}F
+func generic_downcast<T : B>(_ x: T, y: B) -> T {
+ return y as! T
+ // CHECK: unconditional_checked_cast %{{[0-9]+}} : {{.*}} to $T
+ // CHECK: return
+}
+
+// TODO: generic_downcast
+
+// CHECK-LABEL: sil hidden @$S11expressions15metatype_upcast{{[_0-9a-zA-Z]*}}F
+func metatype_upcast() -> B.Type {
+ return D.self
+ // CHECK: metatype $@thick D
+ // CHECK-NEXT: upcast
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions19interpolated_string{{[_0-9a-zA-Z]*}}F
+func interpolated_string(_ x: Int, y: String) -> String {
+ return "The \(x) Million Dollar \(y)"
+}
+
+protocol Runcible {
+ associatedtype U
+ var free:Int { get }
+ var associated:U { get }
+
+ func free_method() -> Int
+ mutating func associated_method() -> U.Type
+ static func static_method()
+}
+
+protocol Mincible {
+ var free:Int { get }
+ func free_method() -> Int
+ static func static_method()
+}
+
+protocol Bendable { }
+protocol Wibbleable { }
+
+// CHECK-LABEL: sil hidden @$S11expressions20archetype_member_ref{{[_0-9a-zA-Z]*}}F
+func archetype_member_ref<T : Runcible>(_ x: T) {
+ var x = x
+ x.free_method()
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X:%.*]]
+ // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $T
+ // CHECK-NEXT: copy_addr [[READ]] to [initialization] [[TEMP]]
+ // CHECK-NEXT: end_access [[READ]]
+ // CHECK-NEXT: witness_method $T, #Runcible.free_method!1
+ // CHECK-NEXT: apply
+ // CHECK-NEXT: destroy_addr [[TEMP]]
+ var u = x.associated_method()
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown]
+ // CHECK-NEXT: witness_method $T, #Runcible.associated_method!1
+ // CHECK-NEXT: apply
+ T.static_method()
+ // CHECK: metatype $@thick T.Type
+ // CHECK-NEXT: witness_method $T, #Runcible.static_method!1
+ // CHECK-NEXT: apply
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions22existential_member_ref{{[_0-9a-zA-Z]*}}F
+func existential_member_ref(_ x: Mincible) {
+ x.free_method()
+ // CHECK: open_existential_addr
+ // CHECK-NEXT: witness_method
+ // CHECK-NEXT: apply
+}
+
+/*TODO archetype and existential properties and subscripts
+func archetype_property_ref<T : Runcible>(_ x: T) -> (Int, T.U) {
+ x.free = x.free_method()
+ x.associated = x.associated_method()
+ return (x.free, x.associated)
+}
+
+func existential_property_ref<T : Runcible>(_ x: T) -> Int {
+ x.free = x.free_method()
+ return x.free
+}
+
+also archetype/existential subscripts
+*/
+
+struct Spoon : Runcible, Mincible {
+ typealias U = Float
+ var free: Int { return 4 }
+ var associated: Float { return 12 }
+
+ func free_method() -> Int {}
+ func associated_method() -> Float.Type {}
+ static func static_method() {}
+}
+
+struct Hat<T> : Runcible {
+ typealias U = [T]
+ var free: Int { return 1 }
+ var associated: U { get {} }
+
+ func free_method() -> Int {}
+
+ // CHECK-LABEL: sil hidden @$S11expressions3HatV17associated_method{{[_0-9a-zA-Z]*}}F
+ mutating
+ func associated_method() -> U.Type {
+ return U.self
+ // CHECK: [[META:%[0-9]+]] = metatype $@thin Array<T>.Type
+ // CHECK: return [[META]]
+ }
+
+ static func static_method() {}
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions7erasure{{[_0-9a-zA-Z]*}}F
+func erasure(_ x: Spoon) -> Mincible {
+ return x
+ // CHECK: init_existential_addr
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions19declref_to_metatypeAA5SpoonVmyF
+func declref_to_metatype() -> Spoon.Type {
+ return Spoon.self
+ // CHECK: metatype $@thin Spoon.Type
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions27declref_to_generic_metatype{{[_0-9a-zA-Z]*}}F
+func declref_to_generic_metatype() -> Generic<UnicodeScalar>.Type {
+ // FIXME parsing of T<U> in expression context
+ typealias GenericChar = Generic<UnicodeScalar>
+ return GenericChar.self
+ // CHECK: metatype $@thin Generic<Unicode.Scalar>.Type
+}
+
+func int(_ x: Int) {}
+func float(_ x: Float) {}
+
+func tuple() -> (Int, Float) { return (1, 1.0) }
+
+// CHECK-LABEL: sil hidden @$S11expressions13tuple_element{{[_0-9a-zA-Z]*}}F
+func tuple_element(_ x: (Int, Float)) {
+ var x = x
+ // CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Float) }
+ // CHECK: [[PB:%.*]] = project_box [[XADDR]]
+
+ int(x.0)
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: tuple_element_addr [[READ]] : {{.*}}, 0
+ // CHECK: apply
+
+ float(x.1)
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: tuple_element_addr [[READ]] : {{.*}}, 1
+ // CHECK: apply
+
+ int(tuple().0)
+ // CHECK: [[ZERO:%.*]] = tuple_extract {{%.*}} : {{.*}}, 0
+ // CHECK: apply {{.*}}([[ZERO]])
+
+ float(tuple().1)
+ // CHECK: [[ONE:%.*]] = tuple_extract {{%.*}} : {{.*}}, 1
+ // CHECK: apply {{.*}}([[ONE]])
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions10containers{{[_0-9a-zA-Z]*}}F
+func containers() -> ([Int], Dictionary<String, Int>) {
+ return ([1, 2, 3], ["Ankeny": 1, "Burnside": 2, "Couch": 3])
+}
+
+// CHECK-LABEL: sil hidden @$S11expressions7if_expr{{[_0-9a-zA-Z]*}}F
+func if_expr(_ a: Bool, b: Bool, x: Int, y: Int, z: Int) -> Int {
+ var a = a
+ var b = b
+ var x = x
+ var y = y
+ var z = z
+ // CHECK: bb0({{.*}}):
+ // CHECK: [[AB:%[0-9]+]] = alloc_box ${ var Bool }
+ // CHECK: [[PBA:%.*]] = project_box [[AB]]
+ // CHECK: [[BB:%[0-9]+]] = alloc_box ${ var Bool }
+ // CHECK: [[PBB:%.*]] = project_box [[BB]]
+ // CHECK: [[XB:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PBX:%.*]] = project_box [[XB]]
+ // CHECK: [[YB:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PBY:%.*]] = project_box [[YB]]
+ // CHECK: [[ZB:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PBZ:%.*]] = project_box [[ZB]]
+
+ return a
+ ? x
+ : b
+ ? y
+ : z
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBA]]
+ // CHECK: [[A:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[ACOND:%[0-9]+]] = apply {{.*}}([[A]])
+ // CHECK: cond_br [[ACOND]], [[IF_A:bb[0-9]+]], [[ELSE_A:bb[0-9]+]]
+ // CHECK: [[IF_A]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBX]]
+ // CHECK: [[XVAL:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: br [[CONT_A:bb[0-9]+]]([[XVAL]] : $Int)
+ // CHECK: [[ELSE_A]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBB]]
+ // CHECK: [[B:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[BCOND:%[0-9]+]] = apply {{.*}}([[B]])
+ // CHECK: cond_br [[BCOND]], [[IF_B:bb[0-9]+]], [[ELSE_B:bb[0-9]+]]
+ // CHECK: [[IF_B]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBY]]
+ // CHECK: [[YVAL:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: br [[CONT_B:bb[0-9]+]]([[YVAL]] : $Int)
+ // CHECK: [[ELSE_B]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBZ]]
+ // CHECK: [[ZVAL:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: br [[CONT_B:bb[0-9]+]]([[ZVAL]] : $Int)
+ // CHECK: [[CONT_B]]([[B_RES:%[0-9]+]] : @trivial $Int):
+ // CHECK: br [[CONT_A:bb[0-9]+]]([[B_RES]] : $Int)
+ // CHECK: [[CONT_A]]([[A_RES:%[0-9]+]] : @trivial $Int):
+ // CHECK: return [[A_RES]]
+}
+
+
+// Test that magic identifiers expand properly. We test #column here because
+// it isn't affected as this testcase slides up and down the file over time.
+func magic_identifier_expansion(_ a: Int = #column) {
+ // CHECK-LABEL: sil hidden @{{.*}}magic_identifier_expansion
+
+ // This should expand to the column number of the first _.
+ var tmp = #column
+ // CHECK: integer_literal $Builtin.Int2048, 13
+
+ // This should expand to the column number of the (, not to the column number
+ // of #column in the default argument list of this function.
+ // rdar://14315674
+ magic_identifier_expansion()
+ // CHECK: integer_literal $Builtin.Int2048, 29
+}
+
+func print_string() {
+ // CHECK-LABEL: print_string
+ var str = "\u{08}\u{09}\thello\r\n\0wörld\u{1e}\u{7f}"
+ // CHECK: string_literal utf16 "\u{08}\t\thello\r\n\0wörld\u{1E}\u{7F}"
+}
+
+
+
+// Test that we can silgen superclass calls that go farther than the immediate
+// superclass.
+class Super1 {
+ func funge() {}
+}
+class Super2 : Super1 {}
+class Super3 : Super2 {
+ override func funge() {
+ super.funge()
+ }
+}
+
+// <rdar://problem/16880240> SILGen crash assigning to _
+func testDiscardLValue() {
+ var a = 42
+ _ = a
+}
+
+
+func dynamicTypePlusZero(_ a: Super1) -> Super1.Type {
+ return type(of: a)
+}
+// CHECK-LABEL: dynamicTypePlusZero
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Super1):
+// CHECK-NOT: copy_value
+// CHECK: value_metatype $@thick Super1.Type, [[ARG]] : $Super1
+
+struct NonTrivialStruct {
+ var c : Super1
+ var x: NonTrivialStruct? {
+ get { return nil }
+ set {}
+ }
+}
+
+func dontEmitIgnoredLoadExpr(_ a: NonTrivialStruct) -> NonTrivialStruct.Type {
+ return type(of: a)
+}
+// CHECK-LABEL: dontEmitIgnoredLoadExpr
+// CHECK: bb0(%0 : @guaranteed $NonTrivialStruct):
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: [[RESULT:%.*]] = metatype $@thin NonTrivialStruct.Type
+// CHECK-NEXT: return [[RESULT]] : $@thin NonTrivialStruct.Type
+
+// Test that we evaluate the force unwrap to get its side effects (a potential trap),
+// but don't actually need to perform the load of its value.
+func dontLoadIgnoredLValueForceUnwrap(_ a: inout NonTrivialStruct?) -> NonTrivialStruct.Type {
+ return type(of: a!)
+}
+// CHECK-LABEL: dontLoadIgnoredLValueForceUnwrap
+// CHECK: bb0(%0 : @trivial $*Optional<NonTrivialStruct>):
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: [[READ:%[0-9]+]] = begin_access [read] [unknown] %0
+// CHECK-NEXT: switch_enum_addr [[READ]] : $*Optional<NonTrivialStruct>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb1:
+// CHECK: unreachable
+// CHECK: bb2:
+// CHECK-NEXT: unchecked_take_enum_data_addr [[READ]] : $*Optional<NonTrivialStruct>, #Optional.some!enumelt.1
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thin NonTrivialStruct.Type
+// CHECK-NEXT: return [[METATYPE]]
+
+func dontLoadIgnoredLValueDoubleForceUnwrap(_ a: inout NonTrivialStruct??) -> NonTrivialStruct.Type {
+ return type(of: a!!)
+}
+// CHECK-LABEL: dontLoadIgnoredLValueDoubleForceUnwrap
+// CHECK: bb0(%0 : @trivial $*Optional<Optional<NonTrivialStruct>>):
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: [[READ:%[0-9]+]] = begin_access [read] [unknown] %0
+// CHECK-NEXT: switch_enum_addr [[READ]] : $*Optional<Optional<NonTrivialStruct>>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb1:
+// CHECK: unreachable
+// CHECK: bb2:
+// CHECK-NEXT: [[UNWRAPPED:%[0-9]+]] = unchecked_take_enum_data_addr [[READ]] : $*Optional<Optional<NonTrivialStruct>>, #Optional.some!enumelt.1
+// CHECK-NEXT: switch_enum_addr [[UNWRAPPED]] : $*Optional<NonTrivialStruct>, case #Optional.some!enumelt.1: bb4, case #Optional.none!enumelt: bb3
+// CHECK: bb3:
+// CHECK: unreachable
+// CHECK: bb4:
+// CHECK-NEXT: unchecked_take_enum_data_addr [[UNWRAPPED]] : $*Optional<NonTrivialStruct>, #Optional.some!enumelt.1
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thin NonTrivialStruct.Type
+// CHECK-NEXT: return [[METATYPE]]
+
+func loadIgnoredLValueForceUnwrap(_ a: inout NonTrivialStruct) -> NonTrivialStruct.Type {
+ return type(of: a.x!)
+}
+// CHECK-LABEL: loadIgnoredLValueForceUnwrap
+// CHECK: bb0(%0 : @trivial $*NonTrivialStruct):
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: [[READ:%[0-9]+]] = begin_access [read] [unknown] %0
+// CHECK-NEXT: [[BORROW:%[0-9]+]] = load_borrow [[READ]]
+// CHECK-NEXT: // function_ref NonTrivialStruct.x.getter
+// CHECK-NEXT: [[GETTER:%[0-9]+]] = function_ref @$S{{[_0-9a-zA-Z]*}}vg : $@convention(method) (@guaranteed NonTrivialStruct) -> @owned Optional<NonTrivialStruct>
+// CHECK-NEXT: [[X:%[0-9]+]] = apply [[GETTER]]([[BORROW]])
+// CHECK-NEXT: end_borrow [[BORROW]] from [[READ]]
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: switch_enum [[X]] : $Optional<NonTrivialStruct>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb1:
+// CHECK: unreachable
+// CHECK: bb2([[UNWRAPPED_X:%[0-9]+]] : @owned $NonTrivialStruct):
+// CHECK-NEXT: destroy_value [[UNWRAPPED_X]]
+// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thin NonTrivialStruct.Type
+// CHECK-NEXT: return [[METATYPE]]
+
+func loadIgnoredLValueThroughForceUnwrap(_ a: inout NonTrivialStruct?) -> NonTrivialStruct.Type {
+ return type(of: a!.x!)
+}
+// CHECK-LABEL: loadIgnoredLValueThroughForceUnwrap
+// CHECK: bb0(%0 : @trivial $*Optional<NonTrivialStruct>):
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: [[READ:%[0-9]+]] = begin_access [read] [unknown] %0
+// CHECK-NEXT: switch_enum_addr [[READ]] : $*Optional<NonTrivialStruct>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb1:
+// CHECK: unreachable
+// CHECK: bb2:
+// CHECK-NEXT: [[UNWRAPPED:%[0-9]+]] = unchecked_take_enum_data_addr [[READ]] : $*Optional<NonTrivialStruct>, #Optional.some!enumelt.1
+// CHECK-NEXT: [[BORROW:%[0-9]+]] = load_borrow [[UNWRAPPED]]
+// CHECK-NEXT: // function_ref NonTrivialStruct.x.getter
+// CHECK-NEXT: [[GETTER:%[0-9]+]] = function_ref @$S{{[_0-9a-zA-Z]*}}vg : $@convention(method) (@guaranteed NonTrivialStruct) -> @owned Optional<NonTrivialStruct>
+// CHECK-NEXT: [[X:%[0-9]+]] = apply [[GETTER]]([[BORROW]])
+// CHECK-NEXT: end_borrow [[BORROW]] from [[UNWRAPPED]]
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: switch_enum [[X]] : $Optional<NonTrivialStruct>, case #Optional.some!enumelt.1: bb4, case #Optional.none!enumelt: bb3
+// CHECK: bb3:
+// CHECK: unreachable
+// CHECK: bb4([[UNWRAPPED_X:%[0-9]+]] : @owned $NonTrivialStruct):
+// CHECK-NEXT: destroy_value [[UNWRAPPED_X]]
+// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thin NonTrivialStruct.Type
+// CHECK-NEXT: return [[METATYPE]]
+
+func evaluateIgnoredKeyPathExpr(_ s: inout NonTrivialStruct, _ kp: WritableKeyPath<NonTrivialStruct, Int>) -> Int.Type {
+ return type(of: s[keyPath: kp])
+}
+// CHECK-LABEL: evaluateIgnoredKeyPathExpr
+// CHECK: bb0(%0 : @trivial $*NonTrivialStruct, %1 : @guaranteed $WritableKeyPath<NonTrivialStruct, Int>):
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: debug_value %1
+// CHECK-NEXT: [[S_READ:%[0-9]+]] = begin_access [read] [unknown] %0
+// CHECK-NEXT: [[S_TEMP:%[0-9]+]] = alloc_stack $NonTrivialStruct
+// CHECK-NEXT: copy_addr [[S_READ]] to [initialization] [[S_TEMP]]
+// CHECK-NEXT: [[KP_TEMP:%[0-9]+]] = copy_value %1
+// CHECK-NEXT: [[KP:%[0-9]+]] = upcast [[KP_TEMP]]
+// CHECK-NEXT: [[RESULT:%[0-9]+]] = alloc_stack $Int
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[PROJECT_FN:%[0-9]+]] = function_ref @$Ss23_projectKeyPathReadOnly{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: [[KP_BORROW:%.*]] = begin_borrow [[KP]]
+// CHECK-NEXT: apply [[PROJECT_FN]]<NonTrivialStruct, Int>([[RESULT]], [[S_TEMP]], [[KP_BORROW]])
+// CHECK-NEXT: end_access [[S_READ]]
+// CHECK-NEXT: end_borrow [[KP_BORROW]]
+// CHECK-NEXT: dealloc_stack [[RESULT]]
+// CHECK-NEXT: destroy_value [[KP]]
+// CHECK-NEXT: destroy_addr [[S_TEMP]]
+// CHECK-NEXT: dealloc_stack [[S_TEMP]]
+// CHECK-NEXT: [[METATYPE:%[0-9]+]] = metatype $@thin Int.Type
+// CHECK-NOT: destroy_value %1
+// CHECK-NEXT: return [[METATYPE]]
+
+
+
+// <rdar://problem/18851497> Swiftc fails to compile nested destructuring tuple binding
+// CHECK-LABEL: sil hidden @$S11expressions21implodeRecursiveTupleyySi_Sit_SitSgF
+// CHECK: bb0(%0 : @trivial $Optional<((Int, Int), Int)>):
+func implodeRecursiveTuple(_ expr: ((Int, Int), Int)?) {
+
+ // CHECK: bb2([[WHOLE:%.*]] : @trivial $((Int, Int), Int)):
+ // CHECK-NEXT: [[X:%[0-9]+]] = tuple_extract [[WHOLE]] : $((Int, Int), Int), 0
+ // CHECK-NEXT: [[X0:%[0-9]+]] = tuple_extract [[X]] : $(Int, Int), 0
+ // CHECK-NEXT: [[X1:%[0-9]+]] = tuple_extract [[X]] : $(Int, Int), 1
+ // CHECK-NEXT: [[Y:%[0-9]+]] = tuple_extract [[WHOLE]] : $((Int, Int), Int), 1
+ // CHECK-NEXT: [[X:%[0-9]+]] = tuple ([[X0]] : $Int, [[X1]] : $Int)
+ // CHECK-NEXT: debug_value [[X]] : $(Int, Int), let, name "x"
+ // CHECK-NEXT: debug_value [[Y]] : $Int, let, name "y"
+
+ let (x, y) = expr!
+}
+
+func test20087517() {
+ class Color {
+ static func greenColor() -> Color { return Color() }
+ }
+ let x: (Color?, Int) = (.greenColor(), 1)
+}
+
+func test20596042() {
+ enum E {
+ case thing1
+ case thing2
+ }
+
+ func f() -> (E?, Int)? {
+ return (.thing1, 1)
+ }
+}
+
+func test21886435() {
+ () = ()
+}
+
diff --git a/test/SILGen/plus_zero_extensions_objc.swift b/test/SILGen/plus_zero_extensions_objc.swift
new file mode 100644
index 0000000..24a9cb7
--- /dev/null
+++ b/test/SILGen/plus_zero_extensions_objc.swift
@@ -0,0 +1,36 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-source-import -emit-silgen -enable-sil-ownership | %FileCheck %s
+//
+// REQUIRES: objc_interop
+
+import Foundation
+
+class Foo {}
+
+extension Foo {
+ dynamic func kay() {}
+ dynamic var cox: Int { return 0 }
+}
+
+// CHECK-LABEL: sil hidden @$S15extensions_objc19extensionReferencesyyAA3FooCF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Foo):
+func extensionReferences(_ x: Foo) {
+ // dynamic extension methods are still dynamically dispatched.
+ // CHECK: objc_method [[ARG]] : $Foo, #Foo.kay!1.foreign
+ x.kay()
+
+ // CHECK: objc_method [[ARG]] : $Foo, #Foo.cox!getter.1.foreign
+ _ = x.cox
+
+}
+
+func extensionMethodCurrying(_ x: Foo) {
+ _ = x.kay
+}
+
+// CHECK-LABEL: sil shared [thunk] @$S15extensions_objc3FooC3kayyyFTc
+// CHECK: function_ref @$S15extensions_objc3FooC3kayyyFTD
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S15extensions_objc3FooC3kayyyFTD
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $Foo):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: objc_method [[SELF_COPY]] : $Foo, #Foo.kay!1.foreign
diff --git a/test/SILGen/plus_zero_external_definitions.swift b/test/SILGen/plus_zero_external_definitions.swift
new file mode 100644
index 0000000..eed168f
--- /dev/null
+++ b/test/SILGen/plus_zero_external_definitions.swift
@@ -0,0 +1,46 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs %s -emit-silgen -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import ansible
+
+var a = NSAnse(Ansible(bellsOn: NSObject()))
+
+var anse = NSAnse
+
+hasNoPrototype()
+
+// CHECK-LABEL: sil @main
+// -- Foreign function is referenced with C calling conv and ownership semantics
+// CHECK: [[NSOBJECT_CTOR:%.*]] = function_ref @$SSo8NSObjectC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick NSObject.Type) -> @owned NSObject
+// CHECK: [[ANSIBLE_CTOR:%.*]] = function_ref @$SSo7AnsibleC{{[_0-9a-zA-Z]*}}fC
+// CHECK: [[ANSIBLE:%.*]] = apply [[ANSIBLE_CTOR]]
+// CHECK: [[NSANSE:%.*]] = function_ref @NSAnse : $@convention(c) (Optional<Ansible>) -> @autoreleased Optional<Ansible>
+// CHECK: [[NSANSE_RESULT:%.*]] = apply [[NSANSE]]([[ANSIBLE]])
+// CHECK: destroy_value [[ANSIBLE]] : $Optional<Ansible>
+// -- Referencing unapplied C function goes through a thunk
+// CHECK: [[NSANSE:%.*]] = function_ref @$SSo6NSAnseySo7AnsibleCSgADFTO : $@convention(thin) (@guaranteed Optional<Ansible>) -> @owned Optional<Ansible>
+// -- Referencing unprototyped C function passes no parameters
+// CHECK: [[NOPROTO:%.*]] = function_ref @hasNoPrototype : $@convention(c) () -> ()
+// CHECK: apply [[NOPROTO]]()
+
+// -- Constructors for imported NSObject
+// CHECK-LABEL: sil shared [serializable] @$SSo8NSObjectC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick NSObject.Type) -> @owned NSObject
+
+// -- Constructors for imported Ansible
+// CHECK-LABEL: sil shared [serializable] @$SSo7AnsibleC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in Optional<Any>, @thick Ansible.Type) -> @owned Optional<Ansible>
+
+// -- Native Swift thunk for NSAnse
+// CHECK: sil shared [serialized] [thunk] @$SSo6NSAnseySo7AnsibleCSgADFTO : $@convention(thin) (@guaranteed Optional<Ansible>) -> @owned Optional<Ansible> {
+// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Optional<Ansible>):
+// CHECK: [[ARG0_COPY:%.*]] = copy_value [[ARG0]]
+// CHECK: [[FUNC:%.*]] = function_ref @NSAnse : $@convention(c) (Optional<Ansible>) -> @autoreleased Optional<Ansible>
+// CHECK: [[RESULT:%.*]] = apply [[FUNC]]([[ARG0_COPY]]) : $@convention(c) (Optional<Ansible>) -> @autoreleased Optional<Ansible>
+// CHECK: destroy_value [[ARG0_COPY]] : $Optional<Ansible>
+// CHECK: return [[RESULT]] : $Optional<Ansible>
+// CHECK: }
+
+// -- Constructor for imported Ansible was unused, should not be emitted.
+// CHECK-NOT: sil {{.*}} @$SSo7AnsibleC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick Ansible.Type) -> @owned Ansible
+
diff --git a/test/SILGen/plus_zero_final.swift b/test/SILGen/plus_zero_final.swift
new file mode 100644
index 0000000..3e9133b
--- /dev/null
+++ b/test/SILGen/plus_zero_final.swift
@@ -0,0 +1,45 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class TestClass {
+
+ final
+ var finalProperty : Int { return 42 }
+
+ final
+ func finalMethod() -> Int { return 12 }
+
+
+ func baseMethod() {}
+}
+
+class TestDerived : TestClass {
+ final
+ override func baseMethod() {}
+}
+
+
+// CHECK-LABEL: sil hidden @{{.*}}testDirectDispatch{{.*}} : $@convention(thin) (@guaranteed TestClass) -> Int {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $TestClass):
+// CHECK: [[FINALMETH:%[0-9]+]] = function_ref @$S5final9TestClassC0A6Method{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[FINALMETH]]([[ARG]])
+// CHECK: [[FINALPROP:%[0-9]+]] = function_ref @$S5final9TestClassC0A8PropertySivg
+// CHECK: apply [[FINALPROP]]([[ARG]])
+func testDirectDispatch(c : TestClass) -> Int {
+ return c.finalMethod()+c.finalProperty
+}
+
+
+// Verify that the non-overriding final methods don't get emitted to the vtable.
+// CHECK-LABEL: sil_vtable TestClass {
+// CHECK-NEXT: #TestClass.baseMethod!1: {{.*}} : @$S5final9TestClassC10baseMethod{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #TestClass.init!initializer.1: {{.*}} : @$S5final9TestClassC{{[_0-9a-zA-Z]*}}fc
+// CHECK-NEXT: #TestClass.deinit!
+// CHECK-NEXT: }
+
+// Verify that overriding final methods don't get emitted to the vtable.
+// CHECK-LABEL: sil_vtable TestDerived {
+// CHECK-NEXT: #TestClass.baseMethod!1: {{.*}} : @$S5final11TestDerivedC10baseMethod{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #TestClass.init!initializer.1: {{.*}} : @$S5final11TestDerivedC{{[_0-9a-zA-Z]*}}fc
+// CHECK-NEXT: #TestDerived.deinit!
+// CHECK-NEXT: }
diff --git a/test/SILGen/plus_zero_force_cast_chained_optional.swift b/test/SILGen/plus_zero_force_cast_chained_optional.swift
new file mode 100644
index 0000000..d903e82
--- /dev/null
+++ b/test/SILGen/plus_zero_force_cast_chained_optional.swift
@@ -0,0 +1,37 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class Foo {
+ var bar: Bar!
+}
+
+class Bar {
+ var bas: C!
+}
+
+class C {}
+class D: C {}
+
+// CHECK-LABEL: sil hidden @$S27force_cast_chained_optional4testyAA1DCAA3FooCF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Foo):
+// CHECK: class_method [[ARG]] : $Foo, #Foo.bar!getter.1 : (Foo) -> () -> Bar?, $@convention(method) (@guaranteed Foo) ->
+// CHECK: select_enum_addr
+// CHECK: cond_br {{%.*}}, [[SOME_BAR:bb[0-9]+]], [[NO_BAR:bb[0-9]+]]
+//
+// CHECK: [[NO_BAR]]:
+// CHECK: br [[TRAP:bb[0-9]+]]
+//
+// CHECK: [[SOME_BAR]]:
+// CHECK: [[PAYLOAD_ADDR:%.*]] = unchecked_take_enum_data_addr {{%.*}} : $*Optional<Bar>
+// CHECK: [[BAR:%.*]] = load [copy] [[PAYLOAD_ADDR]]
+// CHECK: [[BORROWED_BAR:%.*]] = begin_borrow [[BAR]]
+// CHECK: [[METHOD:%.*]] = class_method [[BORROWED_BAR]] : $Bar, #Bar.bas!getter.1 : (Bar) -> () -> C?, $@convention(method) (@guaranteed Bar) ->
+// CHECK: apply [[METHOD]]([[BORROWED_BAR]])
+// CHECK: end_borrow [[BORROWED_BAR]] from [[BAR]]
+// CHECK: unconditional_checked_cast {{%.*}} : $C to $D
+//
+// CHECK: [[TRAP]]:
+// CHECK: unreachable
+func test(_ x: Foo) -> D {
+ return x.bar?.bas as! D
+}
diff --git a/test/SILGen/plus_zero_foreach.swift b/test/SILGen/plus_zero_foreach.swift
new file mode 100644
index 0000000..7a3589b
--- /dev/null
+++ b/test/SILGen/plus_zero_foreach.swift
@@ -0,0 +1,642 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+//////////////////
+// Declarations //
+//////////////////
+
+class C {}
+
+@_silgen_name("loopBodyEnd")
+func loopBodyEnd() -> ()
+
+@_silgen_name("condition")
+func condition() -> Bool
+
+@_silgen_name("loopContinueEnd")
+func loopContinueEnd() -> ()
+
+@_silgen_name("loopBreakEnd")
+func loopBreakEnd() -> ()
+
+@_silgen_name("funcEnd")
+func funcEnd() -> ()
+
+struct TrivialStruct {
+ var value: Int32
+}
+
+struct NonTrivialStruct {
+ var value: C
+}
+
+struct GenericStruct<T> {
+ var value: T
+ var value2: C
+}
+
+protocol P {}
+protocol ClassP : class {}
+
+protocol GenericCollection : Collection {
+
+}
+
+///////////
+// Tests //
+///////////
+
+//===----------------------------------------------------------------------===//
+// Trivial Struct
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: sil hidden @$S7foreach13trivialStructyySaySiGF : $@convention(thin) (@guaranteed Array<Int>) -> () {
+// CHECK: bb0([[ARRAY:%.*]] : @guaranteed $Array<Int>):
+// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<Int>> }, var, name "$x$generator"
+// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
+// CHECK: br [[LOOP_DEST:bb[0-9]+]]
+//
+// CHECK: [[LOOP_DEST]]:
+// CHECK: switch_enum [[IND_VAR:%.*]] : $Optional<Int>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[CONT_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]([[VAR:%.*]] : @trivial $Int):
+// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_END_FUNC]]()
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[CONT_BLOCK]]:
+// CHECK: destroy_value [[ITERATOR_BOX]]
+// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
+// CHECK: apply [[FUNC_END_FUNC]]()
+// CHECK: } // end sil function '$S7foreach13trivialStructyySaySiGF'
+func trivialStruct(_ xx: [Int]) {
+ for x in xx {
+ loopBodyEnd()
+ }
+ funcEnd()
+}
+
+// TODO: Write this test
+func trivialStructContinue(_ xx: [Int]) {
+ for x in xx {
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+// TODO: Write this test
+func trivialStructBreak(_ xx: [Int]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+// CHECK-LABEL: sil hidden @$S7foreach26trivialStructContinueBreakyySaySiGF : $@convention(thin) (@guaranteed Array<Int>) -> () {
+// CHECK: bb0([[ARRAY:%.*]] : @guaranteed $Array<Int>):
+// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<Int>> }, var, name "$x$generator"
+// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
+// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<Int>
+// CHECK: store_borrow [[ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @$Ss10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
+// CHECK: apply [[MAKE_ITERATOR_FUNC]]<[Int]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]])
+// CHECK: br [[LOOP_DEST:bb[0-9]+]]
+//
+// CHECK: [[LOOP_DEST]]:
+// CHECK: [[GET_ELT_STACK:%.*]] = alloc_stack $Optional<Int>
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<Int>>
+// CHECK: [[FUNC_REF:%.*]] = function_ref @$Ss16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
+// CHECK: apply [[FUNC_REF]]<[Int]>([[GET_ELT_STACK]], [[WRITE]])
+// CHECK: [[IND_VAR:%.*]] = load [trivial] [[GET_ELT_STACK]]
+// CHECK: switch_enum [[IND_VAR]] : $Optional<Int>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[CONT_BLOCK_JUMP:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]([[VAR:%.*]] : @trivial $Int):
+// CHECK: cond_br {{%.*}}, [[LOOP_BREAK_END_BLOCK:bb[0-9]+]], [[CONTINUE_CHECK_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_BREAK_END_BLOCK]]:
+// CHECK: [[LOOP_BREAK_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BREAK_FUNC]]()
+// CHECK: br [[CONT_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[CONTINUE_CHECK_BLOCK]]:
+// CHECK: cond_br {{%.*}}, [[LOOP_CONTINUE_END:bb[0-9]+]], [[LOOP_END_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_CONTINUE_END]]:
+// CHECK: [[LOOP_CONTINUE_FUNC:%.*]] = function_ref @loopContinueEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_CONTINUE_FUNC]]() : $@convention(thin) () -> ()
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[LOOP_END_BLOCK]]:
+// CHECK: [[LOOP_BODY_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BODY_FUNC]]()
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[CONT_BLOCK_JUMP]]:
+// CHECK: br [[CONT_BLOCK]]
+//
+// CHECK: [[CONT_BLOCK]]
+// CHECK: destroy_value [[ITERATOR_BOX]] : ${ var IndexingIterator<Array<Int>> }
+// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
+// CHECK: apply [[FUNC_END_FUNC]]()
+// CHECK: } // end sil function '$S7foreach26trivialStructContinueBreakyySaySiGF'
+func trivialStructContinueBreak(_ xx: [Int]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+
+//===----------------------------------------------------------------------===//
+// Existential
+//===----------------------------------------------------------------------===//
+
+func existential(_ xx: [P]) {
+ for x in xx {
+ loopBodyEnd()
+ }
+ funcEnd()
+}
+
+func existentialContinue(_ xx: [P]) {
+ for x in xx {
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+func existentialBreak(_ xx: [P]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+// CHECK-LABEL: sil hidden @$S7foreach24existentialContinueBreakyySayAA1P_pGF : $@convention(thin) (@guaranteed Array<P>) -> () {
+// CHECK: bb0([[ARRAY:%.*]] : @guaranteed $Array<P>):
+// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<P>> }, var, name "$x$generator"
+// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
+// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<P>
+// CHECK: store_borrow [[ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @$Ss10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
+// CHECK: apply [[MAKE_ITERATOR_FUNC]]<[P]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]])
+// CHECK: [[ELT_STACK:%.*]] = alloc_stack $Optional<P>
+// CHECK: br [[LOOP_DEST:bb[0-9]+]]
+//
+// CHECK: [[LOOP_DEST]]:
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<P>>
+// CHECK: [[FUNC_REF:%.*]] = function_ref @$Ss16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
+// CHECK: apply [[FUNC_REF]]<[P]>([[ELT_STACK]], [[WRITE]])
+// CHECK: switch_enum_addr [[ELT_STACK]] : $*Optional<P>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[CONT_BLOCK_JUMP:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]:
+// CHECK: [[T0:%.*]] = alloc_stack $P, let, name "x"
+// CHECK: [[ELT_STACK_TAKE:%.*]] = unchecked_take_enum_data_addr [[ELT_STACK]] : $*Optional<P>, #Optional.some!enumelt.1
+// CHECK: copy_addr [take] [[ELT_STACK_TAKE]] to [initialization] [[T0]]
+// CHECK: cond_br {{%.*}}, [[LOOP_BREAK_END_BLOCK:bb[0-9]+]], [[CONTINUE_CHECK_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_BREAK_END_BLOCK]]:
+// CHECK: [[LOOP_BREAK_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BREAK_FUNC]]()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[CONT_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[CONTINUE_CHECK_BLOCK]]:
+// CHECK: cond_br {{%.*}}, [[LOOP_CONTINUE_END:bb[0-9]+]], [[LOOP_END_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_CONTINUE_END]]:
+// CHECK: [[LOOP_CONTINUE_FUNC:%.*]] = function_ref @loopContinueEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_CONTINUE_FUNC]]() : $@convention(thin) () -> ()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[LOOP_END_BLOCK]]:
+// CHECK: [[LOOP_BODY_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BODY_FUNC]]()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[CONT_BLOCK_JUMP]]:
+// CHECK: br [[CONT_BLOCK]]
+//
+// CHECK: [[CONT_BLOCK]]
+// CHECK: dealloc_stack [[ELT_STACK]]
+// CHECK: destroy_value [[ITERATOR_BOX]] : ${ var IndexingIterator<Array<P>> }
+// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
+// CHECK: apply [[FUNC_END_FUNC]]()
+// CHECK: } // end sil function '$S7foreach24existentialContinueBreakyySayAA1P_pGF'
+func existentialContinueBreak(_ xx: [P]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+//===----------------------------------------------------------------------===//
+// Class Constrainted Existential
+//===----------------------------------------------------------------------===//
+
+func existentialClass(_ xx: [ClassP]) {
+ for x in xx {
+ loopBodyEnd()
+ }
+ funcEnd()
+}
+
+func existentialClassContinue(_ xx: [ClassP]) {
+ for x in xx {
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+func existentialClassBreak(_ xx: [ClassP]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+func existentialClassContinueBreak(_ xx: [ClassP]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+//===----------------------------------------------------------------------===//
+// Generic Struct
+//===----------------------------------------------------------------------===//
+
+func genericStruct<T>(_ xx: [GenericStruct<T>]) {
+ for x in xx {
+ loopBodyEnd()
+ }
+ funcEnd()
+}
+
+func genericStructContinue<T>(_ xx: [GenericStruct<T>]) {
+ for x in xx {
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+func genericStructBreak<T>(_ xx: [GenericStruct<T>]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+// CHECK-LABEL: sil hidden @$S7foreach26genericStructContinueBreakyySayAA07GenericC0VyxGGlF : $@convention(thin) <T> (@guaranteed Array<GenericStruct<T>>) -> () {
+// CHECK: bb0([[ARRAY:%.*]] : @guaranteed $Array<GenericStruct<T>>):
+// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box $<τ_0_0> { var IndexingIterator<Array<GenericStruct<τ_0_0>>> } <T>, var, name "$x$generator"
+// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
+// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<GenericStruct<T>>
+// CHECK: store_borrow [[ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @$Ss10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
+// CHECK: apply [[MAKE_ITERATOR_FUNC]]<[GenericStruct<T>]>([[PROJECT_ITERATOR_BOX]], [[BORROWED_ARRAY_STACK]])
+// CHECK: [[ELT_STACK:%.*]] = alloc_stack $Optional<GenericStruct<T>>
+// CHECK: br [[LOOP_DEST:bb[0-9]+]]
+//
+// CHECK: [[LOOP_DEST]]:
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<GenericStruct<T>>>
+// CHECK: [[FUNC_REF:%.*]] = function_ref @$Ss16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
+// CHECK: apply [[FUNC_REF]]<[GenericStruct<T>]>([[ELT_STACK]], [[WRITE]])
+// CHECK: switch_enum_addr [[ELT_STACK]] : $*Optional<GenericStruct<T>>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[CONT_BLOCK_JUMP:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]:
+// CHECK: [[T0:%.*]] = alloc_stack $GenericStruct<T>, let, name "x"
+// CHECK: [[ELT_STACK_TAKE:%.*]] = unchecked_take_enum_data_addr [[ELT_STACK]] : $*Optional<GenericStruct<T>>, #Optional.some!enumelt.1
+// CHECK: copy_addr [take] [[ELT_STACK_TAKE]] to [initialization] [[T0]]
+// CHECK: cond_br {{%.*}}, [[LOOP_BREAK_END_BLOCK:bb[0-9]+]], [[CONTINUE_CHECK_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_BREAK_END_BLOCK]]:
+// CHECK: [[LOOP_BREAK_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BREAK_FUNC]]()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[CONT_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[CONTINUE_CHECK_BLOCK]]:
+// CHECK: cond_br {{%.*}}, [[LOOP_CONTINUE_END:bb[0-9]+]], [[LOOP_END_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_CONTINUE_END]]:
+// CHECK: [[LOOP_CONTINUE_FUNC:%.*]] = function_ref @loopContinueEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_CONTINUE_FUNC]]() : $@convention(thin) () -> ()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[LOOP_END_BLOCK]]:
+// CHECK: [[LOOP_BODY_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BODY_FUNC]]()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[CONT_BLOCK_JUMP]]:
+// CHECK: br [[CONT_BLOCK]]
+//
+// CHECK: [[CONT_BLOCK]]
+// CHECK: dealloc_stack [[ELT_STACK]]
+// CHECK: destroy_value [[ITERATOR_BOX]]
+// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
+// CHECK: apply [[FUNC_END_FUNC]]()
+// CHECK: } // end sil function '$S7foreach26genericStructContinueBreakyySayAA07GenericC0VyxGGlF'
+func genericStructContinueBreak<T>(_ xx: [GenericStruct<T>]) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+//===----------------------------------------------------------------------===//
+// Fully Generic Collection
+//===----------------------------------------------------------------------===//
+
+func genericCollection<T : Collection>(_ xx: T) {
+ for x in xx {
+ loopBodyEnd()
+ }
+ funcEnd()
+}
+
+func genericCollectionContinue<T : Collection>(_ xx: T) {
+ for x in xx {
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+func genericCollectionBreak<T : Collection>(_ xx: T) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+// CHECK-LABEL: sil hidden @$S7foreach30genericCollectionContinueBreakyyxs0C0RzlF : $@convention(thin) <T where T : Collection> (@in_guaranteed T) -> () {
+// CHECK: bb0([[COLLECTION:%.*]] : @trivial $*T):
+// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : Collection> { var τ_0_0.Iterator } <T>, var, name "$x$generator"
+// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = witness_method $T, #Sequence.makeIterator!1 : <Self where Self : Sequence> (Self) -> () -> Self.Iterator : $@convention(witness_method: Sequence) <τ_0_0 where τ_0_0 : Sequence> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
+// CHECK: apply [[MAKE_ITERATOR_FUNC]]<T>([[PROJECT_ITERATOR_BOX]], [[COLLECTION]])
+// CHECK: [[ELT_STACK:%.*]] = alloc_stack $Optional<T.Element>
+// CHECK: br [[LOOP_DEST:bb[0-9]+]]
+//
+// CHECK: [[LOOP_DEST]]:
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*T.Iterator
+// CHECK: [[GET_NEXT_FUNC:%.*]] = witness_method $T.Iterator, #IteratorProtocol.next!1 : <Self where Self : IteratorProtocol> (inout Self) -> () -> Self.Element? : $@convention(witness_method: IteratorProtocol) <τ_0_0 where τ_0_0 : IteratorProtocol> (@inout τ_0_0) -> @out Optional<τ_0_0.Element>
+// CHECK: apply [[GET_NEXT_FUNC]]<T.Iterator>([[ELT_STACK]], [[WRITE]])
+// CHECK: switch_enum_addr [[ELT_STACK]] : $*Optional<T.Element>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[CONT_BLOCK_JUMP:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]:
+// CHECK: [[T0:%.*]] = alloc_stack $T.Element, let, name "x"
+// CHECK: [[ELT_STACK_TAKE:%.*]] = unchecked_take_enum_data_addr [[ELT_STACK]] : $*Optional<T.Element>, #Optional.some!enumelt.1
+// CHECK: copy_addr [take] [[ELT_STACK_TAKE]] to [initialization] [[T0]]
+// CHECK: cond_br {{%.*}}, [[LOOP_BREAK_END_BLOCK:bb[0-9]+]], [[CONTINUE_CHECK_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_BREAK_END_BLOCK]]:
+// CHECK: [[LOOP_BREAK_FUNC:%.*]] = function_ref @loopBreakEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BREAK_FUNC]]()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[CONT_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[CONTINUE_CHECK_BLOCK]]:
+// CHECK: cond_br {{%.*}}, [[LOOP_CONTINUE_END:bb[0-9]+]], [[LOOP_END_BLOCK:bb[0-9]+]]
+//
+// CHECK: [[LOOP_CONTINUE_END]]:
+// CHECK: [[LOOP_CONTINUE_FUNC:%.*]] = function_ref @loopContinueEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_CONTINUE_FUNC]]() : $@convention(thin) () -> ()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[LOOP_END_BLOCK]]:
+// CHECK: [[LOOP_BODY_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_BODY_FUNC]]()
+// CHECK: destroy_addr [[T0]]
+// CHECK: dealloc_stack [[T0]]
+// CHECK: br [[LOOP_DEST]]
+//
+// CHECK: [[CONT_BLOCK_JUMP]]:
+// CHECK: br [[CONT_BLOCK]]
+//
+// CHECK: [[CONT_BLOCK]]
+// CHECK: dealloc_stack [[ELT_STACK]]
+// CHECK: destroy_value [[ITERATOR_BOX]]
+// CHECK: [[FUNC_END_FUNC:%.*]] = function_ref @funcEnd : $@convention(thin) () -> ()
+// CHECK: apply [[FUNC_END_FUNC]]()
+// CHECK: } // end sil function '$S7foreach30genericCollectionContinueBreakyyxs0C0RzlF'
+func genericCollectionContinueBreak<T : Collection>(_ xx: T) {
+ for x in xx {
+ if (condition()) {
+ loopBreakEnd()
+ break
+ }
+
+ if (condition()) {
+ loopContinueEnd()
+ continue
+ }
+ loopBodyEnd()
+ }
+
+ funcEnd()
+}
+
+//===----------------------------------------------------------------------===//
+// Pattern Match Tests
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: sil hidden @$S7foreach13tupleElementsyySayAA1CC_ADtGF
+func tupleElements(_ xx: [(C, C)]) {
+ // CHECK: bb3([[PAYLOAD:%.*]] : @owned $(C, C)):
+ // CHECK: [[BORROWED_PAYLOAD:%.*]] = begin_borrow [[PAYLOAD]]
+ // CHECK: [[A:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 0
+ // CHECK: [[COPY_A:%.*]] = copy_value [[A]]
+ // CHECK: [[B:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 1
+ // CHECK: [[COPY_B:%.*]] = copy_value [[B]]
+ // CHECK: end_borrow [[BORROWED_PAYLOAD]] from [[PAYLOAD]]
+ // CHECK: destroy_value [[COPY_B]]
+ // CHECK: destroy_value [[COPY_A]]
+ // CHECK: destroy_value [[PAYLOAD]]
+ for (a, b) in xx {}
+ // CHECK: bb7([[PAYLOAD:%.*]] : @owned $(C, C)):
+ // CHECK: [[BORROWED_PAYLOAD:%.*]] = begin_borrow [[PAYLOAD]]
+ // CHECK: [[A:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 0
+ // CHECK: [[COPY_A:%.*]] = copy_value [[A]]
+ // CHECK: [[B:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 1
+ // CHECK: [[COPY_B:%.*]] = copy_value [[B]]
+ // CHECK: destroy_value [[COPY_B]]
+ // CHECK: end_borrow [[BORROWED_PAYLOAD]] from [[PAYLOAD]]
+ // CHECK: destroy_value [[COPY_A]]
+ // CHECK: destroy_value [[PAYLOAD]]
+ for (a, _) in xx {}
+ // CHECK: bb11([[PAYLOAD:%.*]] : @owned $(C, C)):
+ // CHECK: [[BORROWED_PAYLOAD:%.*]] = begin_borrow [[PAYLOAD]]
+ // CHECK: [[A:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 0
+ // CHECK: [[COPY_A:%.*]] = copy_value [[A]]
+ // CHECK: [[B:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 1
+ // CHECK: [[COPY_B:%.*]] = copy_value [[B]]
+ // CHECK: destroy_value [[COPY_A]]
+ // CHECK: end_borrow [[BORROWED_PAYLOAD]] from [[PAYLOAD]]
+ // CHECK: destroy_value [[COPY_B]]
+ // CHECK: destroy_value [[PAYLOAD]]
+ for (_, b) in xx {}
+ // CHECK: bb15([[PAYLOAD:%.*]] : @owned $(C, C)):
+ // CHECK: [[BORROWED_PAYLOAD:%.*]] = begin_borrow [[PAYLOAD]]
+ // CHECK: [[A:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 0
+ // CHECK: [[COPY_A:%.*]] = copy_value [[A]]
+ // CHECK: [[B:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 1
+ // CHECK: [[COPY_B:%.*]] = copy_value [[B]]
+ // CHECK: destroy_value [[COPY_B]]
+ // CHECK: destroy_value [[COPY_A]]
+ // CHECK: end_borrow [[BORROWED_PAYLOAD]] from [[PAYLOAD]]
+ // CHECK: destroy_value [[PAYLOAD]]
+ for (_, _) in xx {}
+ // CHECK: bb19([[PAYLOAD:%.*]] : @owned $(C, C)):
+ // CHECK: [[BORROWED_PAYLOAD:%.*]] = begin_borrow [[PAYLOAD]]
+ // CHECK: [[A:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 0
+ // CHECK: [[COPY_A:%.*]] = copy_value [[A]]
+ // CHECK: [[B:%.*]] = tuple_extract [[BORROWED_PAYLOAD]] : $(C, C), 1
+ // CHECK: [[COPY_B:%.*]] = copy_value [[B]]
+ // CHECK: destroy_value [[COPY_B]]
+ // CHECK: destroy_value [[COPY_A]]
+ // CHECK: end_borrow [[BORROWED_PAYLOAD]] from [[PAYLOAD]]
+ // CHECK: destroy_value [[PAYLOAD]]
+ for _ in xx {}
+}
+
+// Make sure that when we have an unused value, we properly iterate over the
+// loop rather than run through the loop once.
+//
+// CHECK-LABEL: sil hidden @$S7foreach16unusedArgPatternyySaySiGF : $@convention(thin) (@guaranteed Array<Int>) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Array<Int>):
+// CHECK: br [[LOOP_DEST:bb[0-9]+]]
+//
+// CHECK: [[LOOP_DEST]]:
+// CHECK: switch_enum [[OPT_VAL:%.*]] : $Optional<Int>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[CONT_BB:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]([[VAL:%.*]] : @trivial $Int):
+// CHECK: [[LOOP_END_FUNC:%.*]] = function_ref @loopBodyEnd : $@convention(thin) () -> ()
+// CHECK: apply [[LOOP_END_FUNC]]
+func unusedArgPattern(_ xx: [Int]) {
+ for _ in xx {
+ loopBodyEnd()
+ }
+}
diff --git a/test/SILGen/plus_zero_foreign_errors.swift b/test/SILGen/plus_zero_foreign_errors.swift
new file mode 100644
index 0000000..d004d8f
--- /dev/null
+++ b/test/SILGen/plus_zero_foreign_errors.swift
@@ -0,0 +1,311 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-clang-importer-objc-overlays
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-silgen -parse-as-library %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+import errors
+
+// CHECK-LABEL: sil hidden @$S14foreign_errors5test0yyKF : $@convention(thin) () -> @error Error
+func test0() throws {
+ // Create a strong temporary holding nil before we perform any further parts of function emission.
+ // CHECK: [[ERR_TEMP0:%.*]] = alloc_stack $Optional<NSError>
+ // CHECK: inject_enum_addr [[ERR_TEMP0]] : $*Optional<NSError>, #Optional.none!enumelt
+
+ // CHECK: [[SELF:%.*]] = metatype $@objc_metatype ErrorProne.Type
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $@objc_metatype ErrorProne.Type, #ErrorProne.fail!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
+
+ // Create an unmanaged temporary, copy into it, and make a AutoreleasingUnsafeMutablePointer.
+ // CHECK: [[ERR_TEMP1:%.*]] = alloc_stack $@sil_unmanaged Optional<NSError>
+ // CHECK: [[T0:%.*]] = load_borrow [[ERR_TEMP0]]
+ // CHECK: [[T1:%.*]] = ref_to_unmanaged [[T0]]
+ // CHECK: store [[T1]] to [trivial] [[ERR_TEMP1]]
+ // CHECK: address_to_pointer [[ERR_TEMP1]]
+
+ // Call the method.
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{.*}}, [[SELF]])
+
+ // Writeback to the first temporary.
+ // CHECK: [[T0:%.*]] = load [trivial] [[ERR_TEMP1]]
+ // CHECK: [[T1:%.*]] = unmanaged_to_ref [[T0]]
+ // CHECK: [[T1_COPY:%.*]] = copy_value [[T1]]
+ // CHECK: assign [[T1_COPY]] to [[ERR_TEMP0]]
+
+ // Pull out the boolean value and compare it to zero.
+ // CHECK: [[BOOL_OR_INT:%.*]] = struct_extract [[RESULT]]
+ // CHECK: [[RAW_VALUE:%.*]] = struct_extract [[BOOL_OR_INT]]
+ // On some platforms RAW_VALUE will be compared against 0; on others it's
+ // already an i1 (bool) and those instructions will be skipped. Just do a
+ // looser check.
+ // CHECK: cond_br {{%.+}}, [[NORMAL_BB:bb[0-9]+]], [[ERROR_BB:bb[0-9]+]]
+ try ErrorProne.fail()
+
+ // Normal path: fall out and return.
+ // CHECK: [[NORMAL_BB]]:
+ // CHECK: return
+
+ // Error path: fall out and rethrow.
+ // CHECK: [[ERROR_BB]]:
+ // CHECK: [[T0:%.*]] = load [take] [[ERR_TEMP0]]
+ // CHECK: [[T1:%.*]] = function_ref @$S10Foundation22_convertNSErrorToErrorys0E0_pSo0C0CSgF : $@convention(thin) (@guaranteed Optional<NSError>) -> @owned Error
+ // CHECK: [[T2:%.*]] = apply [[T1]]([[T0]])
+ // CHECK: throw [[T2]] : $Error
+}
+
+extension NSObject {
+ @objc func abort() throws {
+ throw NSError(domain: "", code: 1, userInfo: [:])
+ }
+// CHECK-LABEL: sil hidden [thunk] @$SSo8NSObjectC14foreign_errorsE5abortyyKFTo : $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, NSObject) -> ObjCBool
+// CHECK: [[T0:%.*]] = function_ref @$SSo8NSObjectC14foreign_errorsE5abortyyKF : $@convention(method) (@guaranteed NSObject) -> @error Error
+// CHECK: try_apply [[T0]](
+// CHECK: bb1(
+// CHECK: [[BITS:%.*]] = integer_literal $Builtin.Int{{[18]}}, {{1|-1}}
+// CHECK: [[VALUE:%.*]] = struct ${{Bool|UInt8}} ([[BITS]] : $Builtin.Int{{[18]}})
+// CHECK: [[BOOL:%.*]] = struct $ObjCBool ([[VALUE]] : ${{Bool|UInt8}})
+// CHECK: br bb6([[BOOL]] : $ObjCBool)
+// CHECK: bb2([[ERR:%.*]] : $Error):
+// CHECK: switch_enum %0 : $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb4
+// CHECK: bb3([[UNWRAPPED_OUT:%.+]] : $AutoreleasingUnsafeMutablePointer<Optional<NSError>>):
+// CHECK: [[T0:%.*]] = function_ref @$S10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed Error) -> @owned NSError
+// CHECK: [[T1:%.*]] = apply [[T0]]([[ERR]])
+// CHECK: [[OBJCERR:%.*]] = enum $Optional<NSError>, #Optional.some!enumelt.1, [[T1]] : $NSError
+// CHECK: [[TEMP:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: store [[OBJCERR]] to [init] [[TEMP]]
+// CHECK: [[SETTER:%.*]] = function_ref @$Ss33AutoreleasingUnsafeMutablePointerV7pointeexvs :
+// CHECK: apply [[SETTER]]<Optional<NSError>>([[TEMP]], [[UNWRAPPED_OUT]])
+// CHECK: dealloc_stack [[TEMP]]
+// CHECK: br bb5
+// CHECK: bb4:
+// CHECK: destroy_value [[ERR]] : $Error
+// CHECK: br bb5
+// CHECK: bb5:
+// CHECK: [[BITS:%.*]] = integer_literal $Builtin.Int{{[18]}}, 0
+// CHECK: [[VALUE:%.*]] = struct ${{Bool|UInt8}} ([[BITS]] : $Builtin.Int{{[18]}})
+// CHECK: [[BOOL:%.*]] = struct $ObjCBool ([[VALUE]] : ${{Bool|UInt8}})
+// CHECK: br bb6([[BOOL]] : $ObjCBool)
+// CHECK: bb6([[BOOL:%.*]] : $ObjCBool):
+// CHECK: return [[BOOL]] : $ObjCBool
+
+ @objc func badDescription() throws -> String {
+ throw NSError(domain: "", code: 1, userInfo: [:])
+ }
+// CHECK-LABEL: sil hidden [thunk] @$SSo8NSObjectC14foreign_errorsE14badDescriptionSSyKFTo : $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, NSObject) -> @autoreleased Optional<NSString> {
+// CHECK: bb0([[UNOWNED_ARG0:%.*]] : $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, [[UNOWNED_ARG1:%.*]] : $NSObject):
+// CHECK: [[ARG1:%.*]] = copy_value [[UNOWNED_ARG1]]
+// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
+// CHECK: [[T0:%.*]] = function_ref @$SSo8NSObjectC14foreign_errorsE14badDescriptionSSyKF : $@convention(method) (@guaranteed NSObject) -> (@owned String, @error Error)
+// CHECK: try_apply [[T0]]([[BORROWED_ARG1]]) : $@convention(method) (@guaranteed NSObject) -> (@owned String, @error Error), normal [[NORMAL_BB:bb[0-9][0-9]*]], error [[ERROR_BB:bb[0-9][0-9]*]]
+//
+// CHECK: [[NORMAL_BB]]([[RESULT:%.*]] : $String):
+// CHECK: [[T0:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
+// CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+// CHECK: [[T1:%.*]] = apply [[T0]]([[BORROWED_RESULT]])
+// CHECK: [[T2:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[T1]] : $NSString
+// CHECK: end_borrow [[BORROWED_RESULT]] from [[RESULT]]
+// CHECK: destroy_value [[RESULT]]
+// CHECK: br bb6([[T2]] : $Optional<NSString>)
+//
+// CHECK: [[ERROR_BB]]([[ERR:%.*]] : $Error):
+// CHECK: switch_enum [[UNOWNED_ARG0]] : $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9][0-9]*]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9][0-9]*]]
+//
+// CHECK: [[SOME_BB]]([[UNWRAPPED_OUT:%.+]] : $AutoreleasingUnsafeMutablePointer<Optional<NSError>>):
+// CHECK: [[T0:%.*]] = function_ref @$S10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF : $@convention(thin) (@guaranteed Error) -> @owned NSError
+// CHECK: [[T1:%.*]] = apply [[T0]]([[ERR]])
+// CHECK: [[OBJCERR:%.*]] = enum $Optional<NSError>, #Optional.some!enumelt.1, [[T1]] : $NSError
+// CHECK: [[TEMP:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: store [[OBJCERR]] to [init] [[TEMP]]
+// CHECK: [[SETTER:%.*]] = function_ref @$Ss33AutoreleasingUnsafeMutablePointerV7pointeexvs :
+// CHECK: apply [[SETTER]]<Optional<NSError>>([[TEMP]], [[UNWRAPPED_OUT]])
+// CHECK: dealloc_stack [[TEMP]]
+// CHECK: br bb5
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: destroy_value [[ERR]] : $Error
+// CHECK: br bb5
+//
+// CHECK: bb5:
+// CHECK: [[T0:%.*]] = enum $Optional<NSString>, #Optional.none!enumelt
+// CHECK: br bb6([[T0]] : $Optional<NSString>)
+//
+// CHECK: bb6([[T0:%.*]] : $Optional<NSString>):
+// CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
+// CHECK: destroy_value [[ARG1]]
+// CHECK: return [[T0]] : $Optional<NSString>
+
+// CHECK-LABEL: sil hidden [thunk] @$SSo8NSObjectC14foreign_errorsE7takeIntyySiKFTo : $@convention(objc_method) (Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, NSObject) -> ObjCBool
+// CHECK: bb0([[I:%[0-9]+]] : $Int, [[ERROR:%[0-9]+]] : $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, [[SELF:%[0-9]+]] : $NSObject)
+ @objc func takeInt(_ i: Int) throws { }
+
+// CHECK-LABEL: sil hidden [thunk] @$SSo8NSObjectC14foreign_errorsE10takeDouble_3int7closureySd_S3iXEtKFTo : $@convention(objc_method) (Double, Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @convention(block) @noescape (Int) -> Int, NSObject) -> ObjCBool
+// CHECK: bb0([[D:%[0-9]+]] : $Double, [[INT:%[0-9]+]] : $Int, [[ERROR:%[0-9]+]] : $Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, [[CLOSURE:%[0-9]+]] : $@convention(block) @noescape (Int) -> Int, [[SELF:%[0-9]+]] : $NSObject):
+ @objc func takeDouble(_ d: Double, int: Int, closure: (Int) -> Int) throws {
+ throw NSError(domain: "", code: 1, userInfo: [:])
+ }
+}
+
+let fn = ErrorProne.fail
+// CHECK-LABEL: sil shared [serializable] [thunk] @$SSo10ErrorProneC4failyyKFZTcTO : $@convention(thin) (@thick ErrorProne.Type) -> @owned @callee_guaranteed () -> @error Error
+// CHECK: [[T0:%.*]] = function_ref @$SSo10ErrorProneC4failyyKFZTO : $@convention(method) (@thick ErrorProne.Type) -> @error Error
+// CHECK-NEXT: [[T1:%.*]] = partial_apply [callee_guaranteed] [[T0]](%0)
+// CHECK-NEXT: return [[T1]]
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @$SSo10ErrorProneC4failyyKFZTO : $@convention(method) (@thick ErrorProne.Type) -> @error Error {
+// CHECK: [[SELF:%.*]] = thick_to_objc_metatype %0 : $@thick ErrorProne.Type to $@objc_metatype ErrorProne.Type
+// CHECK: [[METHOD:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.fail!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
+// CHECK: [[TEMP:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{%.*}}, [[SELF]])
+// CHECK: cond_br
+// CHECK: return
+// CHECK: [[T0:%.*]] = load [take] [[TEMP]]
+// CHECK: [[T1:%.*]] = apply {{%.*}}([[T0]])
+// CHECK: throw [[T1]]
+
+func testArgs() throws {
+ try ErrorProne.consume(nil)
+}
+// CHECK-LABEL: sil hidden @$S14foreign_errors8testArgsyyKF : $@convention(thin) () -> @error Error
+// CHECK: debug_value undef : $Error, var, name "$error", argno 1
+// CHECK: objc_method {{.*}} : $@objc_metatype ErrorProne.Type, #ErrorProne.consume!1.foreign : (ErrorProne.Type) -> (Any?) throws -> (), $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
+
+func testBridgedResult() throws {
+ let array = try ErrorProne.collection(withCount: 0)
+}
+// CHECK-LABEL: sil hidden @$S14foreign_errors17testBridgedResultyyKF : $@convention(thin) () -> @error Error {
+// CHECK: debug_value undef : $Error, var, name "$error", argno 1
+// CHECK: objc_method {{.*}} : $@objc_metatype ErrorProne.Type, #ErrorProne.collection!1.foreign : (ErrorProne.Type) -> (Int) throws -> [Any], $@convention(objc_method) (Int, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> @autoreleased Optional<NSArray>
+
+// rdar://20861374
+// Clear out the self box before delegating.
+class VeryErrorProne : ErrorProne {
+ init(withTwo two: AnyObject?) throws {
+ try super.init(one: two)
+ }
+}
+
+// SEMANTIC SIL TODO: _TFC14foreign_errors14VeryErrorPronec has a lot more going
+// on than is being tested here, we should consider adding FileCheck tests for
+// it.
+
+// CHECK-LABEL: sil hidden @$S14foreign_errors14VeryErrorProneC7withTwoACyXlSg_tKcfc
+// CHECK: bb0([[ARG1:%.*]] : $Optional<AnyObject>, [[ARG2:%.*]] : $VeryErrorProne):
+// CHECK: [[BOX:%.*]] = alloc_box ${ var VeryErrorProne }
+// CHECK: [[MARKED_BOX:%.*]] = mark_uninitialized [derivedself] [[BOX]]
+// CHECK: [[PB:%.*]] = project_box [[MARKED_BOX]]
+// CHECK: store [[ARG2]] to [init] [[PB]]
+// CHECK: [[T0:%.*]] = load [take] [[PB]]
+// CHECK-NEXT: [[T1:%.*]] = upcast [[T0]] : $VeryErrorProne to $ErrorProne
+// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
+// CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
+// CHECK-NOT: [[BOX]]{{^[0-9]}}
+// CHECK-NOT: [[PB]]{{^[0-9]}}
+// CHECK: [[BORROWED_T1:%.*]] = begin_borrow [[T1]]
+// CHECK-NEXT: [[DOWNCAST_BORROWED_T1:%.*]] = unchecked_ref_cast [[BORROWED_T1]] : $ErrorProne to $VeryErrorProne
+// CHECK-NEXT: [[T2:%.*]] = objc_super_method [[DOWNCAST_BORROWED_T1]] : $VeryErrorProne, #ErrorProne.init!initializer.1.foreign : (ErrorProne.Type) -> (Any?) throws -> ErrorProne, $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @owned ErrorProne) -> @owned Optional<ErrorProne>
+// CHECK: end_borrow [[BORROWED_T1]] from [[T1]]
+// CHECK: apply [[T2]]([[ARG1_COPY]], {{%.*}}, [[T1]])
+
+// rdar://21051021
+// CHECK: sil hidden @$S14foreign_errors12testProtocolyySo010ErrorProneD0_pKF : $@convention(thin) (@guaranteed ErrorProneProtocol) -> @error Error
+// CHECK: bb0([[ARG0:%.*]] : $ErrorProneProtocol):
+func testProtocol(_ p: ErrorProneProtocol) throws {
+ // CHECK: [[T0:%.*]] = open_existential_ref [[ARG0]] : $ErrorProneProtocol to $[[OPENED:@opened(.*) ErrorProneProtocol]]
+ // CHECK: [[T1:%.*]] = objc_method [[T0]] : $[[OPENED]], #ErrorProneProtocol.obliterate!1.foreign : {{.*}}
+ // CHECK: apply [[T1]]<[[OPENED]]>({{%.*}}, [[T0]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ErrorProneProtocol> (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, τ_0_0) -> ObjCBool
+ try p.obliterate()
+
+ // CHECK: [[T0:%.*]] = open_existential_ref [[ARG0]] : $ErrorProneProtocol to $[[OPENED:@opened(.*) ErrorProneProtocol]]
+ // CHECK: [[T1:%.*]] = objc_method [[T0]] : $[[OPENED]], #ErrorProneProtocol.invigorate!1.foreign : {{.*}}
+ // CHECK: apply [[T1]]<[[OPENED]]>({{%.*}}, {{%.*}}, [[T0]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ErrorProneProtocol> (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, Optional<@convention(block) () -> ()>, τ_0_0) -> ObjCBool
+ try p.invigorate(callback: {})
+}
+
+// rdar://21144509 - Ensure that overrides of replace-with-() imports are possible.
+class ExtremelyErrorProne : ErrorProne {
+ override func conflict3(_ obj: Any, error: ()) throws {}
+}
+// CHECK-LABEL: sil hidden @$S14foreign_errors19ExtremelyErrorProneC9conflict3_5erroryyp_yttKF
+// CHECK-LABEL: sil hidden [thunk] @$S14foreign_errors19ExtremelyErrorProneC9conflict3_5erroryyp_yttKFTo : $@convention(objc_method) (AnyObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, ExtremelyErrorProne) -> ObjCBool
+
+// These conventions are usable because of swift_error. rdar://21715350
+func testNonNilError() throws -> Float {
+ return try ErrorProne.bounce()
+}
+// CHECK-LABEL: sil hidden @$S14foreign_errors15testNonNilErrorSfyKF :
+// CHECK: [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.bounce!1.foreign : (ErrorProne.Type) -> () throws -> Float, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Float
+// CHECK: [[RESULT:%.*]] = apply [[T1]](
+// CHECK: assign {{%.*}} to [[OPTERR]]
+// CHECK: [[T0:%.*]] = load [take] [[OPTERR]]
+// CHECK: switch_enum [[T0]] : $Optional<NSError>, case #Optional.some!enumelt.1: [[ERROR_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NORMAL_BB:bb[0-9]+]]
+// CHECK: [[NORMAL_BB]]:
+// CHECK-NOT: destroy_value
+// CHECK: return [[RESULT]]
+// CHECK: [[ERROR_BB]]
+
+func testPreservedResult() throws -> CInt {
+ return try ErrorProne.ounce()
+}
+// CHECK-LABEL: sil hidden @$S14foreign_errors19testPreservedResults5Int32VyKF
+// CHECK: [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.ounce!1.foreign : (ErrorProne.Type) -> () throws -> Int32, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
+// CHECK: [[RESULT:%.*]] = apply [[T1]](
+// CHECK: [[T0:%.*]] = struct_extract [[RESULT]]
+// CHECK: [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
+// CHECK: [[T2:%.*]] = builtin "cmp_ne_Int32"([[T0]] : $[[PRIM]], [[T1]] : $[[PRIM]])
+// CHECK: cond_br [[T2]], [[NORMAL_BB:bb[0-9]+]], [[ERROR_BB:bb[0-9]+]]
+// CHECK: [[NORMAL_BB]]:
+// CHECK-NOT: destroy_value
+// CHECK: return [[RESULT]]
+// CHECK: [[ERROR_BB]]
+
+func testPreservedResultBridged() throws -> Int {
+ return try ErrorProne.ounceWord()
+}
+
+// CHECK-LABEL: sil hidden @$S14foreign_errors26testPreservedResultBridgedSiyKF
+// CHECK: [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.ounceWord!1.foreign : (ErrorProne.Type) -> () throws -> Int, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int
+// CHECK: [[RESULT:%.*]] = apply [[T1]](
+// CHECK: [[T0:%.*]] = struct_extract [[RESULT]]
+// CHECK: [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
+// CHECK: [[T2:%.*]] = builtin "cmp_ne_Int{{.*}}"([[T0]] : $[[PRIM]], [[T1]] : $[[PRIM]])
+// CHECK: cond_br [[T2]], [[NORMAL_BB:bb[0-9]+]], [[ERROR_BB:bb[0-9]+]]
+// CHECK: [[NORMAL_BB]]:
+// CHECK-NOT: destroy_value
+// CHECK: return [[RESULT]]
+// CHECK: [[ERROR_BB]]
+
+func testPreservedResultInverted() throws {
+ try ErrorProne.once()
+}
+
+// CHECK-LABEL: sil hidden @$S14foreign_errors27testPreservedResultInvertedyyKF
+// CHECK: [[OPTERR:%.*]] = alloc_stack $Optional<NSError>
+// CHECK: [[T0:%.*]] = metatype $@objc_metatype ErrorProne.Type
+// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@objc_metatype ErrorProne.Type, #ErrorProne.once!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
+// CHECK: [[RESULT:%.*]] = apply [[T1]](
+// CHECK: [[T0:%.*]] = struct_extract [[RESULT]]
+// CHECK: [[T1:%.*]] = integer_literal $[[PRIM:Builtin.Int[0-9]+]], 0
+// CHECK: [[T2:%.*]] = builtin "cmp_ne_Int32"([[T0]] : $[[PRIM]], [[T1]] : $[[PRIM]])
+// CHECK: cond_br [[T2]], [[ERROR_BB:bb[0-9]+]], [[NORMAL_BB:bb[0-9]+]]
+// CHECK: [[NORMAL_BB]]:
+// CHECK-NOT: destroy_value
+// CHECK: return {{%.+}} : $()
+// CHECK: [[ERROR_BB]]
+
+// Make sure that we do not crash when emitting the error value here.
+//
+// TODO: Add some additional filecheck tests.
+extension NSURL {
+ func resourceValue<T>(forKey key: String) -> T? {
+ var prop: AnyObject? = nil
+ _ = try? self.getResourceValue(&prop, forKey: key)
+ return prop as? T
+ }
+}
diff --git a/test/SILGen/plus_zero_function_conversion.swift b/test/SILGen/plus_zero_function_conversion.swift
new file mode 100644
index 0000000..a3dc163
--- /dev/null
+++ b/test/SILGen/plus_zero_function_conversion.swift
@@ -0,0 +1,643 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -primary-file %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -enable-sil-ownership -primary-file %s
+
+// Check SILGen against various FunctionConversionExprs emitted by Sema.
+
+// ==== Representation conversions
+
+// CHECK-LABEL: sil hidden @$S19function_conversion7cToFuncyS2icS2iXCF : $@convention(thin) (@convention(c) (Int) -> Int) -> @owned @callee_guaranteed (Int) -> Int
+// CHECK: [[THUNK:%.*]] = function_ref @$SS2iIetCyd_S2iIegyd_TR
+// CHECK: [[FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]](%0)
+// CHECK: return [[FUNC]]
+func cToFunc(_ arg: @escaping @convention(c) (Int) -> Int) -> (Int) -> Int {
+ return arg
+}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion8cToBlockyS2iXBS2iXCF : $@convention(thin) (@convention(c) (Int) -> Int) -> @owned @convention(block) (Int) -> Int
+// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage
+// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]]
+// CHECK: [[COPY:%.*]] = copy_block [[BLOCK]] : $@convention(block) (Int) -> Int
+// CHECK: return [[COPY]]
+func cToBlock(_ arg: @escaping @convention(c) (Int) -> Int) -> @convention(block) (Int) -> Int {
+ return arg
+}
+
+// ==== Throws variance
+
+// CHECK-LABEL: sil hidden @$S19function_conversion12funcToThrowsyyyKcyycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @owned @callee_guaranteed () -> @error Error
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed () -> ()):
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[FUNC:%.*]] = convert_function [[ARG_COPY]] : $@callee_guaranteed () -> () to $@callee_guaranteed () -> @error Error
+// CHECK: return [[FUNC]]
+// CHECK: } // end sil function '$S19function_conversion12funcToThrowsyyyKcyycF'
+func funcToThrows(_ x: @escaping () -> ()) -> () throws -> () {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion12thinToThrowsyyyKXfyyXfF : $@convention(thin) (@convention(thin) () -> ()) -> @convention(thin) () -> @error Error
+// CHECK: [[FUNC:%.*]] = convert_function %0 : $@convention(thin) () -> () to $@convention(thin) () -> @error Error
+// CHECK: return [[FUNC]] : $@convention(thin) () -> @error Error
+func thinToThrows(_ x: @escaping @convention(thin) () -> ()) -> @convention(thin) () throws -> () {
+ return x
+}
+
+// FIXME: triggers an assert because we always do a thin to thick conversion on DeclRefExprs
+/*
+func thinFunc() {}
+
+func thinToThrows() {
+ let _: @convention(thin) () -> () = thinFunc
+}
+*/
+
+// ==== Class downcasts and upcasts
+
+class Feral {}
+class Domesticated : Feral {}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion12funcToUpcastyAA5FeralCycAA12DomesticatedCycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> @owned Domesticated) -> @owned @callee_guaranteed () -> @owned Feral {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed () -> @owned Domesticated):
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[FUNC:%.*]] = convert_function [[ARG_COPY]] : $@callee_guaranteed () -> @owned Domesticated to $@callee_guaranteed () -> @owned Feral
+// CHECK: return [[FUNC]]
+// CHECK: } // end sil function '$S19function_conversion12funcToUpcastyAA5FeralCycAA12DomesticatedCycF'
+func funcToUpcast(_ x: @escaping () -> Domesticated) -> () -> Feral {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion12funcToUpcastyyAA12DomesticatedCcyAA5FeralCcF : $@convention(thin) (@guaranteed @callee_guaranteed (@guaranteed Feral) -> ()) -> @owned @callee_guaranteed (@guaranteed Domesticated) -> ()
+// CHECK: bb0([[ARG:%.*]] :
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[FUNC:%.*]] = convert_function [[ARG_COPY]] : $@callee_guaranteed (@guaranteed Feral) -> () to $@callee_guaranteed (@guaranteed Domesticated) -> (){{.*}}
+// CHECK: return [[FUNC]]
+func funcToUpcast(_ x: @escaping (Feral) -> ()) -> (Domesticated) -> () {
+ return x
+}
+
+// ==== Optionals
+
+struct Trivial {
+ let n: Int8
+}
+
+class C {
+ let n: Int8
+
+ init(n: Int8) {
+ self.n = n
+ }
+}
+
+struct Loadable {
+ let c: C
+
+ var n: Int8 {
+ return c.n
+ }
+
+ init(n: Int8) {
+ c = C(n: n)
+ }
+}
+
+struct AddrOnly {
+ let a: Any
+
+ var n: Int8 {
+ return a as! Int8
+ }
+
+ init(n: Int8) {
+ a = n
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion19convOptionalTrivialyyAA0E0VADSgcF
+func convOptionalTrivial(_ t1: @escaping (Trivial?) -> Trivial) {
+// CHECK: function_ref @$S19function_conversion7TrivialVSgACIegyd_AcDIegyd_TR
+// CHECK: partial_apply
+ let _: (Trivial) -> Trivial? = t1
+
+// CHECK: function_ref @$S19function_conversion7TrivialVSgACIegyd_A2DIegyd_TR
+// CHECK: partial_apply
+ let _: (Trivial?) -> Trivial? = t1
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion7TrivialVSgACIegyd_AcDIegyd_TR : $@convention(thin) (Trivial, @guaranteed @callee_guaranteed (Optional<Trivial>) -> Trivial) -> Optional<Trivial>
+// CHECK: [[ENUM:%.*]] = enum $Optional<Trivial>
+// CHECK-NEXT: apply %1([[ENUM]])
+// CHECK-NEXT: enum $Optional<Trivial>
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion7TrivialVSgACIegyd_A2DIegyd_TR : $@convention(thin) (Optional<Trivial>, @guaranteed @callee_guaranteed (Optional<Trivial>) -> Trivial) -> Optional<Trivial>
+// CHECK: apply %1(%0)
+// CHECK-NEXT: enum $Optional<Trivial>
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil hidden @$S19function_conversion20convOptionalLoadableyyAA0E0VADSgcF
+func convOptionalLoadable(_ l1: @escaping (Loadable?) -> Loadable) {
+// CHECK: function_ref @$S19function_conversion8LoadableVSgACIeggo_AcDIeggo_TR
+// CHECK: partial_apply
+ let _: (Loadable) -> Loadable? = l1
+
+// CHECK: function_ref @$S19function_conversion8LoadableVSgACIeggo_A2DIeggo_TR
+// CHECK: partial_apply
+ let _: (Loadable?) -> Loadable? = l1
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion8LoadableVSgACIeggo_A2DIeggo_TR : $@convention(thin) (@guaranteed Optional<Loadable>, @guaranteed @callee_guaranteed (@guaranteed Optional<Loadable>) -> @owned Loadable) -> @owned Optional<Loadable>
+// CHECK: apply %1(%0)
+// CHECK-NEXT: enum $Optional<Loadable>
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil hidden @$S19function_conversion20convOptionalAddrOnlyyyAA0eF0VADSgcF
+func convOptionalAddrOnly(_ a1: @escaping (AddrOnly?) -> AddrOnly) {
+// CHECK: function_ref @$S19function_conversion8AddrOnlyVSgACIegnr_A2DIegnr_TR
+// CHECK: partial_apply
+ let _: (AddrOnly?) -> AddrOnly? = a1
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion8AddrOnlyVSgACIegnr_A2DIegnr_TR : $@convention(thin) (@in_guaranteed Optional<AddrOnly>, @guaranteed @callee_guaranteed (@in_guaranteed Optional<AddrOnly>) -> @out AddrOnly) -> @out Optional<AddrOnly>
+// CHECK: [[TEMP:%.*]] = alloc_stack $AddrOnly
+// CHECK-NEXT: apply %2([[TEMP]], %1)
+// CHECK-NEXT: init_enum_data_addr %0 : $*Optional<AddrOnly>
+// CHECK-NEXT: copy_addr [take] {{.*}} to [initialization] {{.*}} : $*AddrOnly
+// CHECK-NEXT: inject_enum_addr %0 : $*Optional<AddrOnly>
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: dealloc_stack {{.*}} : $*AddrOnly
+// CHECK-NEXT: return
+
+// ==== Existentials
+
+protocol Q {
+ var n: Int8 { get }
+}
+
+protocol P : Q {}
+
+extension Trivial : P {}
+extension Loadable : P {}
+extension AddrOnly : P {}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion22convExistentialTrivial_2t3yAA0E0VAA1Q_pc_AeaF_pSgctF
+func convExistentialTrivial(_ t2: @escaping (Q) -> Trivial, t3: @escaping (Q?) -> Trivial) {
+// CHECK: function_ref @$S19function_conversion1Q_pAA7TrivialVIegnd_AdA1P_pIegyr_TR
+// CHECK: partial_apply
+ let _: (Trivial) -> P = t2
+
+// CHECK: function_ref @$S19function_conversion1Q_pSgAA7TrivialVIegnd_AESgAA1P_pIegyr_TR
+// CHECK: partial_apply
+ let _: (Trivial?) -> P = t3
+
+// CHECK: function_ref @$S19function_conversion1Q_pAA7TrivialVIegnd_AA1P_pAaE_pIegnr_TR
+// CHECK: partial_apply
+ let _: (P) -> P = t2
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pAA7TrivialVIegnd_AdA1P_pIegyr_TR : $@convention(thin) (Trivial, @guaranteed @callee_guaranteed (@in_guaranteed Q) -> Trivial) -> @out P
+// CHECK: alloc_stack $Q
+// CHECK-NEXT: init_existential_addr
+// CHECK-NEXT: store
+// CHECK-NEXT: apply
+// CHECK-NEXT: init_existential_addr
+// CHECK-NEXT: store
+// CHECK: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pSgAA7TrivialVIegnd_AESgAA1P_pIegyr_TR
+// CHECK: switch_enum
+// CHECK: bb1([[TRIVIAL:%.*]] : @trivial $Trivial):
+// CHECK: init_existential_addr
+// CHECK: init_enum_data_addr
+// CHECK: copy_addr
+// CHECK: inject_enum_addr
+// CHECK: bb2:
+// CHECK: inject_enum_addr
+// CHECK: bb3:
+// CHECK: apply
+// CHECK: init_existential_addr
+// CHECK: store
+// CHECK: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pAA7TrivialVIegnd_AA1P_pAaE_pIegnr_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in_guaranteed Q) -> Trivial) -> @out P
+// CHECK: [[TMP:%.*]] = alloc_stack $Q
+// CHECK-NEXT: open_existential_addr immutable_access %1 : $*P
+// CHECK-NEXT: init_existential_addr [[TMP]] : $*Q
+// CHECK-NEXT: copy_addr {{.*}} to [initialization] {{.*}}
+// CHECK-NEXT: apply
+// CHECK-NEXT: init_existential_addr
+// CHECK-NEXT: store
+// CHECK: destroy_addr
+// CHECK: return
+
+// ==== Existential metatypes
+
+// CHECK-LABEL: sil hidden @$S19function_conversion23convExistentialMetatypeyyAA7TrivialVmAA1Q_pXpSgcF
+func convExistentialMetatype(_ em: @escaping (Q.Type?) -> Trivial.Type) {
+// CHECK: function_ref @$S19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtAA1P_pXmTIegyd_TR
+// CHECK: partial_apply
+ let _: (Trivial.Type) -> P.Type = em
+
+// CHECK: function_ref @$S19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtSgAA1P_pXmTIegyd_TR
+// CHECK: partial_apply
+ let _: (Trivial.Type?) -> P.Type = em
+
+// CHECK: function_ref @$S19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AA1P_pXmTAaF_pXmTIegyd_TR
+// CHECK: partial_apply
+ let _: (P.Type) -> P.Type = em
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtAA1P_pXmTIegyd_TR : $@convention(thin) (@thin Trivial.Type, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type
+// CHECK: [[META:%.*]] = metatype $@thick Trivial.Type
+// CHECK-NEXT: init_existential_metatype [[META]] : $@thick Trivial.Type, $@thick Q.Type
+// CHECK-NEXT: enum $Optional<@thick Q.Type>
+// CHECK-NEXT: apply
+// CHECK-NEXT: metatype $@thick Trivial.Type
+// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AEXMtSgAA1P_pXmTIegyd_TR : $@convention(thin) (Optional<@thin Trivial.Type>, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type
+// CHECK: switch_enum %0 : $Optional<@thin Trivial.Type>
+// CHECK: bb1([[META:%.*]] : @trivial $@thin Trivial.Type):
+// CHECK-NEXT: metatype $@thick Trivial.Type
+// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick Q.Type
+// CHECK-NEXT: enum $Optional<@thick Q.Type>
+// CHECK: bb2:
+// CHECK-NEXT: enum $Optional<@thick Q.Type>
+// CHECK: bb3({{.*}}):
+// CHECK-NEXT: apply
+// CHECK-NEXT: metatype $@thick Trivial.Type
+// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pXmTSgAA7TrivialVXMtIegyd_AA1P_pXmTAaF_pXmTIegyd_TR : $@convention(thin) (@thick P.Type, @guaranteed @callee_guaranteed (Optional<@thick Q.Type>) -> @thin Trivial.Type) -> @thick P.Type
+// CHECK: open_existential_metatype %0 : $@thick P.Type to $@thick (@opened({{.*}}) P).Type
+// CHECK-NEXT: init_existential_metatype %2 : $@thick (@opened({{.*}}) P).Type, $@thick Q.Type
+// CHECK-NEXT: enum $Optional<@thick Q.Type>
+// CHECK-NEXT: apply %1
+// CHECK-NEXT: metatype $@thick Trivial.Type
+// CHECK-NEXT: init_existential_metatype {{.*}} : $@thick Trivial.Type, $@thick P.Type
+// CHECK-NEXT: return
+
+// ==== Class metatype upcasts
+
+class Parent {}
+class Child : Parent {}
+
+// Note: we add a Trivial => Trivial? conversion here to force a thunk
+// to be generated
+
+// CHECK-LABEL: sil hidden @$S19function_conversion18convUpcastMetatype_2c5yAA5ChildCmAA6ParentCm_AA7TrivialVSgtc_AEmAGmSg_AJtctF
+func convUpcastMetatype(_ c4: @escaping (Parent.Type, Trivial?) -> Child.Type,
+ c5: @escaping (Parent.Type?, Trivial?) -> Child.Type) {
+// CHECK: function_ref @$S19function_conversion6ParentCXMTAA7TrivialVSgAA5ChildCXMTIegyyd_AHXMTAeCXMTIegyyd_TR
+// CHECK: partial_apply
+ let _: (Child.Type, Trivial) -> Parent.Type = c4
+
+// CHECK: function_ref @$S19function_conversion6ParentCXMTSgAA7TrivialVSgAA5ChildCXMTIegyyd_AIXMTAfCXMTIegyyd_TR
+// CHECK: partial_apply
+ let _: (Child.Type, Trivial) -> Parent.Type = c5
+
+// CHECK: function_ref @$S19function_conversion6ParentCXMTSgAA7TrivialVSgAA5ChildCXMTIegyyd_AIXMTSgAfDIegyyd_TR
+// CHECK: partial_apply
+ let _: (Child.Type?, Trivial) -> Parent.Type? = c5
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion6ParentCXMTAA7TrivialVSgAA5ChildCXMTIegyyd_AHXMTAeCXMTIegyyd_TR : $@convention(thin) (@thick Child.Type, Trivial, @guaranteed @callee_guaranteed (@thick Parent.Type, Optional<Trivial>) -> @thick Child.Type) -> @thick Parent.Type
+// CHECK: upcast %0 : $@thick Child.Type to $@thick Parent.Type
+// CHECK: apply
+// CHECK: upcast {{.*}} : $@thick Child.Type to $@thick Parent.Type
+// CHECK: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion6ParentCXMTSgAA7TrivialVSgAA5ChildCXMTIegyyd_AIXMTAfCXMTIegyyd_TR : $@convention(thin) (@thick Child.Type, Trivial, @guaranteed @callee_guaranteed (Optional<@thick Parent.Type>, Optional<Trivial>) -> @thick Child.Type) -> @thick Parent.Type
+// CHECK: upcast %0 : $@thick Child.Type to $@thick Parent.Type
+// CHECK: enum $Optional<@thick Parent.Type>
+// CHECK: apply
+// CHECK: upcast {{.*}} : $@thick Child.Type to $@thick Parent.Type
+// CHECK: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion6ParentCXMTSgAA7TrivialVSgAA5ChildCXMTIegyyd_AIXMTSgAfDIegyyd_TR : $@convention(thin) (Optional<@thick Child.Type>, Trivial, @guaranteed @callee_guaranteed (Optional<@thick Parent.Type>, Optional<Trivial>) -> @thick Child.Type) -> Optional<@thick Parent.Type>
+// CHECK: unchecked_trivial_bit_cast %0 : $Optional<@thick Child.Type> to $Optional<@thick Parent.Type>
+// CHECK: apply
+// CHECK: upcast {{.*}} : $@thick Child.Type to $@thick Parent.Type
+// CHECK: enum $Optional<@thick Parent.Type>
+// CHECK: return
+
+// ==== Function to existential -- make sure we maximally abstract it
+
+// CHECK-LABEL: sil hidden @$S19function_conversion19convFuncExistentialyyS2icypcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed Any) -> @owned @callee_guaranteed (Int) -> Int) -> ()
+// CHECK: bb0([[ARG:%.*]] :
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[REABSTRACT_THUNK:%.*]] = function_ref @$SypS2iIegyd_Iegno_S2iIgyd_ypIegyr_TR
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT_THUNK]]([[ARG_COPY]])
+// CHECK: destroy_value [[PA]]
+// CHECK: } // end sil function '$S19function_conversion19convFuncExistentialyyS2icypcF'
+func convFuncExistential(_ f1: @escaping (Any) -> (Int) -> Int) {
+ let _: ((Int) -> Int) -> Any = f1
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypS2iIegyd_Iegno_S2iIgyd_ypIegyr_TR : $@convention(thin) (@noescape @callee_guaranteed (Int) -> Int, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> @owned @callee_guaranteed (Int) -> Int) -> @out Any
+// CHECK: alloc_stack $Any
+// CHECK: function_ref @$SS2iIgyd_S2iIegnr_TR
+// CHECK-NEXT: partial_apply
+// CHECK-NEXT: convert_escape_to_noescape
+// CHECK-NEXT: init_existential_addr %3 : $*Any, $(Int) -> Int
+// CHECK-NEXT: store
+// CHECK-NEXT: apply
+// CHECK: function_ref @$SS2iIegyd_S2iIegnr_TR
+// CHECK-NEXT: partial_apply
+// CHECK-NEXT: init_existential_addr %0 : $*Any, $(Int) -> Int
+// CHECK-NEXT: store {{.*}} to {{.*}} : $*@callee_guaranteed (@in_guaranteed Int) -> @out Int
+// CHECK: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS2iIegyd_S2iIegnr_TR : $@convention(thin) (@in_guaranteed Int, @guaranteed @callee_guaranteed (Int) -> Int) -> @out Int
+// CHECK: [[LOADED:%.*]] = load [trivial] %1 : $*Int
+// CHECK-NEXT: apply %2([[LOADED]])
+// CHECK-NEXT: store {{.*}} to [trivial] %0
+// CHECK-NEXT: [[VOID:%.*]] = tuple ()
+// CHECK: return [[VOID]]
+
+// ==== Class-bound archetype upcast
+
+// CHECK-LABEL: sil hidden @$S19function_conversion29convClassBoundArchetypeUpcast{{[_0-9a-zA-Z]*}}F
+func convClassBoundArchetypeUpcast<T : Parent>(_ f1: @escaping (Parent) -> (T, Trivial)) {
+// CHECK: function_ref @$S19function_conversion6ParentCxAA7TrivialVIeggod_xAcESgIeggod_ACRbzlTR
+// CHECK: partial_apply
+ let _: (T) -> (Parent, Trivial?) = f1
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion6ParentCxAA7TrivialVIeggod_xAcESgIeggod_ACRbzlTR : $@convention(thin) <T where T : Parent> (@guaranteed T, @guaranteed @callee_guaranteed (@guaranteed Parent) -> (@owned T, Trivial)) -> (@owned Parent, Optional<Trivial>)
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T, [[CLOSURE:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed Parent) -> (@owned T, Trivial)):
+// CHECK: [[CASTED_ARG:%.*]] = upcast [[ARG]] : $T to $Parent
+// CHECK: [[RESULT:%.*]] = apply %1([[CASTED_ARG]])
+// CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]] : $(T, Trivial)
+// CHECK: [[FIRST_RESULT:%.*]] = tuple_extract [[BORROWED_RESULT]] : $(T, Trivial), 0
+// CHECK: [[COPIED_FIRST_RESULT:%.*]] = copy_value [[FIRST_RESULT]]
+// CHECK: tuple_extract [[BORROWED_RESULT]] : $(T, Trivial), 1
+// CHECK: destroy_value [[RESULT]]
+// CHECK: [[CAST_COPIED_FIRST_RESULT:%.*]] = upcast [[COPIED_FIRST_RESULT]] : $T to $Parent
+// CHECK: enum $Optional<Trivial>
+// CHECK: [[RESULT:%.*]] = tuple ([[CAST_COPIED_FIRST_RESULT]] : $Parent, {{.*}} : $Optional<Trivial>)
+// CHECK: return [[RESULT]]
+
+// CHECK-LABEL: sil hidden @$S19function_conversion37convClassBoundMetatypeArchetypeUpcast{{[_0-9a-zA-Z]*}}F
+func convClassBoundMetatypeArchetypeUpcast<T : Parent>(_ f1: @escaping (Parent.Type) -> (T.Type, Trivial)) {
+// CHECK: function_ref @$S19function_conversion6ParentCXMTxXMTAA7TrivialVIegydd_xXMTACXMTAESgIegydd_ACRbzlTR
+// CHECK: partial_apply
+ let _: (T.Type) -> (Parent.Type, Trivial?) = f1
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion6ParentCXMTxXMTAA7TrivialVIegydd_xXMTACXMTAESgIegydd_ACRbzlTR : $@convention(thin) <T where T : Parent> (@thick T.Type, @guaranteed @callee_guaranteed (@thick Parent.Type) -> (@thick T.Type, Trivial)) -> (@thick Parent.Type, Optional<Trivial>)
+// CHECK: upcast %0 : $@thick T.Type to $@thick Parent.Type
+// CHECK-NEXT: apply
+// CHECK-NEXT: tuple_extract
+// CHECK-NEXT: tuple_extract
+// CHECK-NEXT: upcast {{.*}} : $@thick T.Type to $@thick Parent.Type
+// CHECK-NEXT: enum $Optional<Trivial>
+// CHECK-NEXT: tuple
+// CHECK-NEXT: return
+
+// ==== Make sure we destructure one-element tuples
+
+// CHECK-LABEL: sil hidden @$S19function_conversion15convTupleScalar_2f22f3yyAA1Q_pc_yAaE_pcySi_SitSgctF
+// CHECK: function_ref @$S19function_conversion1Q_pIegn_AA1P_pIegn_TR
+// CHECK: function_ref @$S19function_conversion1Q_pIegn_AA1P_pIegn_TR
+// CHECK: function_ref @$SSi_SitSgIegy_S2iIegyy_TR
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S19function_conversion1Q_pIegn_AA1P_pIegn_TR : $@convention(thin) (@in_guaranteed P, @guaranteed @callee_guaranteed (@in_guaranteed Q) -> ()) -> ()
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSi_SitSgIegy_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (Optional<(Int, Int)>) -> ()) -> ()
+
+func convTupleScalar(_ f1: @escaping (Q) -> (),
+ f2: @escaping (_ parent: Q) -> (),
+ f3: @escaping (_ tuple: (Int, Int)?) -> ()) {
+ let _: (P) -> () = f1
+ let _: (P) -> () = f2
+ let _: (Int, Int) -> () = f3
+}
+
+func convTupleScalarOpaque<T>(_ f: @escaping (T...) -> ()) -> ((_ args: T...) -> ())? {
+ return f
+}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion25convTupleToOptionalDirectySi_SitSgSicSi_SitSicF : $@convention(thin) (@guaranteed @callee_guaranteed (Int) -> (Int, Int)) -> @owned @callee_guaranteed (Int) -> Optional<(Int, Int)>
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (Int) -> (Int, Int)):
+// CHECK: [[FN:%.*]] = copy_value [[ARG]]
+// CHECK: [[THUNK_FN:%.*]] = function_ref @$SS3iIegydd_S2i_SitSgIegyd_TR
+// CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[FN]])
+// CHECK-NEXT: return [[THUNK]]
+// CHECK-NEXT: } // end sil function '$S19function_conversion25convTupleToOptionalDirectySi_SitSgSicSi_SitSicF'
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS3iIegydd_S2i_SitSgIegyd_TR : $@convention(thin) (Int, @guaranteed @callee_guaranteed (Int) -> (Int, Int)) -> Optional<(Int, Int)>
+// CHECK: bb0(%0 : @trivial $Int, %1 : @guaranteed $@callee_guaranteed (Int) -> (Int, Int)):
+// CHECK: [[RESULT:%.*]] = apply %1(%0)
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_extract [[RESULT]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_extract [[RESULT]]
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[LEFT]] : $Int, [[RIGHT]] : $Int)
+// CHECK-NEXT: [[OPTIONAL:%.*]] = enum $Optional<(Int, Int)>, #Optional.some!enumelt.1, [[RESULT]]
+// CHECK-NEXT: return [[OPTIONAL]]
+
+func convTupleToOptionalDirect(_ f: @escaping (Int) -> (Int, Int)) -> (Int) -> (Int, Int)? {
+ return f
+}
+
+// CHECK-LABEL: sil hidden @$S19function_conversion27convTupleToOptionalIndirectyx_xtSgxcx_xtxclF : $@convention(thin) <T> (@guaranteed @callee_guaranteed (@in_guaranteed T) -> (@out T, @out T)) -> @owned @callee_guaranteed (@in_guaranteed T) -> @out Optional<(T, T)>
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $@callee_guaranteed (@in_guaranteed T) -> (@out T, @out T)):
+// CHECK: [[FN:%.*]] = copy_value [[ARG]]
+// CHECK: [[THUNK_FN:%.*]] = function_ref @$SxxxIegnrr_xx_xtSgIegnr_lTR
+// CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<T>([[FN]])
+// CHECK-NEXT: return [[THUNK]]
+// CHECK-NEXT: } // end sil function '$S19function_conversion27convTupleToOptionalIndirectyx_xtSgxcx_xtxclF'
+
+// CHECK: sil shared [transparent] [serializable] [reabstraction_thunk] @$SxxxIegnrr_xx_xtSgIegnr_lTR : $@convention(thin) <T> (@in_guaranteed T, @guaranteed @callee_guaranteed (@in_guaranteed T) -> (@out T, @out T)) -> @out Optional<(T, T)>
+// CHECK: bb0(%0 : @trivial $*Optional<(T, T)>, %1 : @trivial $*T, %2 : @guaranteed $@callee_guaranteed (@in_guaranteed T) -> (@out T, @out T)):
+// CHECK: [[OPTIONAL:%.*]] = init_enum_data_addr %0 : $*Optional<(T, T)>, #Optional.some!enumelt.1
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[OPTIONAL]] : $*(T, T), 0
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[OPTIONAL]] : $*(T, T), 1
+// CHECK-NEXT: apply %2([[LEFT]], [[RIGHT]], %1)
+// CHECK-NEXT: inject_enum_addr %0 : $*Optional<(T, T)>, #Optional.some!enumelt.1
+// CHECK-NEXT: [[VOID:%.*]] = tuple ()
+// CHECK: return [[VOID]]
+
+func convTupleToOptionalIndirect<T>(_ f: @escaping (T) -> (T, T)) -> (T) -> (T, T)? {
+ return f
+}
+
+// ==== Make sure we support AnyHashable erasure
+
+// CHECK-LABEL: sil hidden @$S19function_conversion15convAnyHashable1tyx_ts0E0RzlF
+// CHECK: function_ref @$S19function_conversion15convAnyHashable1tyx_ts0E0RzlFSbs0dE0V_AFtcfU_
+// CHECK: function_ref @$Ss11AnyHashableVABSbIegnnd_xxSbIegnnd_s0B0RzlTR
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$Ss11AnyHashableVABSbIegnnd_xxSbIegnnd_s0B0RzlTR : $@convention(thin) <T where T : Hashable> (@in_guaranteed T, @in_guaranteed T, @guaranteed @callee_guaranteed (@in_guaranteed AnyHashable, @in_guaranteed AnyHashable) -> Bool) -> Bool
+// CHECK: alloc_stack $AnyHashable
+// CHECK: function_ref @$Ss21_convertToAnyHashableys0cD0Vxs0D0RzlF
+// CHECK: apply {{.*}}<T>
+// CHECK: alloc_stack $AnyHashable
+// CHECK: function_ref @$Ss21_convertToAnyHashableys0cD0Vxs0D0RzlF
+// CHECK: apply {{.*}}<T>
+// CHECK: return
+
+func convAnyHashable<T : Hashable>(t: T) {
+ let fn: (T, T) -> Bool = {
+ (x: AnyHashable, y: AnyHashable) in x == y
+ }
+}
+
+// ==== Convert exploded tuples to Any or Optional<Any>
+
+// CHECK-LABEL: sil hidden @$S19function_conversion12convTupleAnyyyyyc_Si_SitycyypcyypSgctF
+// CHECK: function_ref @$SIeg_ypIegr_TR
+// CHECK: partial_apply
+// CHECK: function_ref @$SIeg_ypSgIegr_TR
+// CHECK: partial_apply
+// CHECK: function_ref @$SS2iIegdd_ypIegr_TR
+// CHECK: partial_apply
+// CHECK: function_ref @$SS2iIegdd_ypSgIegr_TR
+// CHECK: partial_apply
+// CHECK: function_ref @$SypIegn_S2iIegyy_TR
+// CHECK: partial_apply
+// CHECK: function_ref @$SypSgIegn_S2iIegyy_TR
+// CHECK: partial_apply
+
+func convTupleAny(_ f1: @escaping () -> (),
+ _ f2: @escaping () -> (Int, Int),
+ _ f3: @escaping (Any) -> (),
+ _ f4: @escaping (Any?) -> ()) {
+ let _: () -> Any = f1
+ let _: () -> Any? = f1
+
+ let _: () -> Any = f2
+ let _: () -> Any? = f2
+
+ let _: ((Int, Int)) -> () = f3
+
+ let _: ((Int, Int)) -> () = f4
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SIeg_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Any
+// CHECK: init_existential_addr %0 : $*Any, $()
+// CHECK-NEXT: apply %1()
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SIeg_ypSgIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Optional<Any>
+// CHECK: [[ENUM_PAYLOAD:%.*]] = init_enum_data_addr %0 : $*Optional<Any>, #Optional.some!enumelt.1
+// CHECK-NEXT: init_existential_addr [[ENUM_PAYLOAD]] : $*Any, $()
+// CHECK-NEXT: apply %1()
+// CHECK-NEXT: inject_enum_addr %0 : $*Optional<Any>, #Optional.some!enumelt.1
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS2iIegdd_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Any
+// CHECK: [[ANY_PAYLOAD:%.*]] = init_existential_addr %0
+// CHECK-NEXT: [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: [[RESULT:%.*]] = apply %1()
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_extract [[RESULT]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_extract [[RESULT]]
+// CHECK-NEXT: store [[LEFT:%.*]] to [trivial] [[LEFT_ADDR]]
+// CHECK-NEXT: store [[RIGHT:%.*]] to [trivial] [[RIGHT_ADDR]]
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS2iIegdd_ypSgIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Optional<Any> {
+// CHECK: [[OPTIONAL_PAYLOAD:%.*]] = init_enum_data_addr %0
+// CHECK-NEXT: [[ANY_PAYLOAD:%.*]] = init_existential_addr [[OPTIONAL_PAYLOAD]]
+// CHECK-NEXT: [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: [[RESULT:%.*]] = apply %1()
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_extract [[RESULT]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_extract [[RESULT]]
+// CHECK-NEXT: store [[LEFT:%.*]] to [trivial] [[LEFT_ADDR]]
+// CHECK-NEXT: store [[RIGHT:%.*]] to [trivial] [[RIGHT_ADDR]]
+// CHECK-NEXT: inject_enum_addr %0
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypIegn_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> ()) -> ()
+// CHECK: [[ANY_VALUE:%.*]] = alloc_stack $Any
+// CHECK-NEXT: [[ANY_PAYLOAD:%.*]] = init_existential_addr [[ANY_VALUE]]
+// CHECK-NEXT: [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: store %0 to [trivial] [[LEFT_ADDR]]
+// CHECK-NEXT: [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: store %1 to [trivial] [[RIGHT_ADDR]]
+// CHECK-NEXT: apply %2([[ANY_VALUE]])
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: destroy_addr [[ANY_VALUE]]
+// CHECK-NEXT: dealloc_stack [[ANY_VALUE]]
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypSgIegn_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Optional<Any>) -> ()) -> ()
+// CHECK: [[ANY_VALUE:%.*]] = alloc_stack $Any
+// CHECK-NEXT: [[ANY_PAYLOAD:%.*]] = init_existential_addr [[ANY_VALUE]]
+// CHECK-NEXT: [[LEFT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: store %0 to [trivial] [[LEFT_ADDR]]
+// CHECK-NEXT: [[RIGHT_ADDR:%.*]] = tuple_element_addr [[ANY_PAYLOAD]]
+// CHECK-NEXT: store %1 to [trivial] [[RIGHT_ADDR]]
+// CHECK-NEXT: [[OPTIONAL_VALUE:%.*]] = alloc_stack $Optional<Any>
+// CHECK-NEXT: [[OPTIONAL_PAYLOAD:%.*]] = init_enum_data_addr [[OPTIONAL_VALUE]]
+// CHECK-NEXT: copy_addr [take] [[ANY_VALUE]] to [initialization] [[OPTIONAL_PAYLOAD]]
+// CHECK-NEXT: inject_enum_addr [[OPTIONAL_VALUE]]
+// CHECK-NEXT: apply %2([[OPTIONAL_VALUE]])
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: destroy_addr [[OPTIONAL_VALUE]]
+// CHECK-NEXT: dealloc_stack [[OPTIONAL_VALUE]]
+// CHECK-NEXT: dealloc_stack [[ANY_VALUE]]
+// CHECK-NEXT: return
+
+// ==== Support collection subtyping in function argument position
+
+protocol Z {}
+class A: Z {}
+
+func foo_arr<T: Z>(type: T.Type, _ fn: ([T]?) -> Void) {}
+func foo_map<T: Z>(type: T.Type, _ fn: ([Int: T]) -> Void) {}
+
+func rdar35702810() {
+ let fn_arr: ([Z]?) -> Void = { _ in }
+ let fn_map: ([Int: Z]) -> Void = { _ in }
+
+ // CHECK: function_ref @$Ss15_arrayForceCastySayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ // CHECK: apply %5<A, Z>(%6) : $@convention(thin) <τ_0_0, τ_0_1> (@guaranteed Array<τ_0_0>) -> @owned Array<τ_0_1>
+ foo_arr(type: A.self, fn_arr)
+
+ // CHECK: function_ref @$Ss17_dictionaryUpCastys10DictionaryVyq0_q1_GACyxq_Gs8HashableRzsAFR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK: apply %2<Int, A, Int, Z>(%0) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+ // CHECK: apply %1(%4) : $@callee_guaranteed (@guaranteed Dictionary<Int, Z>) -> ()
+ foo_map(type: A.self, fn_map)
+}
+
+protocol X: Hashable {}
+class B: X {
+ var hashValue: Int { return 42 }
+ static func == (lhs: B, rhs: B) -> Bool {
+ return lhs.hashValue == rhs.hashValue
+ }
+}
+
+func bar_arr<T: X>(type: T.Type, _ fn: ([T]?) -> Void) {}
+func bar_map<T: X>(type: T.Type, _ fn: ([T: Int]) -> Void) {}
+func bar_set<T: X>(type: T.Type, _ fn: (Set<T>) -> Void) {}
+
+func rdar35702810_anyhashable() {
+ let fn_arr: ([AnyHashable]?) -> Void = { _ in }
+ let fn_map: ([AnyHashable: Int]) -> Void = { _ in }
+ let fn_set: (Set<AnyHashable>) -> Void = { _ in }
+
+
+ // CHECK: [[FN:%.*]] = function_ref @$SSays11AnyHashableVGSgIegg_Say19function_conversion1BCGSgIegg_TR : $@convention(thin) (@guaranteed Optional<Array<B>>, @guaranteed @callee_guaranteed (@guaranteed Optional<Array<AnyHashable>>) -> ()) -> ()
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%{{[0-9]+}}) : $@convention(thin) (@guaranteed Optional<Array<B>>, @guaranteed @callee_guaranteed (@guaranteed Optional<Array<AnyHashable>>) -> ()) -> ()
+ // CHECK: convert_escape_to_noescape [[PA]] : $@callee_guaranteed (@guaranteed Optional<Array<B>>) -> () to $@noescape @callee_guaranteed (@guaranteed Optional<Array<B>>) -> ()
+ bar_arr(type: B.self, fn_arr)
+
+ // CHECK: [[FN:%.*]] = function_ref @$Ss10DictionaryVys11AnyHashableVSiGIegg_ABy19function_conversion1BCSiGIegg_TR : $@convention(thin) (@guaranteed Dictionary<B, Int>, @guaranteed @callee_guaranteed (@guaranteed Dictionary<AnyHashable, Int>) -> ()) -> ()
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%{{[0-9]+}}) : $@convention(thin) (@guaranteed Dictionary<B, Int>, @guaranteed @callee_guaranteed (@guaranteed Dictionary<AnyHashable, Int>) -> ()) -> ()
+ // CHECK: convert_escape_to_noescape [[PA]] : $@callee_guaranteed (@guaranteed Dictionary<B, Int>) -> () to $@noescape @callee_guaranteed (@guaranteed Dictionary<B, Int>) -> ()
+ bar_map(type: B.self, fn_map)
+
+ // CHECK: [[FN:%.*]] = function_ref @$Ss3SetVys11AnyHashableVGIegg_ABy19function_conversion1BCGIegg_TR : $@convention(thin) (@guaranteed Set<B>, @guaranteed @callee_guaranteed (@guaranteed Set<AnyHashable>) -> ()) -> ()
+ // CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[FN]](%{{[0-9]+}}) : $@convention(thin) (@guaranteed Set<B>, @guaranteed @callee_guaranteed (@guaranteed Set<AnyHashable>) -> ()) -> ()
+ // CHECK: convert_escape_to_noescape [[PA]] : $@callee_guaranteed (@guaranteed Set<B>) -> () to $@noescape @callee_guaranteed (@guaranteed Set<B>) -> ()
+ bar_set(type: B.self, fn_set)
+}
diff --git a/test/SILGen/plus_zero_function_conversion_objc.swift b/test/SILGen/plus_zero_function_conversion_objc.swift
new file mode 100644
index 0000000..3314382
--- /dev/null
+++ b/test/SILGen/plus_zero_function_conversion_objc.swift
@@ -0,0 +1,118 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-sil-ownership -enable-source-import -emit-silgen -verify | %FileCheck %s
+
+import Foundation
+
+// REQUIRES: objc_interop
+
+// ==== Metatype to object conversions
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc20convMetatypeToObjectyySo8NSObjectCmADcF
+func convMetatypeToObject(_ f: @escaping (NSObject) -> NSObject.Type) {
+// CHECK: function_ref @$SSo8NSObjectCABXMTIeggd_AByXlIeggo_TR
+// CHECK: partial_apply
+ let _: (NSObject) -> AnyObject = f
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSo8NSObjectCABXMTIeggd_AByXlIeggo_TR : $@convention(thin) (@guaranteed NSObject, @guaranteed @callee_guaranteed (@guaranteed NSObject) -> @thick NSObject.Type) -> @owned AnyObject {
+// CHECK: apply %1(%0)
+// CHECK: thick_to_objc_metatype {{.*}} : $@thick NSObject.Type to $@objc_metatype NSObject.Type
+// CHECK: objc_metatype_to_object {{.*}} : $@objc_metatype NSObject.Type to $AnyObject
+// CHECK: return
+
+@objc protocol NSBurrito {}
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc31convExistentialMetatypeToObjectyyAA9NSBurrito_pXpAaC_pcF
+func convExistentialMetatypeToObject(_ f: @escaping (NSBurrito) -> NSBurrito.Type) {
+// CHECK: function_ref @$S24function_conversion_objc9NSBurrito_pAaB_pXmTIeggd_AaB_pyXlIeggo_TR
+// CHECK: partial_apply
+ let _: (NSBurrito) -> AnyObject = f
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S24function_conversion_objc9NSBurrito_pAaB_pXmTIeggd_AaB_pyXlIeggo_TR : $@convention(thin) (@guaranteed NSBurrito, @guaranteed @callee_guaranteed (@guaranteed NSBurrito) -> @thick NSBurrito.Type) -> @owned AnyObject
+// CHECK: apply %1(%0)
+// CHECK: thick_to_objc_metatype {{.*}} : $@thick NSBurrito.Type to $@objc_metatype NSBurrito.Type
+// CHECK: objc_existential_metatype_to_object {{.*}} : $@objc_metatype NSBurrito.Type to $AnyObject
+// CHECK: return
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc28convProtocolMetatypeToObjectyyAA9NSBurrito_pmycF
+func convProtocolMetatypeToObject(_ f: @escaping () -> NSBurrito.Protocol) {
+// CHECK: function_ref @$S24function_conversion_objc9NSBurrito_pXMtIegd_So8ProtocolCIego_TR
+// CHECK: partial_apply
+ let _: () -> Protocol = f
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S24function_conversion_objc9NSBurrito_pXMtIegd_So8ProtocolCIego_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @thin NSBurrito.Protocol) -> @owned Protocol
+// CHECK: apply %0() : $@callee_guaranteed () -> @thin NSBurrito.Protocol
+// CHECK: objc_protocol #NSBurrito : $Protocol
+// CHECK: copy_value
+// CHECK: return
+
+// ==== Representation conversions
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc11funcToBlockyyyXByycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @owned @convention(block) () -> ()
+// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage
+// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]]
+// CHECK: [[COPY:%.*]] = copy_block [[BLOCK]] : $@convention(block) () -> ()
+// CHECK: return [[COPY]]
+func funcToBlock(_ x: @escaping () -> ()) -> @convention(block) () -> () {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc11blockToFuncyyycyyXBF : $@convention(thin) (@guaranteed @convention(block) () -> ()) -> @owned @callee_guaranteed () -> ()
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $@convention(block) () -> ()):
+// CHECK: [[COPIED:%.*]] = copy_block [[ARG]]
+// CHECK: [[BORROWED_COPIED:%.*]] = begin_borrow [[COPIED]]
+// CHECK: [[COPIED_2:%.*]] = copy_value [[BORROWED_COPIED]]
+// CHECK: [[THUNK:%.*]] = function_ref @$SIeyB_Ieg_TR
+// CHECK: [[FUNC:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[COPIED_2]])
+// CHECK: end_borrow [[BORROWED_COPIED]] from [[COPIED]]
+// CHECK: destroy_value [[COPIED]]
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[FUNC]]
+func blockToFunc(_ x: @escaping @convention(block) () -> ()) -> () -> () {
+ return x
+}
+
+// ==== Representation change + function type conversion
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc22blockToFuncExistentialyypycSiyXBF : $@convention(thin) (@guaranteed @convention(block) () -> Int) -> @owned @callee_guaranteed () -> @out Any
+// CHECK: function_ref @$SSiIeyBd_SiIegd_TR
+// CHECK: partial_apply
+// CHECK: function_ref @$SSiIegd_ypIegr_TR
+// CHECK: partial_apply
+// CHECK: return
+func blockToFuncExistential(_ x: @escaping @convention(block) () -> Int) -> () -> Any {
+ return x
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSiIeyBd_SiIegd_TR : $@convention(thin) (@guaranteed @convention(block) () -> Int) -> Int
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSiIegd_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Any
+
+// C function pointer conversions
+
+class A : NSObject {}
+class B : A {}
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc18cFuncPtrConversionyyAA1BCXCyAA1ACXCF
+func cFuncPtrConversion(_ x: @escaping @convention(c) (A) -> ()) -> @convention(c) (B) -> () {
+// CHECK: convert_function %0 : $@convention(c) (A) -> () to $@convention(c) (B) -> ()
+// CHECK: return
+ return x
+}
+
+func cFuncPtr(_ a: A) {}
+
+// CHECK-LABEL: sil hidden @$S24function_conversion_objc19cFuncDeclConversionyAA1BCXCyF
+func cFuncDeclConversion() -> @convention(c) (B) -> () {
+// CHECK: function_ref @$S24function_conversion_objc8cFuncPtryyAA1ACFTo : $@convention(c) (A) -> ()
+// CHECK: convert_function %0 : $@convention(c) (A) -> () to $@convention(c) (B) -> ()
+// CHECK: return
+ return cFuncPtr
+}
+
+func cFuncPtrConversionUnsupported(_ x: @escaping @convention(c) (@convention(block) () -> ()) -> ())
+ -> @convention(c) (@convention(c) () -> ()) -> () {
+ return x // expected-error{{C function pointer signature '@convention(c) (@convention(block) () -> ()) -> ()' is not compatible with expected type '@convention(c) (@convention(c) () -> ()) -> ()'}}
+}
diff --git a/test/SILGen/plus_zero_functions.swift b/test/SILGen/plus_zero_functions.swift
new file mode 100644
index 0000000..e43048d
--- /dev/null
+++ b/test/SILGen/plus_zero_functions.swift
@@ -0,0 +1,592 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-stdlib -parse-as-library -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+import Swift // just for Optional
+
+func markUsed<T>(_ t: T) {}
+
+typealias Int = Builtin.Int64
+typealias Int64 = Builtin.Int64
+typealias Bool = Builtin.Int1
+
+var zero = getInt()
+func getInt() -> Int { return zero }
+
+func standalone_function(_ x: Int, _ y: Int) -> Int {
+ return x
+}
+
+func higher_order_function(_ f: (_ x: Int, _ y: Int) -> Int, _ x: Int, _ y: Int) -> Int {
+ return f(x, y)
+}
+
+func higher_order_function2(_ f: (Int, Int) -> Int, _ x: Int, _ y: Int) -> Int {
+ return f(x, y)
+}
+
+struct SomeStruct {
+ // -- Constructors and methods are uncurried in 'self'
+ // -- Instance methods use 'method' cc
+
+ init(x:Int, y:Int) {}
+
+ mutating
+ func method(_ x: Int) {}
+
+ static func static_method(_ x: Int) {}
+
+ func generic_method<T>(_ x: T) {}
+}
+
+class SomeClass {
+ // -- Constructors and methods are uncurried in 'self'
+ // -- Instance methods use 'method' cc
+
+ // CHECK-LABEL: sil hidden @$S9functions9SomeClassC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
+ // CHECK: bb0(%0 : @trivial $Builtin.Int64, %1 : @trivial $Builtin.Int64, %2 : @trivial $@thick SomeClass.Type):
+
+ // CHECK-LABEL: sil hidden @$S9functions9SomeClassC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (Builtin.Int64, Builtin.Int64, @owned SomeClass) -> @owned SomeClass
+ // CHECK: bb0(%0 : @trivial $Builtin.Int64, %1 : @trivial $Builtin.Int64, %2 : @owned $SomeClass):
+ init(x:Int, y:Int) {}
+
+ // CHECK-LABEL: sil hidden @$S9functions9SomeClassC6method{{[_0-9a-zA-Z]*}}F : $@convention(method) (Builtin.Int64, @guaranteed SomeClass) -> ()
+ // CHECK: bb0(%0 : @trivial $Builtin.Int64, %1 : @guaranteed $SomeClass):
+ func method(_ x: Int) {}
+
+ // CHECK-LABEL: sil hidden @$S9functions9SomeClassC13static_method{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (Builtin.Int64, @thick SomeClass.Type) -> ()
+ // CHECK: bb0(%0 : @trivial $Builtin.Int64, %1 : @trivial $@thick SomeClass.Type):
+ class func static_method(_ x: Int) {}
+
+ var someProperty: Int {
+ get {
+ return zero
+ }
+ set {}
+ }
+
+ subscript(x:Int, y:Int) -> Int {
+ get {
+ return zero
+ }
+ set {}
+ }
+
+ func generic<T>(_ x: T) -> T {
+ return x
+ }
+}
+
+func SomeClassWithBenefits() -> SomeClass.Type {
+ return SomeClass.self
+}
+
+protocol SomeProtocol {
+ func method(_ x: Int)
+ static func static_method(_ x: Int)
+}
+
+struct ConformsToSomeProtocol : SomeProtocol {
+ func method(_ x: Int) { }
+ static func static_method(_ x: Int) { }
+}
+
+class SomeGeneric<T> {
+ init() { }
+ func method(_ x: T) -> T { return x }
+
+ func generic<U>(_ x: U) -> U { return x }
+}
+
+// CHECK-LABEL: sil hidden @$S9functions5calls{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64, Builtin.Int64) -> ()
+func calls(_ i:Int, j:Int, k:Int) {
+ var i = i
+ var j = j
+ var k = k
+ // CHECK: bb0(%0 : @trivial $Builtin.Int64, %1 : @trivial $Builtin.Int64, %2 : @trivial $Builtin.Int64):
+ // CHECK: [[IBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 }
+ // CHECK: [[IADDR:%.*]] = project_box [[IBOX]]
+ // CHECK: [[JBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 }
+ // CHECK: [[JADDR:%.*]] = project_box [[JBOX]]
+ // CHECK: [[KBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 }
+ // CHECK: [[KADDR:%.*]] = project_box [[KBOX]]
+
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
+ // CHECK: apply [[FUNC]]([[I]], [[J]])
+ standalone_function(i, j)
+
+ // -- Curry 'self' onto struct method argument lists.
+
+ // CHECK: [[ST_ADDR:%.*]] = alloc_box ${ var SomeStruct }
+ // CHECK: [[METATYPE:%.*]] = metatype $@thin SomeStruct.Type
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%.*]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%.*]] = load [trivial] [[READJ]]
+ // CHECK: [[CTOR:%.*]] = function_ref @$S9functions10SomeStructV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
+ // CHECK: apply [[CTOR]]([[I]], [[J]], [[METATYPE]]) : $@convention(method) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> SomeStruct
+ var st = SomeStruct(x: i, y: j)
+
+ // -- Use of unapplied struct methods as values.
+
+ // CHECK: [[THUNK:%.*]] = function_ref @$S9functions10SomeStructV6method{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[THUNK_THICK:%.*]] = thin_to_thick_function [[THUNK]]
+ var stm1 = SomeStruct.method
+ stm1(&st)(i)
+
+ // -- Curry 'self' onto method argument lists dispatched using class_method.
+
+ // CHECK: [[CBOX:%[0-9]+]] = alloc_box ${ var SomeClass }
+ // CHECK: [[CADDR:%.*]] = project_box [[CBOX]]
+ // CHECK: [[META:%[0-9]+]] = metatype $@thick SomeClass.Type
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S9functions9SomeClassC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
+ // CHECK: [[C:%[0-9]+]] = apply [[FUNC]]([[I]], [[J]], [[META]])
+ var c = SomeClass(x: i, y: j)
+
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
+ // CHECK: apply [[METHOD]]([[I]], [[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ c.method(i)
+
+ // -- Curry 'self' onto unapplied methods dispatched using class_method.
+ // CHECK: [[METHOD_CURRY_THUNK:%.*]] = function_ref @$S9functions9SomeClassC6method{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[METHOD_CURRY_THUNK]]
+ var cm1 = SomeClass.method(c)
+ cm1(i)
+
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
+ // CHECK: apply [[METHOD]]([[I]], [[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ SomeClass.method(c)(i)
+
+ // -- Curry the Type onto static method argument lists.
+
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[META:%.*]] = value_metatype $@thick SomeClass.Type, [[C]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[METHOD:%[0-9]+]] = class_method [[META]] : {{.*}}, #SomeClass.static_method!1
+ // CHECK: apply [[METHOD]]([[I]], [[META]])
+ type(of: c).static_method(i)
+
+ // -- Curry property accesses.
+
+ // -- FIXME: class_method-ify class getters.
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[GETTER:%[0-9]+]] = class_method {{.*}} : $SomeClass, #SomeClass.someProperty!getter.1
+ // CHECK: apply [[GETTER]]([[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ i = c.someProperty
+
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[SETTER:%[0-9]+]] = class_method [[BORROWED_C]] : $SomeClass, #SomeClass.someProperty!setter.1 : (SomeClass) -> (Builtin.Int64) -> ()
+ // CHECK: apply [[SETTER]]([[I]], [[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ c.someProperty = i
+
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[READK:%.*]] = begin_access [read] [unknown] [[KADDR]]
+ // CHECK: [[K:%[0-9]+]] = load [trivial] [[READK]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[GETTER:%[0-9]+]] = class_method [[BORROWED_C]] : $SomeClass, #SomeClass.subscript!getter.1 : (SomeClass) -> (Builtin.Int64, Builtin.Int64) -> Builtin.Int64, $@convention(method) (Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> Builtin.Int64
+ // CHECK: apply [[GETTER]]([[J]], [[K]], [[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ i = c[j, k]
+
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[READK:%.*]] = begin_access [read] [unknown] [[KADDR]]
+ // CHECK: [[K:%[0-9]+]] = load [trivial] [[READK]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[SETTER:%[0-9]+]] = class_method [[BORROWED_C]] : $SomeClass, #SomeClass.subscript!setter.1 : (SomeClass) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) -> (), $@convention(method) (Builtin.Int64, Builtin.Int64, Builtin.Int64, @guaranteed SomeClass) -> ()
+ // CHECK: apply [[SETTER]]([[K]], [[I]], [[J]], [[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ c[i, j] = k
+
+ // -- Curry the projected concrete value in an existential (or its Type)
+ // -- onto protocol type methods dispatched using protocol_method.
+
+ // CHECK: [[PBOX:%[0-9]+]] = alloc_box ${ var SomeProtocol }
+ // CHECK: [[PADDR:%.*]] = project_box [[PBOX]]
+ var p : SomeProtocol = ConformsToSomeProtocol()
+
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PADDR]]
+ // CHECK: [[TEMP:%.*]] = alloc_stack $SomeProtocol
+ // CHECK: copy_addr [[READ]] to [initialization] [[TEMP]]
+ // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[TEMP]] : $*SomeProtocol to $*[[OPENED:@opened(.*) SomeProtocol]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
+ // CHECK: apply [[PMETHOD]]<[[OPENED]]>([[I]], [[PVALUE]])
+ // CHECK: destroy_addr [[TEMP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ p.method(i)
+
+ // CHECK: [[PVALUE:%[0-9]+]] = open_existential_addr immutable_access [[PADDR:%.*]] : $*SomeProtocol to $*[[OPENED:@opened(.*) SomeProtocol]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
+ // CHECK: apply [[PMETHOD]]<[[OPENED]]>([[I]], [[PVALUE]])
+ var sp : SomeProtocol = ConformsToSomeProtocol()
+ sp.method(i)
+
+ // FIXME: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED:@opened(.*) SomeProtocol]], #SomeProtocol.static_method!1
+ // FIXME: [[I:%[0-9]+]] = load [trivial] [[IADDR]]
+ // FIXME: apply [[PMETHOD]]([[I]], [[PMETA]])
+ // Needs existential metatypes
+ //type(of: p).static_method(i)
+
+ // -- Use an apply or partial_apply instruction to bind type parameters of a generic.
+
+ // CHECK: [[GBOX:%[0-9]+]] = alloc_box ${ var SomeGeneric<Builtin.Int64> }
+ // CHECK: [[GADDR:%.*]] = project_box [[GBOX]]
+ // CHECK: [[META:%[0-9]+]] = metatype $@thick SomeGeneric<Builtin.Int64>.Type
+ // CHECK: [[CTOR_GEN:%[0-9]+]] = function_ref @$S9functions11SomeGenericC{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@thick SomeGeneric<τ_0_0>.Type) -> @owned SomeGeneric<τ_0_0>
+ // CHECK: apply [[CTOR_GEN]]<Builtin.Int64>([[META]])
+ var g = SomeGeneric<Builtin.Int64>()
+
+ // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
+ // CHECK: [[READG:%.*]] = begin_access [read] [unknown] [[GADDR]]
+ // CHECK: [[G:%[0-9]+]] = load [copy] [[READG]]
+ // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
+ // CHECK: [[TMPI:%.*]] = alloc_stack $Builtin.Int64
+ // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.method!1
+ // CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPI]], [[BORROWED_G]])
+ // CHECK: end_borrow [[BORROWED_G]] from [[G]]
+ // CHECK: destroy_value [[G]]
+ g.method(i)
+
+ // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
+ // CHECK: [[READG:%.*]] = begin_access [read] [unknown] [[GADDR]]
+ // CHECK: [[G:%[0-9]+]] = load [copy] [[READG]]
+ // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
+ // CHECK: [[TMPJ:%.*]] = alloc_stack $Builtin.Int64
+ // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.generic!1
+ // CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPJ]], [[BORROWED_G]])
+ // CHECK: end_borrow [[BORROWED_G]] from [[G]]
+ // CHECK: destroy_value [[G]]
+ g.generic(j)
+
+ // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
+ // CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
+ // CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[TMPK:%.*]] = alloc_stack $Builtin.Int64
+ // CHECK: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.generic!1
+ // CHECK: apply [[METHOD_GEN]]<{{.*}}>([[TMPR]], [[TMPK]], [[BORROWED_C]])
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ // CHECK: destroy_value [[C]]
+ c.generic(k)
+
+ // FIXME: curried generic entry points
+ //var gm1 = g.method
+ //gm1(i)
+
+ //var gg1 : (Int) -> Int = g.generic
+ //gg1(j)
+
+ //var cg1 : (Int) -> Int = c.generic
+ //cg1(k)
+
+ // SIL-level "thin" function values need to be able to convert to
+ // "thick" function values when stored, returned, or passed as arguments.
+
+ // CHECK: [[FBOX:%[0-9]+]] = alloc_box ${ var @callee_guaranteed (Builtin.Int64, Builtin.Int64) -> Builtin.Int64 }
+ // CHECK: [[FADDR:%.*]] = project_box [[FBOX]]
+ // CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
+ // CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
+ // CHECK: store [[FUNC_THICK]] to [init] [[FADDR]]
+ var f = standalone_function
+ // CHECK: [[READF:%.*]] = begin_access [read] [unknown] [[FADDR]]
+ // CHECK: [[F:%[0-9]+]] = load [copy] [[READF]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[BORROW:%.*]] = begin_borrow [[F]]
+ // CHECK: apply [[BORROW]]([[I]], [[J]])
+ // CHECK: end_borrow [[BORROW]]
+ // CHECK: destroy_value [[F]]
+ f(i, j)
+
+ // CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
+ // CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[FUNC_THICK]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[HOF:%[0-9]+]] = function_ref @$S9functions21higher_order_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
+ // CHECK: apply [[HOF]]([[CONVERT]], [[I]], [[J]])
+ higher_order_function(standalone_function, i, j)
+
+ // CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
+ // CHECK: [[FUNC_THICK:%.*]] = thin_to_thick_function [[FUNC_THIN]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[FUNC_THICK]]
+ // CHECK: [[READI:%.*]] = begin_access [read] [unknown] [[IADDR]]
+ // CHECK: [[I:%[0-9]+]] = load [trivial] [[READI]]
+ // CHECK: [[READJ:%.*]] = begin_access [read] [unknown] [[JADDR]]
+ // CHECK: [[J:%[0-9]+]] = load [trivial] [[READJ]]
+ // CHECK: [[HOF2:%[0-9]+]] = function_ref @$S9functions22higher_order_function2{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
+ // CHECK: apply [[HOF2]]([[CONVERT]], [[I]], [[J]])
+ higher_order_function2(standalone_function, i, j)
+}
+
+// -- Curried entry points
+// CHECK-LABEL: sil shared [thunk] @$S9functions10SomeStructV6method{{[_0-9a-zA-Z]*}}FTc : $@convention(thin) (@inout SomeStruct) -> @owned @callee_guaranteed (Builtin.Int64) -> () {
+// CHECK: [[UNCURRIED:%.*]] = function_ref @$S9functions10SomeStructV6method{{[_0-9a-zA-Z]*}}F : $@convention(method) (Builtin.Int64, @inout SomeStruct) -> (){{.*}} // user: %2
+// CHECK: [[CURRIED:%.*]] = partial_apply [callee_guaranteed] [[UNCURRIED]]
+// CHECK: return [[CURRIED]]
+
+// CHECK-LABEL: sil shared [thunk] @$S9functions9SomeClassC6method{{[_0-9a-zA-Z]*}}FTc : $@convention(thin) (@guaranteed SomeClass) -> @owned @callee_guaranteed (Builtin.Int64) -> ()
+// CHECK: bb0(%0 : @guaranteed $SomeClass):
+// CHECK: class_method %0 : $SomeClass, #SomeClass.method!1 : (SomeClass) -> (Builtin.Int64) -> ()
+// CHECK: %2 = copy_value %0 : $SomeClass
+// CHECK: %3 = partial_apply [callee_guaranteed] %1(%2)
+// CHECK: return %3
+
+func return_func() -> (_ x: Builtin.Int64, _ y: Builtin.Int64) -> Builtin.Int64 {
+ // CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @$S9functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
+ // CHECK: [[FUNC_THICK:%[0-9]+]] = thin_to_thick_function [[FUNC_THIN]]
+ // CHECK: return [[FUNC_THICK]]
+ return standalone_function
+}
+
+func standalone_generic<T>(_ x: T, y: T) -> T { return x }
+
+// CHECK-LABEL: sil hidden @$S9functions14return_genericBi64_Bi64__Bi64_tcyF
+func return_generic() -> (_ x:Builtin.Int64, _ y:Builtin.Int64) -> Builtin.Int64 {
+ // CHECK: [[GEN:%.*]] = function_ref @$S9functions18standalone_generic{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: [[SPEC:%.*]] = partial_apply [callee_guaranteed] [[GEN]]<Builtin.Int64>()
+ // CHECK: [[THUNK:%.*]] = function_ref @{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64, @guaranteed @callee_guaranteed (@in_guaranteed Builtin.Int64, @in_guaranteed Builtin.Int64) -> @out Builtin.Int64) -> Builtin.Int64
+ // CHECK: [[T0:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[SPEC]])
+ // CHECK: return [[T0]]
+ return standalone_generic
+}
+
+// CHECK-LABEL: sil hidden @$S9functions20return_generic_tuple{{[_0-9a-zA-Z]*}}F
+func return_generic_tuple()
+-> (_ x: (Builtin.Int64, Builtin.Int64), _ y: (Builtin.Int64, Builtin.Int64)) -> (Builtin.Int64, Builtin.Int64) {
+ // CHECK: [[GEN:%.*]] = function_ref @$S9functions18standalone_generic{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: [[SPEC:%.*]] = partial_apply [callee_guaranteed] [[GEN]]<(Builtin.Int64, Builtin.Int64)>()
+ // CHECK: [[THUNK:%.*]] = function_ref @{{.*}} : $@convention(thin) (Builtin.Int64, Builtin.Int64, Builtin.Int64, Builtin.Int64, @guaranteed @callee_guaranteed (@in_guaranteed (Builtin.Int64, Builtin.Int64), @in_guaranteed (Builtin.Int64, Builtin.Int64)) -> @out (Builtin.Int64, Builtin.Int64)) -> (Builtin.Int64, Builtin.Int64)
+ // CHECK: [[T0:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[SPEC]])
+ // CHECK: return [[T0]]
+ return standalone_generic
+}
+
+// CHECK-LABEL: sil hidden @$S9functions16testNoReturnAttrs5NeverOyF : $@convention(thin) () -> Never
+func testNoReturnAttr() -> Never {}
+// CHECK-LABEL: sil hidden @$S9functions20testNoReturnAttrPoly{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T> (@in_guaranteed T) -> Never
+func testNoReturnAttrPoly<T>(_ x: T) -> Never {}
+
+// CHECK-LABEL: sil hidden @$S9functions21testNoReturnAttrParam{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@noescape @callee_guaranteed () -> Never) -> ()
+func testNoReturnAttrParam(_ fptr: () -> Never) -> () {}
+
+// CHECK-LABEL: sil hidden [transparent] @$S9functions15testTransparent{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int1) -> Builtin.Int1
+@_transparent func testTransparent(_ x: Bool) -> Bool {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S9functions16applyTransparent{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int1) -> Builtin.Int1 {
+func applyTransparent(_ x: Bool) -> Bool {
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S9functions15testTransparent{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int1) -> Builtin.Int1
+ // CHECK: apply [[FUNC]]({{%[0-9]+}}) : $@convention(thin) (Builtin.Int1) -> Builtin.Int1
+ return testTransparent(x)
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S9functions15noinline_calleeyyF : $@convention(thin) () -> ()
+@inline(never)
+func noinline_callee() {}
+
+// CHECK-LABEL: sil hidden [always_inline] @$S9functions20always_inline_calleeyyF : $@convention(thin) () -> ()
+@inline(__always)
+func always_inline_callee() {}
+
+// CHECK-LABEL: sil [serialized] [always_inline] @$S9functions27public_always_inline_calleeyyF : $@convention(thin) () -> ()
+@inline(__always)
+public func public_always_inline_callee() {}
+
+protocol AlwaysInline {
+ func alwaysInlined()
+}
+
+// CHECK-LABEL: sil hidden [always_inline] @$S9functions19AlwaysInlinedMemberV06alwaysC0{{[_0-9a-zA-Z]*}}F : $@convention(method) (AlwaysInlinedMember) -> () {
+
+// protocol witness for functions.AlwaysInline.alwaysInlined <A : functions.AlwaysInline>(functions.AlwaysInline.Self)() -> () in conformance functions.AlwaysInlinedMember : functions.AlwaysInline in functions
+// CHECK-LABEL: sil private [transparent] [thunk] [always_inline] @$S9functions19AlwaysInlinedMemberVAA0B6InlineA2aDP06alwaysC0{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AlwaysInline) (@in_guaranteed AlwaysInlinedMember) -> () {
+struct AlwaysInlinedMember : AlwaysInline {
+ @inline(__always)
+ func alwaysInlined() {}
+}
+
+// CHECK-LABEL: sil hidden [Onone] @$S9functions10onone_funcyyF : $@convention(thin) () -> ()
+@_optimize(none)
+func onone_func() {}
+
+// CHECK-LABEL: sil hidden [Ospeed] @$S9functions11ospeed_funcyyF : $@convention(thin) () -> ()
+@_optimize(speed)
+func ospeed_func() {}
+
+// CHECK-LABEL: sil hidden [Osize] @$S9functions10osize_funcyyF : $@convention(thin) () -> ()
+@_optimize(size)
+func osize_func() {}
+
+struct OptmodeTestStruct {
+
+ // CHECK-LABEL: sil hidden [Ospeed] @$S9functions17OptmodeTestStructV3fooyyF :
+ @_optimize(speed)
+ func foo() { }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @$S9functions17OptmodeTestStructVACycfC :
+ @_optimize(speed)
+ init() { }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @$S9functions17OptmodeTestStructV1xBi64_vg :
+ @_optimize(speed)
+ var x: Int { return getInt() }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @$S9functions17OptmodeTestStructVyBi64_Bi64_cig :
+ @_optimize(speed)
+ subscript(l: Int) -> Int { return getInt() }
+}
+
+// CHECK-LABEL: sil hidden [_semantics "foo"] @$S9functions9semanticsyyF : $@convention(thin) () -> ()
+@_semantics("foo")
+func semantics() {}
+
+
+// <rdar://problem/17828355> curried final method on a class crashes in irgen
+final class r17828355Class {
+ func method(_ x : Int) {
+ var a : r17828355Class
+ var fn = a.method // currying a final method.
+ }
+}
+
+// The curry thunk for the method should not include a class_method instruction.
+// CHECK-LABEL: sil shared [thunk] @$S9functions14r17828355ClassC6method
+// CHECK: bb0(%0 : @guaranteed $r17828355Class):
+// CHECK-NEXT: // function_ref functions.r17828355Class.method(Builtin.Int64) -> ()
+// CHECK-NEXT: %1 = function_ref @$S9functions14r17828355ClassC6method{{[_0-9a-zA-Z]*}}F : $@convention(method) (Builtin.Int64, @guaranteed r17828355Class) -> ()
+// CHECK-NEXT: %2 = copy_value %0
+// CHECK-NEXT: partial_apply [callee_guaranteed] %1(%2) : $@convention(method) (Builtin.Int64, @guaranteed r17828355Class) -> ()
+// CHECK-NEXT: return
+
+
+
+// <rdar://problem/19981118> Swift 1.2 beta 2: Closures nested in closures copy, rather than reference, captured vars.
+func noescapefunc(f: () -> ()) {}
+func escapefunc(_ f : @escaping () -> ()) {}
+
+func testNoescape() {
+ // "a" must be captured by-box into noescapefunc because the inner closure
+ // could escape it.
+ var a = 0
+ noescapefunc {
+ escapefunc { a = 42 }
+ }
+ markUsed(a)
+}
+
+// CHECK-LABEL: functions.testNoescape() -> ()
+// CHECK-NEXT: sil hidden @$S9functions12testNoescapeyyF : $@convention(thin) () -> ()
+// CHECK: function_ref closure #1 () -> () in functions.testNoescape() -> ()
+// CHECK-NEXT: function_ref @$S9functions12testNoescapeyyFyyXEfU_ : $@convention(thin) (@guaranteed { var Int }) -> ()
+
+// Despite being a noescape closure, this needs to capture 'a' by-box so it can
+// be passed to the capturing closure.closure
+// CHECK: closure #1 () -> () in functions.testNoescape() -> ()
+// CHECK-NEXT: sil private @$S9functions12testNoescapeyyFyyXEfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+
+
+
+func testNoescape2() {
+ // "a" must be captured by-box into noescapefunc because the inner closure
+ // could escape it. This also checks for when the outer closure captures it
+ // in a way that could be used with escape: the union of the two requirements
+ // doesn't allow a by-address capture.
+ var a = 0
+ noescapefunc {
+ escapefunc { a = 42 }
+ markUsed(a)
+ }
+ markUsed(a)
+}
+
+// CHECK-LABEL: sil hidden @$S9functions13testNoescape2yyF : $@convention(thin) () -> () {
+
+// CHECK: // closure #1 () -> () in functions.testNoescape2() -> ()
+// CHECK-NEXT: sil private @$S9functions13testNoescape2yyFyyXEfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+
+// CHECK: // closure #1 () -> () in closure #1 () -> () in functions.testNoescape2() -> ()
+// CHECK-NEXT: sil private @$S9functions13testNoescape2yyFyyXEfU_yycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+
+enum PartialApplyEnumPayload<T, U> {
+ case Left(T)
+ case Right(U)
+}
+
+struct S {}
+struct C {}
+
+func partialApplyEnumCases(_ x: S, y: C) {
+ let left = PartialApplyEnumPayload<S, C>.Left
+ let left2 = left(S())
+
+ let right = PartialApplyEnumPayload<S, C>.Right
+ let right2 = right(C())
+}
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$S9functions23PartialApplyEnumPayloadO4Left{{[_0-9a-zA-Z]*}}F
+// CHECK: [[UNCURRIED:%.*]] = function_ref @$S9functions23PartialApplyEnumPayloadO4Left{{[_0-9a-zA-Z]*}}F
+// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[UNCURRIED]]<T, U>(%0)
+// CHECK: [[CANONICAL_THUNK:%.*]] = function_ref @$Sx9functions23PartialApplyEnumPayloadOyxq_GIegir_xADIegnr_r0_lTR : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in τ_0_0) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>
+// CHECK: [[THUNKED_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK]]<T, U>([[CLOSURE]])
+// CHECK: return [[THUNKED_CLOSURE]]
+// CHECK: } // end sil function '$S9functions23PartialApplyEnumPayloadO4Left{{[_0-9a-zA-Z]*}}F'
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$S9functions23PartialApplyEnumPayloadO5Right{{[_0-9a-zA-Z]*}}F
+// CHECK: [[UNCURRIED:%.*]] = function_ref @$S9functions23PartialApplyEnumPayloadO5Right{{[_0-9a-zA-Z]*}}F
+// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[UNCURRIED]]<T, U>(%0)
+// CHECK: [[CANONICAL_THUNK:%.*]] = function_ref @$Sq_9functions23PartialApplyEnumPayloadOyxq_GIegir_q_ADIegnr_r0_lTR : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_1, @guaranteed @callee_guaranteed (@in τ_0_1) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>) -> @out PartialApplyEnumPayload<τ_0_0, τ_0_1>
+// CHECK: [[THUNKED_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK]]<T, U>([[CLOSURE]])
+// CHECK: return [[THUNKED_CLOSURE]]
+// CHECK: } // end sil function '$S9functions23PartialApplyEnumPayloadO5Right{{[_0-9a-zA-Z]*}}F'
diff --git a/test/SILGen/plus_zero_generic_casts.swift b/test/SILGen/plus_zero_generic_casts.swift
new file mode 100644
index 0000000..1f857b0
--- /dev/null
+++ b/test/SILGen/plus_zero_generic_casts.swift
@@ -0,0 +1,290 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-runtime %s
+
+protocol ClassBound : class {}
+protocol NotClassBound {}
+
+class C : ClassBound, NotClassBound {}
+struct S : NotClassBound {}
+struct Unloadable : NotClassBound { var x : NotClassBound }
+
+// CHECK-LABEL: sil hidden @$S13generic_casts020opaque_archetype_to_c1_D0{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_to_opaque_archetype
+<T:NotClassBound, U>(_ t:T) -> U {
+ return t as! U
+ // CHECK: bb0([[RET:%.*]] : @trivial $*U, {{%.*}}: @trivial $*T):
+ // CHECK: unconditional_checked_cast_addr T in {{%.*}} : $*T to U in [[RET]] : $*U
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts020opaque_archetype_is_c1_D0{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_is_opaque_archetype
+<T:NotClassBound, U>(_ t:T, u:U.Type) -> Bool {
+ return t is U
+ // CHECK: checked_cast_addr_br take_always T in [[VAL:%.*]] : $*T to U in [[DEST:%.*]] : $*U, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+ // CHECK: [[YES]]:
+ // CHECK: [[Y:%.*]] = integer_literal $Builtin.Int1, -1
+ // CHECK: destroy_addr [[DEST]]
+ // CHECK: br [[CONT:bb[0-9]+]]([[Y]] : $Builtin.Int1)
+ // CHECK: [[NO]]:
+ // CHECK: [[N:%.*]] = integer_literal $Builtin.Int1, 0
+ // CHECK: br [[CONT]]([[N]] : $Builtin.Int1)
+ // CHECK: [[CONT]]([[I1:%.*]] : @trivial $Builtin.Int1):
+ // -- apply the _getBool library fn
+ // CHECK-NEXT: function_ref Swift._getBool
+ // CHECK-NEXT: [[GETBOOL:%.*]] = function_ref @$Ss8_getBoolySbBi1_F :
+ // CHECK-NEXT: [[RES:%.*]] = apply [[GETBOOL]]([[I1]])
+ // -- we don't consume the checked value
+ // CHECK: return [[RES]] : $Bool
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts026opaque_archetype_to_class_D0{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_to_class_archetype
+<T:NotClassBound, U:ClassBound> (_ t:T) -> U {
+ return t as! U
+ // CHECK: unconditional_checked_cast_addr T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U
+ // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] : $*U
+ // CHECK: return [[DOWNCAST]] : $U
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts026opaque_archetype_is_class_D0{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_is_class_archetype
+<T:NotClassBound, U:ClassBound> (_ t:T, u:U.Type) -> Bool {
+ return t is U
+ // CHECK: copy_addr {{.*}} : $*T
+ // CHECK: checked_cast_addr_br take_always T in [[VAL:%.*]] : {{.*}} to U
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts019class_archetype_to_c1_D0{{[_0-9a-zA-Z]*}}F
+func class_archetype_to_class_archetype
+<T:ClassBound, U:ClassBound>(_ t:T) -> U {
+ return t as! U
+ // Error bridging can change the identity of class-constrained archetypes.
+ // CHECK-objc: unconditional_checked_cast_addr T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U
+ // CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
+ // CHECK-objc: return [[DOWNCAST]] : $U
+
+ // CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $T to $U
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts019class_archetype_is_c1_D0{{[_0-9a-zA-Z]*}}F
+func class_archetype_is_class_archetype
+<T:ClassBound, U:ClassBound>(_ t:T, u:U.Type) -> Bool {
+ return t is U
+ // Error bridging can change the identity of class-constrained archetypes.
+ // CHECK-objc: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
+ // CHECK-native: checked_cast_br {{.*}} : $T to $U
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts38opaque_archetype_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_to_addr_only_concrete
+<T:NotClassBound> (_ t:T) -> Unloadable {
+ return t as! Unloadable
+ // CHECK: bb0([[RET:%.*]] : @trivial $*Unloadable, {{%.*}}: @trivial $*T):
+ // CHECK: unconditional_checked_cast_addr T in {{%.*}} : $*T to Unloadable in [[RET]] : $*Unloadable
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts38opaque_archetype_is_addr_only_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_is_addr_only_concrete
+<T:NotClassBound> (_ t:T) -> Bool {
+ return t is Unloadable
+ // CHECK: checked_cast_addr_br take_always T in [[VAL:%.*]] : {{.*}} to Unloadable in
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts37opaque_archetype_to_loadable_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_to_loadable_concrete
+<T:NotClassBound>(_ t:T) -> S {
+ return t as! S
+ // CHECK: unconditional_checked_cast_addr T in {{%.*}} : $*T to S in [[DOWNCAST_ADDR:%.*]] : $*S
+ // CHECK: [[DOWNCAST:%.*]] = load [trivial] [[DOWNCAST_ADDR]] : $*S
+ // CHECK: return [[DOWNCAST]] : $S
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts37opaque_archetype_is_loadable_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_archetype_is_loadable_concrete
+<T:NotClassBound>(_ t:T) -> Bool {
+ return t is S
+ // CHECK: checked_cast_addr_br take_always T in {{%.*}} : $*T to S in
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts019class_archetype_to_C0{{[_0-9a-zA-Z]*}}F
+func class_archetype_to_class
+<T:ClassBound>(_ t:T) -> C {
+ return t as! C
+ // CHECK: [[DOWNCAST:%.*]] = unconditional_checked_cast {{%.*}} to $C
+ // CHECK: return [[DOWNCAST]] : $C
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts019class_archetype_is_C0{{[_0-9a-zA-Z]*}}F
+func class_archetype_is_class
+<T:ClassBound>(_ t:T) -> Bool {
+ return t is C
+ // CHECK: checked_cast_br {{%.*}} to $C
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts022opaque_existential_to_C10_archetype{{[_0-9a-zA-Z]*}}F
+func opaque_existential_to_opaque_archetype
+<T:NotClassBound>(_ p:NotClassBound) -> T {
+ return p as! T
+ // CHECK: bb0([[RET:%.*]] : @trivial $*T, [[ARG:%.*]] : @trivial $*NotClassBound):
+ // CHECK: [[TEMP:%.*]] = alloc_stack $NotClassBound
+ // CHECK-NEXT: copy_addr [[ARG]] to [initialization] [[TEMP]]
+ // CHECK-NEXT: unconditional_checked_cast_addr NotClassBound in [[TEMP]] : $*NotClassBound to T in [[RET]] : $*T
+ // CHECK-NEXT: dealloc_stack [[TEMP]]
+ // CHECK-NEXT: [[T0:%.*]] = tuple ()
+ // CHECK-NEXT: return [[T0]]
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts022opaque_existential_is_C10_archetype{{[_0-9a-zA-Z]*}}F
+func opaque_existential_is_opaque_archetype
+<T:NotClassBound>(_ p:NotClassBound, _: T) -> Bool {
+ return p is T
+ // CHECK: checked_cast_addr_br take_always NotClassBound in [[CONTAINER:%.*]] : {{.*}} to T in
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts37opaque_existential_to_class_archetype{{[_0-9a-zA-Z]*}}F
+func opaque_existential_to_class_archetype
+<T:ClassBound>(_ p:NotClassBound) -> T {
+ return p as! T
+ // CHECK: unconditional_checked_cast_addr NotClassBound in {{%.*}} : $*NotClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T
+ // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] : $*T
+ // CHECK: return [[DOWNCAST]] : $T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts37opaque_existential_is_class_archetype{{[_0-9a-zA-Z]*}}F
+func opaque_existential_is_class_archetype
+<T:ClassBound>(_ p:NotClassBound, _: T) -> Bool {
+ return p is T
+ // CHECK: checked_cast_addr_br take_always NotClassBound in {{%.*}} : $*NotClassBound to T in
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts021class_existential_to_C10_archetype{{[_0-9a-zA-Z]*}}F
+func class_existential_to_class_archetype
+<T:ClassBound>(_ p:ClassBound) -> T {
+ return p as! T
+ // CHECK-objc: unconditional_checked_cast_addr ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T
+ // CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
+ // CHECK-objc: return [[DOWNCAST]] : $T
+
+ // CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $ClassBound to $T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts021class_existential_is_C10_archetype{{[_0-9a-zA-Z]*}}F
+func class_existential_is_class_archetype
+<T:ClassBound>(_ p:ClassBound, _: T) -> Bool {
+ return p is T
+ // CHECK-objc: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
+ // CHECK-native: checked_cast_br {{.*}} : $ClassBound to $T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts40opaque_existential_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_existential_to_addr_only_concrete(_ p: NotClassBound) -> Unloadable {
+ return p as! Unloadable
+ // CHECK: bb0([[RET:%.*]] : @trivial $*Unloadable, {{%.*}}: @trivial $*NotClassBound):
+ // CHECK: unconditional_checked_cast_addr NotClassBound in {{%.*}} : $*NotClassBound to Unloadable in [[RET]] : $*Unloadable
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts40opaque_existential_is_addr_only_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_existential_is_addr_only_concrete(_ p: NotClassBound) -> Bool {
+ return p is Unloadable
+ // CHECK: checked_cast_addr_br take_always NotClassBound in {{%.*}} : $*NotClassBound to Unloadable in
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts39opaque_existential_to_loadable_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_existential_to_loadable_concrete(_ p: NotClassBound) -> S {
+ return p as! S
+ // CHECK: unconditional_checked_cast_addr NotClassBound in {{%.*}} : $*NotClassBound to S in [[DOWNCAST_ADDR:%.*]] : $*S
+ // CHECK: [[DOWNCAST:%.*]] = load [trivial] [[DOWNCAST_ADDR]] : $*S
+ // CHECK: return [[DOWNCAST]] : $S
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts39opaque_existential_is_loadable_concrete{{[_0-9a-zA-Z]*}}F
+func opaque_existential_is_loadable_concrete(_ p: NotClassBound) -> Bool {
+ return p is S
+ // CHECK: checked_cast_addr_br take_always NotClassBound in {{%.*}} : $*NotClassBound to S in
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts021class_existential_to_C0{{[_0-9a-zA-Z]*}}F
+func class_existential_to_class(_ p: ClassBound) -> C {
+ return p as! C
+ // CHECK: [[DOWNCAST:%.*]] = unconditional_checked_cast {{%.*}} to $C
+ // CHECK: return [[DOWNCAST]] : $C
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts021class_existential_is_C0{{[_0-9a-zA-Z]*}}F
+func class_existential_is_class(_ p: ClassBound) -> Bool {
+ return p is C
+ // CHECK: checked_cast_br {{%.*}} to $C
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts27optional_anyobject_to_classyAA1CCSgyXlSgF
+func optional_anyobject_to_class(_ p: AnyObject?) -> C? {
+ return p as? C
+ // CHECK: checked_cast_br {{%.*}} : $AnyObject to $C
+}
+
+// The below tests are to ensure we don't dig into an optional operand when
+// casting to a non-class archetype, as it could dynamically be an optional type.
+
+// CHECK-LABEL: sil hidden @$S13generic_casts32optional_any_to_opaque_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_to_opaque_archetype<T>(_ x: Any?) -> T {
+ return x as! T
+ // CHECK: bb0([[RET:%.*]] : @trivial $*T, {{%.*}} : @trivial $*Optional<Any>):
+ // CHECK: unconditional_checked_cast_addr Optional<Any> in {{%.*}} : $*Optional<Any> to T in [[RET]] : $*T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts46optional_any_conditionally_to_opaque_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_conditionally_to_opaque_archetype<T>(_ x: Any?) -> T? {
+ return x as? T
+ // CHECK: checked_cast_addr_br take_always Optional<Any> in {{%.*}} : $*Optional<Any> to T in {{%.*}} : $*T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts32optional_any_is_opaque_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_is_opaque_archetype<T>(_ x: Any?, _: T) -> Bool {
+ return x is T
+ // CHECK: checked_cast_addr_br take_always Optional<Any> in {{%.*}} : $*Optional<Any> to T in {{%.*}} : $*T
+}
+
+// But we can dig into at most one layer of the operand if it's
+// an optional archetype...
+
+// CHECK-LABEL: sil hidden @$S13generic_casts016optional_any_to_C17_opaque_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_to_optional_opaque_archetype<T>(_ x: Any?) -> T? {
+ return x as! T?
+ // CHECK: unconditional_checked_cast_addr Any in {{%.*}} : $*Any to T in {{%.*}} : $*T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts030optional_any_conditionally_to_C17_opaque_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_conditionally_to_optional_opaque_archetype<T>(_ x: Any?) -> T?? {
+ return x as? T?
+ // CHECK: checked_cast_addr_br take_always Any in {{%.*}} : $*Any to T in {{%.*}} : $*T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts016optional_any_is_C17_opaque_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_is_optional_opaque_archetype<T>(_ x: Any?, _: T) -> Bool {
+ return x is T?
+ // Because the levels of optional are the same, 'is' doesn't transform into an 'as?',
+ // so we just cast directly without digging into the optional operand.
+ // CHECK: checked_cast_addr_br take_always Optional<Any> in {{%.*}} : $*Optional<Any> to Optional<T> in {{%.*}} : $*Optional<T>
+}
+
+// And we can dig into the operand when casting to a class archetype, as it
+// cannot dynamically be optional...
+
+// CHECK-LABEL: sil hidden @$S13generic_casts31optional_any_to_class_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_to_class_archetype<T : AnyObject>(_ x: Any?) -> T {
+ return x as! T
+ // CHECK: unconditional_checked_cast_addr Any in {{%.*}} : $*Any to T in {{%.*}} : $*T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts45optional_any_conditionally_to_class_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_conditionally_to_class_archetype<T : AnyObject>(_ x: Any?) -> T? {
+ return x as? T
+ // CHECK: checked_cast_addr_br take_always Any in {{%.*}} : $*Any to T in {{%.*}} : $*T
+}
+
+// CHECK-LABEL: sil hidden @$S13generic_casts31optional_any_is_class_archetype{{[_0-9a-zA-Z]*}}F
+func optional_any_is_class_archetype<T : AnyObject>(_ x: Any?, _: T) -> Bool {
+ return x is T
+ // CHECK: checked_cast_addr_br take_always Any in {{%.*}} : $*Any to T in {{%.*}} : $*T
+}
+
diff --git a/test/SILGen/plus_zero_generic_closures.swift b/test/SILGen/plus_zero_generic_closures.swift
new file mode 100644
index 0000000..174912d
--- /dev/null
+++ b/test/SILGen/plus_zero_generic_closures.swift
@@ -0,0 +1,336 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-stdlib -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+import Swift
+
+var zero: Int
+
+// CHECK-LABEL: sil hidden @$S16generic_closures0A21_nondependent_context{{[_0-9a-zA-Z]*}}F
+func generic_nondependent_context<T>(_ x: T, y: Int) -> Int {
+ func foo() -> Int { return y }
+
+ func bar() -> Int { return y }
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
+ // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]](%1)
+ // CHECK: destroy_value [[FOO_CLOSURE]]
+ let _ = foo
+
+ // CHECK: [[BAR:%.*]] = function_ref @$S16generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
+ // CHECK: [[BAR_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[BAR]](%1)
+ // CHECK: destroy_value [[BAR_CLOSURE]]
+ let _ = bar
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
+ // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]
+ _ = foo()
+
+ // CHECK: [[BAR:%.*]] = function_ref @$S16generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
+ // CHECK: [[BAR_CLOSURE:%.*]] = apply [[BAR]]
+
+ // CHECK: [[BAR_CLOSURE]]
+ return bar()
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures0A8_capture{{[_0-9a-zA-Z]*}}F
+func generic_capture<T>(_ x: T) -> Any.Type {
+ func foo() -> Any.Type { return T.self }
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type
+ // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]<T>()
+ // CHECK: destroy_value [[FOO_CLOSURE]]
+ let _ = foo
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type
+ // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]<T>()
+
+ // CHECK: return [[FOO_CLOSURE]]
+ return foo()
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures0A13_capture_cast{{[_0-9a-zA-Z]*}}F
+func generic_capture_cast<T>(_ x: T, y: Any) -> Bool {
+ func foo(_ a: Any) -> Bool { return a is T }
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A13_capture_cast{{.*}} : $@convention(thin) <τ_0_0> (@in_guaranteed Any) -> Bool
+ // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]<T>()
+ // CHECK: destroy_value [[FOO_CLOSURE]]
+ let _ = foo
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A13_capture_cast{{.*}} : $@convention(thin) <τ_0_0> (@in_guaranteed Any) -> Bool
+ // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]<T>([[ARG:%.*]])
+
+ // CHECK: return [[FOO_CLOSURE]]
+ return foo(y)
+}
+
+protocol Concept {
+ var sensical: Bool { get }
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures0A22_nocapture_existential{{[_0-9a-zA-Z]*}}F
+func generic_nocapture_existential<T>(_ x: T, y: Concept) -> Bool {
+ func foo(_ a: Concept) -> Bool { return a.sensical }
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in_guaranteed Concept) -> Bool
+ // CHECK: [[FOO_CLOSURE:%.*]] = thin_to_thick_function [[FOO]]
+ // CHECK: destroy_value [[FOO_CLOSURE]]
+ let _ = foo
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in_guaranteed Concept) -> Bool
+ // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]([[ARG:%.*]])
+
+ // CHECK: return [[FOO_CLOSURE]]
+ return foo(y)
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures0A18_dependent_context{{[_0-9a-zA-Z]*}}F
+func generic_dependent_context<T>(_ x: T, y: Int) -> T {
+ func foo() -> T { return x }
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A18_dependent_context{{.*}} : $@convention(thin) <τ_0_0> (@guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
+ // CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FOO]]<T>([[BOX:%.*]])
+ // CHECK: destroy_value [[FOO_CLOSURE]]
+ let _ = foo
+
+ // CHECK: [[FOO:%.*]] = function_ref @$S16generic_closures0A18_dependent_context{{.*}} : $@convention(thin) <τ_0_0> (@guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
+ // CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]<T>
+
+ // CHECK: return
+ return foo()
+}
+
+enum Optionable<Wrapped> {
+ case none
+ case some(Wrapped)
+}
+
+class NestedGeneric<U> {
+ class func generic_nondependent_context<T>(_ x: T, y: Int, z: U) -> Int {
+ func foo() -> Int { return y }
+ let _ = foo
+ return foo()
+ }
+
+ class func generic_dependent_inner_context<T>(_ x: T, y: Int, z: U) -> T {
+ func foo() -> T { return x }
+ let _ = foo
+ return foo()
+ }
+
+ class func generic_dependent_outer_context<T>(_ x: T, y: Int, z: U) -> U {
+ func foo() -> U { return z }
+ let _ = foo
+ return foo()
+ }
+
+ class func generic_dependent_both_contexts<T>(_ x: T, y: Int, z: U) -> (T, U) {
+ func foo() -> (T, U) { return (x, z) }
+ let _ = foo
+ return foo()
+ }
+
+ // CHECK-LABEL: sil hidden @$S16generic_closures13NestedGenericC20nested_reabstraction{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[REABSTRACT:%.*]] = function_ref @$SIeg_ytytIegnr_TR
+ // CHECK: partial_apply [callee_guaranteed] [[REABSTRACT]]
+ func nested_reabstraction<T>(_ x: T) -> Optionable<() -> ()> {
+ return .some({})
+ }
+}
+
+// <rdar://problem/15417773>
+// Ensure that nested closures capture the generic parameters of their nested
+// context.
+
+// CHECK: sil hidden @$S16generic_closures018nested_closure_in_A0yxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T
+// CHECK: function_ref [[OUTER_CLOSURE:@\$S16generic_closures018nested_closure_in_A0yxxlFxyXEfU_]]
+// CHECK: sil private [[OUTER_CLOSURE]] : $@convention(thin) <T> (@inout_aliasable T) -> @out T
+// CHECK: function_ref [[INNER_CLOSURE:@\$S16generic_closures018nested_closure_in_A0yxxlFxyXEfU_xyXEfU_]]
+// CHECK: sil private [[INNER_CLOSURE]] : $@convention(thin) <T> (@inout_aliasable T) -> @out T {
+func nested_closure_in_generic<T>(_ x:T) -> T {
+ return { { x }() }()
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures16local_properties{{[_0-9a-zA-Z]*}}F
+func local_properties<T>(_ t: inout T) {
+ var prop: T {
+ get {
+ return t
+ }
+ set {
+ t = newValue
+ }
+ }
+
+ // CHECK: [[GETTER_REF:%[0-9]+]] = function_ref [[GETTER_CLOSURE:@\$S16generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@inout_aliasable τ_0_0) -> @out τ_0_0
+ // CHECK: apply [[GETTER_REF]]
+ t = prop
+
+ // CHECK: [[SETTER_REF:%[0-9]+]] = function_ref [[SETTER_CLOSURE:@\$S16generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@in τ_0_0, @inout_aliasable τ_0_0) -> ()
+ // CHECK: apply [[SETTER_REF]]
+ prop = t
+
+ var prop2: T {
+ get {
+ return t
+ }
+ set {
+ // doesn't capture anything
+ }
+ }
+
+ // CHECK: [[GETTER2_REF:%[0-9]+]] = function_ref [[GETTER2_CLOSURE:@\$S16generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@inout_aliasable τ_0_0) -> @out τ_0_0
+ // CHECK: apply [[GETTER2_REF]]
+ t = prop2
+
+ // CHECK: [[SETTER2_REF:%[0-9]+]] = function_ref [[SETTER2_CLOSURE:@\$S16generic_closures16local_properties[_0-9a-zA-Z]*]] : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ // CHECK: apply [[SETTER2_REF]]
+ prop2 = t
+}
+
+protocol Fooable {
+ static func foo() -> Bool
+}
+
+// <rdar://problem/16399018>
+func shmassert(_ f: @autoclosure () -> Bool) {}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures08capture_A6_param{{[_0-9a-zA-Z]*}}F
+func capture_generic_param<A: Fooable>(_ x: A) {
+ shmassert(A.foo())
+}
+
+// Make sure we use the correct convention when capturing class-constrained
+// member types: <rdar://problem/24470533>
+class Class {}
+
+protocol HasClassAssoc { associatedtype Assoc : Class }
+
+// CHECK-LABEL: sil hidden @$S16generic_closures027captures_class_constrained_A0_1fyx_5AssocQzAEctAA08HasClassF0RzlF
+// CHECK: bb0([[ARG1:%.*]] : @trivial $*T, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed T.Assoc) -> @owned T.Assoc):
+// CHECK: [[GENERIC_FN:%.*]] = function_ref @$S16generic_closures027captures_class_constrained_A0_1fyx_5AssocQzAEctAA08HasClassF0RzlFA2EcycfU_
+// CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]]
+// CHECK: [[CONCRETE_FN:%.*]] = partial_apply [callee_guaranteed] [[GENERIC_FN]]<T>([[ARG2_COPY]])
+
+func captures_class_constrained_generic<T : HasClassAssoc>(_ x: T, f: @escaping (T.Assoc) -> T.Assoc) {
+ let _: () -> (T.Assoc) -> T.Assoc = { f }
+}
+
+// Make sure local generic functions can have captures
+
+// CHECK-LABEL: sil hidden @$S16generic_closures06outer_A01t1iyx_SitlF : $@convention(thin) <T> (@in_guaranteed T, Int) -> ()
+func outer_generic<T>(t: T, i: Int) {
+ func inner_generic_nocapture<U>(u: U) -> U {
+ return u
+ }
+
+ func inner_generic1<U>(u: U) -> Int {
+ return i
+ }
+
+ func inner_generic2<U>(u: U) -> T {
+ return t
+ }
+
+ let _: () -> () = inner_generic_nocapture
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures06outer_A01t1iyx_SitlF06inner_A10_nocaptureL_1uqd__qd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0) -> @out τ_1_0
+ // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<T, ()>() : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0) -> @out τ_1_0
+ // CHECK: [[THUNK:%.*]] = function_ref @$SytytIegnr_Ieg_TR
+ // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]])
+ // CHECK: destroy_value [[THUNK_CLOSURE]]
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures06outer_A01t1iyx_SitlF06inner_A10_nocaptureL_1uqd__qd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0) -> @out τ_1_0
+ // CHECK: [[RESULT:%.*]] = apply [[FN]]<T, T>({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0) -> @out τ_1_0
+ _ = inner_generic_nocapture(u: t)
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures06outer_A01t1iyx_SitlF14inner_generic1L_1uSiqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, Int) -> Int
+ // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<T, ()>(%1) : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, Int) -> Int
+ // CHECK: [[THUNK:%.*]] = function_ref @$SytSiIegnd_SiIegd_TR
+ // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]])
+ // CHECK: destroy_value [[THUNK_CLOSURE]]
+ let _: () -> Int = inner_generic1
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures06outer_A01t1iyx_SitlF14inner_generic1L_1uSiqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, Int) -> Int
+ // CHECK: [[RESULT:%.*]] = apply [[FN]]<T, T>({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, Int) -> Int
+ _ = inner_generic1(u: t)
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures06outer_A01t1iyx_SitlF14inner_generic2L_1uxqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
+ // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<T, ()>([[ARG:%.*]]) : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
+ // CHECK: [[THUNK:%.*]] = function_ref @$SytxIegnr_xIegr_lTR
+ // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]<T>([[CLOSURE]])
+ // CHECK: destroy_value [[THUNK_CLOSURE]]
+ let _: () -> T = inner_generic2
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures06outer_A01t1iyx_SitlF14inner_generic2L_1uxqd___tr__lF : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
+ // CHECK: [[RESULT:%.*]] = apply [[FN]]<T, T>({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0> (@in_guaranteed τ_1_0, @guaranteed <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
+ _ = inner_generic2(u: t)
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures14outer_concrete1iySi_tF : $@convention(thin) (Int) -> ()
+func outer_concrete(i: Int) {
+ func inner_generic_nocapture<U>(u: U) -> U {
+ return u
+ }
+
+ func inner_generic<U>(u: U) -> Int {
+ return i
+ }
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures14outer_concrete1iySi_tF06inner_A10_nocaptureL_1uxx_tlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<()>() : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: [[THUNK:%.*]] = function_ref @$SytytIegnr_Ieg_TR
+ // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]])
+ // CHECK: destroy_value [[THUNK_CLOSURE]]
+ let _: () -> () = inner_generic_nocapture
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures14outer_concrete1iySi_tF06inner_A10_nocaptureL_1uxx_tlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: [[RESULT:%.*]] = apply [[FN]]<Int>({{.*}}) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ _ = inner_generic_nocapture(u: i)
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures14outer_concrete1iySi_tF06inner_A0L_1uSix_tlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, Int) -> Int
+ // CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[FN]]<()>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, Int) -> Int
+ // CHECK: [[THUNK:%.*]] = function_ref @$SytSiIegnd_SiIegd_TR
+ // CHECK: [[THUNK_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[CLOSURE]])
+ // CHECK: destroy_value [[THUNK_CLOSURE]]
+ let _: () -> Int = inner_generic
+
+ // CHECK: [[FN:%.*]] = function_ref @$S16generic_closures14outer_concrete1iySi_tF06inner_A0L_1uSix_tlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, Int) -> Int
+ // CHECK: [[RESULT:%.*]] = apply [[FN]]<Int>({{.*}}) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, Int) -> Int
+ _ = inner_generic(u: i)
+}
+
+// CHECK-LABEL: sil hidden @$S16generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF : $@convention(thin) <T> (@in_guaranteed T) -> ()
+func mixed_generic_nongeneric_nesting<T>(t: T) {
+ func outer() {
+ func middle<U>(u: U) {
+ func inner() -> U {
+ return u
+ }
+ inner()
+ }
+ middle(u: 11)
+ }
+ outer()
+}
+
+// CHECK-LABEL: sil private @$S16generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF5outerL_yylF : $@convention(thin) <T> () -> ()
+// CHECK-LABEL: sil private @$S16generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF5outerL_yylF6middleL_1uyqd___tr__lF : $@convention(thin) <T><U> (@in_guaranteed U) -> ()
+// CHECK-LABEL: sil private @$S16generic_closures06mixed_A19_nongeneric_nesting1tyx_tlF5outerL_yylF6middleL_1uyqd___tr__lF5innerL_qd__yr__lF : $@convention(thin) <T><U> (@guaranteed <τ_0_0><τ_1_0> { var τ_1_0 } <T, U>) -> @out U
+
+protocol Doge {
+ associatedtype Nose : NoseProtocol
+}
+
+protocol NoseProtocol {
+ associatedtype Squeegee
+}
+
+protocol Doggo {}
+
+struct DogSnacks<A : Doggo> {}
+
+func capture_same_type_representative<Daisy: Doge, Roo: Doggo>(slobber: Roo, daisy: Daisy)
+ where Roo == Daisy.Nose.Squeegee {
+ var s = DogSnacks<Daisy.Nose.Squeegee>()
+ _ = { _ = s }
+}
diff --git a/test/SILGen/plus_zero_generic_property_base_lifetime.swift b/test/SILGen/plus_zero_generic_property_base_lifetime.swift
new file mode 100644
index 0000000..17f3823
--- /dev/null
+++ b/test/SILGen/plus_zero_generic_property_base_lifetime.swift
@@ -0,0 +1,118 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
+
+protocol ProtocolA: class {
+ var intProp: Int { get set }
+}
+
+protocol ProtocolB {
+ var intProp: Int { get }
+}
+
+@objc protocol ProtocolO: class {
+ var intProp: Int { get set }
+}
+
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolA_pF : $@convention(thin) (@guaranteed ProtocolA) -> Int {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolA):
+// CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]]
+// CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
+// CHECK: [[BORROWED_PROJECTION_COPY:%.*]] = begin_borrow [[PROJECTION_COPY]]
+// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!getter.1 : {{.*}}, [[PROJECTION]]
+// CHECK: [[RESULT:%.*]] = apply [[WITNESS_METHOD]]<@opened{{.*}}>([[BORROWED_PROJECTION_COPY]])
+// CHECK: end_borrow [[BORROWED_PROJECTION_COPY]] from [[PROJECTION_COPY]]
+// CHECK: destroy_value [[PROJECTION_COPY]]
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function '$S30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolA_pF'
+func getIntPropExistential(_ a: ProtocolA) -> Int {
+ return a.intProp
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolA_pF : $@convention(thin) (@guaranteed ProtocolA) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolA):
+// CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]]
+// CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
+// CHECK: [[BORROWED_PROJECTION_COPY:%.*]] = begin_borrow [[PROJECTION_COPY]]
+// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!setter.1 : {{.*}}, [[PROJECTION]]
+// CHECK: apply [[WITNESS_METHOD]]<@opened{{.*}}>({{%.*}}, [[BORROWED_PROJECTION_COPY]])
+// CHECK: end_borrow [[BORROWED_PROJECTION_COPY]] from [[PROJECTION_COPY]]
+// CHECK: destroy_value [[PROJECTION_COPY]]
+// CHECK: } // end sil function '$S30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolA_pF'
+func setIntPropExistential(_ a: ProtocolA) {
+ a.intProp = 0
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime17getIntPropGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T):
+// CHECK: apply {{%.*}}<T>([[ARG]])
+// CHECK: } // end sil function '$S30generic_property_base_lifetime17getIntPropGeneric{{[_0-9a-zA-Z]*}}F'
+func getIntPropGeneric<T: ProtocolA>(_ a: T) -> Int {
+ return a.intProp
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime17setIntPropGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T):
+// CHECK: apply {{%.*}}<T>({{%.*}}, [[ARG]])
+func setIntPropGeneric<T: ProtocolA>(_ a: T) {
+ a.intProp = 0
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolB_pF
+// CHECK: [[PROJECTION:%.*]] = open_existential_addr immutable_access %0
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $@opened({{".*"}}) ProtocolB
+// CHECK: copy_addr [[PROJECTION]] to [initialization] [[STACK]]
+// CHECK: apply {{%.*}}([[STACK]])
+// CHECK: destroy_addr [[STACK]]
+// CHECK: dealloc_stack [[STACK]]
+func getIntPropExistential(_ a: ProtocolB) -> Int {
+ return a.intProp
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime17getIntPropGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T
+// CHECK: copy_addr %0 to [initialization] [[STACK]]
+// CHECK: apply {{%.*}}<T>([[STACK]])
+// CHECK: destroy_addr [[STACK]]
+// CHECK: dealloc_stack [[STACK]]
+func getIntPropGeneric<T: ProtocolB>(_ a: T) -> Int {
+ return a.intProp
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolO_pF : $@convention(thin) (@guaranteed ProtocolO) -> Int {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolO):
+// CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]]
+// CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
+// CHECK: [[METHOD:%.*]] = objc_method [[PROJECTION_COPY]] : $@opened({{.*}}) ProtocolO, #ProtocolO.intProp!getter.1.foreign : {{.*}}
+// CHECK: apply [[METHOD]]<@opened{{.*}}>([[PROJECTION_COPY]])
+// CHECK: destroy_value [[PROJECTION_COPY]]
+// CHECK: } // end sil function '$S30generic_property_base_lifetime21getIntPropExistentialySiAA9ProtocolO_pF'
+func getIntPropExistential(_ a: ProtocolO) -> Int {
+ return a.intProp
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolO_pF : $@convention(thin) (@guaranteed ProtocolO) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $ProtocolO):
+// CHECK: [[PROJECTION:%.*]] = open_existential_ref [[ARG]]
+// CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
+// CHECK: [[METHOD:%.*]] = objc_method [[PROJECTION_COPY]] : $@opened({{.*}}) ProtocolO, #ProtocolO.intProp!setter.1.foreign : {{.*}}
+// CHECK: apply [[METHOD]]<@opened{{.*}}>({{.*}}, [[PROJECTION_COPY]])
+// CHECK: destroy_value [[PROJECTION_COPY]]
+// CHECK: } // end sil function '$S30generic_property_base_lifetime21setIntPropExistentialyyAA9ProtocolO_pF'
+func setIntPropExistential(_ a: ProtocolO) {
+ a.intProp = 0
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime17getIntPropGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T):
+// CHECK: apply {{%.*}}<T>([[ARG]])
+func getIntPropGeneric<T: ProtocolO>(_ a: T) -> Int {
+ return a.intProp
+}
+
+// CHECK-LABEL: sil hidden @$S30generic_property_base_lifetime17setIntPropGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T):
+// CHECK: apply {{%.*}}<T>({{%.*}}, [[ARG]])
+func setIntPropGeneric<T: ProtocolO>(_ a: T) {
+ a.intProp = 0
+}
diff --git a/test/SILGen/plus_zero_generic_tuples.swift b/test/SILGen/plus_zero_generic_tuples.swift
new file mode 100644
index 0000000..d3053a1
--- /dev/null
+++ b/test/SILGen/plus_zero_generic_tuples.swift
@@ -0,0 +1,39 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -parse-as-library -enable-sil-ownership %s | %FileCheck %s
+
+
+func dup<T>(_ x: T) -> (T, T) { return (x,x) }
+// CHECK-LABEL: sil hidden @$S14generic_tuples3dup{{[_0-9a-zA-Z]*}}F
+// CHECK: ([[RESULT_0:%.*]] : @trivial $*T, [[RESULT_1:%.*]] : @trivial $*T, [[XVAR:%.*]] : @trivial $*T):
+// CHECK-NEXT: debug_value_addr [[XVAR]] : $*T, let, name "x"
+// CHECK-NEXT: copy_addr [[XVAR]] to [initialization] [[RESULT_0]]
+// CHECK-NEXT: copy_addr [[XVAR]] to [initialization] [[RESULT_1]]
+// CHECK-NEXT: [[T0:%.*]] = tuple ()
+// CHECK-NEXT: return [[T0]]
+
+// <rdar://problem/13822463>
+// Specializing a generic function on a tuple type changes the number of
+// SIL parameters, which caused a failure in the ownership conventions code.
+
+struct Blub {}
+// CHECK-LABEL: sil hidden @$S14generic_tuples3foo{{[_0-9a-zA-Z]*}}F
+func foo<T>(_ x: T) {}
+// CHECK-LABEL: sil hidden @$S14generic_tuples3bar{{[_0-9a-zA-Z]*}}F
+func bar(_ x: (Blub, Blub)) { foo(x) }
+
+
+// rdar://26279628
+// A type parameter constrained to be a concrete type must be handled
+// as that concrete type throughout SILGen. That's especially true
+// if it's constrained to be a tuple.
+
+protocol HasAssoc {
+ associatedtype A
+}
+extension HasAssoc where A == (Int, Int) {
+ func returnTupleAlias() -> A {
+ return (0, 0)
+ }
+}
+// CHECK-LABEL: sil hidden @$S14generic_tuples8HasAssocPAASi_Sit1ARtzrlE16returnTupleAliasSi_SityF : $@convention(method) <Self where Self : HasAssoc, Self.A == (Int, Int)> (@in_guaranteed Self) -> (Int, Int) {
+// CHECK: return {{.*}} : $(Int, Int)
diff --git a/test/SILGen/plus_zero_generic_witness.swift b/test/SILGen/plus_zero_generic_witness.swift
new file mode 100644
index 0000000..a450270
--- /dev/null
+++ b/test/SILGen/plus_zero_generic_witness.swift
@@ -0,0 +1,57 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -enable-sil-ownership %s
+
+protocol Runcible {
+ func runce<A>(_ x: A)
+}
+
+// CHECK-LABEL: sil hidden @$S15generic_witness3foo{{[_0-9a-zA-Z]*}}F : $@convention(thin) <B where B : Runcible> (@in_guaranteed B) -> () {
+
+func foo<B : Runcible>(_ x: B) {
+ // CHECK: [[METHOD:%.*]] = witness_method $B, #Runcible.runce!1 : {{.*}} : $@convention(witness_method: Runcible) <τ_0_0 where τ_0_0 : Runcible><τ_1_0> (@in_guaranteed τ_1_0, @in_guaranteed τ_0_0) -> ()
+ // CHECK: apply [[METHOD]]<B, Int>
+ x.runce(5)
+}
+
+// CHECK-LABEL: sil hidden @$S15generic_witness3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@in_guaranteed Runcible) -> ()
+func bar(_ x: Runcible) {
+ var x = x
+ // CHECK: [[BOX:%.*]] = alloc_box ${ var Runcible }
+ // CHECK: [[TEMP:%.*]] = alloc_stack $Runcible
+ // CHECK: [[EXIST:%.*]] = open_existential_addr immutable_access [[TEMP]] : $*Runcible to $*[[OPENED:@opened(.*) Runcible]]
+ // CHECK: [[METHOD:%.*]] = witness_method $[[OPENED]], #Runcible.runce!1
+ // CHECK: apply [[METHOD]]<[[OPENED]], Int>
+ x.runce(5)
+}
+
+protocol Color {}
+
+protocol Ink {
+ associatedtype Paint
+}
+
+protocol Pen {}
+
+protocol Pencil : Pen {
+ associatedtype Stroke : Pen
+}
+
+protocol Medium {
+ associatedtype Texture : Ink
+
+ func draw<P : Pencil>(paint: Texture.Paint, pencil: P) where P.Stroke == Texture.Paint
+}
+
+struct Canvas<I : Ink> where I.Paint : Pen {
+ typealias Texture = I
+
+ func draw<P : Pencil>(paint: I.Paint, pencil: P) where P.Stroke == Texture.Paint { }
+}
+
+extension Canvas : Medium {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15generic_witness6CanvasVyxGAA6MediumA2aEP4draw5paint6pencily6StrokeQyd___qd__tAA6PencilRd__7Texture_5PaintQZAKRSlFTW : $@convention(witness_method: Medium) <τ_0_0 where τ_0_0 : Ink><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in_guaranteed τ_0_0.Paint, @in_guaranteed τ_1_0, @in_guaranteed Canvas<τ_0_0>) -> () {
+// CHECK: [[FN:%.*]] = function_ref @$S15generic_witness6CanvasV4draw5paint6pencily5PaintQz_qd__tAA6PencilRd__6StrokeQyd__AHRSlF : $@convention(method) <τ_0_0 where τ_0_0 : Ink><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in_guaranteed τ_0_0.Paint, @in_guaranteed τ_1_0, Canvas<τ_0_0>) -> ()
+// CHECK: apply [[FN]]<τ_0_0, τ_1_0>({{.*}}) : $@convention(method) <τ_0_0 where τ_0_0 : Ink><τ_1_0 where τ_1_0 : Pencil, τ_0_0.Paint == τ_1_0.Stroke> (@in_guaranteed τ_0_0.Paint, @in_guaranteed τ_1_0, Canvas<τ_0_0>) -> ()
+// CHECK: }
diff --git a/test/SILGen/plus_zero_guaranteed_normal_args.swift b/test/SILGen/plus_zero_guaranteed_normal_args.swift
new file mode 100644
index 0000000..fdcec6c
--- /dev/null
+++ b/test/SILGen/plus_zero_guaranteed_normal_args.swift
@@ -0,0 +1,233 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-as-library -module-name Swift -parse-stdlib -emit-silgen -enable-sil-ownership -enable-guaranteed-normal-arguments %s | %FileCheck %s
+
+// This test checks specific codegen related to normal arguments being passed at
+// +0. Eventually, it should be merged into normal SILGen tests.
+
+/////////////////
+// Fake Stdlib //
+/////////////////
+
+precedencegroup AssignmentPrecedence {
+ assignment: true
+}
+
+public protocol ExpressibleByNilLiteral {
+ init(nilLiteral: ())
+}
+
+protocol IteratorProtocol {
+ associatedtype Element
+ mutating func next() -> Element?
+}
+
+protocol Sequence {
+ associatedtype Element
+ associatedtype Iterator : IteratorProtocol where Iterator.Element == Element
+
+ func makeIterator() -> Iterator
+}
+
+enum Optional<T> {
+case none
+case some(T)
+}
+
+extension Optional : ExpressibleByNilLiteral {
+ public init(nilLiteral: ()) {
+ self = .none
+ }
+}
+
+func _diagnoseUnexpectedNilOptional(_filenameStart: Builtin.RawPointer,
+ _filenameLength: Builtin.Word,
+ _filenameIsASCII: Builtin.Int1,
+ _line: Builtin.Word) {
+ // This would usually contain an assert, but we don't need one since we are
+ // just emitting SILGen.
+}
+
+class Klass {
+ init() {}
+}
+
+struct Buffer {
+ var k: Klass
+ init(inK: Klass) {
+ k = inK
+ }
+}
+
+public typealias AnyObject = Builtin.AnyObject
+
+protocol Protocol {
+ associatedtype AssocType
+ static func useInput(_ input: Builtin.Int32, into processInput: (AssocType) -> ())
+}
+
+struct FakeArray<Element> {
+ // Just to make this type non-trivial
+ var k: Klass
+
+ // We are only interested in this being called. We are not interested in its
+ // implementation.
+ mutating func append(_ t: Element) {}
+}
+
+struct FakeDictionary<Key, Value> {
+}
+
+struct FakeDictionaryIterator<Key, Value> {
+ var dictionary: FakeDictionary<Key, Value>?
+
+ init(_ newDictionary: FakeDictionary<Key, Value>) {
+ dictionary = newDictionary
+ }
+}
+
+extension FakeDictionaryIterator : IteratorProtocol {
+ public typealias Element = (Key, Value)
+ public mutating func next() -> Element? {
+ return .none
+ }
+}
+
+extension FakeDictionary : Sequence {
+ public typealias Element = (Key, Value)
+ public typealias Iterator = FakeDictionaryIterator<Key, Value>
+ public func makeIterator() -> FakeDictionaryIterator<Key, Value> {
+ return FakeDictionaryIterator(self)
+ }
+}
+
+public struct Unmanaged<Instance : AnyObject> {
+ internal unowned(unsafe) var _value: Instance
+}
+
+///////////
+// Tests //
+///////////
+
+class KlassWithBuffer {
+ var buffer: Buffer
+
+ // Make sure that the allocating init forwards into the initializing init at +1.
+ // CHECK-LABEL: sil hidden @$Ss15KlassWithBufferC3inKABs0A0C_tcfC : $@convention(method) (@owned Klass, @thick KlassWithBuffer.Type) -> @owned KlassWithBuffer {
+ // CHECK: bb0([[ARG:%.*]] : @owned $Klass,
+ // CHECK: [[INITIALIZING_INIT:%.*]] = function_ref @$Ss15KlassWithBufferC3inKABs0A0C_tcfc : $@convention(method) (@owned Klass, @owned KlassWithBuffer) -> @owned KlassWithBuffer
+ // CHECK: apply [[INITIALIZING_INIT]]([[ARG]],
+ // CHECK: } // end sil function '$Ss15KlassWithBufferC3inKABs0A0C_tcfC'
+ init(inK: Klass = Klass()) {
+ buffer = Buffer(inK: inK)
+ }
+
+ // This test makes sure that we:
+ //
+ // 1. Are able to propagate a +0 value value buffer.k into a +0 value and that
+ // we then copy that +0 value into a +1 value, before we begin the epilog and
+ // then return that value.
+ // CHECK-LABEL: sil hidden @$Ss15KlassWithBufferC03getC14AsNativeObjectBoyF : $@convention(method) (@guaranteed KlassWithBuffer) -> @owned Builtin.NativeObject {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $KlassWithBuffer):
+ // CHECK: [[BUF_BOX:%.*]] = alloc_stack $Buffer
+ // CHECK: [[METHOD:%.*]] = class_method [[SELF]] : $KlassWithBuffer, #KlassWithBuffer.buffer!getter.1
+ // CHECK: [[BUF:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: store [[BUF]] to [init] [[BUF_BOX]]
+ // CHECK: [[GEP:%.*]] = struct_element_addr [[BUF_BOX]] : $*Buffer, #Buffer.k
+ // CHECK: [[BUF_KLASS:%.*]] = load [copy] [[GEP]]
+ // CHECK: destroy_addr [[BUF_BOX]]
+ // CHECK: [[BORROWED_BUF_KLASS:%.*]] = begin_borrow [[BUF_KLASS]]
+ // CHECK: [[CASTED_BORROWED_BUF_KLASS:%.*]] = unchecked_ref_cast [[BORROWED_BUF_KLASS]]
+ // CHECK: [[COPY_CASTED_BORROWED_BUF_KLASS:%.*]] = copy_value [[CASTED_BORROWED_BUF_KLASS]]
+ // CHECK: end_borrow [[BORROWED_BUF_KLASS]]
+ // CHECK: destroy_value [[BUF_KLASS]]
+ // CHECK: return [[COPY_CASTED_BORROWED_BUF_KLASS]]
+ // CHECK: } // end sil function '$Ss15KlassWithBufferC03getC14AsNativeObjectBoyF'
+ func getBufferAsNativeObject() -> Builtin.NativeObject {
+ return Builtin.unsafeCastToNativeObject(buffer.k)
+ }
+}
+
+struct StructContainingBridgeObject {
+ var rawValue: Builtin.BridgeObject
+
+ // CHECK-LABEL: sil hidden @$Ss28StructContainingBridgeObjectV8swiftObjAByXl_tcfC : $@convention(method) (@owned AnyObject, @thin StructContainingBridgeObject.Type) -> @owned StructContainingBridgeObject {
+ // CHECK: bb0([[ARG:%.*]] : @owned $AnyObject,
+ // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK: [[CASTED_ARG:%.*]] = unchecked_ref_cast [[BORROWED_ARG]] : $AnyObject to $Builtin.BridgeObject
+ // CHECK: [[COPY_CASTED_ARG:%.*]] = copy_value [[CASTED_ARG]]
+ // CHECK: assign [[COPY_CASTED_ARG]] to
+ // CHECK: } // end sil function '$Ss28StructContainingBridgeObjectV8swiftObjAByXl_tcfC'
+ init(swiftObj: AnyObject) {
+ rawValue = Builtin.reinterpretCast(swiftObj)
+ }
+}
+
+struct ReabstractionThunkTest : Protocol {
+ typealias AssocType = Builtin.Int32
+
+ static func useInput(_ input: Builtin.Int32, into processInput: (AssocType) -> ()) {
+ processInput(input)
+ }
+}
+
+// Make sure that we provide a cleanup to x properly before we pass it to
+// result.
+extension FakeDictionary {
+ // CHECK-LABEL: sil hidden @$Ss14FakeDictionaryV20makeSureToCopyTuplesyyF : $@convention(method) <Key, Value> (FakeDictionary<Key, Value>) -> () {
+ // CHECK: [[X:%.*]] = alloc_stack $(Key, Value), let, name "x"
+ // CHECK: [[INDUCTION_VAR:%.*]] = unchecked_take_enum_data_addr {{%.*}} : $*Optional<(Key, Value)>, #Optional.some!enumelt.1
+ // CHECK: [[INDUCTION_VAR_0:%.*]] = tuple_element_addr [[INDUCTION_VAR]] : $*(Key, Value), 0
+ // CHECK: [[INDUCTION_VAR_1:%.*]] = tuple_element_addr [[INDUCTION_VAR]] : $*(Key, Value), 1
+ // CHECK: [[X_0:%.*]] = tuple_element_addr [[X]] : $*(Key, Value), 0
+ // CHECK: [[X_1:%.*]] = tuple_element_addr [[X]] : $*(Key, Value), 1
+ // CHECK: copy_addr [take] [[INDUCTION_VAR_0]] to [initialization] [[X_0]]
+ // CHECK: copy_addr [take] [[INDUCTION_VAR_1]] to [initialization] [[X_1]]
+ // CHECK: [[X_0:%.*]] = tuple_element_addr [[X]] : $*(Key, Value), 0
+ // CHECK: [[X_1:%.*]] = tuple_element_addr [[X]] : $*(Key, Value), 1
+ // CHECK: [[TMP_X:%.*]] = alloc_stack $(Key, Value)
+ // CHECK: [[TMP_X_0:%.*]] = tuple_element_addr [[TMP_X]] : $*(Key, Value), 0
+ // CHECK: [[TMP_X_1:%.*]] = tuple_element_addr [[TMP_X]] : $*(Key, Value), 1
+ // CHECK: [[TMP_0:%.*]] = alloc_stack $Key
+ // CHECK: copy_addr [[X_0]] to [initialization] [[TMP_0]]
+ // CHECK: copy_addr [take] [[TMP_0]] to [initialization] [[TMP_X_0]]
+ // CHECK: [[TMP_1:%.*]] = alloc_stack $Value
+ // CHECK: copy_addr [[X_1]] to [initialization] [[TMP_1]]
+ // CHECK: copy_addr [take] [[TMP_1]] to [initialization] [[TMP_X_1]]
+ // CHECK: [[FUNC:%.*]] = function_ref @$Ss9FakeArrayV6appendyyxF : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout FakeArray<τ_0_0>) -> ()
+ // CHECK: apply [[FUNC]]<(Key, Value)>([[TMP_X]],
+ // CHECK: } // end sil function '$Ss14FakeDictionaryV20makeSureToCopyTuplesyyF'
+ func makeSureToCopyTuples() {
+ var result = FakeArray<Element>(k: Klass())
+ for x in self {
+ result.append(x)
+ }
+ }
+}
+
+extension Unmanaged {
+ // Just make sure that we do not crash on this.
+ func unsafeGuaranteedTest<Result>(
+ _ body: (Instance) -> Result
+ ) -> Result {
+ let (guaranteedInstance, token) = Builtin.unsafeGuaranteed(_value)
+ let result = body(guaranteedInstance)
+ Builtin.unsafeGuaranteedEnd(token)
+ return result
+ }
+}
+
+// Make sure that we properly forward x into memory and don't crash.
+public func forwardIntoMemory(fromNative x: AnyObject, y: Builtin.Word) -> Builtin.BridgeObject {
+ // y would normally be 0._builtinWordValue. We don't want to define that
+ // conformance.
+ let object = Builtin.castToBridgeObject(x, y)
+ return object
+}
+
+public struct StructWithOptionalAddressOnlyField<T> {
+ public let newValue: T?
+}
+
+func useStructWithOptionalAddressOnlyField<T>(t: T) -> StructWithOptionalAddressOnlyField<T> {
+ return StructWithOptionalAddressOnlyField<T>(newValue: t)
+}
diff --git a/test/SILGen/plus_zero_guaranteed_self.swift b/test/SILGen/plus_zero_guaranteed_self.swift
new file mode 100644
index 0000000..f8f4faa
--- /dev/null
+++ b/test/SILGen/plus_zero_guaranteed_self.swift
@@ -0,0 +1,557 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
+
+protocol Fooable {
+ init()
+ func foo(_ x: Int)
+ mutating func bar()
+ mutating func bas()
+
+ var prop1: Int { get set }
+ var prop2: Int { get set }
+ var prop3: Int { get nonmutating set }
+}
+
+protocol Barrable: class {
+ init()
+ func foo(_ x: Int)
+ func bar()
+ func bas()
+
+ var prop1: Int { get set }
+ var prop2: Int { get set }
+ var prop3: Int { get set }
+}
+
+struct S: Fooable {
+ var x: C? // Make the type nontrivial, so +0/+1 is observable.
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin S.Type) -> @owned S
+ init() {}
+ // TODO: Way too many redundant r/r pairs here. Should use +0 rvalues.
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (Int, @guaranteed S) -> () {
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: copy_value [[SELF]]
+ // CHECK-NOT: destroy_value [[SELF]]
+ func foo(_ x: Int) {
+ self.foo(x)
+ }
+
+ func foooo(_ x: (Int, Bool)) {
+ self.foooo(x)
+ }
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV3bar{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout S) -> ()
+ // CHECK: bb0([[SELF:%.*]] : @trivial $*S):
+ // CHECK-NOT: destroy_addr [[SELF]]
+ mutating func bar() {
+ self.bar()
+ }
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV3bas{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed S) -> ()
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: copy_value [[SELF]]
+ // CHECK-NOT: destroy_value [[SELF]]
+ func bas() {
+ self.bas()
+ }
+
+ var prop1: Int = 0
+
+ // Getter for prop1
+ // CHECK-LABEL: sil hidden [transparent] @$S15guaranteed_self1SV5prop1Sivg : $@convention(method) (@guaranteed S) -> Int
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: destroy_value [[SELF]]
+
+ // Setter for prop1
+ // CHECK-LABEL: sil hidden [transparent] @$S15guaranteed_self1SV5prop1Sivs : $@convention(method) (Int, @inout S) -> ()
+ // CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+ // CHECK-NOT: load [[SELF_ADDR]]
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+ // materializeForSet for prop1
+ // CHECK-LABEL: sil hidden [transparent] @$S15guaranteed_self1SV5prop1Sivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ // CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+ // CHECK-NOT: load [[SELF_ADDR]]
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+ var prop2: Int {
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV5prop2Sivg : $@convention(method) (@guaranteed S) -> Int
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: destroy_value [[SELF]]
+ get { return 0 }
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV5prop2Sivs : $@convention(method) (Int, @inout S) -> ()
+ // CHECK-LABEL: sil hidden [transparent] @$S15guaranteed_self1SV5prop2Sivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ set { }
+ }
+
+ var prop3: Int {
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV5prop3Sivg : $@convention(method) (@guaranteed S) -> Int
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: destroy_value [[SELF]]
+ get { return 0 }
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1SV5prop3Sivs : $@convention(method) (Int, @guaranteed S) -> ()
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: destroy_value [[SELF]]
+ // CHECK-LABEL: sil hidden [transparent] @$S15guaranteed_self1SV5prop3Sivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @guaranteed $S):
+ // CHECK-NOT: destroy_value [[SELF]]
+ nonmutating set { }
+ }
+}
+
+// Witness thunk for nonmutating 'foo'
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP3foo{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) (Int, @in_guaranteed S) -> () {
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for mutating 'bar'
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP3bar{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) (@inout S) -> () {
+// CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK-NOT: load [[SELF_ADDR]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for 'bas', which is mutating in the protocol, but nonmutating
+// in the implementation
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP3bas{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) (@inout S) -> ()
+// CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK: end_borrow [[SELF]]
+// CHECK-NOT: destroy_value [[SELF]]
+
+// Witness thunk for prop1 getter
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop1SivgTW : $@convention(witness_method: Fooable) (@in_guaranteed S) -> Int
+// CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK-NOT: destroy_value [[SELF]]
+
+// Witness thunk for prop1 setter
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop1SivsTW : $@convention(witness_method: Fooable) (Int, @inout S) -> () {
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop1 materializeForSet
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop1SivmTW : $@convention(witness_method: Fooable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop2 getter
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop2SivgTW : $@convention(witness_method: Fooable) (@in_guaranteed S) -> Int
+// CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop2 setter
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop2SivsTW : $@convention(witness_method: Fooable) (Int, @inout S) -> () {
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop2 materializeForSet
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop2SivmTW : $@convention(witness_method: Fooable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop3 getter
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop3SivgTW : $@convention(witness_method: Fooable) (@in_guaranteed S) -> Int
+// CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop3 nonmutating setter
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop3SivsTW : $@convention(witness_method: Fooable) (Int, @in_guaranteed S) -> ()
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness thunk for prop3 nonmutating materializeForSet
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self1SVAA7FooableA2aDP5prop3SivmTW : $@convention(witness_method: Fooable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed S) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*S):
+// CHECK: [[SELF:%.*]] = load_borrow [[SELF_ADDR]]
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+// CHECK: } // end sil function '$S15guaranteed_self1SVAA7FooableA2aDP5prop3SivmTW'
+
+//
+// TODO: Expected output for the other cases
+//
+
+struct AO<T>: Fooable {
+ var x: T?
+
+ init() {}
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self2AOV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) <T> (Int, @in_guaranteed AO<T>) -> ()
+ // CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*AO<T>):
+ // CHECK: apply {{.*}} [[SELF_ADDR]]
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+ // CHECK: }
+ func foo(_ x: Int) {
+ self.foo(x)
+ }
+ mutating func bar() {
+ self.bar()
+ }
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self2AOV3bas{{[_0-9a-zA-Z]*}}F : $@convention(method) <T> (@in_guaranteed AO<T>) -> ()
+ // CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*AO<T>):
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+ func bas() {
+ self.bas()
+ }
+
+
+ var prop1: Int = 0
+ var prop2: Int {
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self2AOV5prop2Sivg : $@convention(method) <T> (@in_guaranteed AO<T>) -> Int {
+ // CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*AO<T>):
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+ get { return 0 }
+ set { }
+ }
+ var prop3: Int {
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self2AOV5prop3Sivg : $@convention(method) <T> (@in_guaranteed AO<T>) -> Int
+ // CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*AO<T>):
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+ get { return 0 }
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self2AOV5prop3Sivs : $@convention(method) <T> (Int, @in_guaranteed AO<T>) -> ()
+ // CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*AO<T>):
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+ // CHECK-LABEL: sil hidden [transparent] @$S15guaranteed_self2AOV5prop3Sivm : $@convention(method) <T> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed AO<T>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ // CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*AO<T>):
+ // CHECK-NOT: destroy_addr [[SELF_ADDR]]
+ // CHECK: }
+ nonmutating set { }
+ }
+}
+
+// Witness for nonmutating 'foo'
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self2AOVyxGAA7FooableA2aEP3foo{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) <τ_0_0> (Int, @in_guaranteed AO<τ_0_0>) -> ()
+// CHECK: bb0({{.*}} [[SELF_ADDR:%.*]] : @trivial $*AO<τ_0_0>):
+// CHECK: apply {{.*}} [[SELF_ADDR]]
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+// Witness for 'bar', which is mutating in protocol but nonmutating in impl
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15guaranteed_self2AOVyxGAA7FooableA2aEP3bar{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Fooable) <τ_0_0> (@inout AO<τ_0_0>) -> ()
+// CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*AO<τ_0_0>):
+// -- NB: This copy is not necessary, since we're willing to assume an inout
+// parameter is not mutably aliased.
+// CHECK: apply {{.*}}([[SELF_ADDR]])
+// CHECK-NOT: destroy_addr [[SELF_ADDR]]
+
+class C: Fooable, Barrable {
+ // Allocating initializer
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1CC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick C.Type) -> @owned C
+ // CHECK: [[SELF1:%.*]] = alloc_ref $C
+ // CHECK-NOT: [[SELF1]]
+ // CHECK: [[SELF2:%.*]] = apply {{.*}}([[SELF1]])
+ // CHECK-NOT: [[SELF2]]
+ // CHECK: return [[SELF2]]
+
+ // Initializing constructors still have the +1 in, +1 out convention.
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1CC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (@owned C) -> @owned C {
+ // CHECK: bb0([[SELF:%.*]] : @owned $C):
+ // CHECK: [[MARKED_SELF:%.*]] = mark_uninitialized [rootself] [[SELF]]
+ // CHECK: [[MARKED_SELF_RESULT:%.*]] = copy_value [[MARKED_SELF]]
+ // CHECK: destroy_value [[MARKED_SELF]]
+ // CHECK: return [[MARKED_SELF_RESULT]]
+ // CHECK: } // end sil function '$S15guaranteed_self1CC{{[_0-9a-zA-Z]*}}fc'
+
+ // @objc thunk for initializing constructor
+ // CHECK-LABEL: sil hidden [thunk] @$S15guaranteed_self1CC{{[_0-9a-zA-Z]*}}fcTo : $@convention(objc_method) (@owned C) -> @owned C
+ // CHECK: bb0([[SELF:%.*]] : @owned $C):
+ // CHECK-NOT: copy_value [[SELF]]
+ // CHECK: [[SELF2:%.*]] = apply {{%.*}}([[SELF]])
+ // CHECK-NOT: destroy_value [[SELF]]
+ // CHECK-NOT: destroy_value [[SELF2]]
+ // CHECK: return [[SELF2]]
+ // CHECK: } // end sil function '$S15guaranteed_self1CC{{[_0-9a-zA-Z]*}}fcTo'
+ @objc required init() {}
+
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1CC3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (Int, @guaranteed C) -> ()
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @guaranteed $C):
+ // CHECK-NOT: copy_value
+ // CHECK-NOT: destroy_value
+ // CHECK: } // end sil function '$S15guaranteed_self1CC3foo{{[_0-9a-zA-Z]*}}F'
+
+ // CHECK-LABEL: sil hidden [thunk] @$S15guaranteed_self1CC3foo{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (Int, C) -> () {
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @unowned $C):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: apply {{.*}}({{.*}}, [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF]]
+ // CHECK: } // end sil function '$S15guaranteed_self1CC3foo{{[_0-9a-zA-Z]*}}FTo'
+ @objc func foo(_ x: Int) {
+ self.foo(x)
+ }
+ @objc func bar() {
+ self.bar()
+ }
+ @objc func bas() {
+ self.bas()
+ }
+
+ // CHECK-LABEL: sil hidden [transparent] [thunk] @$S15guaranteed_self1CC5prop1SivgTo : $@convention(objc_method) (C) -> Int
+ // CHECK: bb0([[SELF:%.*]] : @unowned $C):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: apply {{.*}}([[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF]]
+ // CHECK-NOT: destroy_value [[SELF_COPY]]
+
+ // CHECK-LABEL: sil hidden [transparent] [thunk] @$S15guaranteed_self1CC5prop1SivsTo : $@convention(objc_method) (Int, C) -> ()
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @unowned $C):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: apply {{.*}} [[BORROWED_SELF_COPY]]
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF]]
+ // CHECK: }
+ @objc var prop1: Int = 0
+ @objc var prop2: Int {
+ get { return 0 }
+ set {}
+ }
+ @objc var prop3: Int {
+ get { return 0 }
+ set {}
+ }
+
+}
+
+class D: C {
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1DC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick D.Type) -> @owned D
+ // CHECK: [[SELF1:%.*]] = alloc_ref $D
+ // CHECK-NOT: [[SELF1]]
+ // CHECK: [[SELF2:%.*]] = apply {{.*}}([[SELF1]])
+ // CHECK-NOT: [[SELF1]]
+ // CHECK-NOT: [[SELF2]]
+ // CHECK: return [[SELF2]]
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self1DC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (@owned D) -> @owned D
+ // CHECK: bb0([[SELF:%.*]] : @owned $D):
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var D }
+ // CHECK-NEXT: [[MARKED_SELF_BOX:%.*]] = mark_uninitialized [derivedself] [[SELF_BOX]]
+ // CHECK-NEXT: [[PB:%.*]] = project_box [[MARKED_SELF_BOX]]
+ // CHECK-NEXT: store [[SELF]] to [init] [[PB]]
+ // CHECK-NOT: [[PB]]
+ // CHECK: [[SELF1:%.*]] = load [take] [[PB]]
+ // CHECK-NEXT: [[SUPER1:%.*]] = upcast [[SELF1]]
+ // CHECK-NOT: [[PB]]
+ // CHECK: [[SUPER2:%.*]] = apply {{.*}}([[SUPER1]])
+ // CHECK-NEXT: [[SELF2:%.*]] = unchecked_ref_cast [[SUPER2]]
+ // CHECK-NEXT: store [[SELF2]] to [init] [[PB]]
+ // CHECK-NOT: [[PB]]
+ // CHECK-NOT: [[SELF1]]
+ // CHECK-NOT: [[SUPER1]]
+ // CHECK-NOT: [[SELF2]]
+ // CHECK-NOT: [[SUPER2]]
+ // CHECK: [[SELF_FINAL:%.*]] = load [copy] [[PB]]
+ // CHECK-NEXT: destroy_value [[MARKED_SELF_BOX]]
+ // CHECK-NEXT: return [[SELF_FINAL]]
+ required init() {
+ super.init()
+ }
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S15guaranteed_self1DC3foo{{[_0-9a-zA-Z]*}}FTD : $@convention(method) (Int, @guaranteed D) -> ()
+ // CHECK: bb0({{.*}} [[SELF:%.*]] : @guaranteed $D):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF_COPY]]
+ // CHECK-NOT: destroy_value [[SELF]]
+ // CHECK: }
+ dynamic override func foo(_ x: Int) {
+ self.foo(x)
+ }
+}
+
+func S_curryThunk(_ s: S) -> ((S) -> (Int) -> ()/*, Int -> ()*/) {
+ return (S.foo /*, s.foo*/)
+}
+
+func AO_curryThunk<T>(_ ao: AO<T>) -> ((AO<T>) -> (Int) -> ()/*, Int -> ()*/) {
+ return (AO.foo /*, ao.foo*/)
+}
+
+// ----------------------------------------------------------------------------
+// Make sure that we properly translate in_guaranteed parameters
+// correctly if we are asked to.
+// ----------------------------------------------------------------------------
+
+
+// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$S15guaranteed_self9FakeArrayVAA8SequenceA2aDP17_constrainElement{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: Sequence) (@in_guaranteed FakeElement, @in_guaranteed FakeArray) -> () {
+// CHECK: bb0([[ARG0_PTR:%.*]] : @trivial $*FakeElement, [[ARG1_PTR:%.*]] : @trivial $*FakeArray):
+// CHECK: [[ARG0:%.*]] = load [trivial] [[ARG0_PTR]]
+// CHECK: function_ref (extension in guaranteed_self):guaranteed_self.SequenceDefaults._constrainElement
+// CHECK: [[FUN:%.*]] = function_ref @{{.*}}
+// CHECK: apply [[FUN]]<FakeArray>([[ARG0]], [[ARG1_PTR]])
+
+class Z {}
+
+public struct FakeGenerator {}
+public struct FakeArray {
+ var z = Z()
+}
+public struct FakeElement {}
+
+public protocol FakeGeneratorProtocol {
+ associatedtype Element
+}
+
+extension FakeGenerator : FakeGeneratorProtocol {
+ public typealias Element = FakeElement
+}
+
+public protocol SequenceDefaults {
+ associatedtype Element
+ associatedtype Generator : FakeGeneratorProtocol
+}
+
+extension SequenceDefaults {
+ public func _constrainElement(_: FakeGenerator.Element) {}
+}
+
+public protocol Sequence : SequenceDefaults {
+ func _constrainElement(_: Element)
+}
+
+
+extension FakeArray : Sequence {
+ public typealias Element = FakeElement
+ public typealias Generator = FakeGenerator
+
+ func _containsElement(_: Element) {}
+}
+
+// -----------------------------------------------------------------------------
+// Make sure that we do not emit extra copy_values when accessing let fields of
+// guaranteed parameters.
+// -----------------------------------------------------------------------------
+
+class Kraken {
+ func enrage() {}
+}
+
+func destroyShip(_ k: Kraken) {}
+
+class LetFieldClass {
+ let letk = Kraken()
+ var vark = Kraken()
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self13LetFieldClassC10letkMethod{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed LetFieldClass) -> () {
+ // CHECK: bb0([[CLS:%.*]] : @guaranteed $LetFieldClass):
+ // CHECK: [[KRAKEN_ADDR:%.*]] = ref_element_addr [[CLS]] : $LetFieldClass, #LetFieldClass.letk
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [read] [dynamic] [[KRAKEN_ADDR]] : $*Kraken
+ // CHECK-NEXT: [[KRAKEN:%.*]] = load_borrow [[WRITE]]
+ // CHECK-NEXT: end_access [[WRITE]] : $*Kraken
+ // CHECK-NEXT: [[KRAKEN_METH:%.*]] = class_method [[KRAKEN]]
+ // CHECK-NEXT: apply [[KRAKEN_METH]]([[KRAKEN]])
+ // CHECK-NEXT: end_borrow [[KRAKEN]] from [[WRITE]]
+ // CHECK-NEXT: [[KRAKEN_ADDR:%.*]] = ref_element_addr [[CLS]] : $LetFieldClass, #LetFieldClass.letk
+ // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[KRAKEN_ADDR]] : $*Kraken
+ // CHECK-NEXT: [[KRAKEN:%.*]] = load [copy] [[READ]]
+ // CHECK-NEXT: end_access [[READ]] : $*Kraken
+ // CHECK: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @$S15guaranteed_self11destroyShipyyAA6KrakenCF : $@convention(thin) (@guaranteed Kraken) -> ()
+ // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[BORROWED_KRAKEN]])
+ // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
+ // CHECK-NEXT: [[KRAKEN_BOX:%.*]] = alloc_box ${ var Kraken }
+ // CHECK-NEXT: [[PB:%.*]] = project_box [[KRAKEN_BOX]]
+ // CHECK-NEXT: [[KRAKEN_ADDR:%.*]] = ref_element_addr [[CLS]] : $LetFieldClass, #LetFieldClass.letk
+ // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[KRAKEN_ADDR]] : $*Kraken
+ // CHECK-NEXT: [[KRAKEN2:%.*]] = load [copy] [[READ]]
+ // CHECK-NEXT: end_access [[READ]] : $*Kraken
+ // CHECK-NEXT: store [[KRAKEN2]] to [init] [[PB]]
+ // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*Kraken
+ // CHECK-NEXT: [[KRAKEN_COPY:%.*]] = load [copy] [[READ]]
+ // CHECK-NEXT: end_access [[READ]] : $*Kraken
+ // CHECK-NEXT: [[BORROWED_KRAKEN_COPY:%.*]] = begin_borrow [[KRAKEN_COPY]]
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @$S15guaranteed_self11destroyShipyyAA6KrakenCF : $@convention(thin) (@guaranteed Kraken) -> ()
+ // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[BORROWED_KRAKEN_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN_COPY]]
+ // CHECK-NEXT: destroy_value [[KRAKEN_COPY]]
+ // CHECK-NEXT: destroy_value [[KRAKEN_BOX]]
+ // CHECK-NEXT: destroy_value [[KRAKEN]]
+ // CHECK-NEXT: tuple
+ // CHECK-NEXT: return
+ func letkMethod() {
+ letk.enrage()
+ let ll = letk
+ destroyShip(ll)
+ var lv = letk
+ destroyShip(lv)
+ }
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self13LetFieldClassC10varkMethod{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed LetFieldClass) -> () {
+ // CHECK: bb0([[CLS:%.*]] : @guaranteed $LetFieldClass):
+ // CHECK: [[KRAKEN_GETTER_FUN:%.*]] = class_method [[CLS]] : $LetFieldClass, #LetFieldClass.vark!getter.1 : (LetFieldClass) -> () -> Kraken, $@convention(method) (@guaranteed LetFieldClass) -> @owned Kraken
+ // CHECK-NEXT: [[KRAKEN:%.*]] = apply [[KRAKEN_GETTER_FUN]]([[CLS]])
+ // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+ // CHECK-NEXT: [[KRAKEN_METH:%.*]] = class_method [[BORROWED_KRAKEN]]
+ // CHECK-NEXT: apply [[KRAKEN_METH]]([[BORROWED_KRAKEN]])
+ // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
+ // CHECK-NEXT: destroy_value [[KRAKEN]]
+ // CHECK-NEXT: [[KRAKEN_GETTER_FUN:%.*]] = class_method [[CLS]] : $LetFieldClass, #LetFieldClass.vark!getter.1 : (LetFieldClass) -> () -> Kraken, $@convention(method) (@guaranteed LetFieldClass) -> @owned Kraken
+ // CHECK-NEXT: [[KRAKEN:%.*]] = apply [[KRAKEN_GETTER_FUN]]([[CLS]])
+ // CHECK: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @$S15guaranteed_self11destroyShipyyAA6KrakenCF : $@convention(thin) (@guaranteed Kraken) -> ()
+ // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[BORROWED_KRAKEN]])
+ // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
+ // CHECK-NEXT: [[KRAKEN_BOX:%.*]] = alloc_box ${ var Kraken }
+ // CHECK-NEXT: [[PB:%.*]] = project_box [[KRAKEN_BOX]]
+ // CHECK-NEXT: [[KRAKEN_GETTER_FUN:%.*]] = class_method [[CLS]] : $LetFieldClass, #LetFieldClass.vark!getter.1 : (LetFieldClass) -> () -> Kraken, $@convention(method) (@guaranteed LetFieldClass) -> @owned Kraken
+ // CHECK-NEXT: [[KRAKEN2:%.*]] = apply [[KRAKEN_GETTER_FUN]]([[CLS]])
+ // CHECK-NEXT: store [[KRAKEN2]] to [init] [[PB]]
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [read] [unknown] [[PB]] : $*Kraken
+ // CHECK-NEXT: [[KRAKEN_COPY:%.*]] = load [copy] [[WRITE]]
+ // CHECK-NEXT: end_access [[WRITE]] : $*Kraken
+ // CHECK-NEXT: [[BORROWED_KRAKEN_COPY:%.*]] = begin_borrow [[KRAKEN_COPY]]
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @$S15guaranteed_self11destroyShipyyAA6KrakenCF : $@convention(thin) (@guaranteed Kraken) -> ()
+ // CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[BORROWED_KRAKEN_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_KRAKEN_COPY]]
+ // CHECK-NEXT: destroy_value [[KRAKEN_COPY]]
+ // CHECK-NEXT: destroy_value [[KRAKEN_BOX]]
+ // CHECK-NEXT: destroy_value [[KRAKEN]]
+ // CHECK-NEXT: tuple
+ // CHECK-NEXT: return
+ func varkMethod() {
+ vark.enrage()
+ let vl = vark
+ destroyShip(vl)
+ var vv = vark
+ destroyShip(vv)
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Make sure that in all of the following cases find has only one copy_value in it.
+// -----------------------------------------------------------------------------
+
+class ClassIntTreeNode {
+ let value : Int
+ let left, right : ClassIntTreeNode
+
+ init() {}
+
+ // CHECK-LABEL: sil hidden @$S15guaranteed_self16ClassIntTreeNodeC4find{{[_0-9a-zA-Z]*}}F : $@convention(method) (Int, @guaranteed ClassIntTreeNode) -> @owned ClassIntTreeNode {
+ // CHECK-NOT: destroy_value
+ // CHECK: copy_value
+ // CHECK-NOT: copy_value
+ // CHECK-NOT: destroy_value
+ // CHECK: return
+ func find(_ v : Int) -> ClassIntTreeNode {
+ if v == value { return self }
+ if v < value { return left.find(v) }
+ return right.find(v)
+ }
+}
diff --git a/test/SILGen/plus_zero_if_while_binding.swift b/test/SILGen/plus_zero_if_while_binding.swift
new file mode 100644
index 0000000..4152501
--- /dev/null
+++ b/test/SILGen/plus_zero_if_while_binding.swift
@@ -0,0 +1,405 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func foo() -> String? { return "" }
+func bar() -> String? { return "" }
+
+func a(_ x: String) {}
+func b(_ x: String) {}
+func c(_ x: String) {}
+
+func marker_1() {}
+func marker_2() {}
+func marker_3() {}
+
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding0A8_no_else{{[_0-9a-zA-Z]*}}F
+func if_no_else() {
+ // CHECK: [[FOO:%.*]] = function_ref @$S16if_while_binding3fooSSSgyF
+ // CHECK: [[OPT_RES:%.*]] = apply [[FOO]]()
+ // CHECK: switch_enum [[OPT_RES]] : $Optional<String>, case #Optional.some!enumelt.1: [[YES:bb[0-9]+]], case #Optional.none!enumelt: [[NO:bb[0-9]+]]
+ //
+ // CHECK: [[NO]]:
+ // CHECK: br [[CONT:bb[0-9]+]]
+ if let x = foo() {
+ // CHECK: [[YES]]([[VAL:%[0-9]+]] : @owned $String):
+ // CHECK: [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]]
+ // CHECK: [[A:%.*]] = function_ref @$S16if_while_binding1a
+ // CHECK: apply [[A]]([[BORROWED_VAL]])
+ // CHECK: end_borrow [[BORROWED_VAL]] from [[VAL]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: br [[CONT]]
+ a(x)
+ }
+ // CHECK: [[CONT]]:
+ // CHECK-NEXT: tuple ()
+}
+// CHECK: } // end sil function '$S16if_while_binding0A8_no_else{{[_0-9a-zA-Z]*}}F'
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding0A11_else_chainyyF : $@convention(thin) () -> () {
+func if_else_chain() {
+ // CHECK: [[FOO:%.*]] = function_ref @$S16if_while_binding3foo{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: [[OPT_RES:%.*]] = apply [[FOO]]()
+ // CHECK-NEXT: switch_enum [[OPT_RES]] : $Optional<String>, case #Optional.some!enumelt.1: [[YESX:bb[0-9]+]], case #Optional.none!enumelt: [[NOX:bb[0-9]+]]
+ if let x = foo() {
+ // CHECK: [[NOX]]:
+ // CHECK: br [[FAILURE_DESTX:bb[0-9]+]]
+ //
+ // CHECK: [[YESX]]([[VAL:%[0-9]+]] : @owned $String):
+ // CHECK: debug_value [[VAL]] : $String, let, name "x"
+ // CHECK: [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]]
+ // CHECK: [[A:%.*]] = function_ref @$S16if_while_binding1a
+ // CHECK: apply [[A]]([[BORROWED_VAL]])
+ // CHECK: end_borrow [[BORROWED_VAL]] from [[VAL]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: br [[CONT_X:bb[0-9]+]]
+ a(x)
+ //
+ // CHECK: [[FAILURE_DESTX]]:
+ // CHECK: alloc_box ${ var String }, var, name "y"
+ // CHECK: switch_enum {{.*}} : $Optional<String>, case #Optional.some!enumelt.1: [[YESY:bb[0-9]+]], case #Optional.none!enumelt: [[ELSE1:bb[0-9]+]]
+ // CHECK: [[ELSE1]]:
+ // CHECK: dealloc_box {{.*}} ${ var String }
+ // CHECK: br [[ELSE:bb[0-9]+]]
+ } else if var y = bar() {
+ // CHECK: [[YESY]]([[VAL:%[0-9]+]] : @owned $String):
+ // CHECK: br [[CONT_Y:bb[0-9]+]]
+ // CHECK: [[CONT_Y]]:
+ // CHECK: br [[CONT_Y2:bb[0-9]+]]
+ b(y)
+ } else {
+ // CHECK: [[ELSE]]:
+ // CHECK: function_ref if_while_binding.c
+ c("")
+ // CHECK: br [[CONT_Y2]]
+ }
+
+ // CHECK: [[CONT_Y2]]:
+ // br [[CONT_X]]
+ // CHECK: [[CONT_X]]:
+}
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding0B5_loopyyF : $@convention(thin) () -> () {
+func while_loop() {
+ // CHECK: br [[LOOP_ENTRY:bb[0-9]+]]
+ //
+ // CHECK: [[LOOP_ENTRY]]:
+ // CHECK: switch_enum {{.*}} : $Optional<String>, case #Optional.some!enumelt.1: [[LOOP_BODY:bb[0-9]+]], case #Optional.none!enumelt: [[NO_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[NO_TRAMPOLINE]]:
+ // CHECK: br [[LOOP_EXIT:bb[0-9]+]]
+ while let x = foo() {
+ // CHECK: [[LOOP_BODY]]([[X:%[0-9]+]] : @owned $String):
+ // CHECK: switch_enum {{.*}} : $Optional<String>, case #Optional.some!enumelt.1: [[YES:bb[0-9]+]], case #Optional.none!enumelt: [[NO_TRAMPOLINE_2:bb[0-9]+]]
+ //
+ // CHECK: [[NO_TRAMPOLINE_2]]:
+ // CHECK: br [[FAILURE_DEST_2:bb[0-9]+]]
+ if let y = bar() {
+ // CHECK: [[YES]]([[Y:%[0-9]+]] : @owned $String):
+ a(y)
+ break
+ // CHECK: destroy_value [[Y]]
+ // CHECK: destroy_value [[X]]
+ // CHECK: br [[LOOP_EXIT]]
+ }
+ // CHECK: [[FAILURE_DEST_2]]:
+ // CHECK: destroy_value [[X]]
+ // CHECK: br [[LOOP_ENTRY]]
+ }
+ // CHECK: [[LOOP_EXIT]]:
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+// Don't leak alloc_stacks for address-only conditional bindings in 'while'.
+// <rdar://problem/16202294>
+// CHECK-LABEL: sil hidden @$S16if_while_binding0B13_loop_generic{{[_0-9a-zA-Z]*}}F
+// CHECK: br [[COND:bb[0-9]+]]
+// CHECK: [[COND]]:
+// CHECK: [[X:%.*]] = alloc_stack $T, let, name "x"
+// CHECK: [[OPTBUF:%[0-9]+]] = alloc_stack $Optional<T>
+// CHECK: switch_enum_addr {{.*}}, case #Optional.some!enumelt.1: [[LOOPBODY:bb.*]], case #Optional.none!enumelt: [[OUT:bb[0-9]+]]
+// CHECK: [[OUT]]:
+// CHECK: dealloc_stack [[OPTBUF]]
+// CHECK: dealloc_stack [[X]]
+// CHECK: br [[DONE:bb[0-9]+]]
+// CHECK: [[LOOPBODY]]:
+// CHECK: [[ENUMVAL:%.*]] = unchecked_take_enum_data_addr
+// CHECK: copy_addr [take] [[ENUMVAL]] to [initialization] [[X]]
+// CHECK: destroy_addr [[X]]
+// CHECK: dealloc_stack [[X]]
+// CHECK: br [[COND]]
+// CHECK: [[DONE]]:
+// CHECK: return
+// CHECK: } // end sil function '$S16if_while_binding0B13_loop_generic{{[_0-9a-zA-Z]*}}F'
+func while_loop_generic<T>(_ source: () -> T?) {
+ while let x = source() {
+ }
+}
+
+// <rdar://problem/19382942> Improve 'if let' to avoid optional pyramid of doom
+// CHECK-LABEL: sil hidden @$S16if_while_binding0B11_loop_multiyyF
+func while_loop_multi() {
+ // CHECK: br [[LOOP_ENTRY:bb[0-9]+]]
+ // CHECK: [[LOOP_ENTRY]]:
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[CHECKBUF2:bb.*]], case #Optional.none!enumelt: [[NONE_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[NONE_TRAMPOLINE]]:
+ // CHECK: br [[LOOP_EXIT0:bb[0-9]+]]
+
+ // CHECK: [[CHECKBUF2]]([[A:%[0-9]+]] : @owned $String):
+ // CHECK: debug_value [[A]] : $String, let, name "a"
+
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[LOOP_BODY:bb.*]], case #Optional.none!enumelt: [[LOOP_EXIT2a:bb[0-9]+]]
+
+ // CHECK: [[LOOP_EXIT2a]]:
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[LOOP_EXIT0]]
+
+ // CHECK: [[LOOP_BODY]]([[B:%[0-9]+]] : @owned $String):
+ while let a = foo(), let b = bar() {
+ // CHECK: debug_value [[B]] : $String, let, name "b"
+ // CHECK: [[BORROWED_A:%.*]] = begin_borrow [[A]]
+ // CHECK: [[A_COPY:%.*]] = copy_value [[BORROWED_A]]
+ // CHECK: debug_value [[A_COPY]] : $String, let, name "c"
+ // CHECK: end_borrow [[BORROWED_A]] from [[A]]
+ // CHECK: destroy_value [[A_COPY]]
+ // CHECK: destroy_value [[B]]
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[LOOP_ENTRY]]
+ let c = a
+ }
+ // CHECK: [[LOOP_EXIT0]]:
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding0A6_multiyyF
+func if_multi() {
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[CHECKBUF2:bb.*]], case #Optional.none!enumelt: [[NONE_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[NONE_TRAMPOLINE]]:
+ // CHECK: br [[IF_DONE:bb[0-9]+]]
+
+ // CHECK: [[CHECKBUF2]]([[A:%[0-9]+]] : @owned $String):
+ // CHECK: debug_value [[A]] : $String, let, name "a"
+ // CHECK: [[B:%[0-9]+]] = alloc_box ${ var String }, var, name "b"
+ // CHECK: [[PB:%[0-9]+]] = project_box [[B]]
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[IF_BODY:bb.*]], case #Optional.none!enumelt: [[IF_EXIT1a:bb[0-9]+]]
+
+ // CHECK: [[IF_EXIT1a]]:
+ // CHECK: dealloc_box {{.*}} ${ var String }
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[IF_DONE]]
+
+ // CHECK: [[IF_BODY]]([[BVAL:%[0-9]+]] : @owned $String):
+ if let a = foo(), var b = bar() {
+ // CHECK: store [[BVAL]] to [init] [[PB]] : $*String
+ // CHECK: debug_value {{.*}} : $String, let, name "c"
+ // CHECK: destroy_value [[B]]
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[IF_DONE]]
+ let c = a
+ }
+ // CHECK: [[IF_DONE]]:
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding0A11_multi_elseyyF
+func if_multi_else() {
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[CHECKBUF2:bb.*]], case #Optional.none!enumelt: [[NONE_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[NONE_TRAMPOLINE]]:
+ // CHECK: br [[ELSE:bb[0-9]+]]
+ // CHECK: [[CHECKBUF2]]([[A:%[0-9]+]] : @owned $String):
+ // CHECK: debug_value [[A]] : $String, let, name "a"
+ // CHECK: [[B:%[0-9]+]] = alloc_box ${ var String }, var, name "b"
+ // CHECK: [[PB:%[0-9]+]] = project_box [[B]]
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[IF_BODY:bb.*]], case #Optional.none!enumelt: [[IF_EXIT1a:bb[0-9]+]]
+
+ // CHECK: [[IF_EXIT1a]]:
+ // CHECK: dealloc_box {{.*}} ${ var String }
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[ELSE]]
+
+ // CHECK: [[IF_BODY]]([[BVAL:%[0-9]+]] : @owned $String):
+ if let a = foo(), var b = bar() {
+ // CHECK: store [[BVAL]] to [init] [[PB]] : $*String
+ // CHECK: debug_value {{.*}} : $String, let, name "c"
+ // CHECK: destroy_value [[B]]
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[IF_DONE:bb[0-9]+]]
+ let c = a
+ } else {
+ let d = 0
+ // CHECK: [[ELSE]]:
+ // CHECK: debug_value {{.*}} : $Int, let, name "d"
+ // CHECK: br [[IF_DONE]]
+ }
+ // CHECK: [[IF_DONE]]:
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding0A12_multi_whereyyF
+func if_multi_where() {
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[CHECKBUF2:bb.*]], case #Optional.none!enumelt: [[NONE_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[NONE_TRAMPOLINE]]:
+ // CHECK: br [[ELSE:bb[0-9]+]]
+ // CHECK: [[CHECKBUF2]]([[A:%[0-9]+]] : @owned $String):
+ // CHECK: debug_value [[A]] : $String, let, name "a"
+ // CHECK: [[BBOX:%[0-9]+]] = alloc_box ${ var String }, var, name "b"
+ // CHECK: [[PB:%[0-9]+]] = project_box [[BBOX]]
+ // CHECK: switch_enum {{.*}}, case #Optional.some!enumelt.1: [[CHECK_WHERE:bb.*]], case #Optional.none!enumelt: [[IF_EXIT1a:bb[0-9]+]]
+ // CHECK: [[IF_EXIT1a]]:
+ // CHECK: dealloc_box {{.*}} ${ var String }
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[ELSE]]
+
+ // CHECK: [[CHECK_WHERE]]([[B:%[0-9]+]] : @owned $String):
+ // CHECK: function_ref Swift.Bool._getBuiltinLogicValue() -> Builtin.Int1
+ // CHECK: cond_br {{.*}}, [[IF_BODY:bb[0-9]+]], [[IF_EXIT3:bb[0-9]+]]
+ // CHECK: [[IF_EXIT3]]:
+ // CHECK: destroy_value [[BBOX]]
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[IF_DONE:bb[0-9]+]]
+ if let a = foo(), var b = bar(), a == b {
+ // CHECK: [[IF_BODY]]:
+ // CHECK: destroy_value [[BBOX]]
+ // CHECK: destroy_value [[A]]
+ // CHECK: br [[IF_DONE]]
+ let c = a
+ }
+ // CHECK: [[IF_DONE]]:
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+
+// <rdar://problem/19797158> Swift 1.2's "if" has 2 behaviors. They could be unified.
+// CHECK-LABEL: sil hidden @$S16if_while_binding0A16_leading_booleanyySiF
+func if_leading_boolean(_ a : Int) {
+ // Test the boolean condition.
+
+ // CHECK: debug_value %0 : $Int, let, name "a"
+ // CHECK: [[EQRESULT:%[0-9]+]] = apply {{.*}}(%0, %0{{.*}}) : $@convention({{.*}}) (Int, Int{{.*}}) -> Bool
+
+ // CHECK: [[FN:%.*]] = function_ref {{.*}}
+ // CHECK-NEXT: [[EQRESULTI1:%[0-9]+]] = apply [[FN:%.*]]([[EQRESULT]]) : $@convention(method) (Bool) -> Builtin.Int1
+ // CHECK-NEXT: cond_br [[EQRESULTI1]], [[CHECKFOO:bb[0-9]+]], [[IFDONE:bb[0-9]+]]
+
+ // Call Foo and test for the optional being present.
+// CHECK: [[CHECKFOO]]:
+ // CHECK: [[OPTRESULT:%[0-9]+]] = apply {{.*}}() : $@convention(thin) () -> @owned Optional<String>
+
+ // CHECK: switch_enum [[OPTRESULT]] : $Optional<String>, case #Optional.some!enumelt.1: [[SUCCESS:bb.*]], case #Optional.none!enumelt: [[IF_DONE:bb[0-9]+]]
+
+// CHECK: [[SUCCESS]]([[B:%[0-9]+]] : @owned $String):
+ // CHECK: debug_value [[B]] : $String, let, name "b"
+ // CHECK: [[BORROWED_B:%.*]] = begin_borrow [[B]]
+ // CHECK: [[B_COPY:%.*]] = copy_value [[BORROWED_B]]
+ // CHECK: debug_value [[B_COPY]] : $String, let, name "c"
+ // CHECK: end_borrow [[BORROWED_B]] from [[B]]
+ // CHECK: destroy_value [[B_COPY]]
+ // CHECK: destroy_value [[B]]
+ // CHECK: br [[IFDONE]]
+ if a == a, let b = foo() {
+ let c = b
+ }
+ // CHECK: [[IFDONE]]:
+ // CHECK-NEXT: tuple ()
+
+}
+
+
+/// <rdar://problem/20364869> Assertion failure when using 'as' pattern in 'if let'
+class BaseClass {}
+class DerivedClass : BaseClass {}
+
+// CHECK-LABEL: sil hidden @$S16if_while_binding20testAsPatternInIfLetyyAA9BaseClassCSgF
+func testAsPatternInIfLet(_ a : BaseClass?) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<BaseClass>):
+ // CHECK: debug_value [[ARG]] : $Optional<BaseClass>, let, name "a"
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $Optional<BaseClass>
+ // CHECK: switch_enum [[ARG_COPY]] : $Optional<BaseClass>, case #Optional.some!enumelt.1: [[OPTPRESENTBB:bb[0-9]+]], case #Optional.none!enumelt: [[NILBB:bb[0-9]+]]
+
+ // CHECK: [[NILBB]]:
+ // CHECK: br [[EXITBB:bb[0-9]+]]
+
+ // CHECK: [[OPTPRESENTBB]]([[CLS:%.*]] : @owned $BaseClass):
+ // CHECK: checked_cast_br [[CLS]] : $BaseClass to $DerivedClass, [[ISDERIVEDBB:bb[0-9]+]], [[ISBASEBB:bb[0-9]+]]
+
+ // CHECK: [[ISDERIVEDBB]]([[DERIVED_CLS:%.*]] : @owned $DerivedClass):
+ // CHECK: [[DERIVED_CLS_SOME:%.*]] = enum $Optional<DerivedClass>, #Optional.some!enumelt.1, [[DERIVED_CLS]] : $DerivedClass
+ // CHECK: br [[MERGE:bb[0-9]+]]([[DERIVED_CLS_SOME]] : $Optional<DerivedClass>)
+
+ // CHECK: [[ISBASEBB]]([[BASECLASS:%.*]] : @owned $BaseClass):
+ // CHECK: destroy_value [[BASECLASS]] : $BaseClass
+ // CHECK: = enum $Optional<DerivedClass>, #Optional.none!enumelt
+ // CHECK: br [[MERGE]](
+
+ // CHECK: [[MERGE]]([[OPTVAL:%[0-9]+]] : @owned $Optional<DerivedClass>):
+ // CHECK: switch_enum [[OPTVAL]] : $Optional<DerivedClass>, case #Optional.some!enumelt.1: [[ISDERIVEDBB:bb[0-9]+]], case #Optional.none!enumelt: [[NILBB:bb[0-9]+]]
+
+ // CHECK: [[ISDERIVEDBB]]([[DERIVEDVAL:%[0-9]+]] : @owned $DerivedClass):
+ // CHECK: debug_value [[DERIVEDVAL]] : $DerivedClass
+ // => SEMANTIC SIL TODO: This is benign, but scoping wise, this end borrow should be after derived val.
+ // CHECK: destroy_value [[DERIVEDVAL]] : $DerivedClass
+ // CHECK: br [[EXITBB]]
+
+ // CHECK: [[EXITBB]]:
+ // CHECK: tuple ()
+ // CHECK: return
+ if case let b as DerivedClass = a {
+
+ }
+}
+
+// <rdar://problem/22312114> if case crashes swift - bools not supported in let/else yet
+// CHECK-LABEL: sil hidden @$S16if_while_binding12testCaseBoolyySbSgF
+func testCaseBool(_ value : Bool?) {
+ // CHECK: bb0([[ARG:%.*]] : @trivial $Optional<Bool>):
+ // CHECK: switch_enum [[ARG]] : $Optional<Bool>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[NONE_TRAMPOLINE]]:
+ // CHECK: br [[CONT_BB:bb[0-9]+]]
+ //
+ // CHECK: [[SOME_BB]]([[PAYLOAD:%.*]] : @trivial $Bool):
+ // CHECK: [[ISTRUE:%[0-9]+]] = struct_extract [[PAYLOAD]] : $Bool, #Bool._value
+ // CHECK: cond_br [[ISTRUE]], [[TRUE_TRAMPOLINE_BB:bb[0-9]+]], [[CONT_BB]]
+ //
+ // CHECK: [[TRUE_TRAMPOLINE_BB:bb[0-9]+]]
+ // CHECK: br [[TRUE_BB:bb[0-9]+]]
+ //
+ // CHECK: [[TRUE_BB]]:
+ // CHECK: function_ref @$S16if_while_binding8marker_1yyF
+ // CHECK: br [[CONT_BB]]
+ if case true? = value {
+ marker_1()
+ }
+
+ // CHECK: [[CONT_BB]]:
+ // CHECK: switch_enum [[ARG]] : $Optional<Bool>, case #Optional.some!enumelt.1: [[SUCC_BB_2:bb[0-9]+]], case #Optional.none!enumelt: [[NO_TRAMPOLINE_2:bb[0-9]+]]
+
+ // CHECK: [[NO_TRAMPOLINE_2]]:
+ // CHECK: br [[EPILOG_BB:bb[0-9]+]]
+
+ // CHECK: [[SUCC_BB_2]]([[PAYLOAD2:%.*]] : @trivial $Bool):
+ // CHECK: [[ISTRUE:%[0-9]+]] = struct_extract [[PAYLOAD2]] : $Bool, #Bool._value
+ // CHECK: cond_br [[ISTRUE]], [[EPILOG_BB]], [[FALSE2_TRAMPOLINE_BB:bb[0-9]+]]
+
+ // CHECK: [[FALSE2_TRAMPOLINE_BB]]:
+ // CHECK: br [[FALSE2_BB:bb[0-9]+]]
+ //
+ // CHECK: [[FALSE2_BB]]:
+ // CHECK: function_ref @$S16if_while_binding8marker_2yyF
+ // CHECK: br [[EPILOG_BB]]
+
+ // CHECK: [[EPILOG_BB]]:
+ // CHECK: return
+ if case false? = value {
+ marker_2()
+ }
+}
diff --git a/test/SILGen/plus_zero_implicitly_unwrapped_optional.swift b/test/SILGen/plus_zero_implicitly_unwrapped_optional.swift
new file mode 100644
index 0000000..55f3112
--- /dev/null
+++ b/test/SILGen/plus_zero_implicitly_unwrapped_optional.swift
@@ -0,0 +1,81 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func foo(f f: (() -> ())!) {
+ var f: (() -> ())! = f
+ f?()
+}
+// CHECK: sil hidden @{{.*}}foo{{.*}} : $@convention(thin) (@guaranteed Optional<@callee_guaranteed () -> ()>) -> () {
+// CHECK: bb0([[T0:%.*]] : @guaranteed $Optional<@callee_guaranteed () -> ()>):
+// CHECK: [[F:%.*]] = alloc_box ${ var Optional<@callee_guaranteed () -> ()> }
+// CHECK: [[PF:%.*]] = project_box [[F]]
+// CHECK: [[T0_COPY:%.*]] = copy_value [[T0]]
+// CHECK: store [[T0_COPY]] to [init] [[PF]]
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PF]] : $*Optional<@callee_guaranteed () -> ()>
+// CHECK: [[T1:%.*]] = select_enum_addr [[READ]]
+// CHECK: cond_br [[T1]], bb2, bb1
+// If it does, project and load the value out of the implicitly unwrapped
+// optional...
+// CHECK: bb2:
+// CHECK-NEXT: [[FN0_ADDR:%.*]] = unchecked_take_enum_data_addr [[READ]]
+// CHECK-NEXT: [[FN0:%.*]] = load [copy] [[FN0_ADDR]]
+// .... then call it
+// CHECK: [[B:%.*]] = begin_borrow [[FN0]]
+// CHECK: apply [[B]]() : $@callee_guaranteed () -> ()
+// CHECK: end_borrow [[B]]
+// CHECK: br bb3
+// CHECK: bb3(
+// CHECK: destroy_value [[F]]
+// CHECK: return
+// CHECK: bb4:
+// CHECK: enum $Optional<()>, #Optional.none!enumelt
+// CHECK: br bb3
+// The rest of this is tested in optional.swift
+// } // end sil function '{{.*}}foo{{.*}}'
+
+func wrap<T>(x x: T) -> T! { return x }
+
+// CHECK-LABEL: sil hidden @$S29implicitly_unwrapped_optional16wrap_then_unwrap{{[_0-9a-zA-Z]*}}F
+func wrap_then_unwrap<T>(x x: T) -> T {
+ // CHECK: switch_enum_addr {{%.*}}, case #Optional.some!enumelt.1: [[OK:bb[0-9]+]], case #Optional.none!enumelt: [[FAIL:bb[0-9]+]]
+ // CHECK: [[FAIL]]:
+ // CHECK: unreachable
+ // CHECK: [[OK]]:
+ return wrap(x: x)!
+}
+
+// CHECK-LABEL: sil hidden @$S29implicitly_unwrapped_optional10tuple_bind1xSSSgSi_SStSg_tF : $@convention(thin) (@guaranteed Optional<(Int, String)>) -> @owned Optional<String> {
+func tuple_bind(x x: (Int, String)!) -> String? {
+ return x?.1
+ // CHECK: cond_br {{%.*}}, [[NONNULL:bb[0-9]+]], [[NULL:bb[0-9]+]]
+ // CHECK: [[NONNULL]]:
+ // CHECK: [[STRING:%.*]] = tuple_extract {{%.*}} : $(Int, String), 1
+ // CHECK-NOT: destroy_value [[STRING]]
+}
+
+// CHECK-LABEL: sil hidden @$S29implicitly_unwrapped_optional011tuple_bind_a1_B01xSSSi_SStSg_tF
+func tuple_bind_implicitly_unwrapped(x x: (Int, String)!) -> String {
+ return x.1
+}
+
+func return_any() -> AnyObject! { return nil }
+func bind_any() {
+ let object : AnyObject? = return_any()
+}
+
+// CHECK-LABEL: sil hidden @$S29implicitly_unwrapped_optional6sr3758yyF
+func sr3758() {
+ // Verify that there are no additional reabstractions introduced.
+ // CHECK: [[CLOSURE:%.+]] = function_ref @$S29implicitly_unwrapped_optional6sr3758yyFyypSgcfU_ : $@convention(thin) (@in_guaranteed Optional<Any>) -> ()
+ // CHECK: [[F:%.+]] = thin_to_thick_function [[CLOSURE]] : $@convention(thin) (@in_guaranteed Optional<Any>) -> () to $@callee_guaranteed (@in_guaranteed Optional<Any>) -> ()
+ // CHECK: [[BORROWED_F:%.*]] = begin_borrow [[F]]
+ // CHECK: [[CALLEE:%.+]] = copy_value [[BORROWED_F]] : $@callee_guaranteed (@in_guaranteed Optional<Any>) -> ()
+ // CHECK: [[BORROWED_CALLEE:%.*]] = begin_borrow [[CALLEE]]
+ // CHECK: = apply [[BORROWED_CALLEE]]({{%.+}}) : $@callee_guaranteed (@in_guaranteed Optional<Any>) -> ()
+ // CHECK: end_borrow [[BORROWED_CALLEE]]
+ // destroy_value [[CALLEE]]
+ // CHECK: end_borrow [[BORROWED_F]] from [[F]]
+ // CHECK: destroy_value [[F]]
+ let f: ((Any?) -> Void) = { (arg: Any!) in }
+ f(nil)
+} // CHECK: end sil function '$S29implicitly_unwrapped_optional6sr3758yyF'
diff --git a/test/SILGen/plus_zero_indirect_enum.swift b/test/SILGen/plus_zero_indirect_enum.swift
new file mode 100644
index 0000000..2d609f0
--- /dev/null
+++ b/test/SILGen/plus_zero_indirect_enum.swift
@@ -0,0 +1,518 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-print-debuginfo -emit-silgen %s | %FileCheck %s
+
+indirect enum TreeA<T> {
+ case Nil
+ case Leaf(T)
+ case Branch(left: TreeA<T>, right: TreeA<T>)
+}
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum11TreeA_cases_1l1ryx_AA0C1AOyxGAGtlF : $@convention(thin) <T> (@in_guaranteed T, @guaranteed TreeA<T>, @guaranteed TreeA<T>) -> () {
+func TreeA_cases<T>(_ t: T, l: TreeA<T>, r: TreeA<T>) {
+// CHECK: bb0([[ARG1:%.*]] : $*T, [[ARG2:%.*]] : $TreeA<T>, [[ARG3:%.*]] : $TreeA<T>):
+// CHECK: [[METATYPE:%.*]] = metatype $@thin TreeA<T>.Type
+// CHECK-NEXT: [[NIL:%.*]] = enum $TreeA<T>, #TreeA.Nil!enumelt
+// CHECK-NOT: destroy_value [[NIL]]
+ let _ = TreeA<T>.Nil
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeA<T>.Type
+// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <T>
+// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
+// CHECK-NEXT: copy_addr [[ARG1]] to [initialization] [[PB]]
+// CHECK-NEXT: [[LEAF:%.*]] = enum $TreeA<T>, #TreeA.Leaf!enumelt.1, [[BOX]]
+// CHECK-NEXT: destroy_value [[LEAF]]
+ let _ = TreeA<T>.Leaf(t)
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeA<T>.Type
+// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>
+// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]] : $*(left: TreeA<T>, right: TreeA<T>), 0
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]] : $*(left: TreeA<T>, right: TreeA<T>), 1
+// CHECK-NEXT: [[ARG2_COPY:%.*]] = copy_value [[ARG2]]
+// CHECK-NEXT: store [[ARG2_COPY]] to [init] [[LEFT]]
+// CHECK-NEXT: [[ARG3_COPY:%.*]] = copy_value [[ARG3]]
+// CHECK-NEXT: store [[ARG3_COPY]] to [init] [[RIGHT]]
+// CHECK-NEXT: [[BRANCH:%.*]] = enum $TreeA<T>, #TreeA.Branch!enumelt.1, [[BOX]]
+// CHECK-NEXT: destroy_value [[BRANCH]]
+ let _ = TreeA<T>.Branch(left: l, right: r)
+
+}
+// CHECK: // end sil function '$S13indirect_enum11TreeA_cases_1l1ryx_AA0C1AOyxGAGtlF'
+
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum16TreeA_reabstractyyS2icF : $@convention(thin) (@guaranteed @callee_guaranteed (Int) -> Int) -> () {
+func TreeA_reabstract(_ f: @escaping (Int) -> Int) {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed (Int) -> Int):
+// CHECK: [[METATYPE:%.*]] = metatype $@thin TreeA<(Int) -> Int>.Type
+// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <(Int) -> Int>
+// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
+// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[THUNK:%.*]] = function_ref @$SS2iIegyd_S2iIegnr_TR
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG_COPY]])
+// CHECK-NEXT: store [[FN]] to [init] [[PB]]
+// CHECK-NEXT: [[LEAF:%.*]] = enum $TreeA<(Int) -> Int>, #TreeA.Leaf!enumelt.1, [[BOX]]
+// CHECK-NEXT: destroy_value [[LEAF]]
+// CHECK: return
+ let _ = TreeA<(Int) -> Int>.Leaf(f)
+}
+// CHECK: } // end sil function '$S13indirect_enum16TreeA_reabstractyyS2icF'
+
+enum TreeB<T> {
+ case Nil
+ case Leaf(T)
+ indirect case Branch(left: TreeB<T>, right: TreeB<T>)
+}
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum11TreeB_cases_1l1ryx_AA0C1BOyxGAGtlF
+func TreeB_cases<T>(_ t: T, l: TreeB<T>, r: TreeB<T>) {
+
+// CHECK: [[METATYPE:%.*]] = metatype $@thin TreeB<T>.Type
+// CHECK: [[NIL:%.*]] = alloc_stack $TreeB<T>
+// CHECK-NEXT: inject_enum_addr [[NIL]] : $*TreeB<T>, #TreeB.Nil!enumelt
+// CHECK-NEXT: destroy_addr [[NIL]]
+// CHECK-NEXT: dealloc_stack [[NIL]]
+ let _ = TreeB<T>.Nil
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeB<T>.Type
+// CHECK-NEXT: [[LEAF:%.*]] = alloc_stack $TreeB<T>
+// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[LEAF]] : $*TreeB<T>, #TreeB.Leaf!enumelt.1
+// CHECK-NEXT: copy_addr %0 to [initialization] [[PAYLOAD]]
+// CHECK-NEXT: inject_enum_addr [[LEAF]] : $*TreeB<T>, #TreeB.Leaf!enumelt
+// CHECK-NEXT: destroy_addr [[LEAF]]
+// CHECK-NEXT: dealloc_stack [[LEAF]]
+ let _ = TreeB<T>.Leaf(t)
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeB<T>.Type
+// CHECK-NEXT: [[BOX:%.*]] = alloc_box $<τ_0_0> { var (left: TreeB<τ_0_0>, right: TreeB<τ_0_0>) } <T>
+// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]]
+// CHECK-NEXT: copy_addr %1 to [initialization] [[LEFT]] : $*TreeB<T>
+// CHECK-NEXT: copy_addr %2 to [initialization] [[RIGHT]] : $*TreeB<T>
+// CHECK-NEXT: [[BRANCH:%.*]] = alloc_stack $TreeB<T>
+// CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[BRANCH]]
+// CHECK-NEXT: store [[BOX]] to [init] [[PAYLOAD]]
+// CHECK-NEXT: inject_enum_addr [[BRANCH]] : $*TreeB<T>, #TreeB.Branch!enumelt.1
+// CHECK-NEXT: destroy_addr [[BRANCH]]
+// CHECK-NEXT: dealloc_stack [[BRANCH]]
+ let _ = TreeB<T>.Branch(left: l, right: r)
+
+// CHECK: return
+
+}
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum13TreeInt_cases_1l1rySi_AA0cD0OAFtF : $@convention(thin) (Int, @guaranteed TreeInt, @guaranteed TreeInt) -> ()
+func TreeInt_cases(_ t: Int, l: TreeInt, r: TreeInt) {
+// CHECK: bb0([[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $TreeInt, [[ARG3:%.*]] : $TreeInt):
+// CHECK: [[METATYPE:%.*]] = metatype $@thin TreeInt.Type
+// CHECK-NEXT: [[NIL:%.*]] = enum $TreeInt, #TreeInt.Nil!enumelt
+// CHECK-NOT: destroy_value [[NIL]]
+ let _ = TreeInt.Nil
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeInt.Type
+// CHECK-NEXT: [[LEAF:%.*]] = enum $TreeInt, #TreeInt.Leaf!enumelt.1, [[ARG1]]
+// CHECK-NOT: destroy_value [[LEAF]]
+ let _ = TreeInt.Leaf(t)
+
+// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin TreeInt.Type
+// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var (left: TreeInt, right: TreeInt) }
+// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_element_addr [[PB]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_element_addr [[PB]]
+// CHECK-NEXT: [[ARG2_COPY:%.*]] = copy_value [[ARG2]]
+// CHECK-NEXT: store [[ARG2_COPY]] to [init] [[LEFT]]
+// CHECK-NEXT: [[ARG3_COPY:%.*]] = copy_value [[ARG3]]
+// CHECK-NEXT: store [[ARG3_COPY]] to [init] [[RIGHT]]
+// CHECK-NEXT: [[BRANCH:%.*]] = enum $TreeInt, #TreeInt.Branch!enumelt.1, [[BOX]]
+// CHECK-NEXT: destroy_value [[BRANCH]]
+ let _ = TreeInt.Branch(left: l, right: r)
+}
+// CHECK: } // end sil function '$S13indirect_enum13TreeInt_cases_1l1rySi_AA0cD0OAFtF'
+
+enum TreeInt {
+ case Nil
+ case Leaf(Int)
+ indirect case Branch(left: TreeInt, right: TreeInt)
+}
+
+
+enum TrivialButIndirect {
+ case Direct(Int)
+ indirect case Indirect(Int)
+}
+
+func a() {}
+func b<T>(_ x: T) {}
+func c<T>(_ x: T, _ y: T) {}
+func d() {}
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum11switchTreeAyyAA0D1AOyxGlF : $@convention(thin) <T> (@guaranteed TreeA<T>) -> () {
+func switchTreeA<T>(_ x: TreeA<T>) {
+ // CHECK: bb0([[ARG:%.*]] : $TreeA<T>):
+ // -- x +2
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>,
+ // CHECK: case #TreeA.Nil!enumelt: [[NIL_CASE:bb1]],
+ // CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE:bb2]],
+ // CHECK: case #TreeA.Branch!enumelt.1: [[BRANCH_CASE:bb3]],
+ switch x {
+ // CHECK: [[NIL_CASE]]:
+ // CHECK: function_ref @$S13indirect_enum1ayyF
+ // CHECK: br [[OUTER_CONT:bb[0-9]+]]
+ case .Nil:
+ a()
+ // CHECK: [[LEAF_CASE]]([[LEAF_BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <T>):
+ // CHECK: [[VALUE:%.*]] = project_box [[LEAF_BOX]]
+ // CHECK: copy_addr [[VALUE]] to [initialization] [[X:%.*]] : $*T
+ // CHECK: function_ref @$S13indirect_enum1b{{[_0-9a-zA-Z]*}}F
+ // CHECK: destroy_addr [[X]]
+ // CHECK: dealloc_stack [[X]]
+ // -- x +1
+ // CHECK: destroy_value [[LEAF_BOX]]
+ // CHECK: br [[OUTER_CONT]]
+ case .Leaf(let x):
+ b(x)
+
+ // CHECK: [[BRANCH_CASE]]([[NODE_BOX:%.*]] : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
+ // CHECK: [[TUPLE_ADDR:%.*]] = project_box [[NODE_BOX]]
+ // CHECK: [[TUPLE:%.*]] = load_borrow [[TUPLE_ADDR]]
+ // CHECK: [[LEFT:%.*]] = tuple_extract [[TUPLE]] {{.*}}, 0
+ // CHECK: [[RIGHT:%.*]] = tuple_extract [[TUPLE]] {{.*}}, 1
+ // CHECK: switch_enum [[LEFT]] : $TreeA<T>,
+ // CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE_LEFT:bb[0-9]+]],
+ // CHECK: default [[FAIL_LEFT:bb[0-9]+]]
+
+ // CHECK: [[LEAF_CASE_LEFT]]([[LEFT_LEAF_BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <T>):
+ // CHECK: [[LEFT_LEAF_VALUE:%.*]] = project_box [[LEFT_LEAF_BOX]]
+ // CHECK: switch_enum [[RIGHT]] : $TreeA<T>,
+ // CHECK: case #TreeA.Leaf!enumelt.1: [[LEAF_CASE_RIGHT:bb[0-9]+]],
+ // CHECK: default [[FAIL_RIGHT:bb[0-9]+]]
+
+ // CHECK: [[LEAF_CASE_RIGHT]]([[RIGHT_LEAF_BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <T>):
+ // CHECK: [[RIGHT_LEAF_VALUE:%.*]] = project_box [[RIGHT_LEAF_BOX]]
+ // CHECK: copy_addr [[LEFT_LEAF_VALUE]]
+ // CHECK: copy_addr [[RIGHT_LEAF_VALUE]]
+ // -- x +1
+ // CHECK: destroy_value [[NODE_BOX]]
+ // CHECK: br [[OUTER_CONT]]
+
+ // CHECK: [[FAIL_RIGHT]]:
+ // CHECK: br [[DEFAULT:bb[0-9]+]]
+
+ // CHECK: [[FAIL_LEFT]]:
+ // CHECK: br [[DEFAULT]]
+
+ case .Branch(.Leaf(let x), .Leaf(let y)):
+ c(x, y)
+
+ // CHECK: [[DEFAULT]]:
+ // -- x +1
+ // CHECK: destroy_value [[ARG_COPY]]
+ default:
+ d()
+ }
+
+ // CHECK: [[OUTER_CONT:%.*]]:
+ // -- x +0
+}
+// CHECK: } // end sil function '$S13indirect_enum11switchTreeAyyAA0D1AOyxGlF'
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum11switchTreeB{{[_0-9a-zA-Z]*}}F
+func switchTreeB<T>(_ x: TreeB<T>) {
+ // CHECK: copy_addr %0 to [initialization] [[SCRATCH:%.*]] :
+ // CHECK: switch_enum_addr [[SCRATCH]]
+ switch x {
+
+ // CHECK: bb{{.*}}:
+ // CHECK: destroy_addr [[SCRATCH]]
+ // CHECK: dealloc_stack [[SCRATCH]]
+ // CHECK: function_ref @$S13indirect_enum1ayyF
+ // CHECK: br [[OUTER_CONT:bb[0-9]+]]
+ case .Nil:
+ a()
+
+ // CHECK: bb{{.*}}:
+ // CHECK: copy_addr [[SCRATCH]] to [initialization] [[LEAF_COPY:%.*]] :
+ // CHECK: [[LEAF_ADDR:%.*]] = unchecked_take_enum_data_addr [[LEAF_COPY]]
+ // CHECK: copy_addr [take] [[LEAF_ADDR]] to [initialization] [[LEAF:%.*]] :
+ // CHECK: function_ref @$S13indirect_enum1b{{[_0-9a-zA-Z]*}}F
+ // CHECK: destroy_addr [[LEAF]]
+ // CHECK: dealloc_stack [[LEAF]]
+ // CHECK-NOT: destroy_addr [[LEAF_COPY]]
+ // CHECK: dealloc_stack [[LEAF_COPY]]
+ // CHECK: destroy_addr [[SCRATCH]]
+ // CHECK: dealloc_stack [[SCRATCH]]
+ // CHECK: br [[OUTER_CONT]]
+ case .Leaf(let x):
+ b(x)
+
+ // CHECK: bb{{.*}}:
+ // CHECK: copy_addr [[SCRATCH]] to [initialization] [[TREE_COPY:%.*]] :
+ // CHECK: [[TREE_ADDR:%.*]] = unchecked_take_enum_data_addr [[TREE_COPY]]
+ // -- box +1 immutable
+ // CHECK: [[BOX:%.*]] = load [take] [[TREE_ADDR]]
+ // CHECK: [[TUPLE:%.*]] = project_box [[BOX]]
+ // CHECK: [[LEFT:%.*]] = tuple_element_addr [[TUPLE]]
+ // CHECK: [[RIGHT:%.*]] = tuple_element_addr [[TUPLE]]
+ // CHECK: switch_enum_addr [[LEFT]] {{.*}}, default [[LEFT_FAIL:bb[0-9]+]]
+
+ // CHECK: bb{{.*}}:
+ // CHECK: copy_addr [[LEFT]] to [initialization] [[LEFT_COPY:%.*]] :
+ // CHECK: [[LEFT_LEAF:%.*]] = unchecked_take_enum_data_addr [[LEFT_COPY]] : $*TreeB<T>, #TreeB.Leaf
+ // CHECK: switch_enum_addr [[RIGHT]] {{.*}}, default [[RIGHT_FAIL:bb[0-9]+]]
+
+ // CHECK: bb{{.*}}:
+ // CHECK: copy_addr [[RIGHT]] to [initialization] [[RIGHT_COPY:%.*]] :
+ // CHECK: [[RIGHT_LEAF:%.*]] = unchecked_take_enum_data_addr [[RIGHT_COPY]] : $*TreeB<T>, #TreeB.Leaf
+ // CHECK: copy_addr [take] [[LEFT_LEAF]] to [initialization] [[X:%.*]] :
+ // CHECK: copy_addr [take] [[RIGHT_LEAF]] to [initialization] [[Y:%.*]] :
+ // CHECK: function_ref @$S13indirect_enum1c{{[_0-9a-zA-Z]*}}F
+ // CHECK: destroy_addr [[Y]]
+ // CHECK: dealloc_stack [[Y]]
+ // CHECK: destroy_addr [[X]]
+ // CHECK: dealloc_stack [[X]]
+ // CHECK-NOT: destroy_addr [[RIGHT_COPY]]
+ // CHECK: dealloc_stack [[RIGHT_COPY]]
+ // CHECK-NOT: destroy_addr [[LEFT_COPY]]
+ // CHECK: dealloc_stack [[LEFT_COPY]]
+ // -- box +0
+ // CHECK: destroy_value [[BOX]]
+ // CHECK-NOT: destroy_addr [[TREE_COPY]]
+ // CHECK: dealloc_stack [[TREE_COPY]]
+ // CHECK: destroy_addr [[SCRATCH]]
+ // CHECK: dealloc_stack [[SCRATCH]]
+ case .Branch(.Leaf(let x), .Leaf(let y)):
+ c(x, y)
+
+ // CHECK: [[RIGHT_FAIL]]:
+ // CHECK: destroy_addr [[LEFT_LEAF]]
+ // CHECK-NOT: destroy_addr [[LEFT_COPY]]
+ // CHECK: dealloc_stack [[LEFT_COPY]]
+ // CHECK: destroy_value [[BOX]]
+ // CHECK-NOT: destroy_addr [[TREE_COPY]]
+ // CHECK: dealloc_stack [[TREE_COPY]]
+ // CHECK: br [[INNER_CONT:bb[0-9]+]]
+
+ // CHECK: [[LEFT_FAIL]]:
+ // CHECK: destroy_value [[BOX]]
+ // CHECK-NOT: destroy_addr [[TREE_COPY]]
+ // CHECK: dealloc_stack [[TREE_COPY]]
+ // CHECK: br [[INNER_CONT:bb[0-9]+]]
+
+ // CHECK: [[INNER_CONT]]:
+ // CHECK: destroy_addr [[SCRATCH]]
+ // CHECK: dealloc_stack [[SCRATCH]]
+ // CHECK: function_ref @$S13indirect_enum1dyyF
+ // CHECK: br [[OUTER_CONT]]
+ default:
+ d()
+ }
+ // CHECK: [[OUTER_CONT]]:
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum10guardTreeA{{[_0-9a-zA-Z]*}}F
+func guardTreeA<T>(_ tree: TreeA<T>) {
+ // CHECK: bb0([[ARG:%.*]] : $TreeA<T>):
+ do {
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>, case #TreeA.Nil!enumelt: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: [[YES]]:
+ guard case .Nil = tree else { return }
+
+ // CHECK: [[X:%.*]] = alloc_stack $T
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>, case #TreeA.Leaf!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <T>):
+ // CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
+ // CHECK: [[TMP:%.*]] = alloc_stack
+ // CHECK: copy_addr [[VALUE_ADDR]] to [initialization] [[TMP]]
+ // CHECK: copy_addr [take] [[TMP]] to [initialization] [[X]]
+ // CHECK: destroy_value [[BOX]]
+ guard case .Leaf(let x) = tree else { return }
+
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>, case #TreeA.Branch!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
+ // CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
+ // CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
+ // CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
+ // CHECK: [[BORROWED_TUPLE_COPY:%.*]] = begin_borrow [[TUPLE_COPY]]
+ // CHECK: [[L:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
+ // CHECK: [[COPY_L:%.*]] = copy_value [[L]]
+ // CHECK: [[R:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
+ // CHECK: [[COPY_R:%.*]] = copy_value [[R]]
+ // CHECK: end_borrow [[BORROWED_TUPLE_COPY]] from [[TUPLE_COPY]]
+ // CHECK: destroy_value [[TUPLE_COPY]]
+ // CHECK: destroy_value [[BOX]]
+ guard case .Branch(left: let l, right: let r) = tree else { return }
+
+ // CHECK: destroy_value [[COPY_R]]
+ // CHECK: destroy_value [[COPY_L]]
+ // CHECK: destroy_addr [[X]]
+ }
+
+ do {
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>, case #TreeA.Nil!enumelt: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: [[YES]]:
+ // CHECK: br
+ if case .Nil = tree { }
+
+ // CHECK: [[X:%.*]] = alloc_stack $T
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>, case #TreeA.Leaf!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var τ_0_0 } <T>):
+ // CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
+ // CHECK: [[TMP:%.*]] = alloc_stack
+ // CHECK: copy_addr [[VALUE_ADDR]] to [initialization] [[TMP]]
+ // CHECK: copy_addr [take] [[TMP]] to [initialization] [[X]]
+ // CHECK: destroy_value [[BOX]]
+ // CHECK: destroy_addr [[X]]
+ if case .Leaf(let x) = tree { }
+
+
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TreeA<T>, case #TreeA.Branch!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]([[ORIGINAL_VALUE:%.*]] : $TreeA<T>):
+ // CHECK: destroy_value [[ORIGINAL_VALUE]]
+ // CHECK: [[YES]]([[BOX:%.*]] : $<τ_0_0> { var (left: TreeA<τ_0_0>, right: TreeA<τ_0_0>) } <T>):
+ // CHECK: [[VALUE_ADDR:%.*]] = project_box [[BOX]]
+ // CHECK: [[TUPLE:%.*]] = load [take] [[VALUE_ADDR]]
+ // CHECK: [[TUPLE_COPY:%.*]] = copy_value [[TUPLE]]
+ // CHECK: [[BORROWED_TUPLE_COPY:%.*]] = begin_borrow [[TUPLE_COPY]]
+ // CHECK: [[L:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
+ // CHECK: [[COPY_L:%.*]] = copy_value [[L]]
+ // CHECK: [[R:%.*]] = tuple_extract [[BORROWED_TUPLE_COPY]]
+ // CHECK: [[COPY_R:%.*]] = copy_value [[R]]
+ // CHECK: end_borrow [[BORROWED_TUPLE_COPY]] from [[TUPLE_COPY]]
+ // CHECK: destroy_value [[TUPLE_COPY]]
+ // CHECK: destroy_value [[BOX]]
+ // CHECK: destroy_value [[COPY_R]]
+ // CHECK: destroy_value [[COPY_L]]
+ if case .Branch(left: let l, right: let r) = tree { }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S13indirect_enum10guardTreeB{{[_0-9a-zA-Z]*}}F
+func guardTreeB<T>(_ tree: TreeB<T>) {
+ do {
+ // CHECK: copy_addr %0 to [initialization] [[TMP:%.*]] :
+ // CHECK: switch_enum_addr [[TMP]] : $*TreeB<T>, case #TreeB.Nil!enumelt: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]:
+ // CHECK: destroy_addr [[TMP]]
+ // CHECK: [[YES]]:
+ // CHECK: destroy_addr [[TMP]]
+ guard case .Nil = tree else { return }
+
+ // CHECK: [[X:%.*]] = alloc_stack $T
+ // CHECK: copy_addr %0 to [initialization] [[TMP:%.*]] :
+ // CHECK: switch_enum_addr [[TMP]] : $*TreeB<T>, case #TreeB.Leaf!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]:
+ // CHECK: destroy_addr [[TMP]]
+ // CHECK: [[YES]]:
+ // CHECK: [[VALUE:%.*]] = unchecked_take_enum_data_addr [[TMP]]
+ // CHECK: copy_addr [take] [[VALUE]] to [initialization] [[X]]
+ // CHECK: dealloc_stack [[TMP]]
+ guard case .Leaf(let x) = tree else { return }
+
+ // CHECK: [[L:%.*]] = alloc_stack $TreeB
+ // CHECK: [[R:%.*]] = alloc_stack $TreeB
+ // CHECK: copy_addr %0 to [initialization] [[TMP:%.*]] :
+ // CHECK: switch_enum_addr [[TMP]] : $*TreeB<T>, case #TreeB.Branch!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]:
+ // CHECK: destroy_addr [[TMP]]
+ // CHECK: [[YES]]:
+ // CHECK: [[BOX_ADDR:%.*]] = unchecked_take_enum_data_addr [[TMP]]
+ // CHECK: [[BOX:%.*]] = load [take] [[BOX_ADDR]]
+ // CHECK: [[TUPLE_ADDR:%.*]] = project_box [[BOX]]
+ // CHECK: copy_addr [[TUPLE_ADDR]] to [initialization] [[TUPLE_COPY:%.*]] :
+ // CHECK: [[L_COPY:%.*]] = tuple_element_addr [[TUPLE_COPY]]
+ // CHECK: copy_addr [take] [[L_COPY]] to [initialization] [[L]]
+ // CHECK: [[R_COPY:%.*]] = tuple_element_addr [[TUPLE_COPY]]
+ // CHECK: copy_addr [take] [[R_COPY]] to [initialization] [[R]]
+ // CHECK: destroy_value [[BOX]]
+ guard case .Branch(left: let l, right: let r) = tree else { return }
+
+ // CHECK: destroy_addr [[R]]
+ // CHECK: destroy_addr [[L]]
+ // CHECK: destroy_addr [[X]]
+ }
+
+ do {
+ // CHECK: copy_addr %0 to [initialization] [[TMP:%.*]] :
+ // CHECK: switch_enum_addr [[TMP]] : $*TreeB<T>, case #TreeB.Nil!enumelt: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]:
+ // CHECK: destroy_addr [[TMP]]
+ // CHECK: [[YES]]:
+ // CHECK: destroy_addr [[TMP]]
+ if case .Nil = tree { }
+
+ // CHECK: [[X:%.*]] = alloc_stack $T
+ // CHECK: copy_addr %0 to [initialization] [[TMP:%.*]] :
+ // CHECK: switch_enum_addr [[TMP]] : $*TreeB<T>, case #TreeB.Leaf!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]:
+ // CHECK: destroy_addr [[TMP]]
+ // CHECK: [[YES]]:
+ // CHECK: [[VALUE:%.*]] = unchecked_take_enum_data_addr [[TMP]]
+ // CHECK: copy_addr [take] [[VALUE]] to [initialization] [[X]]
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: destroy_addr [[X]]
+ if case .Leaf(let x) = tree { }
+
+ // CHECK: [[L:%.*]] = alloc_stack $TreeB
+ // CHECK: [[R:%.*]] = alloc_stack $TreeB
+ // CHECK: copy_addr %0 to [initialization] [[TMP:%.*]] :
+ // CHECK: switch_enum_addr [[TMP]] : $*TreeB<T>, case #TreeB.Branch!enumelt.1: [[YES:bb[0-9]+]], default [[NO:bb[0-9]+]]
+ // CHECK: [[NO]]:
+ // CHECK: destroy_addr [[TMP]]
+ // CHECK: [[YES]]:
+ // CHECK: [[BOX_ADDR:%.*]] = unchecked_take_enum_data_addr [[TMP]]
+ // CHECK: [[BOX:%.*]] = load [take] [[BOX_ADDR]]
+ // CHECK: [[TUPLE_ADDR:%.*]] = project_box [[BOX]]
+ // CHECK: copy_addr [[TUPLE_ADDR]] to [initialization] [[TUPLE_COPY:%.*]] :
+ // CHECK: [[L_COPY:%.*]] = tuple_element_addr [[TUPLE_COPY]]
+ // CHECK: copy_addr [take] [[L_COPY]] to [initialization] [[L]]
+ // CHECK: [[R_COPY:%.*]] = tuple_element_addr [[TUPLE_COPY]]
+ // CHECK: copy_addr [take] [[R_COPY]] to [initialization] [[R]]
+ // CHECK: destroy_value [[BOX]]
+ // CHECK: destroy_addr [[R]]
+ // CHECK: destroy_addr [[L]]
+ if case .Branch(left: let l, right: let r) = tree { }
+ }
+}
+
+// SEMANTIC ARC TODO: This test needs to be made far more comprehensive.
+// CHECK-LABEL: sil hidden @$S13indirect_enum35dontDisableCleanupOfIndirectPayloadyyAA010TrivialButG0OF : $@convention(thin) (@guaranteed TrivialButIndirect) -> () {
+func dontDisableCleanupOfIndirectPayload(_ x: TrivialButIndirect) {
+ // CHECK: bb0([[ARG:%.*]] : $TrivialButIndirect):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TrivialButIndirect, case #TrivialButIndirect.Direct!enumelt.1: [[YES:bb[0-9]+]], case #TrivialButIndirect.Indirect!enumelt.1: [[NO:bb[0-9]+]]
+ //
+ // CHECK: [[NO]]([[PAYLOAD:%.*]] : ${ var Int }):
+ // CHECK: destroy_value [[PAYLOAD]]
+ guard case .Direct(let foo) = x else { return }
+
+ // CHECK: [[YES]]({{%.*}} : $Int):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $TrivialButIndirect, case #TrivialButIndirect.Indirect!enumelt.1: [[YES:bb[0-9]+]], case #TrivialButIndirect.Direct!enumelt.1: [[NO:bb[0-9]+]]
+
+ // CHECK: [[NO]]({{%.*}} : $Int):
+ // CHECK-NOT: destroy_value
+
+ // CHECK: [[YES]]([[BOX:%.*]] : ${ var Int }):
+ // CHECK: destroy_value [[BOX]]
+
+ guard case .Indirect(let bar) = x else { return }
+}
+// CHECK: } // end sil function '$S13indirect_enum35dontDisableCleanupOfIndirectPayloadyyAA010TrivialButG0OF'
diff --git a/test/SILGen/plus_zero_inlineable_attribute.swift b/test/SILGen/plus_zero_inlineable_attribute.swift
new file mode 100644
index 0000000..097ea60
--- /dev/null
+++ b/test/SILGen/plus_zero_inlineable_attribute.swift
@@ -0,0 +1,101 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
+
+// CHECK-LABEL: sil [serialized] @$S20inlineable_attribute15fragileFunctionyyF : $@convention(thin) () -> ()
+@_inlineable public func fragileFunction() {
+
+}
+
+public struct MySt {
+ // CHECK-LABEL: sil [serialized] @$S20inlineable_attribute4MyStV6methodyyF : $@convention(method) (MySt) -> ()
+ @_inlineable public func method() {}
+
+ // CHECK-LABEL: sil [serialized] @$S20inlineable_attribute4MyStV8propertySivg : $@convention(method) (MySt) -> Int
+ @_inlineable public var property: Int {
+ return 5
+ }
+
+ // CHECK-LABEL: sil [serialized] @$S20inlineable_attribute4MyStVyS2icig : $@convention(method) (Int, MySt) -> Int
+ @_inlineable public subscript(x: Int) -> Int {
+ return x
+ }
+}
+
+public class MyCls {
+ // CHECK-LABEL: sil [serialized] @$S20inlineable_attribute5MyClsCfD : $@convention(method) (@owned MyCls) -> ()
+ @_inlineable deinit {}
+
+ // Allocating entry point is [serialized]
+
+ // CHECK-LABEL: sil [serialized] @$S20inlineable_attribute5MyClsC14designatedInitACyt_tcfC : $@convention(method) (@thick MyCls.Type) -> @owned MyCls
+ public init(designatedInit: ()) {}
+
+ // Note -- convenience init is intentionally not [serialized]
+
+ // CHECK-LABEL: sil @$S20inlineable_attribute5MyClsC15convenienceInitACyt_tcfC : $@convention(method) (@thick MyCls.Type) -> @owned MyCls
+ public convenience init(convenienceInit: ()) {
+ self.init(designatedInit: ())
+ }
+}
+
+// Make sure enum case constructors for public and versioned enums are
+// [serialized].
+@_versioned enum MyEnum {
+ case c(MySt)
+}
+
+// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$S20inlineable_attribute6MyEnumO1cyAcA0C2StVcACmFTc : $@convention(thin) (@thin MyEnum.Type) -> @owned @callee_guaranteed (MySt) -> MyEnum
+
+@_inlineable public func referencesMyEnum() {
+ _ = MyEnum.c
+}
+
+// CHECK-LABEL: sil non_abi [transparent] [serialized] @$S20inlineable_attribute15HasInitializersV1xSivpfi : $@convention(thin) () -> Int
+// CHECK-LABEL: sil non_abi [transparent] [serialized] @$S20inlineable_attribute15HasInitializersV1ySivpfi : $@convention(thin) () -> Int
+
+@_fixed_layout
+public struct HasInitializers {
+ public let x = 1234
+ internal let y = 4321
+
+ @_inlineable public init() {}
+}
+
+public class Horse {
+ public func gallop() {}
+}
+
+// CHECK-LABEL: sil [serialized] @$S20inlineable_attribute15talkAboutAHorse1hyAA5HorseC_tF : $@convention(thin) (@guaranteed Horse) -> () {
+// CHECK: function_ref @$S20inlineable_attribute5HorseC6gallopyyFTc
+// CHECK: return
+// CHECK: }
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @$S20inlineable_attribute5HorseC6gallopyyFTc : $@convention(thin) (@guaranteed Horse) -> @owned @callee_guaranteed () -> () {
+// CHECK: class_method
+// CHECK: return
+// CHECK: }
+
+@_inlineable public func talkAboutAHorse(h: Horse) {
+ _ = h.gallop
+}
+
+@_versioned
+@_fixed_layout
+class Base {
+ @_versioned
+ @_inlineable
+ init(horse: Horse) {}
+}
+
+// CHECK-LABEL: sil [serialized] @$S20inlineable_attribute7DerivedCfd : $@convention(method) (@guaranteed Derived) -> @owned Builtin.NativeObject
+// CHECK-LABEL: sil [serialized] @$S20inlineable_attribute7DerivedCfD : $@convention(method) (@owned Derived) -> ()
+
+// Make sure the synthesized delegating initializer is inlineable also
+
+// CHECK-LABEL: sil [serialized] @$S20inlineable_attribute7DerivedC5horseAcA5HorseC_tcfc : $@convention(method) (@owned Horse, @owned Derived) -> @owned Derived
+@_versioned
+@_fixed_layout
+class Derived : Base {
+ // Allow @_inlineable deinits
+ @_inlineable deinit {}
+}
diff --git a/test/SILGen/plus_zero_inlineable_attribute_objc.swift b/test/SILGen/plus_zero_inlineable_attribute_objc.swift
new file mode 100644
index 0000000..a963567
--- /dev/null
+++ b/test/SILGen/plus_zero_inlineable_attribute_objc.swift
@@ -0,0 +1,35 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -Xllvm -sil-full-demangle -primary-file %s -emit-silgen | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+public class Horse : NSObject {
+ public dynamic func gallop() {}
+}
+
+// Make sure we can reference dynamic thunks and curry thunks
+// from inlineable scopes
+
+// CHECK-LABEL: sil [serialized] @$S25inlineable_attribute_objc15talkAboutAHorse1hyAA5HorseC_tF : $@convention(thin) (@guaranteed Horse) -> () {
+// CHECK: function_ref @$S25inlineable_attribute_objc5HorseC6gallopyyFTc : $@convention(thin) (@guaranteed Horse) -> @owned @callee_guaranteed () -> ()
+// CHECK: return
+// CHECK: }
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @$S25inlineable_attribute_objc5HorseC6gallopyyFTc : $@convention(thin) (@guaranteed Horse) -> @owned @callee_guaranteed () -> ()
+// CHECK: %1 = function_ref @$S25inlineable_attribute_objc5HorseC6gallopyyFTD
+// CHECK: return
+// CHECK: }
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [thunk] @$S25inlineable_attribute_objc5HorseC6gallopyyFTD : $@convention(method) (@guaranteed Horse) -> ()
+// CHECK: objc_method
+// CHECK: return
+// CHECK: }
+
+@_inlineable public func talkAboutAHorse(h: Horse) {
+ _ = h.gallop
+}
diff --git a/test/SILGen/plus_zero_keypath_application.swift b/test/SILGen/plus_zero_keypath_application.swift
new file mode 100644
index 0000000..1dbd44e
--- /dev/null
+++ b/test/SILGen/plus_zero_keypath_application.swift
@@ -0,0 +1,124 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class A {}
+class B {}
+protocol P {}
+protocol Q {}
+
+// CHECK-LABEL: sil hidden @{{.*}}loadable
+func loadable(readonly: A, writable: inout A,
+ value: B,
+ kp: KeyPath<A, B>,
+ wkp: WritableKeyPath<A, B>,
+ rkp: ReferenceWritableKeyPath<A, B>) {
+ // CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
+ // CHECK: [[ROOT_COPY:%.*]] = copy_value %0
+ // CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
+ // CHECK: [[KP_COPY:%.*]] = copy_value %3
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ // CHECK: [[BORROWED_KP_COPY:%.*]] = begin_borrow [[KP_COPY]]
+ // CHECK: [[RESULT_TMP:%.*]] = alloc_stack $B
+ // CHECK: apply [[PROJECT]]<A, B>([[RESULT_TMP]], [[ROOT_TMP]], [[BORROWED_KP_COPY]])
+ // CHECK: [[RESULT:%.*]] = load [take] [[RESULT_TMP]]
+ // CHECK: destroy_value [[RESULT]]
+ _ = readonly[keyPath: kp]
+ _ = writable[keyPath: kp]
+ _ = readonly[keyPath: wkp]
+
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: wkp]
+
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: rkp]
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: rkp]
+
+ // CHECK: function_ref @{{.*}}_projectKeyPathWritable
+ writable[keyPath: wkp] = value
+ // CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
+ readonly[keyPath: rkp] = value
+ // CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
+ writable[keyPath: rkp] = value
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}addressOnly
+func addressOnly(readonly: P, writable: inout P,
+ value: Q,
+ kp: KeyPath<P, Q>,
+ wkp: WritableKeyPath<P, Q>,
+ rkp: ReferenceWritableKeyPath<P, Q>) {
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: kp]
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: kp]
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: wkp]
+
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: wkp]
+
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: rkp]
+ // CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: rkp]
+
+ // CHECK: function_ref @{{.*}}_projectKeyPathWritable
+ writable[keyPath: wkp] = value
+ // CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
+ readonly[keyPath: rkp] = value
+ // CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
+ writable[keyPath: rkp] = value
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}reabstracted
+func reabstracted(readonly: @escaping () -> (),
+ writable: inout () -> (),
+ value: @escaping (A) -> B,
+ kp: KeyPath<() -> (), (A) -> B>,
+ wkp: WritableKeyPath<() -> (), (A) -> B>,
+ rkp: ReferenceWritableKeyPath<() -> (), (A) -> B>) {
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: kp]
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: kp]
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: wkp]
+
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: wkp]
+
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = readonly[keyPath: rkp]
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
+ _ = writable[keyPath: rkp]
+
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
+ writable[keyPath: wkp] = value
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
+ readonly[keyPath: rkp] = value
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
+ writable[keyPath: rkp] = value
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}partial
+func partial<A>(valueA: A,
+ valueB: Int,
+ pkpA: PartialKeyPath<A>,
+ pkpB: PartialKeyPath<Int>,
+ akp: AnyKeyPath) {
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathAny
+ // CHECK: apply [[PROJECT]]<A>
+ _ = valueA[keyPath: akp]
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathPartial
+ // CHECK: apply [[PROJECT]]<A>
+ _ = valueA[keyPath: pkpA]
+
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathAny
+ // CHECK: apply [[PROJECT]]<Int>
+ _ = valueB[keyPath: akp]
+ // CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathPartial
+ // CHECK: apply [[PROJECT]]<Int>
+ _ = valueB[keyPath: pkpB]
+}
+
diff --git a/test/SILGen/plus_zero_keypaths.swift b/test/SILGen/plus_zero_keypaths.swift
new file mode 100644
index 0000000..db06785
--- /dev/null
+++ b/test/SILGen/plus_zero_keypaths.swift
@@ -0,0 +1,339 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct S<T> {
+ var x: T
+ let y: String
+ var z: C<T>
+
+ var computed: C<T> { fatalError() }
+ var observed: C<T> { didSet { fatalError() } }
+ var reabstracted: () -> ()
+}
+class C<T> {
+ final var x: T
+ final let y: String
+ final var z: S<T>
+
+ var nonfinal: S<T>
+ var computed: S<T> { fatalError() }
+ var observed: S<T> { didSet { fatalError() } }
+ final var reabstracted: () -> ()
+
+ init() { fatalError() }
+}
+
+protocol P {
+ var x: Int { get }
+ var y: String { get set }
+}
+
+extension P {
+ var z: String {
+ return y
+ }
+ var w: String {
+ get { return "" }
+ nonmutating set { }
+ }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}storedProperties
+func storedProperties<T>(_: T) {
+ // CHECK: keypath $WritableKeyPath<S<T>, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.x : $τ_0_0) <T>
+ _ = \S<T>.x
+ // CHECK: keypath $KeyPath<S<T>, String>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.y : $String) <T>
+ _ = \S<T>.y
+ // CHECK: keypath $ReferenceWritableKeyPath<S<T>, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.z : $C<τ_0_0>; stored_property #C.x : $τ_0_0) <T>
+ _ = \S<T>.z.x
+ // CHECK: keypath $ReferenceWritableKeyPath<C<T>, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.x : $τ_0_0) <T>
+ _ = \C<T>.x
+ // CHECK: keypath $KeyPath<C<T>, String>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.y : $String) <T>
+ _ = \C<T>.y
+ // CHECK: keypath $ReferenceWritableKeyPath<C<T>, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.z : $S<τ_0_0>; stored_property #S.x : $τ_0_0) <T>
+ _ = \C<T>.z.x
+ // CHECK: keypath $KeyPath<C<T>, String>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.z : $S<τ_0_0>; stored_property #S.z : $C<τ_0_0>; stored_property #C.y : $String) <T>
+ _ = \C<T>.z.z.y
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}computedProperties
+func computedProperties<T: P>(_: T) {
+ // CHECK: keypath $ReferenceWritableKeyPath<C<T>, S<T>>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $C<τ_0_0>;
+ // CHECK-SAME: settable_property $S<τ_0_0>,
+ // CHECK-SAME: id #C.nonfinal!getter.1 : <T> (C<T>) -> () -> S<T>,
+ // CHECK-SAME: getter @$S8keypaths1CC8nonfinalAA1SVyxGvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>,
+ // CHECK-SAME: setter @$S8keypaths1CC8nonfinalAA1SVyxGvpAA1PRzlACyxGTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>, @in_guaranteed C<τ_0_0>) -> ()
+ // CHECK-SAME: ) <T>
+ _ = \C<T>.nonfinal
+
+ // CHECK: keypath $KeyPath<C<T>, S<T>>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $C<τ_0_0>;
+ // CHECK-SAME: gettable_property $S<τ_0_0>,
+ // CHECK-SAME: id #C.computed!getter.1 : <T> (C<T>) -> () -> S<T>,
+ // CHECK-SAME: getter @$S8keypaths1CC8computedAA1SVyxGvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>
+ // CHECK-SAME: ) <T>
+ _ = \C<T>.computed
+
+ // CHECK: keypath $ReferenceWritableKeyPath<C<T>, S<T>>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $C<τ_0_0>;
+ // CHECK-SAME: settable_property $S<τ_0_0>,
+ // CHECK-SAME: id #C.observed!getter.1 : <T> (C<T>) -> () -> S<T>,
+ // CHECK-SAME: getter @$S8keypaths1CC8observedAA1SVyxGvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>,
+ // CHECK-SAME: setter @$S8keypaths1CC8observedAA1SVyxGvpAA1PRzlACyxGTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>, @in_guaranteed C<τ_0_0>) -> ()
+ // CHECK-SAME: ) <T>
+ _ = \C<T>.observed
+
+ _ = \C<T>.nonfinal.x
+ _ = \C<T>.computed.x
+ _ = \C<T>.observed.x
+ _ = \C<T>.z.computed
+ _ = \C<T>.z.observed
+ _ = \C<T>.observed.x
+
+ // CHECK: keypath $ReferenceWritableKeyPath<C<T>, () -> ()>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $C<τ_0_0>;
+ // CHECK-SAME: settable_property $() -> (),
+ // CHECK-SAME: id ##C.reabstracted,
+ // CHECK-SAME: getter @$S8keypaths1CC12reabstractedyycvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out @callee_guaranteed (@in_guaranteed ()) -> @out (),
+ // CHECK-SAME: setter @$S8keypaths1CC12reabstractedyycvpAA1PRzlACyxGTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out (), @in_guaranteed C<τ_0_0>) -> ()
+ // CHECK-SAME: ) <T>
+ _ = \C<T>.reabstracted
+
+ // CHECK: keypath $KeyPath<S<T>, C<T>>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $S<τ_0_0>; gettable_property $C<τ_0_0>,
+ // CHECK-SAME: id @$S8keypaths1SV8computedAA1CCyxGvg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @owned C<τ_0_0>,
+ // CHECK-SAME: getter @$S8keypaths1SV8computedAA1CCyxGvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out C<τ_0_0>
+ // CHECK-SAME: ) <T>
+ _ = \S<T>.computed
+
+ // CHECK: keypath $WritableKeyPath<S<T>, C<T>>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $S<τ_0_0>;
+ // CHECK-SAME: settable_property $C<τ_0_0>,
+ // CHECK-SAME: id @$S8keypaths1SV8observedAA1CCyxGvg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @owned C<τ_0_0>,
+ // CHECK-SAME: getter @$S8keypaths1SV8observedAA1CCyxGvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out C<τ_0_0>,
+ // CHECK-SAME: setter @$S8keypaths1SV8observedAA1CCyxGvpAA1PRzlACyxGTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>, @inout S<τ_0_0>) -> ()
+ // CHECK-SAME: ) <T>
+ _ = \S<T>.observed
+ _ = \S<T>.z.nonfinal
+ _ = \S<T>.z.computed
+ _ = \S<T>.z.observed
+ _ = \S<T>.computed.x
+ _ = \S<T>.computed.y
+ // CHECK: keypath $WritableKeyPath<S<T>, () -> ()>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $S<τ_0_0>;
+ // CHECK-SAME: settable_property $() -> (),
+ // CHECK-SAME: id ##S.reabstracted,
+ // CHECK-SAME: getter @$S8keypaths1SV12reabstractedyycvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out @callee_guaranteed (@in_guaranteed ()) -> @out (),
+ // CHECK-SAME: setter @$S8keypaths1SV12reabstractedyycvpAA1PRzlACyxGTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out (), @inout S<τ_0_0>) -> ()
+ // CHECK-SAME: ) <T>
+ _ = \S<T>.reabstracted
+
+ // CHECK: keypath $KeyPath<T, Int>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $τ_0_0;
+ // CHECK-SAME: gettable_property $Int,
+ // CHECK-SAME: id #P.x!getter.1 : <Self where Self : P> (Self) -> () -> Int,
+ // CHECK-SAME: getter @$S8keypaths1PP1xSivpAaBRzlxTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Int
+ // CHECK-SAME: ) <T>
+ _ = \T.x
+ // CHECK: keypath $WritableKeyPath<T, String>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $τ_0_0;
+ // CHECK-SAME: settable_property $String,
+ // CHECK-SAME: id #P.y!getter.1 : <Self where Self : P> (Self) -> () -> String,
+ // CHECK-SAME: getter @$S8keypaths1PP1ySSvpAaBRzlxTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out String,
+ // CHECK-SAME: setter @$S8keypaths1PP1ySSvpAaBRzlxTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed String, @inout τ_0_0) -> ()
+ // CHECK-SAME: ) <T>
+ _ = \T.y
+
+ // CHECK: keypath $KeyPath<T, String>, <τ_0_0 where τ_0_0 : P> (
+ // CHECK-SAME: root $τ_0_0;
+ // CHECK-SAME: gettable_property $String,
+ // CHECK-SAME: id @$S8keypaths1PPAAE1zSSvg
+ _ = \T.z
+}
+
+struct Concrete: P {
+ var x: Int
+ var y: String
+}
+
+// CHECK-LABEL: sil hidden @$S8keypaths35keyPathsWithSpecificGenericInstanceyyF
+func keyPathsWithSpecificGenericInstance() {
+ // CHECK: keypath $KeyPath<Concrete, String>, (
+ // CHECK-SAME: gettable_property $String,
+ // CHECK-SAME: id @$S8keypaths1PPAAE1zSSvg
+ // CHECK-SAME: getter @$S8keypaths1PPAAE1zSSvpAA8ConcreteVTK : $@convention(thin) (@in_guaranteed Concrete) -> @out String
+ _ = \Concrete.z
+ _ = \S<Concrete>.computed
+}
+
+class AA<T> {
+ var a: Int { get { return 0 } set { } }
+}
+class BB<U, V>: AA<V> {
+}
+
+func keyPathForInheritedMember() {
+ _ = \BB<Int, String>.a
+}
+
+func keyPathForExistentialMember() {
+ _ = \P.x
+ _ = \P.y
+ _ = \P.z
+ _ = \P.w
+}
+
+struct OptionalFields {
+ var x: S<Int>?
+}
+struct OptionalFields2 {
+ var y: OptionalFields?
+}
+
+// CHECK-LABEL: sil hidden @$S8keypaths18keyPathForOptionalyyF
+func keyPathForOptional() {
+ // CHECK: keypath $WritableKeyPath<OptionalFields, S<Int>>, (
+ // CHECK-SAME: stored_property #OptionalFields.x : $Optional<S<Int>>;
+ // CHECK-SAME: optional_force : $S<Int>)
+ _ = \OptionalFields.x!
+ // CHECK: keypath $KeyPath<OptionalFields, Optional<String>>, (
+ // CHECK-SAME: stored_property #OptionalFields.x : $Optional<S<Int>>;
+ // CHECK-SAME: optional_chain : $S<Int>;
+ // CHECK-SAME: stored_property #S.y : $String;
+ // CHECK-SAME: optional_wrap : $Optional<String>)
+ _ = \OptionalFields.x?.y
+ // CHECK: keypath $KeyPath<OptionalFields2, Optional<S<Int>>>, (
+ // CHECK-SAME: root $OptionalFields2;
+ // CHECK-SAME: stored_property #OptionalFields2.y : $Optional<OptionalFields>;
+ // CHECK-SAME: optional_chain : $OptionalFields;
+ // CHECK-SAME: stored_property #OptionalFields.x : $Optional<S<Int>>)
+ _ = \OptionalFields2.y?.x
+}
+
+class StorageQualified {
+ weak var tooWeak: StorageQualified?
+ unowned var disowned: StorageQualified
+
+ init() { fatalError() }
+}
+
+final class FinalStorageQualified {
+ weak var tooWeak: StorageQualified?
+ unowned var disowned: StorageQualified
+
+ init() { fatalError() }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}keyPathForStorageQualified
+func keyPathForStorageQualified() {
+ // CHECK: = keypath $ReferenceWritableKeyPath<StorageQualified, Optional<StorageQualified>>,
+ // CHECK-SAME: settable_property $Optional<StorageQualified>, id #StorageQualified.tooWeak!getter.1
+ _ = \StorageQualified.tooWeak
+ // CHECK: = keypath $ReferenceWritableKeyPath<StorageQualified, StorageQualified>,
+ // CHECK-SAME: settable_property $StorageQualified, id #StorageQualified.disowned!getter.1
+ _ = \StorageQualified.disowned
+
+ // CHECK: = keypath $ReferenceWritableKeyPath<FinalStorageQualified, Optional<StorageQualified>>,
+ // CHECK-SAME: settable_property $Optional<StorageQualified>, id ##FinalStorageQualified.tooWeak
+ _ = \FinalStorageQualified.tooWeak
+ // CHECK: = keypath $ReferenceWritableKeyPath<FinalStorageQualified, StorageQualified>,
+ // CHECK-SAME: settable_property $StorageQualified, id ##FinalStorageQualified.disowned
+ _ = \FinalStorageQualified.disowned
+}
+
+struct IUOProperty {
+ var iuo: IUOBlob!
+}
+
+struct IUOBlob {
+ var x: Int
+ subscript(y: String) -> String {
+ get { return y }
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}11iuoKeyPaths
+func iuoKeyPaths() {
+ // CHECK: = keypath $WritableKeyPath<IUOProperty, Int>,
+ // CHECK-SAME: stored_property #IUOProperty.iuo
+ // CHECK-SAME: optional_force
+ // CHECK-SAME: stored_property #IUOBlob.x
+ _ = \IUOProperty.iuo.x
+ // CHECK: = keypath $WritableKeyPath<IUOProperty, Int>,
+ // CHECK-SAME: stored_property #IUOProperty.iuo
+ // CHECK-SAME: optional_force
+ // CHECK-SAME: stored_property #IUOBlob.x
+ _ = \IUOProperty.iuo!.x
+}
+
+class Bass: Hashable {
+ static func ==(_: Bass, _: Bass) -> Bool { return false }
+ var hashValue: Int { return 0 }
+}
+
+class Treble: Bass { }
+
+struct Subscripts<T> {
+ subscript() -> T {
+ get { fatalError() }
+ set { fatalError() }
+ }
+ subscript(generic x: T) -> T {
+ get { fatalError() }
+ set { fatalError() }
+ }
+ subscript(concrete x: String) -> String {
+ get { fatalError() }
+ set { fatalError() }
+ }
+ subscript(x: String, y: String) -> String {
+ get { fatalError() }
+ set { fatalError() }
+ }
+ subscript<U>(subGeneric z: U) -> U {
+ get { fatalError() }
+ set { fatalError() }
+ }
+ subscript(mutable x: T) -> T {
+ get { fatalError() }
+ set { fatalError() }
+ }
+ subscript(bass: Bass) -> Bass {
+ get { return bass }
+ set { }
+ }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}10subscripts
+func subscripts<T: Hashable, U: Hashable>(x: T, y: U, s: String) {
+ _ = \Subscripts<T>.[]
+ _ = \Subscripts<T>.[generic: x]
+ _ = \Subscripts<T>.[concrete: s]
+ _ = \Subscripts<T>.[s, s]
+ _ = \Subscripts<T>.[subGeneric: s]
+ _ = \Subscripts<T>.[subGeneric: x]
+ _ = \Subscripts<T>.[subGeneric: y]
+
+ _ = \Subscripts<U>.[]
+ _ = \Subscripts<U>.[generic: y]
+ _ = \Subscripts<U>.[concrete: s]
+ _ = \Subscripts<U>.[s, s]
+ _ = \Subscripts<U>.[subGeneric: s]
+ _ = \Subscripts<U>.[subGeneric: x]
+ _ = \Subscripts<U>.[subGeneric: y]
+
+ _ = \Subscripts<String>.[]
+ _ = \Subscripts<String>.[generic: s]
+ _ = \Subscripts<String>.[concrete: s]
+ _ = \Subscripts<String>.[s, s]
+ _ = \Subscripts<String>.[subGeneric: s]
+ _ = \Subscripts<String>.[subGeneric: x]
+ _ = \Subscripts<String>.[subGeneric: y]
+
+ _ = \Subscripts<T>.[s, s].count
+
+ _ = \Subscripts<T>.[Bass()]
+ _ = \Subscripts<T>.[Treble()]
+}
diff --git a/test/SILGen/plus_zero_let_decls.swift b/test/SILGen/plus_zero_let_decls.swift
new file mode 100644
index 0000000..d0f7379
--- /dev/null
+++ b/test/SILGen/plus_zero_let_decls.swift
@@ -0,0 +1,518 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func takeClosure(_ a : () -> Int) {}
+
+// Let decls don't get boxes for trivial types.
+//
+// CHECK-LABEL: sil hidden @{{.*}}test1
+func test1(_ a : Int) -> Int {
+ // CHECK-NOT: alloc_box
+ // FIXME(integers): the following check should be updated for the new way +
+ // gets invoked. <rdar://problem/29939484>
+ // XCHECK-NOT: alloc_stack
+
+ let (b,c) = (a, 32)
+
+ return b+c
+
+ // CHECK: return
+}
+
+// rdar://15716277
+// CHECK: @{{.*}}_destructuring
+func let_destructuring() -> Int {
+ let (a, b) = ((1,2), 5)
+ return a.1+a.0+b
+}
+
+// Let decls being closed over.
+//
+// CHECK-LABEL: sil hidden @{{.*}}test2
+func test2() {
+ // No allocations.
+ // CHECK-NOT: alloc_box
+ // CHECK-NOT: alloc_stack
+
+ let x = 42
+
+ takeClosure({x})
+
+
+ // CHECK: return
+}
+
+// The closure just returns its value, which it captured directly.
+
+// CHECK: sil private @$S9let_decls5test2yyFSiyXEfU_ : $@convention(thin) (Int) -> Int
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: return %0 : $Int
+
+// Verify that we can close over let decls of tuple type.
+struct RegularStruct {
+ var a: Int
+}
+func testTupleLetCapture() {
+ let t = (RegularStruct(a: 41), 42)
+
+ takeClosure( { t.0.a })
+}
+
+
+
+func getAString() -> String { return "" }
+func useAString(_ a : String) {}
+
+// rdar://15689514 - Verify that the cleanup for the let decl runs at the end of
+// the 'let' lifetime, not at the end of the initializing expression.
+//
+// CHECK-LABEL: sil hidden @{{.*}}test3
+func test3() {
+ // CHECK: [[GETFN:%[0-9]+]] = function_ref{{.*}}getAString
+ // CHECK-NEXT: [[STR:%[0-9]+]] = apply [[GETFN]]()
+ let o = getAString()
+
+ // CHECK-NEXT: debug_value
+ // CHECK-NOT: destroy_value
+
+ // CHECK-NEXT: [[STR_BORROW:%.*]] = begin_borrow [[STR]]
+ // CHECK: [[USEFN:%[0-9]+]] = function_ref{{.*}}useAString
+ // CHECK-NEXT: [[USE:%[0-9]+]] = apply [[USEFN]]([[STR_BORROW]])
+ useAString(o)
+
+ // CHECK: destroy_value [[STR]]
+}
+// CHECK: } // end sil function '{{.*}}test3{{.*}}'
+
+
+
+struct AddressOnlyStruct<T> {
+ var elt : T
+ var str : String
+}
+
+func produceAddressOnlyStruct<T>(_ x : T) -> AddressOnlyStruct<T> {}
+
+// CHECK-LABEL: sil hidden @{{.*}}testAddressOnlyStructString
+// CHECK: bb0([[FUNC_ARG:%.*]] : @trivial $*T):
+func testAddressOnlyStructString<T>(_ a : T) -> String {
+ return produceAddressOnlyStruct(a).str
+
+ // CHECK: [[TMPSTRUCT:%[0-9]+]] = alloc_stack $AddressOnlyStruct<T>
+ // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
+ // CHECK: apply [[PRODFN]]<T>([[TMPSTRUCT]], [[FUNC_ARG]])
+ // CHECK-NEXT: [[STRADDR:%[0-9]+]] = struct_element_addr [[TMPSTRUCT]] : $*AddressOnlyStruct<T>, #AddressOnlyStruct.str
+ // CHECK-NEXT: [[STRVAL:%[0-9]+]] = load [copy] [[STRADDR]]
+ // CHECK-NEXT: destroy_addr [[TMPSTRUCT]]
+ // CHECK-NEXT: dealloc_stack [[TMPSTRUCT]]
+ // CHECK: return [[STRVAL]]
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}testAddressOnlyStructElt
+func testAddressOnlyStructElt<T>(_ a : T) -> T {
+ return produceAddressOnlyStruct(a).elt
+ // CHECK: bb0([[ARG0:%.*]] : @trivial $*T, [[ARG1:%.*]] : @trivial $*T):
+ // CHECK: [[TMPSTRUCT:%[0-9]+]] = alloc_stack $AddressOnlyStruct<T>
+ // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
+ // CHECK: apply [[PRODFN]]<T>([[TMPSTRUCT]], [[ARG1]])
+ // CHECK-NEXT: [[ELTADDR:%[0-9]+]] = struct_element_addr [[TMPSTRUCT]] : $*AddressOnlyStruct<T>, #AddressOnlyStruct.elt
+ // CHECK-NEXT: copy_addr [[ELTADDR]] to [initialization] %0 : $*T
+ // CHECK-NEXT: destroy_addr [[TMPSTRUCT]]
+}
+
+
+
+// rdar://15717123 - let decls of address-only type.
+
+// CHECK-LABEL: sil hidden @{{.*}}testAddressOnlyLet
+func testAddressOnlyLet<T>(_ a : T) {
+ let x = produceAddressOnlyStruct(a)
+}
+
+
+func produceSubscriptableRValue() -> [String] {}
+
+// CHECK-LABEL: sil hidden @{{.*}}subscriptRValue
+func subscriptRValue() {
+ var a = produceSubscriptableRValue()[0]
+}
+
+
+struct GetOnlySubscriptStruct {
+ // get-only subscript
+ subscript (i : Int) -> Int { get {} }
+}
+
+
+// CHECK-LABEL: sil hidden @{{.*}}testGetOnlySubscript
+func testGetOnlySubscript(_ x : GetOnlySubscriptStruct, idx : Int) -> Int {
+ return x[idx]
+
+ // CHECK: [[SUBFN:%[0-9]+]] = function_ref @{{.*}}i
+ // CHECK-NEXT: [[CALL:%[0-9]+]] = apply [[SUBFN]](
+ // CHECK: return [[CALL]]
+}
+
+// Address-only let's get captured by box.
+extension Optional {
+ func getLV() -> Int { }
+}
+struct CloseOverAddressOnlyConstant<T> {
+ func isError() {
+ let AOV: T?
+ takeClosure({ AOV.getLV() })
+ }
+
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}callThroughLet
+func callThroughLet(_ predicate: @escaping (Int, Int) -> Bool) {
+ let p = predicate
+ if p(1, 2) {
+ }
+}
+
+
+// Verify that we can emit address-only rvalues directly into the result slot in
+// chained calls.
+struct GenericTestStruct<T> {
+ func pass_address_only_rvalue_result(_ i: Int) -> T {
+ return self[i]
+ }
+ subscript (i : Int) -> T {
+ get {}
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}pass_address_only_rvalue_result
+// CHECK: bb0(%0 : @trivial $*T,
+// CHECK: [[FN:%[0-9]+]] = function_ref @{{.*}}GenericTestStructV{{.*}}ig
+// CHECK: apply [[FN]]<T>(%0,
+
+
+struct NonMutableSubscriptable {
+ subscript(x : Int) -> Int {
+ get {}
+ nonmutating
+ set {}
+ }
+}
+
+func produceNMSubscriptableRValue() -> NonMutableSubscriptable {}
+
+
+// CHECK-LABEL: sil hidden @{{.*}}test_nm_subscript_get
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: [[FR1:%[0-9]+]] = function_ref @{{.*}}produceNMSubscriptableRValue
+// CHECK-NEXT: [[RES:%[0-9]+]] = apply [[FR1]]()
+// CHECK: [[GETFN:%[0-9]+]] = function_ref @$S9let_decls23NonMutableSubscriptableV{{[_0-9a-zA-Z]*}}ig
+// CHECK-NEXT: [[RES2:%[0-9]+]] = apply [[GETFN]](%0, [[RES]])
+// CHECK-NEXT: return [[RES2]]
+func test_nm_subscript_get(_ a : Int) -> Int {
+ return produceNMSubscriptableRValue()[a]
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}test_nm_subscript_set
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: [[FR1:%[0-9]+]] = function_ref @{{.*}}produceNMSubscriptableRValue
+// CHECK-NEXT: [[RES:%[0-9]+]] = apply [[FR1]]()
+// CHECK: [[SETFN:%[0-9]+]] = function_ref @$S9let_decls23NonMutableSubscriptableV{{[_0-9a-zA-Z]*}}is
+// CHECK-NEXT: [[RES2:%[0-9]+]] = apply [[SETFN]](%0, %0, [[RES]])
+func test_nm_subscript_set(_ a : Int) {
+ produceNMSubscriptableRValue()[a] = a
+}
+
+struct WeirdPropertyTest {
+ // This property has a mutating getter and !mutating setter.
+ var p : Int {
+ mutating
+ get {}
+ nonmutating
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}test_weird_property
+func test_weird_property(_ v : WeirdPropertyTest, i : Int) -> Int {
+ var v = v
+ // CHECK: [[VBOX:%[0-9]+]] = alloc_box ${ var WeirdPropertyTest }
+ // CHECK: [[PB:%.*]] = project_box [[VBOX]]
+ // CHECK: store %0 to [trivial] [[PB]]
+
+ // The setter isn't mutating, so we need to load the box.
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: [[VVAL:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[SETFN:%[0-9]+]] = function_ref @$S9let_decls17WeirdPropertyTestV1pSivs
+ // CHECK: apply [[SETFN]](%1, [[VVAL]])
+ v.p = i
+
+ // The getter is mutating, so it takes the box address.
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[GETFN:%[0-9]+]] = function_ref @$S9let_decls17WeirdPropertyTestV1pSivg
+ // CHECK-NEXT: [[RES:%[0-9]+]] = apply [[GETFN]]([[WRITE]])
+ // CHECK: return [[RES]]
+ return v.p
+}
+
+
+// CHECK-LABEL: sil hidden @{{.*}}generic_identity
+// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $*T):
+// CHECK-NEXT: debug_value_addr %1 : $*T
+// CHECK-NEXT: copy_addr %1 to [initialization] %0 : $*T
+// CHECK-NOT: destroy_addr %1
+// CHECK: } // end sil function '{{.*}}generic_identity{{.*}}'
+func generic_identity<T>(_ a : T) -> T {
+ // Should be a single copy_addr, with no temporary.
+ return a
+}
+
+struct StaticLetMember {
+ static let x = 5
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}testStaticLetMember
+func testStaticLetMember() -> Int {
+
+ // CHECK: function_ref @{{.*}}StaticLetMemberV1xSi
+ // CHECK: load {{.*}} : $*Int
+ // CHECK-NEXT: return
+ return StaticLetMember.x
+}
+
+protocol SimpleProtocol {
+ func doSomethingGreat()
+}
+
+// Verify that no temporaries+copies are produced when calling non-@mutable
+// methods on protocol and archetypes calls.
+
+// CHECK-LABEL: sil hidden @{{.*}}testLetProtocolBases
+// CHECK: bb0(%0 : @trivial $*SimpleProtocol):
+func testLetProtocolBases(_ p : SimpleProtocol) {
+ // CHECK-NEXT: debug_value_addr
+ // CHECK-NEXT: open_existential_addr
+ // CHECK-NEXT: witness_method
+ // CHECK-NEXT: apply
+ p.doSomethingGreat()
+
+ // CHECK-NEXT: open_existential_addr
+ // CHECK-NEXT: witness_method
+ // CHECK-NEXT: apply
+ p.doSomethingGreat()
+
+ // CHECK-NOT: destroy_addr %0
+ // CHECK-NEXT: tuple
+ // CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}testLetArchetypeBases
+// CHECK: bb0(%0 : @trivial $*T):
+func testLetArchetypeBases<T : SimpleProtocol>(_ p : T) {
+ // CHECK-NEXT: debug_value_addr
+ // CHECK-NEXT: witness_method $T
+ // CHECK-NEXT: apply
+ p.doSomethingGreat()
+ // CHECK-NEXT: witness_method $T
+ // CHECK-NEXT: apply
+ p.doSomethingGreat()
+
+ // CHECK-NOT: destroy_addr %0
+ // CHECK-NEXT: tuple
+ // CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}testDebugValue
+// CHECK: bb0(%0 : @trivial $Int, %1 : @trivial $*SimpleProtocol):
+// CHECK-NEXT: debug_value %0 : $Int, let, name "a"
+// CHECK-NEXT: debug_value_addr %1 : $*SimpleProtocol, let, name "b"
+func testDebugValue(_ a : Int, b : SimpleProtocol) -> Int {
+
+ // CHECK-NEXT: debug_value %0 : $Int, let, name "x"
+ let x = a
+
+ // CHECK: apply
+ b.doSomethingGreat()
+
+ // CHECK-NOT: destroy_addr
+
+ // CHECK: return %0
+ return x
+}
+
+
+// CHECK-LABEL: sil hidden @{{.*}}testAddressOnlyTupleArgument
+func testAddressOnlyTupleArgument(_ bounds: (start: SimpleProtocol, pastEnd: Int)) {
+// CHECK: bb0(%0 : @trivial $*SimpleProtocol, %1 : @trivial $Int):
+// CHECK-NEXT: %2 = alloc_stack $(start: SimpleProtocol, pastEnd: Int), let, name "bounds"
+// CHECK-NEXT: %3 = tuple_element_addr %2 : $*(start: SimpleProtocol, pastEnd: Int), 0
+// CHECK-NEXT: copy_addr %0 to [initialization] %3 : $*SimpleProtocol
+// CHECK-NEXT: %5 = tuple_element_addr %2 : $*(start: SimpleProtocol, pastEnd: Int), 1
+// CHECK-NEXT: store %1 to [trivial] %5 : $*Int
+// CHECK-NEXT: debug_value_addr %2
+// CHECK-NEXT: destroy_addr %2 : $*(start: SimpleProtocol, pastEnd: Int)
+// CHECK-NEXT: dealloc_stack %2 : $*(start: SimpleProtocol, pastEnd: Int)
+}
+
+
+func address_only_let_closure<T>(_ x:T) -> T {
+ return { { x }() }()
+}
+
+struct GenericFunctionStruct<T, U> {
+ var f: (T) -> U
+}
+
+
+// CHECK-LABEL: sil hidden @{{.*}}member_ref_abstraction_change
+// CHECK: function_ref reabstraction thunk helper
+// CHECK: return
+func member_ref_abstraction_change(_ x: GenericFunctionStruct<Int, Int>) -> (Int) -> Int {
+ return x.f
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}call_auto_closure
+// CHECK: bb0([[CLOSURE:%.*]] : @trivial $@noescape @callee_guaranteed () -> Bool):
+// CHECK: apply [[CLOSURE]]() : $@noescape @callee_guaranteed () -> Bool
+// CHECK: } // end sil function '{{.*}}call_auto_closure{{.*}}'
+func call_auto_closure(x: @autoclosure () -> Bool) -> Bool {
+ return x() // Calls of autoclosures should be marked transparent.
+}
+
+
+class SomeClass {}
+
+struct AnotherStruct {
+ var i : Int
+ var c : SomeClass
+}
+
+struct StructMemberTest {
+ var c : SomeClass
+ var i = 42
+ var s : AnotherStruct
+ var t : (Int, AnotherStruct)
+
+ // rdar://15867140 - Accessing the int member here should not copy_value the
+ // whole struct.
+ func testIntMemberLoad() -> Int {
+ return i
+ }
+ // CHECK-LABEL: sil hidden @$S9let_decls16StructMemberTestV07testIntD4LoadSiyF : $@convention(method) (@guaranteed StructMemberTest)
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $StructMemberTest):
+ // CHECK: debug_value [[ARG]] : $StructMemberTest, let, name "self"
+ // CHECK: [[TRIVIAL_VALUE:%.*]] = struct_extract [[ARG]] : $StructMemberTest, #StructMemberTest.i
+ // CHECK-NOT: destroy_value [[ARG]] : $StructMemberTest
+ // CHECK-NOT: destroy_value [[BORROWED_ARG]] : $StructMemberTest
+ // CHECK: return [[TRIVIAL_VALUE]] : $Int
+
+ // Accessing the int member in s should not copy_value the whole struct.
+ func testRecursiveIntMemberLoad() -> Int {
+ return s.i
+ }
+ // CHECK-LABEL: sil hidden @$S9let_decls16StructMemberTestV016testRecursiveIntD4LoadSiyF : $@convention(method) (@guaranteed StructMemberTest)
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $StructMemberTest):
+ // CHECK: debug_value %0 : $StructMemberTest, let, name "self"
+ // CHECK: %2 = struct_extract %0 : $StructMemberTest, #StructMemberTest.s
+ // CHECK: %3 = struct_extract %2 : $AnotherStruct, #AnotherStruct.i
+ // CHECK-NOT: destroy_value %0 : $StructMemberTest
+ // CHECK: return %3 : $Int
+
+ func testTupleMemberLoad() -> Int {
+ return t.1.i
+ }
+ // CHECK-LABEL: sil hidden @$S9let_decls16StructMemberTestV09testTupleD4LoadSiyF : $@convention(method) (@guaranteed StructMemberTest)
+ // CHECK: bb0(%0 : @guaranteed $StructMemberTest):
+ // CHECK-NEXT: debug_value %0 : $StructMemberTest, let, name "self"
+ // CHECK-NEXT: [[T0:%.*]] = struct_extract %0 : $StructMemberTest, #StructMemberTest.t
+ // CHECK-NEXT: [[T1:%.*]] = tuple_extract [[T0]] : $(Int, AnotherStruct), 0
+ // CHECK-NEXT: [[T2:%.*]] = tuple_extract [[T0]] : $(Int, AnotherStruct), 1
+ // CHECK-NEXT: [[T3:%.*]] = struct_extract [[T2]] : $AnotherStruct, #AnotherStruct.i
+ // CHECK-NEXT: return [[T3]] : $Int
+
+}
+
+struct GenericStruct<T> {
+ var a : T
+ var b : Int
+
+ func getA() -> T {
+ return a
+ }
+ // CHECK-LABEL: sil hidden @{{.*}}GenericStructV4getA{{.*}} : $@convention(method) <T> (@in_guaranteed GenericStruct<T>) -> @out T
+ // CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $*GenericStruct<T>):
+ // CHECK-NEXT: debug_value_addr %1 : $*GenericStruct<T>, let, name "self"
+ // CHECK-NEXT: %3 = struct_element_addr %1 : $*GenericStruct<T>, #GenericStruct.a
+ // CHECK-NEXT: copy_addr %3 to [initialization] %0 : $*T
+ // CHECK-NEXT: %5 = tuple ()
+ // CHECK-NEXT: return %5 : $()
+
+ func getB() -> Int {
+ return b
+ }
+
+ // CHECK-LABEL: sil hidden @{{.*}}GenericStructV4getB{{.*}} : $@convention(method) <T> (@in_guaranteed GenericStruct<T>) -> Int
+ // CHECK: bb0([[SELF_ADDR:%.*]] : @trivial $*GenericStruct<T>):
+ // CHECK-NEXT: debug_value_addr [[SELF_ADDR]] : $*GenericStruct<T>, let, name "self"
+ // CHECK-NEXT: [[PROJ_ADDR:%.*]] = struct_element_addr [[SELF_ADDR]] : $*GenericStruct<T>, #GenericStruct.b
+ // CHECK-NEXT: [[PROJ_VAL:%.*]] = load [trivial] [[PROJ_ADDR]] : $*Int
+ // CHECK-NOT: destroy_addr [[SELF]] : $*GenericStruct<T>
+ // CHECK-NEXT: return [[PROJ_VAL]] : $Int
+}
+
+
+// rdar://15877337
+struct LetPropertyStruct {
+ let lp : Int
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}testLetPropertyAccessOnLValueBase
+// CHECK: bb0(%0 : @trivial $LetPropertyStruct):
+// CHECK: [[ABOX:%[0-9]+]] = alloc_box ${ var LetPropertyStruct }
+// CHECK: [[A:%[0-9]+]] = project_box [[ABOX]]
+// CHECK: store %0 to [trivial] [[A]] : $*LetPropertyStruct
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[A]]
+// CHECK: [[STRUCT:%[0-9]+]] = load [trivial] [[READ]] : $*LetPropertyStruct
+// CHECK: [[PROP:%[0-9]+]] = struct_extract [[STRUCT]] : $LetPropertyStruct, #LetPropertyStruct.lp
+// CHECK: destroy_value [[ABOX]] : ${ var LetPropertyStruct }
+// CHECK: return [[PROP]] : $Int
+func testLetPropertyAccessOnLValueBase(_ a : LetPropertyStruct) -> Int {
+ var a = a
+ return a.lp
+}
+
+
+var addressOnlyGetOnlyGlobalProperty : SimpleProtocol { get {} }
+
+// CHECK-LABEL: sil hidden @$S9let_decls018testAddressOnlyGetE14GlobalPropertyAA14SimpleProtocol_pyF
+// CHECK: bb0(%0 : @trivial $*SimpleProtocol):
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: %1 = function_ref @$S9let_decls014addressOnlyGetD14GlobalPropertyAA14SimpleProtocol_pvg
+// CHECK-NEXT: %2 = apply %1(%0) : $@convention(thin) () -> @out SimpleProtocol
+// CHECK-NEXT: %3 = tuple ()
+// CHECK-NEXT: return %3 : $()
+// CHECK-NEXT: }
+func testAddressOnlyGetOnlyGlobalProperty() -> SimpleProtocol {
+ return addressOnlyGetOnlyGlobalProperty
+}
+
+
+// rdar://15962740
+struct LetDeclInStruct {
+ let immutable: Int
+ init() {
+ immutable = 1
+ }
+}
+
+// rdar://19854166 - Swift 1.2 uninitialized constant causes crash
+// The destroy_addr for a let stack temporary should be generated against
+// mark_uninitialized instruction, so DI will see it.
+func test_unassigned_let_constant() {
+ let string : String
+}
+// CHECK: [[S:%[0-9]+]] = alloc_stack $String, let, name "string"
+// CHECK-NEXT: [[MUI:%[0-9]+]] = mark_uninitialized [var] [[S]] : $*String
+// CHECK-NEXT: destroy_addr [[MUI]] : $*String
+// CHECK-NEXT: dealloc_stack [[S]] : $*String
+
diff --git a/test/SILGen/plus_zero_lifetime.swift b/test/SILGen/plus_zero_lifetime.swift
new file mode 100644
index 0000000..f5917ab
--- /dev/null
+++ b/test/SILGen/plus_zero_lifetime.swift
@@ -0,0 +1,812 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-silgen -primary-file %s | %FileCheck %s
+
+struct Buh<T> {
+ var x: Int {
+ get {}
+ set {}
+ }
+}
+
+class Ref {
+ init() { }
+}
+struct Val {
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime13local_valtypeyyF
+func local_valtype() {
+ var b: Val
+ // CHECK: [[B:%[0-9]+]] = alloc_box ${ var Val }
+ // CHECK: [[MARKED_B:%.*]] = mark_uninitialized [var] [[B]]
+ // CHECK: destroy_value [[MARKED_B]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime20local_valtype_branch{{[_0-9a-zA-Z]*}}F
+func local_valtype_branch(_ a: Bool) {
+ var a = a
+ // CHECK: [[A:%[0-9]+]] = alloc_box ${ var Bool }
+
+ if a { return }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: br [[EPILOG:bb[0-9]+]]
+
+ var x:Int
+ // CHECK: [[X:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[MARKED_X:%.*]] = mark_uninitialized [var] [[X]]
+
+ if a { return }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_X]]
+ // CHECK: br [[EPILOG]]
+
+ while a {
+ // CHECK: cond_br
+ if a { break }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK-NOT: destroy_value [[X]]
+ // CHECK: br
+
+ if a { return }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_X]]
+ // CHECK: br [[EPILOG]]
+
+ var y:Int
+ // CHECK: [[Y:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[MARKED_Y:%.*]] = mark_uninitialized [var] [[Y]]
+
+ if a { break }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_Y]]
+ // CHECK-NOT: destroy_value [[MARKED_X]]
+ // CHECK-NOT: destroy_value [[A]]
+ // CHECK: br
+
+ if a { return }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_Y]]
+ // CHECK: destroy_value [[MARKED_X]]
+ // CHECK: br [[EPILOG]]
+
+ if true {
+ var z:Int
+ // CHECK: [[Z:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[MARKED_Z:%.*]] = mark_uninitialized [var] [[Z]]
+
+ if a { break }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_Z]]
+ // CHECK: destroy_value [[MARKED_Y]]
+ // CHECK-NOT: destroy_value [[MARKED_X]]
+ // CHECK-NOT: destroy_value [[A]]
+ // CHECK: br
+
+ if a { return }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_Z]]
+ // CHECK: destroy_value [[MARKED_Y]]
+ // CHECK: destroy_value [[MARKED_X]]
+ // CHECK: br [[EPILOG]]
+
+ // CHECK: destroy_value [[MARKED_Z]]
+ }
+ if a { break }
+ // CHECK: cond_br
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_Y]]
+ // CHECK-NOT: destroy_value [[MARKED_X]]
+ // CHECK-NOT: destroy_value [[A]]
+ // CHECK: br
+
+ // CHECK: {{bb.*:}}
+ // CHECK: destroy_value [[MARKED_Y]]
+ // CHECK: br
+ }
+ // CHECK: destroy_value [[MARKED_X]]
+ // CHECK: [[EPILOG]]:
+ // CHECK: return
+}
+
+func reftype_func() -> Ref {}
+func reftype_func_with_arg(_ x: Ref) -> Ref {}
+
+// CHECK-LABEL: sil hidden @$S8lifetime14reftype_returnAA3RefCyF
+func reftype_return() -> Ref {
+ return reftype_func()
+ // CHECK: [[RF:%[0-9]+]] = function_ref @$S8lifetime12reftype_funcAA3RefCyF : $@convention(thin) () -> @owned Ref
+ // CHECK-NOT: destroy_value
+ // CHECK: [[RET:%[0-9]+]] = apply [[RF]]()
+ // CHECK-NOT: destroy_value
+ // CHECK: return [[RET]]
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime11reftype_argyyAA3RefCF : $@convention(thin) (@guaranteed Ref) -> () {
+// CHECK: bb0([[A:%[0-9]+]] : $Ref):
+// CHECK: [[AADDR:%[0-9]+]] = alloc_box ${ var Ref }
+// CHECK: [[PA:%[0-9]+]] = project_box [[AADDR]]
+// CHECK: [[A_COPY:%.*]] = copy_value [[A]]
+// CHECK: store [[A_COPY]] to [init] [[PA]]
+// CHECK: destroy_value [[AADDR]]
+// CHECK-NOT: destroy_value [[A]]
+// CHECK: return
+// CHECK: } // end sil function '$S8lifetime11reftype_argyyAA3RefCF'
+func reftype_arg(_ a: Ref) {
+ var a = a
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime26reftype_call_ignore_returnyyF
+func reftype_call_ignore_return() {
+ reftype_func()
+ // CHECK: = function_ref @$S8lifetime12reftype_funcAA3RefCyF : $@convention(thin) () -> @owned Ref
+ // CHECK-NEXT: [[R:%[0-9]+]] = apply
+ // CHECK: destroy_value [[R]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime27reftype_call_store_to_localyyF
+func reftype_call_store_to_local() {
+ var a = reftype_func()
+ // CHECK: [[A:%[0-9]+]] = alloc_box ${ var Ref }
+ // CHECK-NEXT: [[PB:%.*]] = project_box [[A]]
+ // CHECK: = function_ref @$S8lifetime12reftype_funcAA3RefCyF : $@convention(thin) () -> @owned Ref
+ // CHECK-NEXT: [[R:%[0-9]+]] = apply
+ // CHECK-NOT: copy_value [[R]]
+ // CHECK: store [[R]] to [init] [[PB]]
+ // CHECK-NOT: destroy_value [[R]]
+ // CHECK: destroy_value [[A]]
+ // CHECK-NOT: destroy_value [[R]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime16reftype_call_argyyF
+func reftype_call_arg() {
+ reftype_func_with_arg(reftype_func())
+ // CHECK: [[RF:%[0-9]+]] = function_ref @$S8lifetime12reftype_func{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[R1:%[0-9]+]] = apply [[RF]]
+ // CHECK: [[RFWA:%[0-9]+]] = function_ref @$S8lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[R2:%[0-9]+]] = apply [[RFWA]]([[R1]])
+ // CHECK: destroy_value [[R2]]
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime21reftype_call_with_arg{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[A1:%[0-9]+]] : $Ref):
+// CHECK: [[AADDR:%[0-9]+]] = alloc_box ${ var Ref }
+// CHECK: [[PB:%.*]] = project_box [[AADDR]]
+// CHECK: [[A1_COPY:%.*]] = copy_value [[A1]]
+// CHECK: store [[A1_COPY]] to [init] [[PB]]
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+// CHECK: [[A2:%[0-9]+]] = load [copy] [[READ]]
+// CHECK: [[RFWA:%[0-9]+]] = function_ref @$S8lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
+// CHECK: [[RESULT:%.*]] = apply [[RFWA]]([[A2]])
+// CHECK: destroy_value [[RESULT]]
+// CHECK: destroy_value [[AADDR]]
+// CHECK-NOT: destroy_value [[A1]]
+// CHECK: return
+func reftype_call_with_arg(_ a: Ref) {
+ var a = a
+
+ reftype_func_with_arg(a)
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime16reftype_reassign{{[_0-9a-zA-Z]*}}F
+func reftype_reassign(_ a: inout Ref, b: Ref) {
+ var b = b
+ // CHECK: bb0([[AADDR:%[0-9]+]] : $*Ref, [[B1:%[0-9]+]] : $Ref):
+ // CHECK: [[BADDR:%[0-9]+]] = alloc_box ${ var Ref }
+ // CHECK: [[PBB:%.*]] = project_box [[BADDR]]
+ a = b
+ // CHECK: destroy_value
+
+ // CHECK: return
+}
+
+func tuple_with_ref_elements() -> (Val, (Ref, Val), Ref) {}
+
+// CHECK-LABEL: sil hidden @$S8lifetime28tuple_with_ref_ignore_returnyyF
+func tuple_with_ref_ignore_return() {
+ tuple_with_ref_elements()
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S8lifetime23tuple_with_ref_elementsAA3ValV_AA3RefC_ADtAFtyF
+ // CHECK: [[TUPLE:%[0-9]+]] = apply [[FUNC]]
+ // CHECK: [[BORROWED_TUPLE:%.*]] = begin_borrow [[TUPLE]]
+ // CHECK: [[T0:%[0-9]+]] = tuple_extract [[BORROWED_TUPLE]] : {{.*}}, 0
+ // CHECK: [[T1_0:%[0-9]+]] = tuple_extract [[BORROWED_TUPLE]] : {{.*}}, 1
+ // CHECK: [[T1_0_COPY:%.*]] = copy_value [[T1_0]]
+ // CHECK: [[T1_1:%[0-9]+]] = tuple_extract [[BORROWED_TUPLE]] : {{.*}}, 2
+ // CHECK: [[T2:%[0-9]+]] = tuple_extract [[BORROWED_TUPLE]] : {{.*}}, 3
+ // CHECK: [[T2_COPY:%.*]] = copy_value [[T2]]
+ // CHECK: end_borrow [[BORROWED_TUPLE]] from [[TUPLE]]
+ // CHECK: destroy_value [[TUPLE]]
+ // CHECK: destroy_value [[T2_COPY]]
+ // CHECK: destroy_value [[T1_0_COPY]]
+ // CHECK: return
+}
+
+struct Aleph {
+ var a:Ref
+ var b:Val
+
+ // -- loadable value constructor:
+ // CHECK-LABEL: sil hidden @$S8lifetime5AlephV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned Ref, Val, @thin Aleph.Type) -> @owned Aleph
+ // CHECK: bb0([[A:%.*]] : $Ref, [[B:%.*]] : $Val, {{%.*}} : $@thin Aleph.Type):
+ // CHECK-NEXT: [[RET:%.*]] = struct $Aleph ([[A]] : {{.*}}, [[B]] : {{.*}})
+ // CHECK-NEXT: return [[RET]]
+}
+
+struct Beth {
+ var a:Val
+ var b:Aleph
+ var c:Ref
+
+ func gimel() {}
+}
+
+protocol Unloadable {}
+
+struct Daleth {
+ var a:Aleph
+ var b:Beth
+ var c:Unloadable
+
+ // -- address-only value constructor:
+ // CHECK-LABEL: sil hidden @$S8lifetime6DalethV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned Aleph, @owned Beth, @in Unloadable, @thin Daleth.Type) -> @out Daleth {
+ // CHECK: bb0([[THIS:%.*]] : $*Daleth, [[A:%.*]] : $Aleph, [[B:%.*]] : $Beth, [[C:%.*]] : $*Unloadable, {{%.*}} : $@thin Daleth.Type):
+ // CHECK-NEXT: [[A_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Daleth, #Daleth.a
+ // CHECK-NEXT: store [[A]] to [init] [[A_ADDR]]
+ // CHECK-NEXT: [[B_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Daleth, #Daleth.b
+ // CHECK-NEXT: store [[B]] to [init] [[B_ADDR]]
+ // CHECK-NEXT: [[C_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Daleth, #Daleth.c
+ // CHECK-NEXT: copy_addr [take] [[C]] to [initialization] [[C_ADDR]]
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+class He {
+
+ // -- default allocator:
+ // CHECK-LABEL: sil hidden @$S8lifetime2HeC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick He.Type) -> @owned He {
+ // CHECK: bb0({{%.*}} : $@thick He.Type):
+ // CHECK-NEXT: [[THIS:%.*]] = alloc_ref $He
+ // CHECK-NEXT: // function_ref lifetime.He.init
+ // CHECK-NEXT: [[INIT:%.*]] = function_ref @$S8lifetime2HeC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (@owned He) -> @owned He
+ // CHECK-NEXT: [[THIS1:%.*]] = apply [[INIT]]([[THIS]])
+ // CHECK-NEXT: return [[THIS1]]
+ // CHECK-NEXT: }
+
+ // -- default initializer:
+ // CHECK-LABEL: sil hidden @$S8lifetime2HeC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (@owned He) -> @owned He {
+ // CHECK: bb0([[SELF:%.*]] : $He):
+ // CHECK-NEXT: debug_value
+ // CHECK-NEXT: [[UNINITIALIZED_SELF:%.*]] = mark_uninitialized [rootself] [[SELF]]
+ // CHECK-NEXT: [[UNINITIALIZED_SELF_COPY:%.*]] = copy_value [[UNINITIALIZED_SELF]]
+ // CHECK-NEXT: destroy_value [[UNINITIALIZED_SELF]]
+ // CHECK-NEXT: return [[UNINITIALIZED_SELF_COPY]]
+ // CHECK: } // end sil function '$S8lifetime2HeC{{[_0-9a-zA-Z]*}}fc'
+
+ init() { }
+}
+
+struct Waw {
+ var a:(Ref, Val)
+ var b:Val
+
+ // -- loadable value initializer with tuple destructuring:
+ // CHECK-LABEL: sil hidden @$S8lifetime3WawV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned Ref, Val, Val, @thin Waw.Type) -> @owned Waw
+ // CHECK: bb0([[A0:%.*]] : $Ref, [[A1:%.*]] : $Val, [[B:%.*]] : $Val, {{%.*}} : $@thin Waw.Type):
+ // CHECK-NEXT: [[A:%.*]] = tuple ([[A0]] : {{.*}}, [[A1]] : {{.*}})
+ // CHECK-NEXT: [[RET:%.*]] = struct $Waw ([[A]] : {{.*}}, [[B]] : {{.*}})
+ // CHECK-NEXT: return [[RET]]
+}
+
+struct Zayin {
+ var a:(Unloadable, Val)
+ var b:Unloadable
+
+ // -- address-only value initializer with tuple destructuring:
+ // CHECK-LABEL: sil hidden @$S8lifetime5ZayinV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in Unloadable, Val, @in Unloadable, @thin Zayin.Type) -> @out Zayin
+ // CHECK: bb0([[THIS:%.*]] : $*Zayin, [[A0:%.*]] : $*Unloadable, [[A1:%.*]] : $Val, [[B:%.*]] : $*Unloadable, {{%.*}} : $@thin Zayin.Type):
+ // CHECK-NEXT: [[THIS_A_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Zayin, #Zayin.a
+ // CHECK-NEXT: [[THIS_A0_ADDR:%.*]] = tuple_element_addr [[THIS_A_ADDR]] : {{.*}}, 0
+ // CHECK-NEXT: [[THIS_A1_ADDR:%.*]] = tuple_element_addr [[THIS_A_ADDR]] : {{.*}}, 1
+ // CHECK-NEXT: copy_addr [take] [[A0]] to [initialization] [[THIS_A0_ADDR]]
+ // CHECK-NEXT: store [[A1]] to [trivial] [[THIS_A1_ADDR]]
+ // CHECK-NEXT: [[THIS_B_ADDR:%.*]] = struct_element_addr [[THIS]] : $*Zayin, #Zayin.b
+ // CHECK-NEXT: copy_addr [take] [[B]] to [initialization] [[THIS_B_ADDR]]
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+func fragile_struct_with_ref_elements() -> Beth {}
+
+// CHECK-LABEL: sil hidden @$S8lifetime29struct_with_ref_ignore_returnyyF
+func struct_with_ref_ignore_return() {
+ fragile_struct_with_ref_elements()
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S8lifetime32fragile_struct_with_ref_elementsAA4BethVyF
+ // CHECK: [[STRUCT:%[0-9]+]] = apply [[FUNC]]
+ // CHECK: destroy_value [[STRUCT]] : $Beth
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime28struct_with_ref_materializedyyF
+func struct_with_ref_materialized() {
+ fragile_struct_with_ref_elements().gimel()
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S8lifetime32fragile_struct_with_ref_elementsAA4BethVyF
+ // CHECK: [[STRUCT:%[0-9]+]] = apply [[FUNC]]
+ // CHECK: [[METHOD:%[0-9]+]] = function_ref @$S8lifetime4BethV5gimel{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[METHOD]]([[STRUCT]])
+}
+
+class RefWithProp {
+ var int_prop: Int { get {} set {} }
+ var aleph_prop: Aleph { get {} set {} }
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime015logical_lvalue_A0yyAA11RefWithPropC_SiAA3ValVtF : $@convention(thin) (@guaranteed RefWithProp, Int, Val) -> () {
+func logical_lvalue_lifetime(_ r: RefWithProp, _ i: Int, _ v: Val) {
+ var r = r
+ var i = i
+ var v = v
+ // CHECK: [[RADDR:%[0-9]+]] = alloc_box ${ var RefWithProp }
+ // CHECK: [[PR:%[0-9]+]] = project_box [[RADDR]]
+ // CHECK: [[IADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PI:%[0-9]+]] = project_box [[IADDR]]
+ // CHECK: store %1 to [trivial] [[PI]]
+ // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
+ // CHECK: [[PV:%[0-9]+]] = project_box [[VADDR]]
+
+ // -- Reference types need to be copy_valued as property method args.
+ r.int_prop = i
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PR]]
+ // CHECK: [[R1:%[0-9]+]] = load [copy] [[READ]]
+ // CHECK: [[SETTER_METHOD:%[0-9]+]] = class_method {{.*}} : $RefWithProp, #RefWithProp.int_prop!setter.1 : (RefWithProp) -> (Int) -> (), $@convention(method) (Int, @guaranteed RefWithProp) -> ()
+ // CHECK: apply [[SETTER_METHOD]]({{.*}}, [[R1]])
+ // CHECK: destroy_value [[R1]]
+
+ r.aleph_prop.b = v
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PR]]
+ // CHECK: [[R2:%[0-9]+]] = load [copy] [[READ]]
+ // CHECK: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+ // CHECK: [[ALEPH_PROP_TEMP:%[0-9]+]] = alloc_stack $Aleph
+ // CHECK: [[BORROWED_R2:%.*]] = begin_borrow [[R2]]
+ // CHECK: [[T0:%.*]] = address_to_pointer [[ALEPH_PROP_TEMP]]
+ // CHECK: [[MATERIALIZE_METHOD:%[0-9]+]] = class_method [[BORROWED_R2]] : $RefWithProp, #RefWithProp.aleph_prop!materializeForSet.1 :
+ // CHECK: [[MATERIALIZE:%.*]] = apply [[MATERIALIZE_METHOD]]([[T0]], [[STORAGE]], [[BORROWED_R2]])
+ // CHECK: [[PTR:%.*]] = tuple_extract [[MATERIALIZE]] : {{.*}}, 0
+ // CHECK: [[OPTCALLBACK:%.*]] = tuple_extract [[MATERIALIZE]] : {{.*}}, 1
+ // CHECK: [[ADDR:%.*]] = pointer_to_address [[PTR]]
+ // CHECK: [[MARKED_ADDR:%.*]] = mark_dependence [[ADDR]] : $*Aleph on [[R2]]
+ // CHECK: {{.*}}([[CALLBACK_ADDR:%.*]] :
+ // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> ()
+ // CHECK: [[TEMP:%.*]] = alloc_stack $RefWithProp
+ // CHECK: store [[R2]] to [init] [[TEMP]]
+ // CHECK: apply [[CALLBACK]]({{.*}}, [[STORAGE]], [[TEMP]], {{%.*}})
+}
+
+func bar() -> Int {}
+
+class Foo<T> {
+ var x : Int
+ var y = (Int(), Ref())
+ var z : T
+ var w = Ref()
+
+ class func makeT() -> T {}
+
+ // Class initializer
+ init() {
+ // -- allocating entry point
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fC :
+ // CHECK: bb0([[METATYPE:%[0-9]+]] : $@thick Foo<T>.Type):
+ // CHECK: [[THIS:%[0-9]+]] = alloc_ref $Foo<T>
+ // CHECK: [[INIT_METHOD:%[0-9]+]] = function_ref @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: [[INIT_THIS:%[0-9]+]] = apply [[INIT_METHOD]]<{{.*}}>([[THIS]])
+ // CHECK: return [[INIT_THIS]]
+
+ // -- initializing entry point
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fc :
+ // CHECK: bb0([[THISIN:%[0-9]+]] : $Foo<T>):
+ // CHECK: [[THIS:%[0-9]+]] = mark_uninitialized
+
+ // -- initialization for y
+ // CHECK: [[Y_INIT:%[0-9]+]] = function_ref @$S8lifetime3FooC1ySi_AA3RefCtvpfi : $@convention(thin) <τ_0_0> () -> (Int, @owned Ref)
+ // CHECK: [[Y_VALUE:%[0-9]+]] = apply [[Y_INIT]]<T>()
+ // CHECK: [[BORROWED_Y_VALUE:%.*]] = begin_borrow [[Y_VALUE]]
+ // CHECK: [[Y_EXTRACTED_0:%.*]] = tuple_extract [[BORROWED_Y_VALUE]] : $(Int, Ref), 0
+ // CHECK: [[Y_EXTRACTED_1:%.*]] = tuple_extract [[BORROWED_Y_VALUE]] : $(Int, Ref), 1
+ // CHECK: [[COPIED_Y_EXTRACTED_1:%.*]] = copy_value [[Y_EXTRACTED_1]]
+ // CHECK: end_borrow [[BORROWED_Y_VALUE]] from [[Y_VALUE]]
+ // CHECK: destroy_value [[Y_VALUE]]
+ // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK: [[THIS_Y:%.*]] = ref_element_addr [[BORROWED_THIS]] : {{.*}}, #Foo.y
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[THIS_Y]] : $*(Int, Ref)
+ // CHECK: [[THIS_Y_0:%.*]] = tuple_element_addr [[WRITE]] : $*(Int, Ref), 0
+ // CHECK: assign [[Y_EXTRACTED_0]] to [[THIS_Y_0]]
+ // CHECK: [[THIS_Y_1:%.*]] = tuple_element_addr [[WRITE]] : $*(Int, Ref), 1
+ // CHECK: assign [[COPIED_Y_EXTRACTED_1]] to [[THIS_Y_1]]
+ // CHECK: end_access [[WRITE]] : $*(Int, Ref)
+ // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
+
+ // -- Initialization for w
+ // CHECK: [[Z_FUNC:%.*]] = function_ref @$S{{.*}}8lifetime3FooC1wAA3RefCvpfi : $@convention(thin) <τ_0_0> () -> @owned Ref
+ // CHECK: [[Z_RESULT:%.*]] = apply [[Z_FUNC]]<T>()
+ // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK: [[THIS_Z:%.*]] = ref_element_addr [[BORROWED_THIS]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[THIS_Z]] : $*Ref
+ // CHECK: assign [[Z_RESULT]] to [[WRITE]]
+ // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
+
+ // -- Initialization for x
+ // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK: [[THIS_X:%[0-9]+]] = ref_element_addr [[BORROWED_THIS]] : {{.*}}, #Foo.x
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[THIS_X]] : $*Int
+ // CHECK: assign {{.*}} to [[WRITE]]
+ // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
+
+ x = bar()
+
+ z = Foo<T>.makeT()
+ // CHECK: [[FOOMETA:%[0-9]+]] = metatype $@thick Foo<T>.Type
+ // CHECK: [[MAKET:%[0-9]+]] = class_method [[FOOMETA]] : {{.*}}, #Foo.makeT!1
+ // CHECK: ref_element_addr
+
+ // -- cleanup this lvalue and return this
+ // CHECK: [[THIS_RESULT:%.*]] = copy_value [[THIS]]
+ // -- TODO: This copy should be unnecessary.
+ // CHECK: destroy_value [[THIS]]
+ // CHECK: return [[THIS_RESULT]]
+
+ }
+
+ init(chi:Int) {
+ var chi = chi
+ z = Foo<T>.makeT()
+
+ // -- allocating entry point
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fC :
+ // CHECK: bb0([[CHI:%[0-9]+]] : $Int, [[METATYPE:%[0-9]+]] : $@thick Foo<T>.Type):
+ // CHECK: [[THIS:%[0-9]+]] = alloc_ref $Foo<T>
+ // CHECK: [[INIT_METHOD:%[0-9]+]] = function_ref @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: [[INIT_THIS:%[0-9]+]] = apply [[INIT_METHOD]]<{{.*}}>([[CHI]], [[THIS]])
+ // CHECK: return [[INIT_THIS]]
+
+ // -- initializing entry point
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooC3chiACyxGSi_tcfc : $@convention(method) <T> (Int, @owned Foo<T>) -> @owned Foo<T> {
+ // CHECK: bb0([[CHI:%[0-9]+]] : $Int, [[THISIN:%[0-9]+]] : $Foo<T>):
+ // CHECK: [[THIS:%[0-9]+]] = mark_uninitialized [rootself] [[THISIN]]
+
+ // -- First we initialize #Foo.y.
+ // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK: [[THIS_Y:%.*]] = ref_element_addr [[BORROWED_THIS]] : $Foo<T>, #Foo.y
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[THIS_Y]] : $*(Int, Ref)
+ // CHECK: [[THIS_Y_1:%.*]] = tuple_element_addr [[WRITE]] : $*(Int, Ref), 0
+ // CHECK: assign {{.*}} to [[THIS_Y_1]] : $*Int
+ // CHECK: [[THIS_Y_2:%.*]] = tuple_element_addr [[WRITE]] : $*(Int, Ref), 1
+ // CHECK: assign {{.*}} to [[THIS_Y_2]] : $*Ref
+ // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
+
+ // -- Then we create a box that we will use to perform a copy_addr into #Foo.x a bit later.
+ // CHECK: [[CHIADDR:%[0-9]+]] = alloc_box ${ var Int }, var, name "chi"
+ // CHECK: [[PCHI:%[0-9]+]] = project_box [[CHIADDR]]
+ // CHECK: store [[CHI]] to [trivial] [[PCHI]]
+
+ // -- Then we initialize #Foo.z
+ // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK: [[THIS_Z:%.*]] = ref_element_addr [[BORROWED_THIS]] : {{.*}}, #Foo.z
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[THIS_Z]] : $*T
+ // CHECK: copy_addr [take] {{.*}} to [[WRITE]]
+ // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
+
+ // -- Then initialize #Foo.x using the earlier stored value of CHI to THIS_Z.
+ x = chi
+ // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PCHI]]
+ // CHECK: [[X:%.*]] = load [trivial] [[READ]]
+ // CHECK: [[THIS_X:%[0-9]+]] = ref_element_addr [[BORROWED_THIS]] : {{.*}}, #Foo.x
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[THIS_X]] : $*Int
+ // CHECK: assign [[X]] to [[WRITE]]
+ // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
+
+ // -- cleanup chi
+ // CHECK: destroy_value [[CHIADDR]]
+
+ // -- Then begin the epilogue sequence
+ // CHECK: [[THIS_RETURN:%.*]] = copy_value [[THIS]]
+ // CHECK: destroy_value [[THIS]]
+ // CHECK: return [[THIS_RETURN]]
+ // CHECK: } // end sil function '$S8lifetime3FooC3chiACyxGSi_tcfc'
+ }
+
+ // -- allocating entry point
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fC :
+ // CHECK: [[INIT_METHOD:%[0-9]+]] = function_ref @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fc
+
+ // -- initializing entry point
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooC{{[_0-9a-zA-Z]*}}fc :
+
+ init<U:Intifiable>(chi:U) {
+ z = Foo<T>.makeT()
+
+ x = chi.intify()
+ }
+
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooCfd : $@convention(method) <T> (@guaranteed Foo<T>) -> @owned Builtin.NativeObject
+
+ deinit {
+ // CHECK: bb0([[THIS:%[0-9]+]] : $Foo<T>):
+ bar()
+ // CHECK: function_ref @$S8lifetime3barSiyF
+ // CHECK: apply
+
+ // -- don't need to destroy_value x because it's trivial
+ // CHECK-NOT: ref_element_addr [[THIS]] : {{.*}}, #Foo.x
+ // -- destroy_value y
+ // CHECK: [[YADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #Foo.y
+ // CHECK: destroy_addr [[YADDR]]
+ // -- destroy_value z
+ // CHECK: [[ZADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #Foo.z
+ // CHECK: destroy_addr [[ZADDR]]
+ // -- destroy_value w
+ // CHECK: [[WADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #Foo.w
+ // CHECK: destroy_addr [[WADDR]]
+ // -- return back this
+ // CHECK: [[PTR:%.*]] = unchecked_ref_cast [[THIS]] : $Foo<T> to $Builtin.NativeObject
+ // CHECK: [[PTR_OWNED:%.*]] = unchecked_ownership_conversion [[PTR]] : $Builtin.NativeObject, @guaranteed to @owned
+ // CHECK: return [[PTR_OWNED]]
+ // CHECK: } // end sil function '$S8lifetime3FooCfd'
+ }
+
+ // Deallocating destructor for Foo.
+ // CHECK-LABEL: sil hidden @$S8lifetime3FooCfD : $@convention(method) <T> (@owned Foo<T>) -> ()
+ // CHECK: bb0([[SELF:%[0-9]+]] : $Foo<T>):
+ // CHECK: [[DESTROYING_REF:%[0-9]+]] = function_ref @$S8lifetime3FooCfd : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
+ // CHECK-NEXT: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
+ // CHECK-NEXT: [[RESULT_SELF:%[0-9]+]] = apply [[DESTROYING_REF]]<T>([[BORROWED_SELF]]) : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
+ // CHECK-NEXT: end_lifetime [[SELF]]
+ // CHECK-NEXT: [[SELF:%[0-9]+]] = unchecked_ref_cast [[RESULT_SELF]] : $Builtin.NativeObject to $Foo<T>
+ // CHECK-NEXT: dealloc_ref [[SELF]] : $Foo<T>
+ // CHECK-NEXT: [[RESULT:%[0-9]+]] = tuple ()
+ // CHECK-NEXT: return [[RESULT]] : $()
+ // CHECK-NEXT: } // end sil function '$S8lifetime3FooCfD'
+
+}
+
+class FooSubclass<T> : Foo<T> {
+
+ // CHECK-LABEL: sil hidden @$S8lifetime11FooSubclassCfd : $@convention(method) <T> (@guaranteed FooSubclass<T>) -> @owned Builtin.NativeObject
+ // CHECK: bb0([[THIS:%[0-9]+]] : $FooSubclass<T>):
+ // -- base dtor
+ // CHECK: [[BASE:%[0-9]+]] = upcast [[THIS]] : ${{.*}} to $Foo<T>
+ // CHECK: [[BASE_DTOR:%[0-9]+]] = function_ref @$S8lifetime3FooCfd : $@convention(method) <τ_0_0> (@guaranteed Foo<τ_0_0>) -> @owned Builtin.NativeObject
+ // CHECK: [[PTR:%.*]] = apply [[BASE_DTOR]]<T>([[BASE]])
+ // CHECK: [[BORROWED_PTR:%.*]] = begin_borrow [[PTR]]
+ // CHECK: end_borrow [[BORROWED_PTR]] from [[PTR]]
+ // CHECK: return [[PTR]]
+
+
+ deinit {
+ bar()
+ }
+}
+
+class ImplicitDtor {
+ var x:Int
+ var y:(Int, Ref)
+ var w:Ref
+ init() { }
+
+ // CHECK-LABEL: sil hidden @$S8lifetime12ImplicitDtorCfd
+ // CHECK: bb0([[THIS:%[0-9]+]] : $ImplicitDtor):
+ // -- don't need to destroy_value x because it's trivial
+ // CHECK-NOT: ref_element_addr [[THIS]] : {{.*}}, #ImplicitDtor.x
+ // -- destroy_value y
+ // CHECK: [[YADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #ImplicitDtor.y
+ // CHECK: destroy_addr [[YADDR]]
+ // -- destroy_value w
+ // CHECK: [[WADDR:%[0-9]+]] = ref_element_addr [[THIS]] : {{.*}}, #ImplicitDtor.w
+ // CHECK: destroy_addr [[WADDR]]
+ // CHECK: return
+}
+
+class ImplicitDtorDerived<T> : ImplicitDtor {
+ var z:T
+
+ init(z : T) {
+ super.init()
+ self.z = z
+ }
+
+ // CHECK: sil hidden @$S8lifetime19ImplicitDtorDerivedCfd : $@convention(method) <T> (@guaranteed ImplicitDtorDerived<T>) -> @owned Builtin.NativeObject {
+ // CHECK: bb0([[THIS:%[0-9]+]] : $ImplicitDtorDerived<T>):
+ // -- base dtor
+ // CHECK: [[BASE:%[0-9]+]] = upcast [[THIS]] : ${{.*}} to $ImplicitDtor
+ // CHECK: [[BASE_DTOR:%[0-9]+]] = function_ref @$S8lifetime12ImplicitDtorCfd
+ // CHECK: [[PTR:%.*]] = apply [[BASE_DTOR]]([[BASE]])
+ // -- destroy_value z
+ // CHECK: [[BORROWED_PTR:%.*]] = begin_borrow [[PTR]]
+ // CHECK: [[CAST_BORROWED_PTR:%.*]] = unchecked_ref_cast [[BORROWED_PTR]] : $Builtin.NativeObject to $ImplicitDtorDerived<T>
+ // CHECK: [[ZADDR:%[0-9]+]] = ref_element_addr [[CAST_BORROWED_PTR]] : {{.*}}, #ImplicitDtorDerived.z
+ // CHECK: destroy_addr [[ZADDR]]
+ // CHECK: end_borrow [[BORROWED_PTR]] from [[PTR]]
+ // -- epilog
+ // CHECK-NOT: unchecked_ref_cast
+ // CHECK-NOT: unchecked_ownership_conversion
+ // CHECK: return [[PTR]]
+}
+
+class ImplicitDtorDerivedFromGeneric<T> : ImplicitDtorDerived<Int> {
+ init() { super.init(z: 5) }
+
+ // CHECK-LABEL: sil hidden @$S8lifetime30ImplicitDtorDerivedFromGenericC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: bb0([[THIS:%[0-9]+]] : $ImplicitDtorDerivedFromGeneric<T>):
+ // -- base dtor
+ // CHECK: [[BASE:%[0-9]+]] = upcast [[THIS]] : ${{.*}} to $ImplicitDtorDerived<Int>
+ // CHECK: [[BASE_DTOR:%[0-9]+]] = function_ref @$S8lifetime19ImplicitDtorDerivedCfd
+ // CHECK: [[PTR:%.*]] = apply [[BASE_DTOR]]<Int>([[BASE]])
+ // CHECK: return [[PTR]]
+}
+
+protocol Intifiable {
+ func intify() -> Int
+}
+
+struct Bar {
+ var x:Int
+
+ // Loadable struct initializer
+ // CHECK-LABEL: sil hidden @$S8lifetime3BarV{{[_0-9a-zA-Z]*}}fC
+ init() {
+ // CHECK: bb0([[METATYPE:%[0-9]+]] : $@thin Bar.Type):
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Bar }
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [rootself] [[SELF_BOX]]
+ // CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+
+ x = bar()
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]]
+ // CHECK: [[SELF_X:%[0-9]+]] = struct_element_addr [[WRITE]] : $*Bar, #Bar.x
+ // CHECK: assign {{.*}} to [[SELF_X]]
+
+ // -- load and return this
+ // CHECK: [[SELF_VAL:%[0-9]+]] = load [trivial] [[PB_BOX]]
+ // CHECK: destroy_value [[MARKED_SELF_BOX]]
+ // CHECK: return [[SELF_VAL]]
+ }
+
+ init<T:Intifiable>(xx:T) {
+ x = xx.intify()
+ }
+}
+
+struct Bas<T> {
+ var x:Int
+ var y:T
+
+ // Address-only struct initializer
+ // CHECK-LABEL: sil hidden @$S8lifetime3BasV{{[_0-9a-zA-Z]*}}fC
+ init(yy:T) {
+ // CHECK: bb0([[THISADDRPTR:%[0-9]+]] : $*Bas<T>, [[YYADDR:%[0-9]+]] : $*T, [[META:%[0-9]+]] : $@thin Bas<T>.Type):
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box $<τ_0_0> { var Bas<τ_0_0> } <T>
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [rootself] [[SELF_BOX]]
+ // CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+
+ x = bar()
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]]
+ // CHECK: [[SELF_X:%[0-9]+]] = struct_element_addr [[WRITE]] : $*Bas<T>, #Bas.x
+ // CHECK: assign {{.*}} to [[SELF_X]]
+
+ y = yy
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]]
+ // CHECK: [[SELF_Y:%[0-9]+]] = struct_element_addr [[WRITE]] : $*Bas<T>, #Bas.y
+ // CHECK: copy_addr {{.*}} to [[SELF_Y]]
+ // CHECK: destroy_value
+
+ // -- 'self' was emplaced into indirect return slot
+ // CHECK: return
+ }
+
+ init<U:Intifiable>(xx:U, yy:T) {
+ x = xx.intify()
+ y = yy
+ }
+}
+
+class B { init(y:Int) {} }
+class D : B {
+ // CHECK-LABEL: sil hidden @$S8lifetime1DC1x1yACSi_Sitcfc
+ // CHECK: bb0([[X:%[0-9]+]] : $Int, [[Y:%[0-9]+]] : $Int, [[SELF:%[0-9]+]] : $D):
+ init(x: Int, y: Int) {
+ var x = x
+ var y = y
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var D }
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [derivedself] [[SELF_BOX]]
+ // CHECK: [[PB_BOX:%[0-9]+]] = project_box [[MARKED_SELF_BOX]]
+ // CHECK: store [[SELF]] to [init] [[PB_BOX]]
+ // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PX:%[0-9]+]] = project_box [[XADDR]]
+ // CHECK: store [[X]] to [trivial] [[PX]]
+ // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PY:%[0-9]+]] = project_box [[YADDR]]
+ // CHECK: store [[Y]] to [trivial] [[PY]]
+
+ super.init(y: y)
+ // CHECK: [[THIS1:%[0-9]+]] = load [take] [[PB_BOX]]
+ // CHECK: [[THIS1_SUP:%[0-9]+]] = upcast [[THIS1]] : ${{.*}} to $B
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PY]]
+ // CHECK: [[Y:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[SUPER_CTOR:%[0-9]+]] = function_ref @$S8lifetime1BC1yACSi_tcfc : $@convention(method) (Int, @owned B) -> @owned B
+ // CHECK: [[THIS2_SUP:%[0-9]+]] = apply [[SUPER_CTOR]]([[Y]], [[THIS1_SUP]])
+ // CHECK: [[THIS2:%[0-9]+]] = unchecked_ref_cast [[THIS2_SUP]] : $B to $D
+ // CHECK: [[THIS1:%[0-9]+]] = load [copy] [[PB_BOX]]
+ // CHECK: destroy_value [[MARKED_SELF_BOX]]
+ }
+
+ func foo() {}
+}
+
+// CHECK-LABEL: sil hidden @$S8lifetime8downcast{{[_0-9a-zA-Z]*}}F
+func downcast(_ b: B) {
+ var b = b
+ // CHECK: [[BADDR:%[0-9]+]] = alloc_box ${ var B }
+ // CHECK: [[PB:%[0-9]+]] = project_box [[BADDR]]
+ (b as! D).foo()
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: [[B:%[0-9]+]] = load [copy] [[READ]]
+ // CHECK: [[D:%[0-9]+]] = unconditional_checked_cast [[B]] : {{.*}} to $D
+ // CHECK: apply {{.*}}([[D]])
+ // CHECK-NOT: destroy_value [[B]]
+ // CHECK: destroy_value [[D]]
+ // CHECK: destroy_value [[BADDR]]
+ // CHECK: return
+}
+
+func int(_ x: Int) {}
+func ref(_ x: Ref) {}
+
+func tuple() -> (Int, Ref) { return (1, Ref()) }
+
+func tuple_explosion() {
+ int(tuple().0)
+ // CHECK: [[F:%[0-9]+]] = function_ref @$S8lifetime5tupleSi_AA3RefCtyF
+ // CHECK: [[TUPLE:%[0-9]+]] = apply [[F]]()
+ // CHECK: [[BORROWED_TUPLE:%.*]] = begin_borrow [[TUPLE]]
+ // CHECK: [[T1:%[0-9]+]] = tuple_extract [[BORROWED_TUPLE]] : {{.*}}, 1
+ // CHECK: [[T1_COPY:%.*]] = copy_value [[T1]]
+ // CHECK: end_borrow [[BORROWED_TUPLE]] from [[TUPLE]]
+ // CHECK: destroy_value [[T1_COPY]]
+ // CHECK-NOT: tuple_extract [[TUPLE]] : {{.*}}, 1
+ // CHECK-NOT: destroy_value
+
+ ref(tuple().1)
+ // CHECK: [[F:%[0-9]+]] = function_ref @$S8lifetime5tupleSi_AA3RefCtyF
+ // CHECK: [[TUPLE:%[0-9]+]] = apply [[F]]()
+ // CHECK: [[BORROWED_TUPLE:%.*]] = begin_borrow [[TUPLE]]
+ // CHECK: [[T1:%[0-9]+]] = tuple_extract [[BORROWED_TUPLE]] : {{.*}}, 1
+ // CHECK: [[T1_COPY:%.*]] = copy_value [[T1]]
+ // CHECK: end_borrow [[BORROWED_TUPLE]] from [[TUPLE]]
+ // CHECK: destroy_value [[TUPLE]]
+ // CHECK-NOT: destroy_value [[T1]]
+ // CHECK-NOT: tuple_extract [[TUPLE]] : {{.*}}, 1
+ // CHECK-NOT: destroy_value [[TUPLE]]
+}
+
+class C {
+ var v = ""
+ // CHECK-LABEL: sil hidden @$S8lifetime1CC18ignored_assignment{{[_0-9a-zA-Z]*}}F
+ func ignored_assignment() {
+ // CHECK: [[STRING:%.*]] = alloc_stack $String
+ // CHECK: [[UNINIT:%.*]] = mark_uninitialized [var] [[STRING]]
+ // CHECK: assign {{%.*}} to [[UNINIT]]
+ // CHECK: destroy_addr [[UNINIT]]
+ _ = self.v
+ }
+}
diff --git a/test/SILGen/plus_zero_mangling.swift b/test/SILGen/plus_zero_mangling.swift
new file mode 100644
index 0000000..a0357ce
--- /dev/null
+++ b/test/SILGen/plus_zero_mangling.swift
@@ -0,0 +1,191 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import gizmo
+
+// Test mangling of Unicode identifiers.
+// These examples are from RFC 3492, which defines the Punycode encoding used
+// by name mangling.
+
+// CHECK-LABEL: sil hidden @$S8mangling0022egbpdajGbuEbxfgehfvwxnyyF
+func ليهمابتكلموشعربي؟() { }
+// CHECK-LABEL: sil hidden @$S8mangling0024ihqwcrbEcvIaIdqgAFGpqjyeyyF
+func 他们为什么不说中文() { }
+// CHECK-LABEL: sil hidden @$S8mangling0027ihqwctvzcJBfGFJdrssDxIboAybyyF
+func 他們爲什麽不說中文() { }
+// CHECK-LABEL: sil hidden @$S8mangling0030Proprostnemluvesky_uybCEdmaEBayyF
+func Pročprostěnemluvíčesky() { }
+
+// <rdar://problem/13757744> Variadic tuples need a different mangling from
+// non-variadic tuples.
+
+// CHECK-LABEL: sil hidden @$S8mangling9r137577441xySaySiG_tF
+func r13757744(x: [Int]) {}
+// CHECK-LABEL: sil hidden @$S8mangling9r137577441xySid_tF
+func r13757744(x: Int...) {}
+
+// <rdar://problem/13757750> Prefix, postfix, and infix operators need
+// distinct manglings.
+
+prefix operator +-
+postfix operator +-
+infix operator +-
+
+// CHECK-LABEL: sil hidden @$S8mangling2psopyyxlF
+prefix func +- <T>(a: T) {}
+// CHECK-LABEL: sil hidden @$S8mangling2psoPyyxlF
+postfix func +- <T>(a: T) {}
+
+// CHECK-LABEL: sil hidden @$S8mangling2psoiyyx_xtlF
+func +- <T>(a: T, b: T) {}
+
+// CHECK-LABEL: sil hidden @$S8mangling2psopyyx1a_x1bt_tlF
+prefix func +- <T>(_: (a: T, b: T)) {}
+// CHECK-LABEL: sil hidden @$S8mangling2psoPyyx1a_x1bt_tlF
+postfix func +- <T>(_: (a: T, b: T)) {}
+
+infix operator «+» {}
+
+// CHECK-LABEL: sil hidden @$S8mangling007p_qcaDcoiyS2i_SitF
+func «+»(a: Int, b: Int) -> Int { return a + b }
+
+protocol Foo {}
+protocol Bar {}
+
+// Ensure protocol list manglings are '_' terminated regardless of length
+// CHECK-LABEL: sil hidden @$S8mangling12any_protocolyyypF
+func any_protocol(_: Any) {}
+// CHECK-LABEL: sil hidden @$S8mangling12one_protocolyyAA3Foo_pF
+func one_protocol(_: Foo) {}
+// CHECK-LABEL: sil hidden @$S8mangling18one_protocol_twiceyyAA3Foo_p_AaC_ptF
+func one_protocol_twice(_: Foo, _: Foo) {}
+// CHECK-LABEL: sil hidden @$S8mangling12two_protocolyyAA3Bar_AA3FoopF
+func two_protocol(_: Foo & Bar) {}
+
+// Ensure archetype depths are mangled correctly.
+class Zim<T> {
+ // CHECK-LABEL: sil hidden @$S8mangling3ZimC4zangyyx_qd__tlF
+ func zang<U>(_: T, _: U) {}
+ // CHECK-LABEL: sil hidden @$S8mangling3ZimC4zungyyqd___xtlF
+ func zung<U>(_: U, _: T) {}
+}
+
+// Don't crash mangling single-protocol "composition" types.
+// CHECK-LABEL: sil hidden @$S8mangling27single_protocol_composition1xyAA3Foo_p_tF
+func single_protocol_composition(x: protocol<Foo>) {} // expected-warning {{'protocol<...>' composition syntax is deprecated; join the protocols using '&'}}
+
+// Clang-imported classes and protocols get mangled into a magic 'So' context
+// to make collisions into link errors. <rdar://problem/14221244>
+// CHECK-LABEL: sil hidden @$S8mangling28uses_objc_class_and_protocol1o1p2p2ySo8NSObjectC_So8NSAnsing_pSo14NSBetterAnsing_ptF
+func uses_objc_class_and_protocol(o: NSObject, p: NSAnsing, p2: BetterAnsing) {}
+
+// Clang-imported structs get mangled using their Clang module name.
+// FIXME: Temporarily mangles everything into the virtual module __C__
+// <rdar://problem/14221244>
+// CHECK-LABEL: sil hidden @$S8mangling17uses_clang_struct1rySo6NSRectV_tF
+func uses_clang_struct(r: NSRect) {}
+
+// CHECK-LABEL: sil hidden @$S8mangling14uses_optionals1xs7UnicodeO6ScalarVSgSiSg_tF
+func uses_optionals(x: Int?) -> UnicodeScalar? { return nil }
+
+enum GenericUnion<T> {
+ // CHECK-LABEL: sil shared [transparent] @$S8mangling12GenericUnionO3FooyACyxGSicAEmlF
+ case Foo(Int)
+}
+
+func instantiateGenericUnionConstructor<T>(_ t: T) {
+ _ = GenericUnion<T>.Foo
+}
+
+struct HasVarInit {
+ static var state = true && false
+}
+// CHECK-LABEL: // function_ref implicit closure #1 : @autoclosure () throws -> Swift.Bool in variable initialization expression of static mangling.HasVarInit.state : Swift.Bool
+// CHECK-NEXT: function_ref @$S8mangling10HasVarInitV5stateSbvpZfiSbyKXKfu_
+
+// auto_closures should not collide with the equivalent non-auto_closure
+// function type.
+
+// CHECK-LABEL: sil hidden @$S8mangling19autoClosureOverload1fySiyXK_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> () {
+func autoClosureOverload(f: @autoclosure () -> Int) {}
+// CHECK-LABEL: sil hidden @$S8mangling19autoClosureOverload1fySiyXE_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> () {
+func autoClosureOverload(f: () -> Int) {}
+
+// CHECK-LABEL: sil hidden @$S8mangling24autoClosureOverloadCallsyyF : $@convention(thin) () -> () {
+func autoClosureOverloadCalls() {
+ // CHECK: function_ref @$S8mangling19autoClosureOverload1fySiyXK_tF
+ autoClosureOverload(f: 1)
+ // CHECK: function_ref @$S8mangling19autoClosureOverload1fySiyXE_tF
+ autoClosureOverload {1}
+}
+
+// <rdar://problem/16079822> Associated type requirements need to appear in the
+// mangling.
+
+protocol AssocReqt {}
+
+protocol HasAssocType {
+ associatedtype Assoc
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling4fooAyyxAA12HasAssocTypeRzlF : $@convention(thin) <T where T : HasAssocType> (@in_guaranteed T) -> ()
+func fooA<T: HasAssocType>(_: T) {}
+// CHECK-LABEL: sil hidden @$S8mangling4fooByyxAA12HasAssocTypeRzAA0D4Reqt0D0RpzlF : $@convention(thin) <T where T : HasAssocType, T.Assoc : AssocReqt> (@in_guaranteed T) -> ()
+func fooB<T: HasAssocType>(_: T) where T.Assoc: AssocReqt {}
+
+// CHECK-LABEL: sil hidden @$S8mangling2qqoiyySi_SitF
+func ??(x: Int, y: Int) {}
+
+struct InstanceAndClassProperty {
+ var property: Int {
+ // CHECK-LABEL: sil hidden @$S8mangling24InstanceAndClassPropertyV8propertySivg
+ get { return 0 }
+ // CHECK-LABEL: sil hidden @$S8mangling24InstanceAndClassPropertyV8propertySivs
+ set {}
+ }
+ static var property: Int {
+ // CHECK-LABEL: sil hidden @$S8mangling24InstanceAndClassPropertyV8propertySivgZ
+ get { return 0 }
+ // CHECK-LABEL: sil hidden @$S8mangling24InstanceAndClassPropertyV8propertySivsZ
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling6curry1yyF : $@convention(thin) () -> ()
+func curry1() {
+
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling3barSiyKF : $@convention(thin) () -> (Int, @error Error)
+func bar() throws -> Int { return 0 }
+
+// CHECK-LABEL: sil hidden @$S8mangling12curry1ThrowsyyKF : $@convention(thin) () -> @error Error
+func curry1Throws() throws {
+
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling12curry2ThrowsyycyKF : $@convention(thin) () -> (@owned @callee_guaranteed () -> (), @error Error)
+func curry2Throws() throws -> () -> () {
+ return curry1
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling6curry3yyKcyF : $@convention(thin) () -> @owned @callee_guaranteed () -> @error Error
+func curry3() -> () throws -> () {
+ return curry1Throws
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling12curry3ThrowsyyKcyKF : $@convention(thin) () -> (@owned @callee_guaranteed () -> @error Error, @error Error)
+func curry3Throws() throws -> () throws -> () {
+ return curry1Throws
+}
+
+// CHECK-LABEL: sil hidden @$S8mangling14varargsVsArray3arr1nySid_SStF : $@convention(thin) (@guaranteed Array<Int>, @guaranteed String) -> ()
+func varargsVsArray(arr: Int..., n: String) { }
+
+// CHECK-LABEL: sil hidden @$S8mangling14varargsVsArray3arr1nySaySiG_SStF : $@convention(thin) (@guaranteed Array<Int>, @guaranteed String) -> ()
+func varargsVsArray(arr: [Int], n: String) { }
+
+// CHECK-LABEL: sil hidden @$S8mangling14varargsVsArray3arr1nySaySiGd_SStF : $@convention(thin) (@guaranteed Array<Array<Int>>, @guaranteed String) -> ()
+func varargsVsArray(arr: [Int]..., n: String) { }
diff --git a/test/SILGen/plus_zero_materializeForSet.swift b/test/SILGen/plus_zero_materializeForSet.swift
new file mode 100644
index 0000000..f742400a
--- /dev/null
+++ b/test/SILGen/plus_zero_materializeForSet.swift
@@ -0,0 +1,677 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enforce-exclusivity=unchecked %s | %FileCheck --check-prefix=UNCHECKED %s
+
+class Base {
+ var stored: Int = 0
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet4BaseC6storedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed Base) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $Base):
+// CHECK: [[T0:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.stored
+// CHECK: [[T1:%.*]] = address_to_pointer [[T0]] : $*Int to $Builtin.RawPointer
+// CHECK: [[T2:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some
+// CHECK: [[T3:%.*]] = tuple ([[T1]] : $Builtin.RawPointer, [[T2]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T3]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+
+// UNCHECKED-LABEL: sil hidden [transparent] @$S17materializeForSet4BaseC6storedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed Base) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// UNCHECKED: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $Base):
+// UNCHECKED: [[T0:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.stored
+// UNCHECKED: [[T1:%.*]] = address_to_pointer [[T0]] : $*Int to $Builtin.RawPointer
+// UNCHECKED: [[T2:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.none
+// UNCHECKED: [[T3:%.*]] = tuple ([[T1]] : $Builtin.RawPointer, [[T2]] : $Optional<Builtin.RawPointer>)
+// UNCHECKED: return [[T3]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// UNCHECKED: }
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet4BaseC8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Base, [[SELFTYPE:%.*]] : $@thick Base.Type):
+// CHECK: [[T0:%.*]] = load_borrow [[SELF]]
+// CHECK: [[T1:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T2:%.*]] = load [trivial] [[T1]] : $*Int
+// CHECK: [[SETTER:%.*]] = function_ref @$S17materializeForSet4BaseC8computedSivs
+// CHECK: apply [[SETTER]]([[T2]], [[T0]])
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet4BaseC8computedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed Base) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $Base):
+// CHECK: [[ADDR:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet4BaseC8computedSivg
+// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
+// CHECK: store [[T1]] to [trivial] [[ADDR]] : $*Int
+// CHECK: [[BUFFER:%.*]] = address_to_pointer [[ADDR]]
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet4BaseC8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> ()
+// CHECK: [[T2:%.*]] = thin_function_to_pointer [[T0]]
+// CHECK: [[T3:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T2]] : $Builtin.RawPointer
+// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[T3]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+
+ var computed: Int {
+ get { return 0 }
+ set(value) {}
+ }
+
+ var storedFunction: () -> Int = { 0 }
+ final var finalStoredFunction: () -> Int = { 0 }
+ var computedFunction: () -> Int {
+ get { return {0} }
+ set {}
+ }
+ static var staticFunction: () -> Int {
+ get { return {0} }
+ set {}
+ }
+}
+
+class Derived : Base {}
+
+protocol Abstractable {
+ associatedtype Result
+ var storedFunction: () -> Result { get set }
+ var finalStoredFunction: () -> Result { get set }
+ var computedFunction: () -> Result { get set }
+ static var staticFunction: () -> Result { get set }
+}
+
+// Validate that we thunk materializeForSet correctly when there's
+// an abstraction pattern present.
+
+extension Derived : Abstractable {}
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14storedFunction6ResultQzycvmytfU_TW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> ()
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
+// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegr_SiIegd_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out Int) -> Int
+// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[VALUE]])
+// CHECK-NEXT: [[FN:%.*]] = class_method [[SELF]] : $Base, #Base.storedFunction!setter.1 : (Base) -> (@escaping () -> Int) -> ()
+// CHECK-NEXT: apply [[FN]]([[NEWVALUE]], [[SELF]])
+// CHECK-NEXT: end_borrow [[T0]] from %2
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14storedFunction{{[_0-9a-zA-Z]*}}vmTW
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived):
+// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $@callee_guaranteed () -> Int
+// CHECK-NEXT: [[FN:%.*]] = class_method [[SELF]] : $Base, #Base.storedFunction!getter.1
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[SELF]])
+// CHECK-NEXT: store [[RESULT]] to [init] [[TEMP]]
+// CHECK-NEXT: [[RESULT:%.*]] = load [copy] [[TEMP]]
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegd_SiIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
+// CHECK-NEXT: [[T1:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[RESULT]])
+// CHECK-NEXT: destroy_addr [[TEMP]]
+// CHECK-NEXT: store [[T1]] to [init] [[RESULT_ADDR]]
+// CHECK-NEXT: [[RESULT_PTR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[T2:%.*]] = function_ref @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14storedFunction6ResultQzycvmytfU_TW
+// CHECK-NEXT: [[T3:%.*]] = thin_function_to_pointer [[T2]]
+// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T3]]
+// CHECK-NEXT: [[T4:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: dealloc_stack [[TEMP]]
+// CHECK-NEXT: end_borrow [[T0]] from %2
+// CHECK-NEXT: return [[T4]]
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP19finalStoredFunction6ResultQzycvmytfU_TW :
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
+// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegr_SiIegd_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out Int) -> Int
+// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[VALUE]])
+// CHECK-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
+// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: assign [[NEWVALUE]] to [[WRITE]]
+// CHECK-NEXT: end_access [[WRITE]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: end_borrow [[T0]] from %2
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// UNCHECKED-LABEL: sil private [transparent] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP19finalStoredFunction6ResultQzycvmytfU_TW :
+// UNCHECKED: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type):
+// UNCHECKED-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// UNCHECKED-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// UNCHECKED-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// UNCHECKED-NEXT: [[VALUE:%.*]] = load [take] [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int
+// UNCHECKED-NEXT: // function_ref
+// UNCHECKED-NEXT: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegr_SiIegd_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out Int) -> Int
+// UNCHECKED-NEXT: [[NEWVALUE:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[VALUE]])
+// UNCHECKED-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
+// UNCHECKED-NEXT: assign [[NEWVALUE]] to [[ADDR]]
+// UNCHECKED-NEXT: end_borrow [[T0]] from %2
+// UNCHECKED-NEXT: tuple ()
+// UNCHECKED-NEXT: return
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP19finalStoredFunction{{[_0-9a-zA-Z]*}}vmTW
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived):
+// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// CHECK-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[ADDR]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: [[RESULT:%.*]] = load [copy] [[READ]]
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegd_SiIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
+// CHECK-NEXT: [[T1:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[RESULT]])
+// CHECK-NEXT: end_access [[READ]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: store [[T1]] to [init] [[RESULT_ADDR]]
+// CHECK-NEXT: [[RESULT_PTR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[T2:%.*]] = function_ref @$S17materializeForSet7DerivedCAA12AbstractableA2aDP19finalStoredFunction6ResultQzycvmytfU_TW
+// CHECK-NEXT: [[T3:%.*]] = thin_function_to_pointer [[T2]]
+// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T3]]
+// CHECK-NEXT: [[T4:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: end_borrow [[T0]] from %2
+// CHECK-NEXT: return [[T4]]
+
+// UNCHECKED-LABEL: sil private [transparent] [thunk] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP19finalStoredFunction{{[_0-9a-zA-Z]*}}vmTW
+// UNCHECKED: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived):
+// UNCHECKED-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// UNCHECKED-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived
+// UNCHECKED-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base
+// UNCHECKED-NEXT: [[ADDR:%.*]] = ref_element_addr [[SELF]] : $Base, #Base.finalStoredFunction
+// UNCHECKED-NEXT: [[RESULT:%.*]] = load [copy] [[ADDR]]
+// UNCHECKED-NEXT: function_ref
+// UNCHECKED-NEXT: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegd_SiIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
+// UNCHECKED-NEXT: [[T1:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[RESULT]])
+// UNCHECKED-NEXT: store [[T1]] to [init] [[RESULT_ADDR]]
+// UNCHECKED-NEXT: [[RESULT_PTR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
+// UNCHECKED-NEXT: function_ref
+// UNCHECKED-NEXT: [[T2:%.*]] = function_ref @$S17materializeForSet7DerivedCAA12AbstractableA2aDP19finalStoredFunction6ResultQzycvmytfU_TW
+// UNCHECKED-NEXT: [[T3:%.*]] = thin_function_to_pointer [[T2]]
+// UNCHECKED-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[T3]]
+// UNCHECKED-NEXT: [[T4:%.*]] = tuple ([[RESULT_PTR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// UNCHECKED-NEXT: end_borrow [[T0]] from %2
+// UNCHECKED-NEXT: return [[T4]]
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14staticFunction6ResultQzycvmZytfU_TW
+// CHECK: bb0([[ARG1:%.*]] : $Builtin.RawPointer, [[ARG2:%.*]] : $*Builtin.UnsafeValueBuffer, [[ARG3:%.*]] : $*@thick Derived.Type, [[ARG4:%.*]] : $@thick Derived.Type.Type):
+// CHECK-NEXT: [[SELF:%.*]] = load [trivial] [[ARG3]] : $*@thick Derived.Type
+// CHECK-NEXT: [[BASE_SELF:%.*]] = upcast [[SELF]] : $@thick Derived.Type to $@thick Base.Type
+// CHECK-NEXT: [[BUFFER:%.*]] = pointer_to_address [[ARG1]] : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[VALUE:%.*]] = load [take] [[BUFFER]] : $*@callee_guaranteed () -> @out Int
+// CHECK: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegr_SiIegd_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out Int) -> Int
+// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[VALUE]]) : $@convention(thin) (@guaranteed @callee_guaranteed () -> @out Int) -> Int
+// CHECK: [[SETTER_FN:%.*]] = function_ref @$S17materializeForSet4BaseC14staticFunctionSiycvsZ : $@convention(method) (@owned @callee_guaranteed () -> Int, @thick Base.Type) -> ()
+// CHECK-NEXT: apply [[SETTER_FN]]([[NEWVALUE]], [[BASE_SELF]]) : $@convention(method) (@owned @callee_guaranteed () -> Int, @thick Base.Type) -> ()
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]] : $()
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14staticFunction6ResultQzycvmZTW
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $@thick Derived.Type):
+// CHECK-NEXT: [[RESULT_ADDR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[SELF:%.*]] = upcast %2 : $@thick Derived.Type to $@thick Base.Type
+// CHECK-NEXT: [[OUT:%.*]] = alloc_stack $@callee_guaranteed () -> Int
+// CHECK: [[GETTER:%.*]] = function_ref @$S17materializeForSet4BaseC14staticFunctionSiycvgZ : $@convention(method) (@thick Base.Type) -> @owned @callee_guaranteed () -> Int
+// CHECK-NEXT: [[VALUE:%.*]] = apply [[GETTER]]([[SELF]]) : $@convention(method) (@thick Base.Type) -> @owned @callee_guaranteed () -> Int
+// CHECK-NEXT: store [[VALUE]] to [init] [[OUT]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: [[VALUE:%.*]] = load [copy] [[OUT]] : $*@callee_guaranteed () -> Int
+// CHECK: [[REABSTRACTOR:%.*]] = function_ref @$SSiIegd_SiIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> Int) -> @out Int
+// CHECK-NEXT: [[NEWVALUE:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[VALUE]])
+// CHECK-NEXT: destroy_addr [[OUT]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: store [[NEWVALUE]] to [init] [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int
+// CHECK-NEXT: [[ADDR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet7DerivedCAA12AbstractableA2aDP14staticFunction6ResultQzycvmZytfU_TW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> ()
+// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer
+// CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] : $Builtin.RawPointer
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ADDR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: dealloc_stack [[OUT]] : $*@callee_guaranteed () -> Int
+// CHECK-NEXT: return [[RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+
+protocol ClassAbstractable : class {
+ associatedtype Result
+ var storedFunction: () -> Result { get set }
+ var finalStoredFunction: () -> Result { get set }
+ var computedFunction: () -> Result { get set }
+ static var staticFunction: () -> Result { get set }
+}
+
+extension Derived : ClassAbstractable {}
+
+protocol Signatures {
+ associatedtype Result
+ var computedFunction: () -> Result { get set }
+}
+protocol Implementations {}
+extension Implementations {
+ var computedFunction: () -> Int {
+ get { return {0} }
+ set {}
+ }
+}
+
+class ImplementingClass : Implementations, Signatures {}
+struct ImplementingStruct : Implementations, Signatures {
+ var ref: ImplementingClass?
+}
+
+class HasDidSet : Base {
+ override var stored: Int {
+ didSet {}
+ }
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet06HasDidC0C6storedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasDidSet):
+// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet06HasDidC0C6storedSivg
+// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
+// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
+// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet06HasDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
+// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
+// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
+// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+
+ override var computed: Int {
+ get { return 0 }
+ set(value) {}
+ }
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet06HasDidC0C8computedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasDidSet):
+// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet06HasDidC0C8computedSivg
+// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
+// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
+// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet06HasDidC0C8computedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> ()
+// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
+// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
+// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+}
+
+class HasStoredDidSet {
+ var stored: Int = 0 {
+ didSet {}
+ }
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*HasStoredDidSet, [[METATYPE:%.*]] : $@thick HasStoredDidSet.Type):
+// CHECK: [[SELF_VALUE:%.*]] = load_borrow [[SELF]] : $*HasStoredDidSet
+// CHECK: [[BUFFER_ADDR:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[VALUE:%.*]] = load [trivial] [[BUFFER_ADDR]] : $*Int
+// CHECK: [[SETTER_FN:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivs : $@convention(method) (Int, @guaranteed HasStoredDidSet) -> ()
+// CHECK: apply [[SETTER_FN]]([[VALUE]], [[SELF_VALUE]]) : $@convention(method) (Int, @guaranteed HasStoredDidSet) -> ()
+// CHECK: return
+// CHECK: }
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet012HasStoredDidC0C6storedSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasStoredDidSet) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasStoredDidSet):
+// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivg
+// CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]])
+// CHECK: store [[T1]] to [trivial] [[T2]] : $*Int
+// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
+// CHECK: [[CALLBACK_FN:%.*]] = function_ref @$S17materializeForSet012HasStoredDidC0C6storedSivmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> ()
+// CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]]
+// CHECK: [[CALLBACK:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_ADDR]]
+// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+}
+
+class HasWeak {
+ weak var weakvar: HasWeak?
+}
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet7HasWeakC7weakvarACSgXwvm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasWeak) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasWeak):
+// CHECK: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Optional<HasWeak>
+// CHECK: [[T0:%.*]] = ref_element_addr [[SELF]] : $HasWeak, #HasWeak.weakvar
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[T0]] : $*@sil_weak Optional<HasWeak>
+// CHECK: [[T1:%.*]] = load_weak [[READ]] : $*@sil_weak Optional<HasWeak>
+// CHECK: end_access [[READ]] : $*@sil_weak Optional<HasWeak>
+// CHECK: store [[T1]] to [init] [[T2]] : $*Optional<HasWeak>
+// CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]]
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet7HasWeakC7weakvarACSgXwvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> ()
+// CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, {{.*}} : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+
+// UNCHECKED-LABEL: sil hidden [transparent] @$S17materializeForSet7HasWeakC7weakvarACSgXwvm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasWeak) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// UNCHECKED: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $HasWeak):
+// UNCHECKED: [[T2:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Optional<HasWeak>
+// UNCHECKED: [[T0:%.*]] = ref_element_addr [[SELF]] : $HasWeak, #HasWeak.weakvar
+// UNCHECKED: [[T1:%.*]] = load_weak [[T0]] : $*@sil_weak Optional<HasWeak>
+// UNCHECKED: store [[T1]] to [init] [[T2]] : $*Optional<HasWeak>
+// UNCHECKED: [[BUFFER:%.*]] = address_to_pointer [[T2]]
+// UNCHECKED: [[T0:%.*]] = function_ref @$S17materializeForSet7HasWeakC7weakvarACSgXwvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> ()
+// UNCHECKED: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, {{.*}} : $Optional<Builtin.RawPointer>)
+// UNCHECKED: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// UNCHECKED: }
+
+// rdar://22109071
+// Test that we don't use materializeForSet from a protocol extension.
+protocol Magic {}
+extension Magic {
+ var hocus: Int {
+ get { return 0 }
+ set {}
+ }
+}
+struct Wizard : Magic {}
+func improve(_ x: inout Int) {}
+func improveWizard(_ wizard: inout Wizard) {
+ improve(&wizard.hocus)
+}
+// CHECK-LABEL: sil hidden @$S17materializeForSet13improveWizardyyAA0E0VzF
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Wizard
+// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Int
+// Call the getter and materialize the result in the temporary.
+// CHECK-NEXT: [[T0:%.*]] = load [trivial] [[WRITE:.*]] : $*Wizard
+// CHECK: [[WTEMP:%.*]] = alloc_stack $Wizard
+// CHECK-NEXT: store [[T0]] to [trivial] [[WTEMP]]
+// CHECK: [[GETTER:%.*]] = function_ref @$S17materializeForSet5MagicPAAE5hocusSivg
+// CHECK-NEXT: [[T0:%.*]] = apply [[GETTER]]<Wizard>([[WTEMP]])
+// CHECK-NEXT: dealloc_stack [[WTEMP]]
+// CHECK-NEXT: store [[T0]] to [trivial] [[TEMP]]
+// Call improve.
+// CHECK: [[IMPROVE:%.*]] = function_ref @$S17materializeForSet7improveyySizF :
+// CHECK-NEXT: apply [[IMPROVE]]([[TEMP]])
+// CHECK-NEXT: [[T0:%.*]] = load [trivial] [[TEMP]]
+// CHECK: [[SETTER:%.*]] = function_ref @$S17materializeForSet5MagicPAAE5hocusSivs
+// CHECK-NEXT: apply [[SETTER]]<Wizard>([[T0]], [[WRITE]])
+// CHECK-NEXT: end_access [[WRITE]] : $*Wizard
+// CHECK-NEXT: dealloc_stack [[TEMP]]
+
+protocol Totalled {
+ var total: Int { get set }
+}
+
+struct Bill : Totalled {
+ var total: Int
+}
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet4BillV5totalSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Bill) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Bill):
+// CHECK: [[T0:%.*]] = struct_element_addr [[SELF]] : $*Bill, #Bill.total
+// CHECK: [[T1:%.*]] = address_to_pointer [[T0]] : $*Int to $Builtin.RawPointer
+// CHECK: [[T3:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.none!enumelt
+// CHECK: [[T4:%.*]] = tuple ([[T1]] : $Builtin.RawPointer, [[T3]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[T4]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S17materializeForSet4BillVAA8TotalledA2aDP5totalSivmTW : $@convention(witness_method: Totalled) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Bill) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Bill):
+// CHECK: [[T0:%.*]] = function_ref @$S17materializeForSet4BillV5totalSivm
+// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[BUFFER]], [[STORAGE]], [[SELF]])
+// CHECK-NEXT: [[LEFT:%.*]] = tuple_extract [[T1]]
+// CHECK-NEXT: [[RIGHT:%.*]] = tuple_extract [[T1]]
+// CHECK-NEXT: [[T1:%.*]] = tuple ([[LEFT]] : $Builtin.RawPointer, [[RIGHT]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: return [[T1]] :
+
+protocol AddressOnlySubscript {
+ associatedtype Index
+ subscript(i: Index) -> Index { get set }
+}
+
+struct Foo<T>: AddressOnlySubscript {
+ subscript(i: T) -> T {
+ get { return i }
+ set { print("\(i) = \(newValue)") }
+ }
+}
+
+func increment(_ x: inout Int) { x += 1 }
+
+// Generic subscripts.
+
+protocol GenericSubscriptProtocol {
+ subscript<T>(_: T) -> T { get set }
+}
+
+struct GenericSubscriptWitness : GenericSubscriptProtocol {
+ subscript<T>(_: T) -> T { get { } set { } }
+}
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet23GenericSubscriptWitnessVyxxcluimytfU_ : $@convention(method) <T> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericSubscriptWitness, @thick GenericSubscriptWitness.Type) -> () {
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*GenericSubscriptWitness, %3 : $@thick GenericSubscriptWitness.Type):
+// CHECK: [[BUFFER:%.*]] = project_value_buffer $T in %1 : $*Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[INDICES:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T
+// CHECK: [[SETTER:%.*]] = function_ref @$S17materializeForSet23GenericSubscriptWitnessVyxxcluis : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @inout GenericSubscriptWitness) -> ()
+// CHECK-NEXT: apply [[SETTER]]<T>([[INDICES]], [[BUFFER]], %2) : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @inout GenericSubscriptWitness) -> ()
+// CHECK-NEXT: dealloc_value_buffer $*T in %1 : $*Builtin.UnsafeValueBuffer
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]] : $()
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet23GenericSubscriptWitnessVyxxcluim : $@convention(method) <T> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed T, @inout GenericSubscriptWitness) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*T, %3 : $*GenericSubscriptWitness):
+// CHECK-NEXT: [[BUFFER:%.*]] = alloc_value_buffer $T in %1 : $*Builtin.UnsafeValueBuffer
+// CHECK-NEXT: copy_addr %2 to [initialization] [[BUFFER]] : $*T
+// CHECK-NEXT: [[VALUE:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T
+// CHECK-NEXT: [[SELF:%.*]] = load [trivial] %3 : $*GenericSubscriptWitness
+// CHECK: [[GETTER:%.*]] = function_ref @$S17materializeForSet23GenericSubscriptWitnessVyxxcluig : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, GenericSubscriptWitness) -> @out τ_0_0
+// CHECK-NEXT: apply [[GETTER]]<T>([[VALUE]], %2, [[SELF]]) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, GenericSubscriptWitness) -> @out τ_0_0
+// CHECK-NEXT: [[VALUE_PTR:%.*]] = address_to_pointer [[VALUE]] : $*T to $Builtin.RawPointer
+// CHECK: [[CALLBACK:%.*]] = function_ref @$S17materializeForSet23GenericSubscriptWitnessVyxxcluimytfU_
+// CHECK-NEXT: [[CALLBACK_PTR:%.*]] = thin_function_to_pointer [[CALLBACK]] : $@convention(method) <τ_0_0> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericSubscriptWitness, @thick GenericSubscriptWitness.Type) -> () to $Builtin.RawPointer
+// CHECK-NEXT: [[CALLBACK_OPTIONAL:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[CALLBACK_PTR]] : $Builtin.RawPointer
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[VALUE_PTR]] : $Builtin.RawPointer, [[CALLBACK_OPTIONAL]] : $Optional<Builtin.RawPointer>)
+// CHECK-NEXT: return [[RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+
+extension GenericSubscriptProtocol {
+ subscript<T>(t: T) -> T { get { } set { } }
+}
+
+struct GenericSubscriptDefaultWitness : GenericSubscriptProtocol { }
+
+// Make sure we correctly infer the 'T : Magic' requirement on all the accessors
+// of the subscript.
+
+struct GenericTypeWithRequirement<T : Magic> {}
+
+protocol InferredRequirementOnSubscriptProtocol {
+ subscript<T>(i: Int) -> GenericTypeWithRequirement<T> { get set }
+}
+
+struct InferredRequirementOnSubscript : InferredRequirementOnSubscriptProtocol {
+ subscript<T>(i: Int) -> GenericTypeWithRequirement<T> {
+ get { }
+ set { }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S17materializeForSet30InferredRequirementOnSubscriptVyAA015GenericTypeWithE0VyxGSicAA5MagicRzluig : $@convention(method) <T where T : Magic> (Int, InferredRequirementOnSubscript) -> GenericTypeWithRequirement<T>
+
+// CHECK-LABEL: sil hidden @$S17materializeForSet30InferredRequirementOnSubscriptVyAA015GenericTypeWithE0VyxGSicAA5MagicRzluis : $@convention(method) <T where T : Magic> (GenericTypeWithRequirement<T>, Int, @inout InferredRequirementOnSubscript) -> ()
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet30InferredRequirementOnSubscriptVyAA015GenericTypeWithE0VyxGSicAA5MagicRzluim : $@convention(method) <T where T : Magic> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, Int, @inout InferredRequirementOnSubscript) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+
+// Test for materializeForSet vs static properties of structs.
+
+protocol Beverage {
+ static var abv: Int { get set }
+}
+
+struct Beer : Beverage {
+ static var abv: Int {
+ get {
+ return 7
+ }
+ set { }
+ }
+}
+
+struct Wine<Color> : Beverage {
+ static var abv: Int {
+ get {
+ return 14
+ }
+ set { }
+ }
+}
+
+// Make sure we can perform an inout access of such a property too.
+
+func inoutAccessOfStaticProperty<T : Beverage>(_ t: T.Type) {
+ increment(&t.abv)
+}
+
+// Test for materializeForSet vs overridden computed property of classes.
+class BaseForOverride {
+ var valueStored: Int
+ var valueComputed: Int { get { } set { } }
+
+ init(valueStored: Int) {
+ self.valueStored = valueStored
+ }
+}
+
+class DerivedForOverride : BaseForOverride {
+ override var valueStored: Int { get { } set { } }
+ override var valueComputed: Int { get { } set { } }
+}
+
+// Test for materializeForSet vs static properties of classes.
+
+class ReferenceBeer {
+ class var abv: Int {
+ get {
+ return 7
+ }
+ set { }
+ }
+}
+
+func inoutAccessOfClassProperty() {
+ increment(&ReferenceBeer.abv)
+}
+
+// Test for materializeForSet when Self is re-abstracted.
+//
+// We have to open-code the materializeForSelf witness, and not screw up
+// the re-abstraction.
+
+protocol Panda {
+ var x: (Self) -> Self { get set }
+}
+
+func id<T>(_ t: T) -> T { return t }
+
+extension Panda {
+ var x: (Self) -> Self {
+ get { return id }
+ set { }
+ }
+}
+
+struct TuxedoPanda : Panda { }
+
+// CHECK-LABEL: sil private [transparent] @$S17materializeForSet11TuxedoPandaVAA0E0A2aDP1xyxxcvmytfU_TW : $@convention(witness_method: Panda) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> ()
+
+ // FIXME: Useless re-abstractions
+
+ // CHECK: function_ref @$S17materializeForSet11TuxedoPandaVACIegnr_A2CIegyd_TR : $@convention(thin) (TuxedoPanda, @guaranteed @callee_guaranteed (@in_guaranteed TuxedoPanda) -> @out TuxedoPanda) -> TuxedoPanda
+
+ // CHECK: function_ref @$S17materializeForSet11TuxedoPandaVACIegyd_A2CIegnr_TR : $@convention(thin) (@in_guaranteed TuxedoPanda, @guaranteed @callee_guaranteed (TuxedoPanda) -> TuxedoPanda) -> @out TuxedoPanda
+
+ // CHECK: function_ref @$S17materializeForSet5PandaPAAE1xyxxcvs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
+
+// CHECK: }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S17materializeForSet11TuxedoPandaVAA0E0A2aDP1xyxxcvmTW
+
+// Call the getter:
+
+ // CHECK: function_ref @$S17materializeForSet5PandaPAAE1xyxxcvg : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_0_0
+
+// Result of calling the getter is re-abstracted to the maximally substituted type
+// by SILGenFunction::emitApply():
+
+ // CHECK: function_ref @$S17materializeForSet11TuxedoPandaVACIegnr_A2CIegyd_TR : $@convention(thin) (TuxedoPanda, @guaranteed @callee_guaranteed (@in_guaranteed TuxedoPanda) -> @out TuxedoPanda) -> TuxedoPanda
+
+// ... then we re-abstract to the requirement signature:
+// FIXME: Peephole this away with the previous one since there's actually no
+// abstraction change in this case.
+
+ // CHECK: function_ref @$S17materializeForSet11TuxedoPandaVACIegyd_A2CIegnr_TR : $@convention(thin) (@in_guaranteed TuxedoPanda, @guaranteed @callee_guaranteed (TuxedoPanda) -> TuxedoPanda) -> @out TuxedoPanda
+
+// The callback:
+
+ // CHECK: function_ref @$S17materializeForSet11TuxedoPandaVAA0E0A2aDP1xyxxcvmytfU_TW : $@convention(witness_method: Panda) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> ()
+
+// CHECK: }
+
+
+// Test for materializeForSet vs lazy properties of structs.
+
+struct LazyStructProperty {
+ lazy var cat: Int = 5
+}
+
+// CHECK-LABEL: sil hidden @$S17materializeForSet31inoutAccessOfLazyStructProperty1lyAA0ghI0Vz_tF
+// CHECK: function_ref @$S17materializeForSet18LazyStructPropertyV3catSivg
+// CHECK: function_ref @$S17materializeForSet18LazyStructPropertyV3catSivs
+func inoutAccessOfLazyStructProperty(l: inout LazyStructProperty) {
+ increment(&l.cat)
+}
+
+// Test for materializeForSet vs lazy properties of classes.
+
+// CHECK-LABEL: sil hidden [transparent] @$S17materializeForSet17LazyClassPropertyC3catSivm
+
+class LazyClassProperty {
+ lazy var cat: Int = 5
+}
+
+// CHECK-LABEL: sil hidden @$S17materializeForSet30inoutAccessOfLazyClassProperty1lyAA0ghI0Cz_tF
+// CHECK: class_method {{.*}} : $LazyClassProperty, #LazyClassProperty.cat!materializeForSet.1
+func inoutAccessOfLazyClassProperty(l: inout LazyClassProperty) {
+ increment(&l.cat)
+}
+
+// Test for materializeForSet vs lazy properties of final classes.
+
+final class LazyFinalClassProperty {
+ lazy var cat: Int = 5
+}
+
+// CHECK-LABEL: sil hidden @$S17materializeForSet35inoutAccessOfLazyFinalClassProperty1lyAA0ghiJ0Cz_tF
+// CHECK: function_ref @$S17materializeForSet22LazyFinalClassPropertyC3catSivg
+// CHECK: function_ref @$S17materializeForSet22LazyFinalClassPropertyC3catSivs
+func inoutAccessOfLazyFinalClassProperty(l: inout LazyFinalClassProperty) {
+ increment(&l.cat)
+}
+
+// Make sure the below doesn't crash SILGen
+struct FooClosure {
+ var computed: (((Int) -> Int) -> Int)? {
+ get { return stored }
+ set {}
+ }
+ var stored: (((Int) -> Int) -> Int)? = nil
+}
+
+// CHECK-LABEL: $S17materializeForSet22testMaterializedSetteryyF
+func testMaterializedSetter() {
+ // CHECK: function_ref @$S17materializeForSet10FooClosureVACycfC
+ var f = FooClosure()
+ // CHECK: function_ref @$S17materializeForSet10FooClosureV8computedS3iXEcSgvg
+ // CHECK: function_ref @$S17materializeForSet10FooClosureV8computedS3iXEcSgvs
+ f.computed = f.computed
+}
+
+// CHECK-LABEL: sil_vtable DerivedForOverride {
+// CHECK: #BaseForOverride.valueStored!getter.1: (BaseForOverride) -> () -> Int : @$S17materializeForSet07DerivedB8OverrideC11valueStoredSivg
+// CHECK: #BaseForOverride.valueStored!setter.1: (BaseForOverride) -> (Int) -> () : @$S17materializeForSet07DerivedB8OverrideC11valueStoredSivs
+// CHECK: #BaseForOverride.valueStored!materializeForSet.1: (BaseForOverride) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : @$S17materializeForSet07DerivedB8OverrideC11valueStoredSivm
+// CHECK: #BaseForOverride.valueComputed!getter.1: (BaseForOverride) -> () -> Int : @$S17materializeForSet07DerivedB8OverrideC13valueComputedSivg
+// CHECK: #BaseForOverride.valueComputed!setter.1: (BaseForOverride) -> (Int) -> () : @$S17materializeForSet07DerivedB8OverrideC13valueComputedSivs
+// CHECK: #BaseForOverride.valueComputed!materializeForSet.1: (BaseForOverride) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?) : @$S17materializeForSet07DerivedB8OverrideC13valueComputedSivm
+// CHECK: }
+
+// CHECK-LABEL: sil_witness_table hidden Bill: Totalled module materializeForSet {
+// CHECK: method #Totalled.total!getter.1: {{.*}} : @$S17materializeForSet4BillVAA8TotalledA2aDP5totalSivgTW
+// CHECK: method #Totalled.total!setter.1: {{.*}} : @$S17materializeForSet4BillVAA8TotalledA2aDP5totalSivsTW
+// CHECK: method #Totalled.total!materializeForSet.1: {{.*}} : @$S17materializeForSet4BillVAA8TotalledA2aDP5totalSivmTW
+// CHECK: }
diff --git a/test/SILGen/plus_zero_metatype_abstraction.swift b/test/SILGen/plus_zero_metatype_abstraction.swift
new file mode 100644
index 0000000..8dfa81f
--- /dev/null
+++ b/test/SILGen/plus_zero_metatype_abstraction.swift
@@ -0,0 +1,142 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -module-name Swift -parse-stdlib %s | %FileCheck %s
+
+enum Optional<Wrapped> {
+ case none
+ case some(Wrapped)
+}
+
+struct S {}
+class C {}
+
+struct Generic<T> {
+ var value: T
+}
+
+struct GenericMetatype<T> {
+ var value: T.Type
+}
+
+// CHECK-LABEL: sil hidden @$Ss26genericMetatypeFromGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[ADDR:%.*]] = struct_element_addr {{%.*}} : $*Generic<T.Type>, #Generic.value
+// CHECK: [[META:%.*]] = load [trivial] [[ADDR]] : $*@thick T.Type
+// CHECK: return [[META]] : $@thick T.Type
+// CHECK: }
+func genericMetatypeFromGeneric<T>(_ x: Generic<T.Type>) -> T.Type {
+ var x = x
+ return x.value
+}
+// CHECK-LABEL: sil hidden @$Ss26dynamicMetatypeFromGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[ADDR:%.*]] = struct_element_addr {{%.*}} : $*Generic<C.Type>, #Generic.value
+// CHECK: [[META:%.*]] = load [trivial] [[ADDR]] : $*@thick C.Type
+// CHECK: return [[META]] : $@thick C.Type
+// CHECK: }
+func dynamicMetatypeFromGeneric(_ x: Generic<C.Type>) -> C.Type {
+ var x = x
+ return x.value
+}
+// CHECK-LABEL: sil hidden @$Ss25staticMetatypeFromGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[META:%.*]] = metatype $@thin S.Type
+// CHECK: return [[META]] : $@thin S.Type
+// CHECK: }
+func staticMetatypeFromGeneric(_ x: Generic<S.Type>) -> S.Type {
+ return x.value
+}
+
+// CHECK-LABEL: sil hidden @$Ss026genericMetatypeFromGenericB0{{[_0-9a-zA-Z]*}}F
+// CHECK: [[ADDR:%.*]] = struct_element_addr {{%.*}} : $*GenericMetatype<T>, #GenericMetatype.value
+// CHECK: [[META:%.*]] = load [trivial] [[ADDR]] : $*@thick T.Type
+// CHECK: return [[META]] : $@thick T.Type
+// CHECK: }
+func genericMetatypeFromGenericMetatype<T>(_ x: GenericMetatype<T>)-> T.Type {
+ var x = x
+ return x.value
+}
+// CHECK-LABEL: sil hidden @$Ss026dynamicMetatypeFromGenericB0ys1CCms0dB0VyACGF
+// CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var GenericMetatype<C> }
+// CHECK: [[PX:%[0-9]+]] = project_box [[XBOX]]
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PX]] : $*GenericMetatype<C>
+// CHECK: [[ADDR:%.*]] = struct_element_addr [[READ]] : $*GenericMetatype<C>, #GenericMetatype.value
+// CHECK: [[META:%.*]] = load [trivial] [[ADDR]] : $*@thick C.Type
+// CHECK: return [[META]] : $@thick C.Type
+// CHECK: }
+func dynamicMetatypeFromGenericMetatype(_ x: GenericMetatype<C>) -> C.Type {
+ var x = x
+ return x.value
+}
+
+func takeGeneric<T>(_ x: T) {}
+func takeGenericMetatype<T>(_ x: T.Type) {}
+
+// CHECK-LABEL: sil hidden @$Ss23staticMetatypeToGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[MAT:%.*]] = alloc_stack $@thick S.Type
+// CHECK: [[META:%.*]] = metatype $@thick S.Type
+// CHECK: store [[META]] to [trivial] [[MAT]] : $*@thick S.Type
+// CHECK: apply {{%.*}}<S.Type>([[MAT]])
+func staticMetatypeToGeneric(_ x: S.Type) {
+ takeGeneric(x)
+}
+// CHECK-LABEL: sil hidden @$Ss023staticMetatypeToGenericB0{{[_0-9a-zA-Z]*}}F
+// CHECK: [[META:%.*]] = metatype $@thick S.Type
+// CHECK: apply {{%.*}}<S>([[META]])
+func staticMetatypeToGenericMetatype(_ x: S.Type) {
+ takeGenericMetatype(x)
+}
+// CHECK-LABEL: sil hidden @$Ss24dynamicMetatypeToGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[MAT:%.*]] = alloc_stack $@thick C.Type
+// CHECK: apply {{%.*}}<C.Type>([[MAT]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
+func dynamicMetatypeToGeneric(_ x: C.Type) {
+ var x = x
+ takeGeneric(x)
+}
+// CHECK-LABEL: sil hidden @$Ss024dynamicMetatypeToGenericB0yys1CCmF
+// CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var @thick C.Type }
+// CHECK: [[PX:%[0-9]+]] = project_box [[XBOX]]
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PX]] : $*@thick C.Type
+// CHECK: [[META:%.*]] = load [trivial] [[READ]] : $*@thick C.Type
+// CHECK: apply {{%.*}}<C>([[META]]) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> ()
+func dynamicMetatypeToGenericMetatype(_ x: C.Type) {
+ var x = x
+ takeGenericMetatype(x)
+}
+// CHECK-LABEL: sil hidden @$Ss24genericMetatypeToGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: [[MAT:%.*]] = alloc_stack $@thick U.Type
+// CHECK: apply {{%.*}}<U.Type>([[MAT]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> ()
+func genericMetatypeToGeneric<U>(_ x: U.Type) {
+ var x = x
+ takeGeneric(x)
+}
+func genericMetatypeToGenericMetatype<U>(_ x: U.Type) {
+ takeGenericMetatype(x)
+}
+
+// CHECK-LABEL: sil hidden @$Ss019static_metatype_of_B0ys1SVmmACF
+// CHECK: metatype $@thin S.Type.Type
+func static_metatype_of_metatype(_ x: S) -> S.Type.Type {
+ return type(of: type(of: x))
+}
+
+// CHECK-LABEL: sil hidden @$Ss018class_metatype_of_B0ys1CCmmACF
+// CHECK: [[METATYPE:%.*]] = value_metatype $@thick C.Type
+// CHECK: [[META_METATYPE:%.*]] = value_metatype $@thick C.Type.Type, [[METATYPE]]
+func class_metatype_of_metatype(_ x: C) -> C.Type.Type {
+ return type(of: type(of: x))
+}
+
+// CHECK-LABEL: sil hidden @$Ss020generic_metatype_of_B0{{[_0-9a-zA-Z]*}}F
+// CHECK: [[METATYPE:%.*]] = value_metatype $@thick T.Type
+// CHECK: [[META_METATYPE:%.*]] = value_metatype $@thick T.Type.Type, [[METATYPE]]
+func generic_metatype_of_metatype<T>(_ x: T) -> T.Type.Type {
+ return type(of: type(of: x))
+}
+
+// FIXME rdar://problem/18419772
+/*
+func existential_metatype_of_metatype(_ x: Any) -> Any.Type.Type {
+ return type(of: type(of: x))
+}
+ */
+
+func function_metatype_of_metatype(_ x: @escaping () -> ()) -> (() -> ()).Type.Type {
+ return type(of: type(of: x))
+}
diff --git a/test/SILGen/plus_zero_multi_file.swift b/test/SILGen/plus_zero_multi_file.swift
new file mode 100644
index 0000000..aaccbcc
--- /dev/null
+++ b/test/SILGen/plus_zero_multi_file.swift
@@ -0,0 +1,53 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -primary-file %s %S/Inputs/multi_file_helper.swift | %FileCheck %s
+
+func markUsed<T>(_ t: T) {}
+
+// CHECK-LABEL: sil hidden @$S10multi_file12rdar16016713{{[_0-9a-zA-Z]*}}F
+func rdar16016713(_ r: Range) {
+ // CHECK: [[LIMIT:%[0-9]+]] = function_ref @$S10multi_file5RangeV5limitSivg : $@convention(method) (Range) -> Int
+ // CHECK: {{%[0-9]+}} = apply [[LIMIT]]({{%[0-9]+}}) : $@convention(method) (Range) -> Int
+ markUsed(r.limit)
+}
+
+// CHECK-LABEL: sil hidden @$S10multi_file26lazyPropertiesAreNotStored{{[_0-9a-zA-Z]*}}F
+func lazyPropertiesAreNotStored(_ container: LazyContainer) {
+ var container = container
+ // CHECK: {{%[0-9]+}} = function_ref @$S10multi_file13LazyContainerV7lazyVarSivg : $@convention(method) (@inout LazyContainer) -> Int
+ markUsed(container.lazyVar)
+}
+
+// CHECK-LABEL: sil hidden @$S10multi_file29lazyRefPropertiesAreNotStored{{[_0-9a-zA-Z]*}}F
+func lazyRefPropertiesAreNotStored(_ container: LazyContainerClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $LazyContainerClass):
+ // CHECK: {{%[0-9]+}} = class_method [[ARG]] : $LazyContainerClass, #LazyContainerClass.lazyVar!getter.1 : (LazyContainerClass) -> () -> Int, $@convention(method) (@guaranteed LazyContainerClass) -> Int
+ markUsed(container.lazyVar)
+}
+
+// CHECK-LABEL: sil hidden @$S10multi_file25finalVarsAreDevirtualizedyyAA18FinalPropertyClassCF
+func finalVarsAreDevirtualized(_ obj: FinalPropertyClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $FinalPropertyClass):
+ // CHECK: ref_element_addr [[ARG]] : $FinalPropertyClass, #FinalPropertyClass.foo
+ markUsed(obj.foo)
+ // CHECK: class_method [[ARG]] : $FinalPropertyClass, #FinalPropertyClass.bar!getter.1
+ markUsed(obj.bar)
+}
+
+// rdar://18448869
+// CHECK-LABEL: sil hidden @$S10multi_file34finalVarsDontNeedMaterializeForSetyyAA27ObservingPropertyFinalClassCF
+func finalVarsDontNeedMaterializeForSet(_ obj: ObservingPropertyFinalClass) {
+ obj.foo += 1
+ // CHECK: function_ref @$S10multi_file27ObservingPropertyFinalClassC3fooSivg
+ // CHECK: function_ref @$S10multi_file27ObservingPropertyFinalClassC3fooSivs
+}
+
+// rdar://18503960
+// Ensure that we type-check the materializeForSet accessor from the protocol.
+class HasComputedProperty: ProtocolWithProperty {
+ var foo: Int {
+ get { return 1 }
+ set {}
+ }
+}
+// CHECK-LABEL: sil hidden [transparent] @$S10multi_file19HasComputedPropertyC3fooSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed HasComputedProperty) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK-LABEL: sil private [transparent] [thunk] @$S10multi_file19HasComputedPropertyCAA012ProtocolWithE0A2aDP3fooSivmTW : $@convention(witness_method: ProtocolWithProperty) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasComputedProperty) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
diff --git a/test/SILGen/plus_zero_nested_generics.swift b/test/SILGen/plus_zero_nested_generics.swift
new file mode 100644
index 0000000..32abb9f
--- /dev/null
+++ b/test/SILGen/plus_zero_nested_generics.swift
@@ -0,0 +1,261 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-silgen -parse-as-library %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-sil -parse-as-library %s > /dev/null
+// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-sil -O -parse-as-library %s > /dev/null
+// RUN: %target-swift-frontend -enable-sil-ownership -Xllvm -sil-full-demangle -emit-ir -parse-as-library %s > /dev/null
+
+// TODO:
+// - test generated SIL -- mostly we're just testing mangling here
+// - class_method calls
+// - witness_method calls
+// - inner generic parameters on protocol requirements
+// - generic parameter list on method in nested type
+// - types nested inside unconstrained extensions of generic types
+
+protocol Pizza : class {
+ associatedtype Topping
+}
+
+protocol HotDog {
+ associatedtype Condiment
+}
+
+protocol CuredMeat {}
+
+// Generic nested inside generic
+
+struct Lunch<T : Pizza> where T.Topping : CuredMeat {
+ struct Dinner<U : HotDog> where U.Condiment == Deli<Pepper>.Mustard {
+ let firstCourse: T
+ let secondCourse: U?
+
+ var leftovers: T
+ var transformation: (T) -> U
+
+ func coolCombination(t: T.Topping, u: U.Condiment) {
+ func nestedGeneric<X, Y>(x: X, y: Y) -> (X, Y) {
+ return (x, y)
+ }
+ _ = nestedGeneric(x: t, y: u)
+ }
+ }
+}
+
+// CHECK-LABEL: // nested_generics.Lunch.Dinner.coolCombination(t: A.Topping, u: nested_generics.Deli<nested_generics.Pepper>.Mustard) -> ()
+// CHECK-LABEL: sil hidden @$S15nested_generics5LunchV6DinnerV15coolCombination1t1uy7ToppingQz_AA4DeliC7MustardOyAA6PepperV_GtF : $@convention(method) <T where T : Pizza, T.Topping : CuredMeat><U where U : HotDog, U.Condiment == Deli<Pepper>.Mustard> (@in_guaranteed T.Topping, Deli<Pepper>.Mustard, @in_guaranteed Lunch<T>.Dinner<U>) -> ()
+
+// CHECK-LABEL: // nestedGeneric #1 <A><A1><A2, B2 where A: nested_generics.Pizza, A1: nested_generics.HotDog, A.Topping: nested_generics.CuredMeat, A1.Condiment == nested_generics.Deli<nested_generics.Pepper>.Mustard>(x: A2, y: B2) -> (A2, B2) in nested_generics.Lunch.Dinner.coolCombination(t: A.Topping, u: nested_generics.Deli<nested_generics.Pepper>.Mustard) -> ()
+// CHECK-LABEL: sil private @$S15nested_generics5LunchV6DinnerV15coolCombination1t1uy7ToppingQz_AA4DeliC7MustardOyAA6PepperV_GtF0A7GenericL_1x1yqd0___qd0_0_tqd0___qd0_0_tAA5PizzaRzAA6HotDogRd__AA9CuredMeatAJRQAQ9CondimentRtd__r__0_lF : $@convention(thin) <T where T : Pizza, T.Topping : CuredMeat><U where U : HotDog, U.Condiment == Deli<Pepper>.Mustard><X, Y> (@in_guaranteed X, @in_guaranteed Y) -> (@out X, @out Y)
+
+// CHECK-LABEL: // nested_generics.Lunch.Dinner.init(firstCourse: A, secondCourse: Swift.Optional<A1>, leftovers: A, transformation: (A) -> A1) -> nested_generics.Lunch<A>.Dinner<A1>
+// CHECK-LABEL: sil hidden @$S15nested_generics5LunchV6DinnerV11firstCourse06secondF09leftovers14transformationAEyx_qd__Gx_qd__Sgxqd__xctcfC : $@convention(method) <T where T : Pizza, T.Topping : CuredMeat><U where U : HotDog, U.Condiment == Deli<Pepper>.Mustard> (@owned T, @in Optional<U>, @owned T, @owned @callee_guaranteed (@guaranteed T) -> @out U, @thin Lunch<T>.Dinner<U>.Type) -> @out Lunch<T>.Dinner<U>
+
+// Non-generic nested inside generic
+
+class Deli<Spices> : CuredMeat {
+
+ class Pepperoni : CuredMeat {}
+ struct Sausage : CuredMeat {}
+
+ enum Mustard {
+ case Yellow
+ case Dijon
+ case DeliStyle(Spices)
+ }
+}
+
+// CHECK-LABEL: // nested_generics.Deli.Pepperoni.init() -> nested_generics.Deli<A>.Pepperoni
+// CHECK-LABEL: sil hidden @$S15nested_generics4DeliC9PepperoniCAEyx_Gycfc : $@convention(method) <Spices> (@owned Deli<Spices>.Pepperoni) -> @owned Deli<Spices>.Pepperoni
+
+// Typealiases referencing outer generic parameters
+
+struct Pizzas<Spices> {
+ class NewYork : Pizza {
+ typealias Topping = Deli<Spices>.Pepperoni
+ }
+
+ class DeepDish : Pizza {
+ typealias Topping = Deli<Spices>.Sausage
+ }
+}
+
+class HotDogs {
+ struct Bratwurst : HotDog {
+ typealias Condiment = Deli<Pepper>.Mustard
+ }
+ struct American : HotDog {
+ typealias Condiment = Deli<Pepper>.Mustard
+ }
+}
+
+// Local type in extension of type in another module
+extension String {
+ func foo() {
+ // CHECK-LABEL: // init(material: A) -> Cheese #1 in (extension in nested_generics):Swift.String.foo() -> ()<A> in Cheese #1 in (extension in nested_generics):Swift.String.foo() -> ()
+ // CHECK-LABEL: sil private @$SSS15nested_genericsE3fooyyF6CheeseL_V8materialADyxGx_tcfC
+ struct Cheese<Milk> {
+ let material: Milk
+ }
+ let _ = Cheese(material: "cow")
+ }
+}
+
+// Local type in extension of type in same module
+extension HotDogs {
+ func applyRelish() {
+ // CHECK-LABEL: // init(material: A) -> Relish #1 in nested_generics.HotDogs.applyRelish() -> ()<A> in Relish #1 in nested_generics.HotDogs.applyRelish() -> ()
+ // CHECK-LABEL: sil private @$S15nested_generics7HotDogsC11applyRelishyyF0F0L_V8materialAFyxGx_tcfC
+
+ struct Relish<Material> {
+ let material: Material
+ }
+ let _ = Relish(material: "pickles")
+ }
+}
+
+struct Pepper {}
+struct ChiliFlakes {}
+
+// CHECK-LABEL: // nested_generics.eatDinnerGeneric<A, B where A: nested_generics.Pizza, B: nested_generics.HotDog, A.Topping: nested_generics.CuredMeat, B.Condiment == nested_generics.Deli<nested_generics.Pepper>.Mustard>(d: inout nested_generics.Lunch<A>.Dinner<B>, t: A.Topping, u: nested_generics.Deli<nested_generics.Pepper>.Mustard) -> ()
+// CHECK-LABEL: sil hidden @$S15nested_generics16eatDinnerGeneric1d1t1uyAA5LunchV0D0Vyx_q_Gz_7ToppingQzAA4DeliC7MustardOyAA6PepperV_GtAA5PizzaRzAA6HotDogR_AA9CuredMeatALRQAS9CondimentRt_r0_lF : $@convention(thin) <T, U where T : Pizza, U : HotDog, T.Topping : CuredMeat, U.Condiment == Deli<Pepper>.Mustard> (@inout Lunch<T>.Dinner<U>, @in_guaranteed T.Topping, Deli<Pepper>.Mustard) -> ()
+
+func eatDinnerGeneric<T, U>(d: inout Lunch<T>.Dinner<U>, t: T.Topping, u: U.Condiment) {
+ // Method call
+ _ = d.coolCombination(t: t, u: u)
+
+ // Read a let, store into var
+ d.leftovers = d.firstCourse
+
+ // Read a var
+ let _ = d.secondCourse
+
+ // Call property of function type
+ _ = d.transformation(d.leftovers)
+}
+
+// Overloading concrete function with different bound generic arguments in parent type
+
+// CHECK-LABEL: // nested_generics.eatDinnerConcrete(d: inout nested_generics.Lunch<nested_generics.Pizzas<nested_generics.ChiliFlakes>.NewYork>.Dinner<nested_generics.HotDogs.American>, t: nested_generics.Deli<nested_generics.ChiliFlakes>.Pepperoni, u: nested_generics.Deli<nested_generics.Pepper>.Mustard) -> ()
+// CHECK-LABEL: sil hidden @$S15nested_generics17eatDinnerConcrete1d1t1uyAA5LunchV0D0VyAA6PizzasV7NewYorkCyAA11ChiliFlakesV_G_AA7HotDogsC8AmericanVGz_AA4DeliC9PepperoniCyAO_GAW7MustardOyAA6PepperV_GtF : $@convention(thin) (@inout Lunch<Pizzas<ChiliFlakes>.NewYork>.Dinner<HotDogs.American>, @guaranteed Deli<ChiliFlakes>.Pepperoni, Deli<Pepper>.Mustard) -> ()
+
+func eatDinnerConcrete(d: inout Lunch<Pizzas<ChiliFlakes>.NewYork>.Dinner<HotDogs.American>,
+ t: Deli<ChiliFlakes>.Pepperoni,
+ u: Deli<Pepper>.Mustard) {
+ // Method call
+ _ = d.coolCombination(t: t, u: u)
+
+ // Read a let, store into var
+ d.leftovers = d.firstCourse
+
+ // Read a var
+ let _ = d.secondCourse
+
+ // Call property of function type
+ _ = d.transformation(d.leftovers)
+}
+
+// CHECK-LABEL: // reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed nested_generics.Pizzas<nested_generics.ChiliFlakes>.NewYork) -> (@out nested_generics.HotDogs.American) to @escaping @callee_guaranteed (@guaranteed nested_generics.Pizzas<nested_generics.ChiliFlakes>.NewYork) -> (@unowned nested_generics.HotDogs.American)
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S15nested_generics6PizzasV7NewYorkCyAA11ChiliFlakesV_GAA7HotDogsC8AmericanVIeggr_AhLIeggd_TR : $@convention(thin) (@guaranteed Pizzas<ChiliFlakes>.NewYork, @guaranteed @callee_guaranteed (@guaranteed Pizzas<ChiliFlakes>.NewYork) -> @out HotDogs.American) -> HotDogs.American
+
+// CHECK-LABEL: // nested_generics.eatDinnerConcrete(d: inout nested_generics.Lunch<nested_generics.Pizzas<nested_generics.Pepper>.NewYork>.Dinner<nested_generics.HotDogs.American>, t: nested_generics.Deli<nested_generics.Pepper>.Pepperoni, u: nested_generics.Deli<nested_generics.Pepper>.Mustard) -> ()
+// CHECK-LABEL: sil hidden @$S15nested_generics17eatDinnerConcrete1d1t1uyAA5LunchV0D0VyAA6PizzasV7NewYorkCyAA6PepperV_G_AA7HotDogsC8AmericanVGz_AA4DeliC9PepperoniCyAO_GAW7MustardOyAO_GtF : $@convention(thin) (@inout Lunch<Pizzas<Pepper>.NewYork>.Dinner<HotDogs.American>, @guaranteed Deli<Pepper>.Pepperoni, Deli<Pepper>.Mustard) -> ()
+
+func eatDinnerConcrete(d: inout Lunch<Pizzas<Pepper>.NewYork>.Dinner<HotDogs.American>,
+ t: Deli<Pepper>.Pepperoni,
+ u: Deli<Pepper>.Mustard) {
+ // Method call
+ _ = d.coolCombination(t: t, u: u)
+
+ // Read a let, store into var
+ d.leftovers = d.firstCourse
+
+ // Read a var
+ let _ = d.secondCourse
+
+ // Call property of function type
+ _ = d.transformation(d.leftovers)
+}
+
+// CHECK-LABEL: // reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed nested_generics.Pizzas<nested_generics.Pepper>.NewYork) -> (@out nested_generics.HotDogs.American) to @escaping @callee_guaranteed (@guaranteed nested_generics.Pizzas<nested_generics.Pepper>.NewYork) -> (@unowned nested_generics.HotDogs.American)
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S15nested_generics6PizzasV7NewYorkCyAA6PepperV_GAA7HotDogsC8AmericanVIeggr_AhLIeggd_TR : $@convention(thin) (@guaranteed Pizzas<Pepper>.NewYork, @guaranteed @callee_guaranteed (@guaranteed Pizzas<Pepper>.NewYork) -> @out HotDogs.American) -> HotDogs.American
+
+// CHECK-LABEL: // closure #1 (nested_generics.Pizzas<nested_generics.Pepper>.NewYork) -> nested_generics.HotDogs.American in nested_generics.calls() -> ()
+// CHECK-LABEL: sil private @$S15nested_generics5callsyyFAA7HotDogsC8AmericanVAA6PizzasV7NewYorkCyAA6PepperV_GcfU_ : $@convention(thin) (@guaranteed Pizzas<Pepper>.NewYork) -> HotDogs.American
+
+func calls() {
+
+ let firstCourse = Pizzas<Pepper>.NewYork()
+ let secondCourse = HotDogs.American()
+
+ var dinner = Lunch<Pizzas<Pepper>.NewYork>.Dinner<HotDogs.American>(
+ firstCourse: firstCourse,
+ secondCourse: secondCourse,
+ leftovers: firstCourse,
+ transformation: { _ in HotDogs.American() })
+
+ let topping = Deli<Pepper>.Pepperoni()
+
+ let condiment1 = Deli<Pepper>.Mustard.Dijon
+ let condiment2 = Deli<Pepper>.Mustard.DeliStyle(Pepper())
+
+ eatDinnerGeneric(d: &dinner, t: topping, u: condiment1)
+ eatDinnerConcrete(d: &dinner, t: topping, u: condiment2)
+
+}
+
+protocol ProtocolWithGenericRequirement {
+ associatedtype T
+ associatedtype U
+ func method<V>(t: T, u: U, v: V) -> (T, U, V)
+}
+
+class OuterRing<T> {
+ class InnerRing<U> : ProtocolWithGenericRequirement {
+ func method<V>(t: T, u: U, v: V) -> (T, U, V) {
+ return (t, u, v)
+ }
+ }
+}
+
+class SubclassOfInner<T, U> : OuterRing<T>.InnerRing<U> {
+ override func method<V>(t: T, u: U, v: V) -> (T, U, V) {
+ return super.method(t: t, u: u, v: v)
+ }
+}
+
+// CHECK-LABEL: // reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed nested_generics.Pizzas<nested_generics.Pepper>.NewYork) -> (@unowned nested_generics.HotDogs.American) to @escaping @callee_guaranteed (@guaranteed nested_generics.Pizzas<nested_generics.Pepper>.NewYork) -> (@out nested_generics.HotDogs.American)
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S15nested_generics6PizzasV7NewYorkCyAA6PepperV_GAA7HotDogsC8AmericanVIeggd_AhLIeggr_TR : $@convention(thin) (@guaranteed Pizzas<Pepper>.NewYork, @guaranteed @callee_guaranteed (@guaranteed Pizzas<Pepper>.NewYork) -> HotDogs.American) -> @out HotDogs.American
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15nested_generics9OuterRingC05InnerD0Cyx_qd__GAA30ProtocolWithGenericRequirementA2aGP6method1t1u1v1TQz_1UQzqd__tAN_APqd__tlFTW : $@convention(witness_method: ProtocolWithGenericRequirement) <τ_0_0><τ_1_0><τ_2_0> (@in_guaranteed τ_0_0, @in_guaranteed τ_1_0, @in_guaranteed τ_2_0, @in_guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0) {
+// CHECK: bb0([[T:%[0-9]+]] : @trivial $*τ_0_0, [[U:%[0-9]+]] : @trivial $*τ_1_0, [[V:%[0-9]+]] : @trivial $*τ_2_0, [[TOut:%[0-9]+]] : @trivial $*τ_0_0, [[UOut:%[0-9]+]] : @trivial $*τ_1_0, [[VOut:%[0-9]+]] : @trivial $*τ_2_0, [[SELF:%[0-9]+]] : @trivial $*OuterRing<τ_0_0>.InnerRing<τ_1_0>):
+// CHECK: [[SELF_COPY_VAL:%[0-9]+]] = load_borrow [[SELF]] : $*OuterRing<τ_0_0>.InnerRing<τ_1_0>
+// CHECK: [[METHOD:%[0-9]+]] = class_method [[SELF_COPY_VAL]] : $OuterRing<τ_0_0>.InnerRing<τ_1_0>, #OuterRing.InnerRing.method!1 : <T><U><V> (OuterRing<T>.InnerRing<U>) -> (T, U, V) -> (T, U, V), $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in_guaranteed τ_0_0, @in_guaranteed τ_1_0, @in_guaranteed τ_2_0, @guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0)
+// CHECK: apply [[METHOD]]<τ_0_0, τ_1_0, τ_2_0>([[T]], [[U]], [[V]], [[TOut]], [[UOut]], [[VOut]], [[SELF_COPY_VAL]]) : $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in_guaranteed τ_0_0, @in_guaranteed τ_1_0, @in_guaranteed τ_2_0, @guaranteed OuterRing<τ_0_0>.InnerRing<τ_1_0>) -> (@out τ_0_0, @out τ_1_0, @out τ_2_0)
+// CHECK: [[RESULT:%[0-9]+]] = tuple ()
+// CHECK: end_borrow [[SELF_COPY_VAL]] from [[SELF]]
+// CHECK: return [[RESULT]] : $()
+
+// CHECK: sil_witness_table hidden <Spices> Deli<Spices>.Pepperoni: CuredMeat module nested_generics {
+// CHECK: }
+
+// CHECK: sil_witness_table hidden <Spices> Deli<Spices>.Sausage: CuredMeat module nested_generics {
+// CHECK: }
+
+// CHECK: sil_witness_table hidden <Spices> Deli<Spices>: CuredMeat module nested_generics {
+// CHECK: }
+
+// CHECK: sil_witness_table hidden <Spices> Pizzas<Spices>.NewYork: Pizza module nested_generics {
+// CHECK: associated_type Topping: Deli<Spices>.Pepperoni
+// CHECK: }
+
+// CHECK: sil_witness_table hidden <Spices> Pizzas<Spices>.DeepDish: Pizza module nested_generics {
+// CHECK: associated_type Topping: Deli<Spices>.Sausage
+// CHECK: }
+
+// CHECK: sil_witness_table hidden HotDogs.Bratwurst: HotDog module nested_generics {
+// CHECK: associated_type Condiment: Deli<Pepper>.Mustard
+// CHECK: }
+
+// CHECK: sil_witness_table hidden HotDogs.American: HotDog module nested_generics {
+// CHECK: associated_type Condiment: Deli<Pepper>.Mustard
+// CHECK: }
diff --git a/test/SILGen/plus_zero_nested_types_referencing_nested_functions.swift b/test/SILGen/plus_zero_nested_types_referencing_nested_functions.swift
new file mode 100644
index 0000000..a0aa92e
--- /dev/null
+++ b/test/SILGen/plus_zero_nested_types_referencing_nested_functions.swift
@@ -0,0 +1,34 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+do {
+ func foo() { bar(2) }
+ func bar<T>(_: T) { foo() }
+
+ class Foo {
+ // CHECK-LABEL: sil private @$S025nested_types_referencing_A10_functions3FooL_CACycfc : $@convention(method) (@owned Foo) -> @owned Foo {
+ init() {
+ foo()
+ }
+ // CHECK-LABEL: sil private @$S025nested_types_referencing_A10_functions3FooL_C3zimyyF : $@convention(method) (@guaranteed Foo) -> ()
+ func zim() {
+ foo()
+ }
+ // CHECK-LABEL: sil private @$S025nested_types_referencing_A10_functions3FooL_C4zangyyxlF : $@convention(method) <T> (@in_guaranteed T, @guaranteed Foo) -> ()
+ func zang<T>(_ x: T) {
+ bar(x)
+ }
+ // CHECK-LABEL: sil private @$S025nested_types_referencing_A10_functions3FooL_CfD : $@convention(method) (@owned Foo) -> ()
+ deinit {
+ foo()
+ }
+ }
+
+ let x = Foo()
+ x.zim()
+ x.zang(1)
+ _ = Foo.zim
+ _ = Foo.zang as (Foo) -> (Int) -> ()
+ _ = x.zim
+ _ = x.zang as (Int) -> ()
+}
diff --git a/test/SILGen/plus_zero_newtype.swift b/test/SILGen/plus_zero_newtype.swift
new file mode 100644
index 0000000..778e1bb
--- /dev/null
+++ b/test/SILGen/plus_zero_newtype.swift
@@ -0,0 +1,86 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s -check-prefix=CHECK-RAW
+
+// RUN: %target-swift-frontend -emit-sil -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s -check-prefix=CHECK-CANONICAL
+
+// REQUIRES: objc_interop
+
+import Newtype
+
+// CHECK-CANONICAL-LABEL: sil hidden @$S7newtype17createErrorDomain{{[_0-9a-zA-Z]*}}F
+// CHECK-CANONICAL: bb0([[STR:%[0-9]+]] : $String)
+func createErrorDomain(str: String) -> ErrorDomain {
+ // CHECK-CANONICAL: [[BRIDGE_FN:%[0-9]+]] = function_ref @{{.*}}_bridgeToObjectiveC
+ // CHECK-CANONICAL-NEXT: [[BRIDGED:%[0-9]+]] = apply [[BRIDGE_FN]]([[STR]])
+ // CHECK-CANONICAL: struct $ErrorDomain ([[BRIDGED]] : $NSString)
+ return ErrorDomain(rawValue: str)
+}
+
+// CHECK-RAW-LABEL: sil shared [transparent] [serializable] @$SSo14SNTErrorDomaina8rawValueABSS_tcfC
+// CHECK-RAW: bb0([[STR:%[0-9]+]] : $String,
+// CHECK-RAW: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var ErrorDomain }, var, name "self"
+// CHECK-RAW: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [rootself] [[SELF_BOX]]
+// CHECK-RAW: [[PB_BOX:%[0-9]+]] = project_box [[MARKED_SELF_BOX]]
+// CHECK-RAW: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+// CHECK-RAW: [[COPIED_STR:%.*]] = copy_value [[BORROWED_STR]]
+// CHECK-RAW: [[BRIDGE_FN:%[0-9]+]] = function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK-RAW: [[BORROWED_COPIED_STR:%.*]] = begin_borrow [[COPIED_STR]]
+// CHECK-RAW: [[BRIDGED:%[0-9]+]] = apply [[BRIDGE_FN]]([[BORROWED_COPIED_STR]])
+// CHECK-RAW: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]]
+// CHECK-RAW: [[RAWVALUE_ADDR:%[0-9]+]] = struct_element_addr [[WRITE]]
+// CHECK-RAW: assign [[BRIDGED]] to [[RAWVALUE_ADDR]]
+// CHECK-RAW: end_borrow [[BORROWED_COPIED_STR]] from [[COPIED_STR]]
+// CHECK-RAW: end_borrow [[BORROWED_STR]] from [[STR]]
+
+func getRawValue(ed: ErrorDomain) -> String {
+ return ed.rawValue
+}
+
+// CHECK-RAW-LABEL: sil shared [serializable] @$SSo14SNTErrorDomaina8rawValueSSvg
+// CHECK-RAW: bb0([[SELF:%[0-9]+]] : $ErrorDomain):
+// CHECK-RAW: [[STORED_VALUE:%[0-9]+]] = struct_extract [[SELF]] : $ErrorDomain, #ErrorDomain._rawValue
+// CHECK-RAW: [[STORED_VALUE_COPY:%.*]] = copy_value [[STORED_VALUE]]
+// CHECK-RAW: [[BRIDGE_FN:%[0-9]+]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK-RAW: [[OPT_STORED_VALUE_COPY:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[STORED_VALUE_COPY]]
+// CHECK-RAW: [[STRING_META:%[0-9]+]] = metatype $@thin String.Type
+// CHECK-RAW: [[STRING_RESULT:%[0-9]+]] = apply [[BRIDGE_FN]]([[OPT_STORED_VALUE_COPY]], [[STRING_META]])
+// CHECK-RAW: return [[STRING_RESULT]]
+
+class ObjCTest {
+ // CHECK-RAW-LABEL: sil hidden @$S7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGF : $@convention(method) (@guaranteed Optional<ErrorDomain>, @guaranteed ObjCTest) -> @owned Optional<ErrorDomain> {
+ // CHECK-RAW: sil hidden [thunk] @$S7newtype8ObjCTestC19optionalPassThroughySo14SNTErrorDomainaSgAGFTo : $@convention(objc_method) (Optional<ErrorDomain>, ObjCTest) -> Optional<ErrorDomain> {
+ @objc func optionalPassThrough(_ ed: ErrorDomain?) -> ErrorDomain? {
+ return ed
+ }
+
+ // CHECK-RAW-LABEL: sil hidden @$S7newtype8ObjCTestC18integerPassThroughySo5MyIntaAFF : $@convention(method) (MyInt, @guaranteed ObjCTest) -> MyInt {
+ // CHECK-RAW: sil hidden [thunk] @$S7newtype8ObjCTestC18integerPassThroughySo5MyIntaAFFTo : $@convention(objc_method) (MyInt, ObjCTest) -> MyInt {
+ @objc func integerPassThrough(_ ed: MyInt) -> MyInt {
+ return ed
+ }
+}
+
+// These use a bridging conversion with a specialization of a generic witness.
+// CHECK-RAW-LABEL: sil hidden @$S7newtype15bridgeToNewtypeSo8MyStringayF
+func bridgeToNewtype() -> MyString {
+// CHECK-RAW: [[STRING:%.*]] = apply
+// CHECK-RAW: [[TO_NS:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+// CHECK-RAW: [[BORROW:%.*]] = begin_borrow [[STRING]]
+// CHECK-RAW: [[NS:%.*]] = apply [[TO_NS]]([[BORROW]])
+// CHECK-RAW: [[TO_MY:%.*]] = function_ref @$Ss20_SwiftNewtypeWrapperPss21_ObjectiveCBridgeable8RawValueRpzrlE026_unconditionallyBridgeFromD1CyxAD_01_D5CTypeQZSgFZ : $@convention(method) <τ_0_0 where τ_0_0 : _SwiftNewtypeWrapper, τ_0_0.RawValue : _ObjectiveCBridgeable> (@guaranteed Optional<τ_0_0.RawValue._ObjectiveCType>, @thick τ_0_0.Type)
+// CHECK-RAW: [[OPTNS:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NS]]
+// CHECK-RAW: [[META:%.*]] = metatype $@thick MyString.Type
+// CHECK-RAW: apply [[TO_MY]]<MyString, String>({{.*}}, [[OPTNS]], [[META]])
+ return "foo" as NSString as MyString
+}
+
+// CHECK-RAW-LABEL: sil hidden @$S7newtype17bridgeFromNewtype6stringSSSo8MyStringa_tF
+func bridgeFromNewtype(string: MyString) -> String {
+// CHECK-RAW: [[FROM_MY:%.*]] = function_ref @$Ss20_SwiftNewtypeWrapperPss21_ObjectiveCBridgeable8RawValueRpzrlE09_bridgeToD1CAD_01_D5CTypeQZyF : $@convention(method) <τ_0_0 where τ_0_0 : _SwiftNewtypeWrapper, τ_0_0.RawValue : _ObjectiveCBridgeable> (@in_guaranteed τ_0_0) -> @owned τ_0_0.RawValue._ObjectiveCType
+// CHECK-RAW: [[NS:%.*]] = apply [[FROM_MY]]<MyString, String>(
+// CHECK-RAW: [[FROM_NS:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK-RAW: [[OPTNS:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NS]]
+// CHECK-RAW: [[META:%.*]] = metatype $@thin String.Type
+// CHECK-RAW: apply [[FROM_NS]]([[OPTNS]], [[META]])
+ return string as NSString as String
+}
diff --git a/test/SILGen/plus_zero_noescape_reabstraction.swift b/test/SILGen/plus_zero_noescape_reabstraction.swift
new file mode 100644
index 0000000..36d8a93
--- /dev/null
+++ b/test/SILGen/plus_zero_noescape_reabstraction.swift
@@ -0,0 +1,24 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct S {}
+
+func noescape_concrete(_ x: (S) -> S) {
+ noescape_generic(x)
+}
+
+func noescape_generic<T>(_ x: (T) -> T) {
+}
+
+// CHECK-LABEL: sil hidden @$S22noescape_reabstraction0A9_concreteyyAA1SVADXEF
+// CHECK: function_ref [[REABSTRACTION_THUNK:@\$S22noescape_reabstraction1SVACIgyd_A2CIegnr_TR]]
+
+func concrete(_ x: (S) -> S) {
+ noescape_generic(x)
+}
+
+func generic<T>(_ x: (T) -> T) {
+}
+
+// CHECK-LABEL: sil hidden @$S22noescape_reabstraction8concreteyyAA1SVADXEF
+// CHECK: function_ref [[REABSTRACTION_THUNK]]
diff --git a/test/SILGen/plus_zero_objc_attr_NSManaged.swift b/test/SILGen/plus_zero_objc_attr_NSManaged.swift
new file mode 100644
index 0000000..64754aa
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_attr_NSManaged.swift
@@ -0,0 +1,137 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs %s -I %S/Inputs -enable-source-import -emit-silgen -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+// This file is also used by objc_attr_NSManaged_multi.swift.
+
+import Foundation
+import gizmo
+
+@objc class X : NSObject {
+ func foo() -> X { return self }
+}
+
+class SwiftGizmo : Gizmo {
+ @NSManaged var x: X
+
+ @NSManaged func kvc()
+
+ // CHECK-NOT: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC1x{{[_0-9a-zA-Z]*}}fgTo
+ // CHECK-NOT: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC1x{{[_0-9a-zA-Z]*}}fsTo
+ // CHECK-NOT: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC3kvc{{[_0-9a-zA-Z]*}}FTo
+
+ // Make sure that we're calling through the @objc entry points.
+ // CHECK-LABEL: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC7modifyX{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed SwiftGizmo) -> () {
+ func modifyX() {
+ // CHECK: [[GETTER:%[0-9]+]] = objc_method [[SELF:%.*]] : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : (SwiftGizmo) -> () -> X, $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
+ // CHECK-NEXT: apply [[GETTER]]([[SELF]]) : $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
+ // CHECK-NOT: return
+ // CHECK: [[SETTER:%[0-9]+]] = objc_method [[SELF]] : $SwiftGizmo, #SwiftGizmo.x!setter.1.foreign : (SwiftGizmo) -> (X) -> (), $@convention(objc_method) (X, SwiftGizmo) -> ()
+ // CHECK: apply [[SETTER]]([[XMOD:%.*]], [[SELF]]) : $@convention(objc_method) (X, SwiftGizmo) -> ()
+ x = x.foo()
+ // CHECK: return
+ }
+
+ // CHECK-LABEL: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC8testFunc{{[_0-9a-zA-Z]*}}F
+ func testFunc() {
+ // CHECK: = objc_method %0 : $SwiftGizmo, #SwiftGizmo.kvc!1.foreign : (SwiftGizmo) -> () -> (), $@convention(objc_method) (SwiftGizmo) -> ()
+ // CHECK: return
+ kvc()
+ }
+}
+
+extension SwiftGizmo {
+ @NSManaged func extKVC()
+
+ // CHECK-LABEL: $S19objc_attr_NSManaged10SwiftGizmoC7testExt{{[_0-9a-zA-Z]*}}F
+ func testExt() {
+ // CHECK: = objc_method %0 : $SwiftGizmo, #SwiftGizmo.extKVC!1.foreign : (SwiftGizmo) -> () -> (), $@convention(objc_method) (SwiftGizmo) -> ()
+ // CHECK: return
+ extKVC()
+ }
+}
+
+final class FinalGizmo : SwiftGizmo {
+ @NSManaged var y: String
+
+ @NSManaged func kvc2()
+}
+
+extension FinalGizmo {
+ @NSManaged func extKVC2()
+
+ // CHECK-LABEL: $S19objc_attr_NSManaged10FinalGizmoC8testExt2{{[_0-9a-zA-Z]*}}F
+ func testExt2() {
+ // CHECK: = objc_method %0 : $FinalGizmo, #FinalGizmo.extKVC2!1.foreign : (FinalGizmo) -> () -> (), $@convention(objc_method) (FinalGizmo) -> ()
+ // CHECK: return
+ extKVC2()
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S19objc_attr_NSManaged9testFinalySSAA0E5GizmoCF : $@convention(thin) (@guaranteed FinalGizmo) -> @owned String {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $FinalGizmo):
+// CHECK: objc_method [[ARG]] : $FinalGizmo, #FinalGizmo.kvc2!1.foreign : (FinalGizmo) -> () -> (), $@convention(objc_method) (FinalGizmo) -> ()
+// CHECK-NOT: return
+// CHECK: objc_method [[ARG]] : $FinalGizmo, #FinalGizmo.y!getter.1.foreign : (FinalGizmo) -> () -> String, $@convention(objc_method) (FinalGizmo) -> @autoreleased NSString
+// CHECK: return
+func testFinal(_ obj: FinalGizmo) -> String {
+ obj.kvc2()
+ return obj.y
+}
+
+// SR-2673: @NSManaged property can't satisfy protocol requirement
+@objc protocol ObjCProto {
+ var managedProp: String { get set }
+ var managedExtProp: AnyObject { get }
+}
+
+class ProtoAdopter: Gizmo, ObjCProto {
+ @NSManaged var managedProp: String
+}
+extension ProtoAdopter {
+ @NSManaged var managedExtProp: AnyObject
+}
+
+
+// SR-6534: @NSManaged properties can be 'final'
+protocol EntityIDProto {
+ var entityID: String { get set }
+}
+
+class FinalEntity: NSObject, EntityIDProto {
+ @NSManaged final var entityID: String
+}
+
+// CHECK-LABEL: sil private @$S19objc_attr_NSManaged11FinalEntityC8entityIDSSvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout FinalEntity, @thick FinalEntity.Type) -> ()
+// CHECK: objc_method {{.*}} : $FinalEntity, #FinalEntity.entityID!setter.1.foreign
+// CHECK: return
+
+// CHECK-LABEL: sil hidden @$S19objc_attr_NSManaged11FinalEntityC8entityIDSSvm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed FinalEntity) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK: objc_method {{.*}} : $FinalEntity, #FinalEntity.entityID!getter.1.foreign
+// CHECK: return
+
+// CHECK-NOT: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC1xAA1XCfgTo : $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
+// CHECK-NOT: sil hidden @$S19objc_attr_NSManaged10SwiftGizmoC1xAA1XCfsTo
+// CHECK-NOT: sil hidden @$S19objc_attr_NSManaged10{{[_0-9a-zA-Z]*}}FinalGizmoC1yytfgTo
+
+// The vtable should not contain any entry points for getters and setters.
+// CHECK-LABEL: sil_vtable SwiftGizmo {
+// CHECK-NEXT: #SwiftGizmo.modifyX!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7modifyXyyF
+// CHECK-NEXT: #SwiftGizmo.testFunc!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC8testFuncyyF
+// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoCACSgycfc
+// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7bellsOnACSgSi_tcfc
+// CHECK-NEXT: #SwiftGizmo.deinit!deallocator: @$S19objc_attr_NSManaged10SwiftGizmoCfD
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_vtable FinalGizmo {
+// CHECK-NEXT: #SwiftGizmo.modifyX!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC7modifyX{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #SwiftGizmo.testFunc!1: {{.*}} : @$S19objc_attr_NSManaged10SwiftGizmoC8testFunc{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10FinalGizmoC{{[_0-9a-zA-Z]*}}fc
+// CHECK-NEXT: #SwiftGizmo.init!initializer.1: {{.*}} : @$S19objc_attr_NSManaged10FinalGizmoC{{[_0-9a-zA-Z]*}}fc
+// CHECK-NEXT: #FinalGizmo.deinit!deallocator: @$S19objc_attr_NSManaged10FinalGizmoCfD
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_vtable ProtoAdopter {
+// CHECK-NOT: managed{{.*}}Prop
+// CHECK: {{^}$}}
diff --git a/test/SILGen/plus_zero_objc_attr_NSManaged_multi.swift b/test/SILGen/plus_zero_objc_attr_NSManaged_multi.swift
new file mode 100644
index 0000000..c1c9a5f
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_attr_NSManaged_multi.swift
@@ -0,0 +1,34 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs -primary-file %s %S/objc_attr_NSManaged.swift -I %S/Inputs -enable-source-import -emit-silgen -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+// CHECK-LABEL: sil hidden @$S25objc_attr_NSManaged_multi9testMultiyyXlAA10SwiftGizmoCF : $@convention(thin) (@guaranteed SwiftGizmo) -> @owned AnyObject {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $SwiftGizmo):
+// CHECK: = objc_method [[ARG]] : $SwiftGizmo, #SwiftGizmo.kvc!1.foreign : (SwiftGizmo) -> () -> (), $@convention(objc_method) (SwiftGizmo) -> ()
+// CHECK-NOT: return
+// CHECK: = objc_method [[ARG]] : $SwiftGizmo, #SwiftGizmo.extKVC!1.foreign : (SwiftGizmo) -> () -> (), $@convention(objc_method) (SwiftGizmo) -> ()
+// CHECK-NOT: return
+// CHECK: objc_method [[ARG]] : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : (SwiftGizmo) -> () -> X, $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
+// CHECK: return
+func testMulti(_ obj: SwiftGizmo) -> AnyObject {
+ obj.kvc()
+ obj.extKVC()
+ return obj.x
+}
+
+// CHECK-LABEL: sil hidden @$S25objc_attr_NSManaged_multi14testFinalMultiySSAA0F5GizmoCF : $@convention(thin) (@guaranteed FinalGizmo) -> @owned String {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $FinalGizmo):
+// CHECK: objc_method [[ARG]] : $FinalGizmo, #FinalGizmo.kvc2!1.foreign : (FinalGizmo) -> () -> (), $@convention(objc_method) (FinalGizmo) -> ()
+// CHECK-NOT: return
+// CHECK: objc_method [[ARG]] : $FinalGizmo, #FinalGizmo.extKVC2!1.foreign : (FinalGizmo) -> () -> (), $@convention(objc_method) (FinalGizmo) -> ()
+// CHECK-NOT: return
+// CHECK: objc_method [[ARG]] : $FinalGizmo, #FinalGizmo.y!getter.1.foreign : (FinalGizmo) -> () -> String, $@convention(objc_method) (FinalGizmo) -> @autoreleased NSString
+// CHECK: return
+func testFinalMulti(_ obj: FinalGizmo) -> String {
+ obj.kvc2()
+ obj.extKVC2()
+ return obj.y
+}
diff --git a/test/SILGen/plus_zero_objc_blocks_bridging.swift b/test/SILGen/plus_zero_objc_blocks_bridging.swift
new file mode 100644
index 0000000..06b79c0
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_blocks_bridging.swift
@@ -0,0 +1,202 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -verify -emit-silgen -I %S/Inputs -disable-objc-attr-requires-foundation-module -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -verify -emit-silgen -I %S/Inputs -disable-objc-attr-requires-foundation-module -enable-sil-ownership %s | %FileCheck %s --check-prefix=GUARANTEED
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+@objc class Foo {
+// CHECK-LABEL: sil hidden [thunk] @$S20objc_blocks_bridging3FooC3foo_1xS3iXE_SitFTo :
+ // CHECK: bb0([[ARG1:%.*]] : @unowned $@convention(block) @noescape (Int) -> Int, {{.*}}, [[SELF:%.*]] : @unowned $Foo):
+ // CHECK: [[ARG1_COPY:%.*]] = copy_block [[ARG1]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[THUNK:%.*]] = function_ref @$SS2iIyByd_S2iIegyd_TR
+ // CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG1_COPY]])
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[BRIDGED]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@noescape @callee_guaranteed (Int) -> Int, Int, @guaranteed Foo) -> Int
+ // CHECK: apply [[NATIVE]]([[CONVERT]], {{.*}}, [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: } // end sil function '$S20objc_blocks_bridging3FooC3foo_1xS3iXE_SitFTo'
+ dynamic func foo(_ f: (Int) -> Int, x: Int) -> Int {
+ return f(x)
+ }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S20objc_blocks_bridging3FooC3bar_1xS3SXE_SStFTo : $@convention(objc_method) (@convention(block) @noescape (NSString) -> @autoreleased NSString, NSString, Foo) -> @autoreleased NSString {
+ // CHECK: bb0([[BLOCK:%.*]] : @unowned $@convention(block) @noescape (NSString) -> @autoreleased NSString, [[NSSTRING:%.*]] : @unowned $NSString, [[SELF:%.*]] : @unowned $Foo):
+ // CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ // CHECK: [[NSSTRING_COPY:%.*]] = copy_value [[NSSTRING]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[THUNK:%.*]] = function_ref @$SSo8NSStringCABIyBya_S2SIeggo_TR
+ // CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[BLOCK_COPY]])
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[BRIDGED]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC3bar{{[_0-9a-zA-Z]*}}F : $@convention(method) (@noescape @callee_guaranteed (@guaranteed String) -> @owned String, @guaranteed String, @guaranteed Foo) -> @owned String
+ // CHECK: apply [[NATIVE]]([[CONVERT]], {{%.*}}, [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: } // end sil function '$S20objc_blocks_bridging3FooC3bar_1xS3SXE_SStFTo'
+ dynamic func bar(_ f: (String) -> String, x: String) -> String {
+ return f(x)
+ }
+
+ // GUARANTEED-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSo8NSStringCABIyBya_S2SIeggo_TR : $@convention(thin) (@guaranteed String, @guaranteed @convention(block) @noescape (NSString) -> @autoreleased NSString) -> @owned String {
+ // GUARANTEED: bb0(%0 : @guaranteed $String, [[BLOCK:%.*]] : @guaranteed $@convention(block) @noescape (NSString) -> @autoreleased NSString):
+ // GUARANTEED: [[BRIDGE:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // GUARANTEED: [[NSSTR:%.*]] = apply [[BRIDGE]](%0)
+ // GUARANTEED: apply [[BLOCK]]([[NSSTR]]) : $@convention(block) @noescape (NSString) -> @autoreleased NSString
+ // GUARANTEED: } // end sil function '$SSo8NSStringCABIyBya_S2SIeggo_TR'
+
+ // CHECK-LABEL: sil hidden [thunk] @$S20objc_blocks_bridging3FooC3bas_1xSSSgA2FXE_AFtFTo : $@convention(objc_method) (@convention(block) @noescape (Optional<NSString>) -> @autoreleased Optional<NSString>, Optional<NSString>, Foo) -> @autoreleased Optional<NSString> {
+ // CHECK: bb0([[BLOCK:%.*]] : @unowned $@convention(block) @noescape (Optional<NSString>) -> @autoreleased Optional<NSString>, [[OPT_STRING:%.*]] : @unowned $Optional<NSString>, [[SELF:%.*]] : @unowned $Foo):
+ // CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ // CHECK: [[OPT_STRING_COPY:%.*]] = copy_value [[OPT_STRING]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[THUNK:%.*]] = function_ref @$SSo8NSStringCSgACIyBya_SSSgADIeggo_TR
+ // CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[BLOCK_COPY]])
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[BRIDGED]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC3bas{{[_0-9a-zA-Z]*}}F : $@convention(method) (@noescape @callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>, @guaranteed Optional<String>, @guaranteed Foo) -> @owned Optional<String>
+ // CHECK: apply [[NATIVE]]([[CONVERT]], {{%.*}}, [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ dynamic func bas(_ f: (String?) -> String?, x: String?) -> String? {
+ return f(x)
+ }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S20objc_blocks_bridging3FooC16cFunctionPointer{{[_0-9a-zA-Z]*}}FTo
+ // CHECK: bb0([[F:%.*]] : @trivial $@convention(c) @noescape (Int) -> Int, [[X:%.*]] : @trivial $Int, [[SELF:%.*]] : @unowned $Foo):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC16cFunctionPointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[NATIVE]]([[F]], [[X]], [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ dynamic func cFunctionPointer(_ fp: @convention(c) (Int) -> Int, x: Int) -> Int {
+ _ = fp(x)
+ }
+
+ // Blocks and C function pointers must not be reabstracted when placed in optionals.
+ // CHECK-LABEL: sil hidden [thunk] @$S20objc_blocks_bridging3FooC7optFunc{{[_0-9a-zA-Z]*}}FTo
+ // CHECK: bb0([[ARG0:%.*]] : @unowned $Optional<@convention(block) (NSString) -> @autoreleased NSString>,
+ // CHECK: [[COPY:%.*]] = copy_block [[ARG0]]
+ // CHECK: switch_enum [[COPY]] : $Optional<@convention(block) (NSString) -> @autoreleased NSString>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_BB]]([[BLOCK:%.*]] : @owned $@convention(block) (NSString) -> @autoreleased NSString):
+ // TODO: redundant reabstractions here
+ // CHECK: [[BLOCK_THUNK:%.*]] = function_ref @$SSo8NSStringCABIeyBya_S2SIeggo_TR
+ // CHECK: [[BRIDGED:%.*]] = partial_apply [callee_guaranteed] [[BLOCK_THUNK]]([[BLOCK]])
+ // CHECK: enum $Optional<@callee_guaranteed (@guaranteed String) -> @owned String>, #Optional.some!enumelt.1, [[BRIDGED]]
+ // CHECK: [[NATIVE:%.*]] = function_ref @$S20objc_blocks_bridging3FooC7optFunc{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed Optional<@callee_guaranteed (@guaranteed String) -> @owned String>, @guaranteed String, @guaranteed Foo) -> @owned Optional<String>
+ // CHECK: apply [[NATIVE]]
+ dynamic func optFunc(_ f: ((String) -> String)?, x: String) -> String? {
+ return f?(x)
+ }
+
+ // CHECK-LABEL: sil hidden @$S20objc_blocks_bridging3FooC19optCFunctionPointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[FP_BUF:%.*]] = unchecked_enum_data %0
+ dynamic func optCFunctionPointer(_ fp: (@convention(c) (String) -> String)?, x: String) -> String? {
+ return fp?(x)
+ }
+}
+
+// => SEMANTIC SIL TODO: This test needs to be filled out more for ownership
+//
+// CHECK-LABEL: sil hidden @$S20objc_blocks_bridging10callBlocks{{[_0-9a-zA-Z]*}}F
+func callBlocks(_ x: Foo,
+ f: @escaping (Int) -> Int,
+ g: @escaping (String) -> String,
+ h: @escaping (String?) -> String?
+) -> (Int, String, String?, String?) {
+ // CHECK: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @guaranteed $@callee_guaranteed (Int) -> Int, [[ARG2:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed String) -> @owned String, [[ARG3:%.*]] : @guaranteed $@callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>):
+ // CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[ARG1]]
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[CLOSURE_COPY]]
+ // CHECK: [[F_BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage
+ // CHECK: [[F_BLOCK_CAPTURE:%.*]] = project_block_storage [[F_BLOCK_STORAGE]]
+ // CHECK: store [[CONVERT]] to [trivial] [[F_BLOCK_CAPTURE]]
+ // CHECK: [[F_BLOCK_INVOKE:%.*]] = function_ref @$SS2iIgyd_S2iIyByd_TR
+ // CHECK: [[F_STACK_BLOCK:%.*]] = init_block_storage_header [[F_BLOCK_STORAGE]] : {{.*}}, invoke [[F_BLOCK_INVOKE]]
+ // CHECK: [[F_BLOCK:%.*]] = copy_block [[F_STACK_BLOCK]]
+ // CHECK: [[FOO:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.foo!1.foreign
+ // CHECK: apply [[FOO]]([[F_BLOCK]]
+
+ // CHECK: [[G_BLOCK_INVOKE:%.*]] = function_ref @$SS2SIggo_So8NSStringCABIyBya_TR
+ // CHECK: [[G_STACK_BLOCK:%.*]] = init_block_storage_header {{.*}}, invoke [[G_BLOCK_INVOKE]]
+ // CHECK: [[G_BLOCK:%.*]] = copy_block [[G_STACK_BLOCK]]
+ // CHECK: [[BAR:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.bar!1.foreign
+ // CHECK: apply [[BAR]]([[G_BLOCK]]
+
+ // CHECK: [[H_BLOCK_INVOKE:%.*]] = function_ref @$SSSSgAAIggo_So8NSStringCSgADIyBya_TR
+ // CHECK: [[H_STACK_BLOCK:%.*]] = init_block_storage_header {{.*}}, invoke [[H_BLOCK_INVOKE]]
+ // CHECK: [[H_BLOCK:%.*]] = copy_block [[H_STACK_BLOCK]]
+ // CHECK: [[BAS:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.bas!1.foreign
+ // CHECK: apply [[BAS]]([[H_BLOCK]]
+
+ // CHECK: [[G_BLOCK:%.*]] = copy_block {{%.*}} : $@convention(block) (NSString) -> @autoreleased NSString
+ // CHECK: enum $Optional<@convention(block) (NSString) -> @autoreleased NSString>, #Optional.some!enumelt.1, [[G_BLOCK]]
+
+ return (x.foo(f, x: 0), x.bar(g, x: "one"), x.bas(h, x: "two"), x.optFunc(g, x: "three"))
+}
+
+class Test: NSObject {
+ func blockTakesBlock() -> ((Int) -> Int) -> Int {}
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS2iIgyd_SiIegyd_S2iIyByd_SiIeyByd_TR
+// CHECK: [[BLOCK_COPY:%.*]] = copy_block [[ORIG_BLOCK:%.*]] :
+// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[BLOCK_COPY]])
+// CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[CLOSURE]]
+// CHECK: [[RESULT:%.*]] = apply {{%.*}}([[CONVERT]])
+// CHECK: return [[RESULT]]
+
+func clearDraggingItemImageComponentsProvider(_ x: NSDraggingItem) {
+ x.imageComponentsProvider = {}
+}
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSayypGIego_So7NSArrayCSgIeyBa_TR
+// CHECK: [[CONVERT:%.*]] = function_ref @$SSa10FoundationE19_bridgeToObjectiveCSo7NSArrayCyF
+// CHECK: [[CONVERTED:%.*]] = apply [[CONVERT]]
+// CHECK: [[OPTIONAL:%.*]] = enum $Optional<NSArray>, #Optional.some!enumelt.1, [[CONVERTED]]
+// CHECK: return [[OPTIONAL]]
+
+// CHECK-LABEL: sil hidden @{{.*}}bridgeNonnullBlockResult{{.*}}
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSSIego_So8NSStringCSgIeyBa_TR
+// CHECK: [[CONVERT:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+// CHECK: [[BRIDGED:%.*]] = apply [[CONVERT]]
+// CHECK: [[OPTIONAL_BRIDGED:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK: return [[OPTIONAL_BRIDGED]]
+func bridgeNonnullBlockResult() {
+ nonnullStringBlockResult { return "test" }
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}bridgeNoescapeBlock{{.*}}
+func bridgeNoescapeBlock() {
+ // CHECK: function_ref @$SIg_IyB_TR
+ noescapeBlockAlias { }
+ // CHECK: function_ref @$SIg_IyB_TR
+ noescapeNonnullBlockAlias { }
+}
+
+class ObjCClass : NSObject {}
+
+extension ObjCClass {
+ func someDynamicMethod(closure: (() -> ()) -> ()) {}
+}
+
+struct GenericStruct<T> {
+ let closure: (() -> ()) -> ()
+
+ func doStuff(o: ObjCClass) {
+ o.someDynamicMethod(closure: closure)
+ }
+}
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SIg_Igy_IyB_IyBy_TR : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_guaranteed (@noescape @callee_guaranteed () -> ()) -> (), @convention(block) @noescape () -> ()) -> () {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SIyB_Ieg_TR : $@convention(thin) (@guaranteed @convention(block) @noescape () -> ()) -> ()
+
+// rdar://35402696
+func takeOptStringFunction(fn: (String) -> String?) {}
+func testGlobalBlock() {
+ takeOptStringFunction(fn: GlobalBlock)
+}
+// CHECK-LABEL: sil hidden @$S20objc_blocks_bridging15testGlobalBlockyyF
+// CHECK: global_addr @GlobalBlock : $*@convention(block) (NSString) -> @autoreleased Optional<NSString>
+// CHECK: function_ref @$SSo8NSStringCABSgIeyBya_S2SIeggo_TR : $@convention(thin) (@guaranteed String, @guaranteed @convention(block) (NSString) -> @autoreleased Optional<NSString>) -> @owned String
diff --git a/test/SILGen/plus_zero_objc_bridged_results.swift b/test/SILGen/plus_zero_objc_bridged_results.swift
new file mode 100644
index 0000000..862c5b1
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_bridged_results.swift
@@ -0,0 +1,154 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen %s -Xllvm -sil-print-debuginfo -import-objc-header %S/Inputs/objc_bridged_results.h -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results11testNonnullySayypGSo4TestCF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+// CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.nonnullArray!getter.1.foreign : (Test) -> () -> [Any], $@convention(objc_method) (Test) -> @autoreleased Optional<NSArray>
+// CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSArray>
+// CHECK: [[CONVERT:%[0-9]+]] = function_ref @$SSa10FoundationE36_unconditionallyBridgeFromObjectiveCySayxGSo7NSArrayCSgFZ
+// CHECK: [[ARRAY_META:%[0-9]+]] = metatype $@thin Array<Any>.Type
+// CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<Any>([[COCOA_VAL]], [[ARRAY_META]])
+// CHECK-NOT: destroy_value %0 : $Test
+// CHECK: return [[RESULT]] : $Array<Any>
+func testNonnull(_ obj: Test) -> [Any] {
+ return obj.nonnullArray
+} // CHECK: } // end sil function '$S20objc_bridged_results11testNonnullySayypGSo4TestCF'
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results12testNullableySayypGSgSo4TestCF
+func testNullable(_ obj: Test) -> [Any]? {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.nullableArray!getter.1.foreign : (Test) -> () -> [Any]?, $@convention(objc_method) (Test) -> @autoreleased Optional<NSArray>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSArray>
+ // CHECK: switch_enum [[COCOA_VAL]] : $Optional<NSArray>, case #Optional.some!enumelt.1: [[CASE_NON_NIL:bb[0-9]+]], case #Optional.none!enumelt: [[CASE_NIL:bb[0-9]+]]
+ //
+ // CHECK: [[CASE_NON_NIL]]([[COCOA_VAL_NON_NIL:%.*]] : @owned $NSArray):
+ // CHECK-NOT: unchecked_enum_data
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$SSa10FoundationE36_unconditionallyBridgeFromObjectiveCySayxGSo7NSArrayCSgFZ
+ // CHECK: [[COCOA_SOME_VAL:%[0-9]+]] = enum $Optional<NSArray>, #Optional.some!enumelt.1, [[COCOA_VAL_NON_NIL]]
+ // CHECK: [[ARRAY_META:%[0-9]+]] = metatype $@thin Array<Any>.Type
+ // CHECK: [[RESULT_VAL:%[0-9]+]] = apply [[CONVERT]]<Any>([[COCOA_SOME_VAL]], [[ARRAY_META]])
+ // CHECK: [[RESULT_SOME:%[0-9]+]] = enum $Optional<Array<Any>>, #Optional.some!enumelt.1, [[RESULT_VAL]] : $Array<Any>
+ // CHECK: br [[FINISH:bb[0-9]+]]([[RESULT_SOME]] : $Optional<Array<Any>>)
+
+ // CHECK: [[CASE_NIL]]:
+ // CHECK: [[RESULT_NONE:%[0-9]+]] = enum $Optional<Array<Any>>, #Optional.none!enumelt
+ // CHECK: br [[FINISH]]([[RESULT_NONE]] : $Optional<Array<Any>>)
+
+ // CHECK: [[FINISH]]([[RESULT:%[0-9]+]] : @owned $Optional<Array<Any>>):
+ // CHECK-NOT: destroy_value [[ARG]] : $Test
+ // CHECK: return [[RESULT]] : $Optional<Array<Any>>
+ return obj.nullableArray
+} // CHECK: } // end sil function '$S20objc_bridged_results12testNullableySayypGSgSo4TestCF'
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results19testNullUnspecifiedySayypGSgSo4TestCF
+func testNullUnspecified(_ obj: Test) -> [Any]! {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.nullUnspecifiedArray!getter.1.foreign : (Test) -> () -> [Any]?, $@convention(objc_method) (Test) -> @autoreleased Optional<NSArray>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSArray>
+ // CHECK: switch_enum [[COCOA_VAL]] : $Optional<NSArray>, case #Optional.some!enumelt.1: [[CASE_NON_NIL:bb[0-9]+]], case #Optional.none!enumelt: [[CASE_NIL:bb[0-9]+]]
+
+ // CHECK: [[CASE_NON_NIL]]([[COCOA_VAL_NON_NIL:%.*]] : @owned $NSArray):
+ // CHECK-NOT: unchecked_enum_data
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$SSa10FoundationE36_unconditionallyBridgeFromObjectiveCySayxGSo7NSArrayCSgFZ
+ // CHECK: [[COCOA_SOME_VAL:%[0-9]+]] = enum $Optional<NSArray>, #Optional.some!enumelt.1, [[COCOA_VAL_NON_NIL]]
+ // CHECK: [[ARRAY_META:%[0-9]+]] = metatype $@thin Array<Any>.Type
+ // CHECK: [[RESULT_VAL:%[0-9]+]] = apply [[CONVERT]]<Any>([[COCOA_SOME_VAL]], [[ARRAY_META]])
+ // CHECK: [[RESULT_SOME:%[0-9]+]] = enum $Optional<Array<Any>>, #Optional.some!enumelt.1, [[RESULT_VAL]] : $Array<Any>
+ // CHECK: br [[FINISH:bb[0-9]+]]([[RESULT_SOME]] : $Optional<Array<Any>>)
+
+ // CHECK: [[CASE_NIL]]:
+ // CHECK: [[RESULT_NONE:%[0-9]+]] = enum $Optional<Array<Any>>, #Optional.none!enumelt
+ // CHECK: br [[FINISH]]([[RESULT_NONE]] : $Optional<Array<Any>>)
+
+ // CHECK: [[FINISH]]([[RESULT:%[0-9]+]] : @owned $Optional<Array<Any>>):
+ // CHECK-NOT: destroy_value [[ARG]] : $Test
+ // CHECK: return [[RESULT]] : $Optional<Array<Any>>
+ return obj.nullUnspecifiedArray
+} // CHECK: } // end sil function '$S20objc_bridged_results19testNullUnspecifiedySayypGSgSo4TestCF'
+
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results21testNonnullDictionaryys0F0Vys11AnyHashableVypGSo4TestCF
+func testNonnullDictionary(_ obj: Test) -> [AnyHashable: Any] {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.nonnullDictionary!getter.1.foreign : (Test) -> () -> [AnyHashable : Any], $@convention(objc_method) (Test) -> @autoreleased Optional<NSDictionary>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSDictionary>
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$Ss10DictionaryV10FoundationE36_unconditionallyBridgeFromObjectiveCyAByxq_GSo12NSDictionaryCSgFZ
+ // CHECK: [[DICT_META:%[0-9]+]] = metatype $@thin Dictionary<AnyHashable, Any>.Type
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<AnyHashable, Any>([[COCOA_VAL]], [[DICT_META]])
+ // CHECK-NOT: destroy_value [[ARG]] : $Test
+ // CHECK: return [[RESULT]] : $Dictionary<AnyHashable, Any>
+ return obj.nonnullDictionary
+} // CHECK: } // end sil function '$S20objc_bridged_results21testNonnullDictionaryys0F0Vys11AnyHashableVypGSo4TestCF'
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results14testNonnullSetys0F0Vys11AnyHashableVGSo4TestCF
+func testNonnullSet(_ obj: Test) -> Set<AnyHashable> {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.nonnullSet!getter.1.foreign : (Test) -> () -> Set<AnyHashable>, $@convention(objc_method) (Test) -> @autoreleased Optional<NSSet>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSSet>
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$Ss3SetV10FoundationE36_unconditionallyBridgeFromObjectiveCyAByxGSo5NSSetCSgFZ
+ // CHECK: [[SET_META:%[0-9]+]] = metatype $@thin Set<AnyHashable>.Type
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<AnyHashable>([[COCOA_VAL]], [[SET_META]])
+ // CHECK-NOT: destroy_value [[ARG]] : $Test
+ // CHECK: return [[RESULT]] : $Set<AnyHashable>
+ return obj.nonnullSet
+} // CHECK: } // end sil function '$S20objc_bridged_results14testNonnullSetys0F0Vys11AnyHashableVGSo4TestCF'
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results17testNonnullStringySSSo4TestCF
+func testNonnullString(_ obj: Test) -> String {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.nonnullString!getter.1.foreign : (Test) -> () -> String, $@convention(objc_method) (Test) -> @autoreleased Optional<NSString>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Test) -> @autoreleased Optional<NSString>
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: [[STRING_META:%[0-9]+]] = metatype $@thin String.Type
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]([[COCOA_VAL]], [[STRING_META]]) : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
+ // CHECK-NOT: destroy_value [[ARG]] : $Test
+ // CHECK: return [[RESULT]] : $String
+ return obj.nonnullString
+} // CHECK: } // end sil function '$S20objc_bridged_results17testNonnullStringySSSo4TestCF'
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results13testClassPropSSyF
+func testClassProp() -> String {
+ // CHECK: [[CLASS:%.+]] = metatype $@objc_metatype Test.Type
+ // CHECK: [[METHOD:%.+]] = objc_method [[CLASS]] : $@objc_metatype Test.Type, #Test.nonnullSharedString!getter.1.foreign : (Test.Type) -> () -> String, $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[CLASS]]) : $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: [[STRING_META:%[0-9]+]] = metatype $@thin String.Type
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]([[COCOA_VAL]], [[STRING_META]]) : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
+ // CHECK: return [[RESULT]] : $String
+ return Test.nonnullSharedString
+} // CHECK: } // end sil function '$S20objc_bridged_results13testClassPropSSyF'
+
+
+// Note: This doesn't really "work" in that it doesn't accept a nil value the
+// way the others do, because subscripts are thunked. But the main thing is
+// not to crash trying to generate the thunk.
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results20testNonnullSubscriptySayypGSo4TestCF
+func testNonnullSubscript(_ obj: Test) -> [Any] {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Test):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $Test, #Test.subscript!getter.1.foreign : (Test) -> (Int) -> [Any], $@convention(objc_method) (Int, Test) -> @autoreleased Optional<NSArray>
+ // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]({{%[0-9]+}}, [[ARG]]) : $@convention(objc_method) (Int, Test) -> @autoreleased Optional<NSArray>
+ // CHECK: [[CONVERT:%[0-9]+]] = function_ref @$SSa10FoundationE36_unconditionallyBridgeFromObjectiveCySayxGSo7NSArrayCSgFZ
+ // CHECK: [[ARRAY_META:%[0-9]+]] = metatype $@thin Array<Any>.Type,
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]<Any>([[COCOA_VAL]], [[ARRAY_META]])
+ // CHECK-NOT: destroy_value [[ARG]] : $Test
+ // CHECK: return [[RESULT]] : $Array<Any>
+ return obj[0]
+} // CHECK: } // end sil function '$S20objc_bridged_results20testNonnullSubscriptySayypGSo4TestCF'
+
+
+// CHECK-LABEL: sil hidden @$S20objc_bridged_results19testPerformSelectoryySo8NSObjectCF
+func testPerformSelector(_ obj: NSObject) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $NSObject):
+ // CHECK: [[METHOD:%[0-9]+]] = objc_method [[ARG]] : $NSObject, #NSObject.perform!1.foreign
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[METHOD]]({{%[0-9]+}}, {{%[0-9]+}}, [[ARG]])
+ _ = obj.perform("foo", with: nil)
+ // CHECK-NOT: {{(retain|release).+}}[[RESULT]]
+ // CHECK-NOT: {{(retain|release).+}}[[RESULT]]
+} // CHECK: } // end sil function '$S20objc_bridged_results19testPerformSelectoryySo8NSObjectCF'
diff --git a/test/SILGen/plus_zero_objc_bridging.swift b/test/SILGen/plus_zero_objc_bridging.swift
new file mode 100644
index 0000000..c4c6e1a
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_bridging.swift
@@ -0,0 +1,648 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module -o %t -I %S/../Inputs/ObjCBridging %S/../Inputs/ObjCBridging/Appliances.swift
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %S/../Inputs/ObjCBridging -Xllvm -sil-full-demangle -emit-silgen %s -enable-sil-ownership | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-cpu --check-prefix=CHECK-%target-os-%target-cpu
+
+// REQUIRES: objc_interop
+
+import Foundation
+import Appliances
+
+
+func getDescription(_ o: NSObject) -> String {
+ return o.description
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging14getDescription{{.*}}F
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $NSObject):
+// CHECK: [[DESCRIPTION:%.*]] = objc_method [[ARG]] : $NSObject, #NSObject.description!getter.1.foreign
+// CHECK: [[OPT_BRIDGED:%.*]] = apply [[DESCRIPTION]]([[ARG]])
+// CHECK: switch_enum [[OPT_BRIDGED]] : $Optional<NSString>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]([[BRIDGED:%.*]] : @owned $NSString):
+// CHECK-NOT: unchecked_enum_data
+// CHECK: [[NSSTRING_TO_STRING:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK: [[BRIDGED_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK: [[NATIVE:%.*]] = apply [[NSSTRING_TO_STRING]]([[BRIDGED_BOX]],
+// CHECK: [[OPT_NATIVE:%.*]] = enum $Optional<String>, #Optional.some!enumelt.1, [[NATIVE]]
+// CHECK: br [[CONT_BB:bb[0-9]+]]([[OPT_NATIVE]] : $Optional<String>)
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: [[OPT_NATIVE:%.*]] = enum $Optional<String>, #Optional.none!enumelt
+// CHECK: br [[CONT_BB]]([[OPT_NATIVE]] : $Optional<String>)
+//
+// CHECK: [[CONT_BB]]([[OPT_NATIVE:%.*]] : @owned $Optional<String>):
+// CHECK: switch_enum [[OPT_NATIVE]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: unreachable
+//
+// CHECK: [[SOME_BB]]([[NATIVE:%.*]] : @owned $String):
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[NATIVE]]
+// CHECK:}
+
+func getUppercaseString(_ s: NSString) -> String {
+ return s.uppercase()
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging18getUppercaseString{{.*}}F
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $NSString):
+// -- The 'self' argument of NSString methods doesn't bridge.
+// CHECK-NOT: function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK-NOT: function_ref @swift_StringToNSString
+// CHECK: [[UPPERCASE_STRING:%.*]] = objc_method [[ARG]] : $NSString, #NSString.uppercase!1.foreign
+// CHECK: [[OPT_BRIDGED:%.*]] = apply [[UPPERCASE_STRING]]([[ARG]]) : $@convention(objc_method) (NSString) -> @autoreleased Optional<NSString>
+// CHECK: switch_enum [[OPT_BRIDGED]] : $Optional<NSString>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+//
+// CHECK: [[SOME_BB]]([[BRIDGED:%.*]] :
+// CHECK-NOT: unchecked_enum_data
+// CHECK: [[NSSTRING_TO_STRING:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK: [[BRIDGED_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK: [[NATIVE:%.*]] = apply [[NSSTRING_TO_STRING]]([[BRIDGED_BOX]]
+// CHECK: [[OPT_NATIVE:%.*]] = enum $Optional<String>, #Optional.some!enumelt.1, [[NATIVE]]
+// CHECK: br [[CONT_BB:bb[0-9]+]]([[OPT_NATIVE]] : $Optional<String>)
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: [[OPT_NATIVE:%.*]] = enum $Optional<String>, #Optional.none!enumelt
+// CHECK: br [[CONT_BB]]([[OPT_NATIVE]] : $Optional<String>)
+//
+// CHECK: [[CONT_BB]]([[OPT_NATIVE:%.*]] : @owned $Optional<String>):
+// CHECK: switch_enum [[OPT_NATIVE]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: unreachable
+//
+// CHECK: [[SOME_BB]]([[NATIVE:%.*]] : @owned $String):
+// CHECK: return [[NATIVE]]
+// CHECK: }
+
+// @interface Foo -(void) setFoo: (NSString*)s; @end
+func setFoo(_ f: Foo, s: String) {
+ var s = s
+ f.setFoo(s)
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging6setFoo{{.*}}F
+// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Foo, {{%.*}} : @guaranteed $String):
+// CHECK: [[NATIVE:%.*]] = load
+// CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+// CHECK: [[BORROWED_NATIVE:%.*]] = begin_borrow [[NATIVE]]
+// CHECK: [[BRIDGED:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_NATIVE]])
+// CHECK: [[OPT_BRIDGED:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK: [[SET_FOO:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.setFoo!1.foreign
+// CHECK: apply [[SET_FOO]]([[OPT_BRIDGED]], [[ARG0]]) : $@convention(objc_method) (Optional<NSString>, Foo) -> ()
+// CHECK: destroy_value [[OPT_BRIDGED]]
+// CHECK-NOT: destroy_value [[ARG0]]
+// CHECK: }
+
+// @interface Foo -(BOOL) zim; @end
+func getZim(_ f: Foo) -> Bool {
+ return f.zim()
+}
+
+// CHECK-ios-i386-LABEL: sil hidden @$S13objc_bridging6getZim{{.*}}F
+// CHECK-ios-i386: bb0([[SELF:%.*]] : @guaranteed $Foo):
+// CHECK-ios-i386: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
+// CHECK-ios-i386: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Bool
+// CHECK-ios-i386: [[OBJC_BOOL:%.*]] = apply [[METHOD]]([[BORROWED_SELF]]) : $@convention(objc_method) (Foo) -> ObjCBool
+// CHECK-ios-i386: end_borrow [[BORROWED_SELF]] from [[SELF]]
+// CHECK-ios-i386: [[CONVERT:%.*]] = function_ref @swift_ObjCBoolToBool : $@convention(thin) (ObjCBool) -> Bool
+// CHECK-ios-i386: [[SWIFT_BOOL:%.*]] = apply [[CONVERT]]([[OBJC_BOOL]]) : $@convention(thin) (ObjCBool) -> Bool
+// CHECK-ios-i386: return [[SWIFT_BOOL]] : $Bool
+// CHECK-ios-i386: }
+
+// CHECK-watchos-i386-LABEL: sil hidden @$S13objc_bridging6getZim{{.*}}F
+// CHECK-watchos-i386: bb0([[SELF:%.*]] : @guaranteed $Foo):
+// CHECK-watchos-i386: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
+// CHECK-watchos-i386: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Boo
+// CHECK-watchos-i386: [[BOOL:%.*]] = apply [[METHOD]]([[BORROWED_SELF]]) : $@convention(objc_method) (Foo) -> Bool
+// CHECK-watchos-i386: end_borrow [[BORROWED_SELF]] from [[SELF]]
+// CHECK-watchos-i386: return [[BOOL]] : $Bool
+// CHECK-watchos-i386: }
+
+// CHECK-macosx-x86_64-LABEL: sil hidden @$S13objc_bridging6getZim{{.*}}F
+// CHECK-macosx-x86_64: bb0([[SELF:%.*]] : @guaranteed $Foo):
+// CHECK-macosx-x86_64: [[METHOD:%.*]] = objc_method [[SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Bool
+// CHECK-macosx-x86_64: [[OBJC_BOOL:%.*]] = apply [[METHOD]]([[SELF]]) : $@convention(objc_method) (Foo) -> ObjCBool
+// CHECK-macosx-x86_64: [[CONVERT:%.*]] = function_ref @swift_ObjCBoolToBool : $@convention(thin) (ObjCBool) -> Bool
+// CHECK-macosx-x86_64: [[SWIFT_BOOL:%.*]] = apply [[CONVERT]]([[OBJC_BOOL]]) : $@convention(thin) (ObjCBool) -> Bool
+// CHECK-macosx-x86_64: return [[SWIFT_BOOL]] : $Bool
+// CHECK-macosx-x86_64: }
+
+// CHECK-ios-x86_64-LABEL: sil hidden @$S13objc_bridging6getZim{{.*}}F
+// CHECK-ios-x86_64: bb0([[SELF:%.*]] : @guaranteed $Foo):
+// CHECK-ios-x86_64: [[METHOD:%.*]] = objc_method [[SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Boo
+// CHECK-ios-x86_64: [[BOOL:%.*]] = apply [[METHOD]]([[SELF]]) : $@convention(objc_method) (Foo) -> Bool
+// CHECK-ios-x86_64: return [[BOOL]] : $Bool
+// CHECK-ios-x86_64: }
+
+// CHECK-arm64-LABEL: sil hidden @$S13objc_bridging6getZim{{.*}}F
+// CHECK-arm64: bb0([[SELF:%.*]] : @guaranteed $Foo):
+// CHECK-arm64: [[METHOD:%.*]] = objc_method [[SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Boo
+// CHECK-arm64: [[BOOL:%.*]] = apply [[METHOD]]([[SELF]]) : $@convention(objc_method) (Foo) -> Bool
+// CHECK-arm64: return [[BOOL]] : $Bool
+// CHECK-arm64: }
+
+// @interface Foo -(void) setZim: (BOOL)b; @end
+func setZim(_ f: Foo, b: Bool) {
+ f.setZim(b)
+}
+// CHECK-ios-i386-LABEL: sil hidden @$S13objc_bridging6setZim{{.*}}F
+// CHECK-ios-i386: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @trivial $Bool):
+// CHECK-ios-i386: [[CONVERT:%.*]] = function_ref @swift_BoolToObjCBool : $@convention(thin) (Bool) -> ObjCBool
+// CHECK-ios-i386: [[OBJC_BOOL:%.*]] = apply [[CONVERT]]([[ARG1]]) : $@convention(thin) (Bool) -> ObjCBool
+// CHECK-ios-i386: [[METHOD:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.setZim!1.foreign
+// CHECK-ios-i386: apply [[METHOD]]([[OBJC_BOOL]], [[ARG0]]) : $@convention(objc_method) (ObjCBool, Foo) -> ()
+// CHECK-ios-i386-NOT: destroy_value [[ARG0]]
+// CHECK-ios-i386: }
+
+// CHECK-macosx-x86_64-LABEL: sil hidden @$S13objc_bridging6setZim{{.*}}F
+// CHECK-macosx-x86_64: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @trivial $Bool):
+// CHECK-macosx-x86_64: [[CONVERT:%.*]] = function_ref @swift_BoolToObjCBool : $@convention(thin) (Bool) -> ObjCBool
+// CHECK-macosx-x86_64: [[OBJC_BOOL:%.*]] = apply [[CONVERT]]([[ARG1]]) : $@convention(thin) (Bool) -> ObjCBool
+// CHECK-macosx-x86_64: [[METHOD:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.setZim!1.foreign
+// CHECK-macosx-x86_64: apply [[METHOD]]([[OBJC_BOOL]], [[ARG0]]) : $@convention(objc_method) (ObjCBool, Foo) -> ()
+// CHECK-macosx-x86_64-NOT: destroy_value [[ARG0]]
+// CHECK-macosx-x86_64: }
+
+// CHECK-ios-x86_64-LABEL: sil hidden @$S13objc_bridging6setZim{{.*}}F
+// CHECK-ios-x86_64: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @trivial $Bool):
+// CHECK-ios-x86_64: [[METHOD:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.setZim!1.foreign
+// CHECK-ios-x86_64: apply [[METHOD]]([[ARG1]], [[ARG0]]) : $@convention(objc_method) (Bool, Foo) -> ()
+// CHECK-ios-x86_64-NOT: destroy_value [[ARG0]]
+// CHECK-ios-x86_64: }
+
+// CHECK-arm64-LABEL: sil hidden @$S13objc_bridging6setZim{{.*}}F
+// CHECK-arm64: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @trivial $Bool):
+// CHECK-arm64: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
+// CHECK-arm64: [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
+// CHECK-arm64: apply [[METHOD]]([[ARG1]], [[BORROWED_ARG0]]) : $@convention(objc_method) (Bool, Foo) -> ()
+// CHECK-arm64: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
+// CHECK-arm64: destroy_value [[ARG0]]
+// CHECK-arm64: }
+
+// CHECK-watchos-i386-LABEL: sil hidden @$S13objc_bridging6setZim{{.*}}F
+// CHECK-watchos-i386: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @trivial $Bool):
+// CHECK-watchos-i386: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
+// CHECK-watchos-i386: [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
+// CHECK-watchos-i386: apply [[METHOD]]([[ARG1]], [[BORROWED_ARG0]]) : $@convention(objc_method) (Bool, Foo) -> ()
+// CHECK-watchos-i386: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
+// CHECK-watchos-i386: destroy_value [[ARG0]]
+// CHECK-watchos-i386: }
+
+// @interface Foo -(_Bool) zang; @end
+func getZang(_ f: Foo) -> Bool {
+ return f.zang()
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging7getZangySbSo3FooCF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Foo)
+// CHECK: [[METHOD:%.*]] = objc_method [[ARG]] : $Foo, #Foo.zang!1.foreign
+// CHECK: [[BOOL:%.*]] = apply [[METHOD]]([[ARG]]) : $@convention(objc_method) (Foo) -> Bool
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[BOOL]]
+
+// @interface Foo -(void) setZang: (_Bool)b; @end
+func setZang(_ f: Foo, _ b: Bool) {
+ f.setZang(b)
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging7setZangyySo3FooC_SbtF
+// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Foo, [[ARG1:%.*]] : @trivial $Bool):
+// CHECK: [[METHOD:%.*]] = objc_method [[ARG0]] : $Foo, #Foo.setZang!1.foreign
+// CHECK: apply [[METHOD]]([[ARG1]], [[ARG0]]) : $@convention(objc_method) (Bool, Foo) -> ()
+// CHECK-NOT: destroy_value [[ARG0]]
+// CHECK: } // end sil function '$S13objc_bridging7setZangyySo3FooC_SbtF'
+
+// NSString *bar(void);
+func callBar() -> String {
+ return bar()
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging7callBar{{.*}}F
+// CHECK: bb0:
+// CHECK: [[BAR:%.*]] = function_ref @bar
+// CHECK: [[OPT_BRIDGED:%.*]] = apply [[BAR]]() : $@convention(c) () -> @autoreleased Optional<NSString>
+// CHECK: switch_enum [[OPT_BRIDGED]] : $Optional<NSString>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+
+// CHECK: [[SOME_BB]]([[BRIDGED:%.*]] : @owned $NSString):
+// CHECK: [[NSSTRING_TO_STRING:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK: [[BRIDGED_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK: [[NATIVE:%.*]] = apply [[NSSTRING_TO_STRING]]([[BRIDGED_BOX]]
+// CHECK: [[OPT_NATIVE:%.*]] = enum $Optional<String>, #Optional.some!enumelt.1, [[NATIVE]]
+// CHECK: bb5([[NATIVE:%.*]] : @owned $String):
+// CHECK: return [[NATIVE]]
+// CHECK: }
+
+// void setBar(NSString *s);
+func callSetBar(_ s: String) {
+ var s = s
+ setBar(s)
+}
+// CHECK-LABEL: sil hidden @$S13objc_bridging10callSetBar{{.*}}F
+// CHECK: bb0({{%.*}} : @guaranteed $String):
+// CHECK: [[NATIVE:%.*]] = load
+// CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+// CHECK: [[BORROWED_NATIVE:%.*]] = begin_borrow [[NATIVE]]
+// CHECK: [[BRIDGED:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_NATIVE]])
+// CHECK: [[OPT_BRIDGED:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[BRIDGED]]
+// CHECK: end_borrow [[BORROWED_NATIVE]] from [[NATIVE]]
+// CHECK: [[SET_BAR:%.*]] = function_ref @setBar
+// CHECK: apply [[SET_BAR]]([[OPT_BRIDGED]])
+// CHECK: destroy_value [[OPT_BRIDGED]]
+// CHECK: }
+
+var NSS: NSString
+
+// -- NSString methods don't convert 'self'
+extension NSString {
+ var nsstrFakeProp: NSString {
+ get { return NSS }
+ set {}
+ }
+ // CHECK-LABEL: sil hidden [thunk] @$SSo8NSStringC13objc_bridgingE13nsstrFakePropABvgTo
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+ // CHECK-LABEL: sil hidden [thunk] @$SSo8NSStringC13objc_bridgingE13nsstrFakePropABvsTo
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+
+ func nsstrResult() -> NSString { return NSS }
+ // CHECK-LABEL: sil hidden [thunk] @$SSo8NSStringC13objc_bridgingE11nsstrResultAByFTo
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+
+ func nsstrArg(_ s: NSString) { }
+ // CHECK-LABEL: sil hidden [thunk] @$SSo8NSStringC13objc_bridgingE8nsstrArgyyABFTo
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+
+}
+
+class Bas : NSObject {
+ // -- Bridging thunks for String properties convert between NSString
+ var strRealProp: String = "Hello"
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC11strRealPropSSvgTo : $@convention(objc_method) (Bas) -> @autoreleased NSString {
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Bas):
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]] : $Bas
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: // function_ref objc_bridging.Bas.strRealProp.getter
+ // CHECK: [[PROPIMPL:%.*]] = function_ref @$S13objc_bridging3BasC11strRealPropSSvg
+ // CHECK: [[PROP_COPY:%.*]] = apply [[PROPIMPL]]([[BORROWED_THIS_COPY]]) : $@convention(method) (@guaranteed Bas) -> @owned String
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_PROP_COPY:%.*]] = begin_borrow [[PROP_COPY]]
+ // CHECK: [[NSSTR:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_PROP_COPY]])
+ // CHECK: end_borrow [[BORROWED_PROP_COPY]] from [[PROP_COPY]]
+ // CHECK: destroy_value [[PROP_COPY]]
+ // CHECK: return [[NSSTR]]
+ // CHECK: }
+
+
+ // CHECK-LABEL: sil hidden @$S13objc_bridging3BasC11strRealPropSSvg
+ // CHECK: [[PROP_ADDR:%.*]] = ref_element_addr %0 : {{.*}}, #Bas.strRealProp
+ // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[PROP_ADDR]] : $*String
+ // CHECK: [[PROP:%.*]] = load [copy] [[READ]]
+
+
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC11strRealPropSSvsTo : $@convention(objc_method) (NSString, Bas) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $NSString, [[THIS:%.*]] : @unowned $Bas):
+ // CHECK: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK: [[NSSTRING_TO_STRING:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: [[VALUE_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[VALUE_COPY]]
+ // CHECK: [[STR:%.*]] = apply [[NSSTRING_TO_STRING]]([[VALUE_BOX]]
+
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: [[SETIMPL:%.*]] = function_ref @$S13objc_bridging3BasC11strRealPropSSvs
+ // CHECK: apply [[SETIMPL]]([[STR]], [[BORROWED_THIS_COPY]])
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: } // end sil function '$S13objc_bridging3BasC11strRealPropSSvsTo'
+
+ // CHECK-LABEL: sil hidden @$S13objc_bridging3BasC11strRealPropSSvs
+ // CHECK: bb0(%0 : @owned $String, %1 : @guaranteed $Bas):
+
+ // CHECK: [[STR_ADDR:%.*]] = ref_element_addr %1 : {{.*}}, #Bas.strRealProp
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[STR_ADDR]] : $*String
+ // CHECK: assign {{.*}} to [[WRITE]]
+ // CHECK: }
+
+ var strFakeProp: String {
+ get { return "" }
+ set {}
+ }
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC11strFakePropSSvgTo : $@convention(objc_method) (Bas) -> @autoreleased NSString {
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Bas):
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: [[GETTER:%.*]] = function_ref @$S13objc_bridging3BasC11strFakePropSSvg
+ // CHECK: [[STR:%.*]] = apply [[GETTER]]([[BORROWED_THIS_COPY]])
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+ // CHECK: [[NSSTR:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_STR]])
+ // CHECK: end_borrow [[BORROWED_STR]] from [[STR]]
+ // CHECK: destroy_value [[STR]]
+ // CHECK: return [[NSSTR]]
+ // CHECK: }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC11strFakePropSSvsTo : $@convention(objc_method) (NSString, Bas) -> () {
+ // CHECK: bb0([[NSSTR:%.*]] : @unowned $NSString, [[THIS:%.*]] : @unowned $Bas):
+ // CHECK: [[NSSTR_COPY:%.*]] = copy_value [[NSSTR]]
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK: [[NSSTRING_TO_STRING:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: [[NSSTR_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NSSTR_COPY]]
+ // CHECK: [[STR:%.*]] = apply [[NSSTRING_TO_STRING]]([[NSSTR_BOX]]
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: [[SETTER:%.*]] = function_ref @$S13objc_bridging3BasC11strFakePropSSvs
+ // CHECK: apply [[SETTER]]([[STR]], [[BORROWED_THIS_COPY]])
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: } // end sil function '$S13objc_bridging3BasC11strFakePropSSvsTo'
+
+ // -- Bridging thunks for explicitly NSString properties don't convert
+ var nsstrRealProp: NSString
+ var nsstrFakeProp: NSString {
+ get { return NSS }
+ set {}
+ }
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC13nsstrRealPropSo8NSStringCvgTo : $@convention(objc_method) (Bas) -> @autoreleased NSString {
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC13nsstrRealPropSo8NSStringCvsTo : $@convention(objc_method) (NSString, Bas) ->
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+
+ // -- Bridging thunks for String methods convert between NSString
+ func strResult() -> String { return "" }
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC9strResultSSyFTo
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Bas):
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: [[METHOD:%.*]] = function_ref @$S13objc_bridging3BasC9strResultSSyF
+ // CHECK: [[STR:%.*]] = apply [[METHOD]]([[BORROWED_THIS_COPY]])
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+ // CHECK: [[NSSTR:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_STR]])
+ // CHECK: end_borrow [[BORROWED_STR]] from [[STR]]
+ // CHECK: destroy_value [[STR]]
+ // CHECK: return [[NSSTR]]
+ // CHECK: }
+ func strArg(_ s: String) { }
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC6strArgyySSFTo
+ // CHECK: bb0([[NSSTR:%.*]] : @unowned $NSString, [[THIS:%.*]] : @unowned $Bas):
+ // CHECK: [[NSSTR_COPY:%.*]] = copy_value [[NSSTR]]
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK: [[NSSTRING_TO_STRING:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: [[NSSTR_BOX:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NSSTR_COPY]]
+ // CHECK: [[STR:%.*]] = apply [[NSSTRING_TO_STRING]]([[NSSTR_BOX]]
+ // CHECK: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: [[METHOD:%.*]] = function_ref @$S13objc_bridging3BasC6strArgyySSF
+ // CHECK: apply [[METHOD]]([[BORROWED_STR]], [[BORROWED_THIS_COPY]])
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: } // end sil function '$S13objc_bridging3BasC6strArgyySSFTo'
+
+ // -- Bridging thunks for explicitly NSString properties don't convert
+ func nsstrResult() -> NSString { return NSS }
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC11nsstrResultSo8NSStringCyFTo
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+ func nsstrArg(_ s: NSString) { }
+ // CHECK-LABEL: sil hidden @$S13objc_bridging3BasC8nsstrArgyySo8NSStringCF
+ // CHECK-NOT: swift_StringToNSString
+ // CHECK-NOT: $SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: }
+
+ init(str: NSString) {
+ nsstrRealProp = str
+ super.init()
+ }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC8arrayArgyySayyXlGFTo : $@convention(objc_method) (NSArray, Bas) -> ()
+ // CHECK: bb0([[NSARRAY:%[0-9]+]] : @unowned $NSArray, [[SELF:%[0-9]+]] : @unowned $Bas):
+ // CHECK: [[NSARRAY_COPY:%.*]] = copy_value [[NSARRAY]] : $NSArray
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Bas
+ // CHECK: [[CONV_FN:%[0-9]+]] = function_ref @$SSa10FoundationE36_unconditionallyBridgeFromObjectiveCySayxGSo7NSArrayCSgFZ
+ // CHECK: [[OPT_NSARRAY:%[0-9]+]] = enum $Optional<NSArray>, #Optional.some!enumelt.1, [[NSARRAY_COPY]] : $NSArray
+ // CHECK: [[ARRAY_META:%[0-9]+]] = metatype $@thin Array<AnyObject>.Type
+ // CHECK: [[ARRAY:%[0-9]+]] = apply [[CONV_FN]]<AnyObject>([[OPT_NSARRAY]], [[ARRAY_META]])
+ // CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SWIFT_FN:%[0-9]+]] = function_ref @$S13objc_bridging3BasC8arrayArgyySayyXlGF : $@convention(method) (@guaranteed Array<AnyObject>, @guaranteed Bas) -> ()
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[SWIFT_FN]]([[BORROWED_ARRAY]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Array<AnyObject>, @guaranteed Bas) -> ()
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]] : $Bas
+ // CHECK: return [[RESULT]] : $()
+ func arrayArg(_ array: [AnyObject]) { }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC11arrayResultSayyXlGyFTo : $@convention(objc_method) (Bas) -> @autoreleased NSArray
+ // CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Bas):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Bas
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SWIFT_FN:%[0-9]+]] = function_ref @$S13objc_bridging3BasC11arrayResultSayyXlGyF : $@convention(method) (@guaranteed Bas) -> @owned Array<AnyObject>
+ // CHECK: [[ARRAY:%[0-9]+]] = apply [[SWIFT_FN]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Bas) -> @owned Array<AnyObject>
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: [[CONV_FN:%[0-9]+]] = function_ref @$SSa10FoundationE19_bridgeToObjectiveCSo7NSArrayCyF
+ // CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
+ // CHECK: [[NSARRAY:%[0-9]+]] = apply [[CONV_FN]]<AnyObject>([[BORROWED_ARRAY]]) : $@convention(method) <τ_0_0> (@guaranteed Array<τ_0_0>) -> @owned NSArray
+ // CHECK: end_borrow [[BORROWED_ARRAY]] from [[ARRAY]]
+ // CHECK: destroy_value [[ARRAY]]
+ // CHECK: return [[NSARRAY]]
+ func arrayResult() -> [AnyObject] { return [] }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC9arrayPropSaySSGvgTo : $@convention(objc_method) (Bas) -> @autoreleased NSArray
+ // CHECK-LABEL: sil hidden [thunk] @$S13objc_bridging3BasC9arrayPropSaySSGvsTo : $@convention(objc_method) (NSArray, Bas) -> ()
+ var arrayProp: [String] = []
+}
+
+// CHECK-LABEL: sil hidden @$S13objc_bridging16applyStringBlock_1xS3SXB_SStF
+func applyStringBlock(_ f: @convention(block) (String) -> String, x: String) -> String {
+ // CHECK: bb0([[BLOCK:%.*]] : @guaranteed $@convention(block) @noescape (NSString) -> @autoreleased NSString, [[STRING:%.*]] : @guaranteed $String):
+ // CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ // CHECK: [[BORROWED_BLOCK_COPY:%.*]] = begin_borrow [[BLOCK_COPY]]
+ // CHECK: [[BLOCK_COPY_COPY:%.*]] = copy_value [[BORROWED_BLOCK_COPY]]
+ // CHECK: [[STRING_COPY:%.*]] = copy_value [[STRING]]
+ // CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_STRING_COPY:%.*]] = begin_borrow [[STRING_COPY]]
+ // CHECK: [[NSSTR:%.*]] = apply [[STRING_TO_NSSTRING]]([[BORROWED_STRING_COPY]]) : $@convention(method) (@guaranteed String)
+ // CHECK: end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
+ // CHECK: destroy_value [[STRING_COPY]]
+ // CHECK: [[RESULT_NSSTR:%.*]] = apply [[BLOCK_COPY_COPY]]([[NSSTR]]) : $@convention(block) @noescape (NSString) -> @autoreleased NSString
+ // CHECK: destroy_value [[NSSTR]]
+ // CHECK: [[FINAL_BRIDGE:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: [[OPTIONAL_NSSTR:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[RESULT_NSSTR]]
+ // CHECK: [[RESULT:%.*]] = apply [[FINAL_BRIDGE]]([[OPTIONAL_NSSTR]], {{.*}}) : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
+ // CHECK: destroy_value [[BLOCK_COPY_COPY]]
+ // CHECK-NOT: destroy_value [[STRING]]
+ // CHECK: destroy_value [[BLOCK_COPY]]
+ // CHECK-NOT: destroy_value [[BLOCK]]
+ // CHECK: return [[RESULT]] : $String
+ return f(x)
+}
+// CHECK: } // end sil function '$S13objc_bridging16applyStringBlock_1xS3SXB_SStF'
+
+// CHECK-LABEL: sil hidden @$S13objc_bridging15bridgeCFunction{{.*}}F
+func bridgeCFunction() -> (String?) -> (String?) {
+ // CHECK: [[THUNK:%.*]] = function_ref @$SSo18NSStringFromStringySSSgABFTO : $@convention(thin) (@guaranteed Optional<String>) -> @owned Optional<String>
+ // CHECK: [[THICK:%.*]] = thin_to_thick_function [[THUNK]]
+ // CHECK: return [[THICK]]
+ return NSStringFromString
+}
+
+func forceNSArrayMembers() -> (NSArray, NSArray) {
+ let x = NSArray(objects: nil, count: 0)
+ return (x, x)
+}
+
+// Check that the allocating initializer shim for initializers that take pointer
+// arguments lifetime-extends the bridged pointer for the right duration.
+// <rdar://problem/16738050>
+
+// CHECK-LABEL: sil shared [serializable] @$SSo7NSArrayC7objects5countABSPyyXlSgGSg_s5Int32VtcfC
+// CHECK: [[SELF:%.*]] = alloc_ref_dynamic
+// CHECK: [[METHOD:%.*]] = function_ref @$SSo7NSArrayC7objects5countABSPyyXlSgGSg_s5Int32VtcfcTO
+// CHECK: [[RESULT:%.*]] = apply [[METHOD]]
+// CHECK: return [[RESULT]]
+
+// Check that type lowering preserves the bool/BOOL distinction when bridging
+// imported C functions.
+
+// CHECK-ios-i386-LABEL: sil hidden @$S13objc_bridging5boolsySb_SbtSbF
+// CHECK-ios-i386: function_ref @useBOOL : $@convention(c) (ObjCBool) -> ()
+// CHECK-ios-i386: function_ref @useBool : $@convention(c) (Bool) -> ()
+// CHECK-ios-i386: function_ref @getBOOL : $@convention(c) () -> ObjCBool
+// CHECK-ios-i386: function_ref @getBool : $@convention(c) () -> Bool
+
+// CHECK-macosx-x86_64-LABEL: sil hidden @$S13objc_bridging5boolsySb_SbtSbF
+// CHECK-macosx-x86_64: function_ref @useBOOL : $@convention(c) (ObjCBool) -> ()
+// CHECK-macosx-x86_64: function_ref @useBool : $@convention(c) (Bool) -> ()
+// CHECK-macosx-x86_64: function_ref @getBOOL : $@convention(c) () -> ObjCBool
+// CHECK-macosx-x86_64: function_ref @getBool : $@convention(c) () -> Bool
+
+// FIXME: no distinction on x86_64, arm64 or watchos-i386, since SILGen looks
+// at the underlying Clang decl of the bridged decl to decide whether it needs
+// bridging.
+//
+// CHECK-watchos-i386-LABEL: sil hidden @$S13objc_bridging5boolsySb_SbtSbF
+// CHECK-watchos-i386: function_ref @useBOOL : $@convention(c) (Bool) -> ()
+// CHECK-watchos-i386: function_ref @useBool : $@convention(c) (Bool) -> ()
+// CHECK-watchos-i386: function_ref @getBOOL : $@convention(c) () -> Bool
+// CHECK-watchos-i386: function_ref @getBool : $@convention(c) () -> Bool
+
+// CHECK-ios-x86_64-LABEL: sil hidden @$S13objc_bridging5boolsySb_SbtSbF
+// CHECK-ios-x86_64: function_ref @useBOOL : $@convention(c) (Bool) -> ()
+// CHECK-ios-x86_64: function_ref @useBool : $@convention(c) (Bool) -> ()
+// CHECK-ios-x86_64: function_ref @getBOOL : $@convention(c) () -> Bool
+// CHECK-ios-x86_64: function_ref @getBool : $@convention(c) () -> Bool
+
+// CHECK-arm64-LABEL: sil hidden @$S13objc_bridging5boolsySb_SbtSbF
+// CHECK-arm64: function_ref @useBOOL : $@convention(c) (Bool) -> ()
+// CHECK-arm64: function_ref @useBool : $@convention(c) (Bool) -> ()
+// CHECK-arm64: function_ref @getBOOL : $@convention(c) () -> Bool
+// CHECK-arm64: function_ref @getBool : $@convention(c) () -> Bool
+
+func bools(_ x: Bool) -> (Bool, Bool) {
+ useBOOL(x)
+ useBool(x)
+
+ return (getBOOL(), getBool())
+}
+
+// CHECK-LABEL: sil hidden @$S13objc_bridging9getFridge{{.*}}F
+// CHECK: bb0([[HOME:%[0-9]+]] : @guaranteed $APPHouse):
+func getFridge(_ home: APPHouse) -> Refrigerator {
+ // CHECK: [[GETTER:%[0-9]+]] = objc_method [[HOME]] : $APPHouse, #APPHouse.fridge!getter.1.foreign
+ // CHECK: [[OBJC_RESULT:%[0-9]+]] = apply [[GETTER]]([[HOME]])
+ // CHECK: [[BRIDGE_FN:%[0-9]+]] = function_ref @$S10Appliances12RefrigeratorV36_unconditionallyBridgeFromObjectiveCyACSo15APPRefrigeratorCSgFZ
+ // CHECK: [[REFRIGERATOR_META:%[0-9]+]] = metatype $@thin Refrigerator.Type
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[BRIDGE_FN]]([[OBJC_RESULT]], [[REFRIGERATOR_META]])
+ // CHECK-NOT: destroy_value [[HOME]] : $APPHouse
+ // CHECK: return [[RESULT]] : $Refrigerator
+ return home.fridge
+}
+
+// FIXME(integers): the following checks should be updated for the new integer
+// protocols. <rdar://problem/29939484>
+// XCHECK-LABEL: sil hidden @$S13objc_bridging16updateFridgeTemp{{.*}}F
+// XCHECK: bb0([[HOME:%[0-9]+]] : $APPHouse, [[DELTA:%[0-9]+]] : $Double):
+func updateFridgeTemp(_ home: APPHouse, delta: Double) {
+ // +=
+ // XCHECK: [[PLUS_EQ:%[0-9]+]] = function_ref @$Ss2peoiyySdz_SdtF
+
+ // Temporary fridge
+ // XCHECK: [[TEMP_FRIDGE:%[0-9]+]] = alloc_stack $Refrigerator
+
+ // Get operation
+ // CHECK: [[GETTER:%[0-9]+]] = objc_method [[HOME]] : $APPHouse, #APPHouse.fridge!getter.1.foreign
+ // CHECK: [[OBJC_FRIDGE:%[0-9]+]] = apply [[GETTER]]([[HOME]])
+ // CHECK: [[BRIDGE_FROM_FN:%[0-9]+]] = function_ref @$S10Appliances12RefrigeratorV36_unconditionallyBridgeFromObjectiveCyACSo15APPRefrigeratorCSgFZ
+ // CHECK: [[REFRIGERATOR_META:%[0-9]+]] = metatype $@thin Refrigerator.Type
+ // CHECK: [[FRIDGE:%[0-9]+]] = apply [[BRIDGE_FROM_FN]]([[OBJC_FRIDGE]], [[REFRIGERATOR_META]])
+
+ // Addition
+ // XCHECK: [[TEMP:%[0-9]+]] = struct_element_addr [[TEMP_FRIDGE]] : $*Refrigerator, #Refrigerator.temperature
+ // XCHECK: apply [[PLUS_EQ]]([[TEMP]], [[DELTA]])
+
+ // Setter
+ // XCHECK: [[FRIDGE:%[0-9]+]] = load [trivial] [[TEMP_FRIDGE]] : $*Refrigerator
+ // XCHECK: [[SETTER:%[0-9]+]] = objc_method [[BORROWED_HOME]] : $APPHouse, #APPHouse.fridge!setter.1.foreign
+ // XCHECK: [[BRIDGE_TO_FN:%[0-9]+]] = function_ref @$S10Appliances12RefrigeratorV19_bridgeToObjectiveCSo15APPRefrigeratorCyF
+ // XCHECK: [[OBJC_ARG:%[0-9]+]] = apply [[BRIDGE_TO_FN]]([[FRIDGE]])
+ // XCHECK: apply [[SETTER]]([[OBJC_ARG]], [[BORROWED_HOME]]) : $@convention(objc_method) (APPRefrigerator, APPHouse) -> ()
+ // XCHECK: destroy_value [[OBJC_ARG]]
+ // XCHECK: end_borrow [[BORROWED_HOME]] from [[HOME]]
+ // XCHECK: destroy_value [[HOME]]
+ home.fridge.temperature += delta
+}
+
+// CHECK-LABEL: sil hidden @$S13objc_bridging20callNonStandardBlock5valueySi_tF
+func callNonStandardBlock(value: Int) {
+ // CHECK: enum $Optional<@convention(block) () -> @owned Optional<AnyObject>>
+ takesNonStandardBlock { return value }
+}
+
+func takeTwoAnys(_ lhs: Any, _ rhs: Any) -> Any { return lhs }
+
+// CHECK-LABEL: sil hidden @$S13objc_bridging22defineNonStandardBlock1xyyp_tF
+func defineNonStandardBlock(x: Any) {
+ // CHECK: function_ref @$S13objc_bridging22defineNonStandardBlock1xyyp_tFypypcfU_
+ // CHECK: function_ref @$SypypIegnr_yXlyXlIeyBya_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@in_guaranteed Any) -> @out Any, AnyObject) -> @autoreleased AnyObject
+
+ let fn : @convention(block) (Any) -> Any = { y in takeTwoAnys(x, y) }
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypypIegnr_yXlyXlIeyBya_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@in_guaranteed Any) -> @out Any, AnyObject) -> @autoreleased AnyObject
+// CHECK: bb0(%0 : @trivial $*@block_storage @callee_guaranteed (@in_guaranteed Any) -> @out Any, %1 : @unowned $AnyObject):
+// CHECK: [[T0:%.*]] = copy_value %1 : $AnyObject
+// CHECK: [[T1:%.*]] = open_existential_ref [[T0]] : $AnyObject
+// CHECK: [[ARG:%.*]] = alloc_stack $Any
+// CHECK: [[T2:%.*]] = init_existential_addr [[ARG]]
+// CHECK: store [[T1]] to [init] [[T2]]
+// CHECK: [[RESULT:%.*]] = alloc_stack $Any
+// CHECK: apply {{.*}}([[RESULT]], [[ARG]])
+
+// CHECK-LABEL: sil hidden @$S13objc_bridging15castToCFunction3ptrySV_tF : $@convention(thin) (UnsafeRawPointer) -> () {
+func castToCFunction(ptr: UnsafeRawPointer) {
+ // CHECK: [[OUT:%.*]] = alloc_stack $@convention(c) (Optional<AnyObject>) -> ()
+ // CHECK: [[IN:%.]] = alloc_stack $UnsafeRawPointer
+ // CHECK: store %0 to [trivial] [[IN]] : $*UnsafeRawPointer
+ // CHECK: [[META:%.*]] = metatype $@thick (@convention(c) (Optional<AnyObject>) -> ()).Type
+ // CHECK: [[CASTFN:%.*]] = function_ref @$Ss13unsafeBitCast_2toq_x_q_mtr0_lF
+ // CHECK: apply [[CASTFN]]<UnsafeRawPointer, @convention(c) (AnyObject?) -> ()>([[OUT]], [[IN]], [[META]]) : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @thick τ_0_1.Type) -> @out τ_0_1
+ // CHECK: [[RESULT:%.*]] = load [trivial] [[OUT]] : $*@convention(c) (Optional<AnyObject>) -> ()
+ typealias Fn = @convention(c) (AnyObject?) -> Void
+ unsafeBitCast(ptr, to: Fn.self)(nil)
+}
diff --git a/test/SILGen/plus_zero_objc_bridging_any.swift b/test/SILGen/plus_zero_objc_bridging_any.swift
new file mode 100644
index 0000000..6e994ee
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_bridging_any.swift
@@ -0,0 +1,692 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -Xllvm -sil-print-debuginfo -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+import Foundation
+import objc_generics
+
+protocol P {}
+protocol CP: class {}
+
+struct KnownUnbridged {}
+
+// CHECK-LABEL: sil hidden @$S17objc_bridging_any11passingToId{{.*}}F
+func passingToId<T: CP, U>(receiver: NSIdLover,
+ string: String,
+ nsString: NSString,
+ object: AnyObject,
+ classGeneric: T,
+ classExistential: CP,
+ generic: U,
+ existential: P,
+ error: Error,
+ any: Any,
+ knownUnbridged: KnownUnbridged,
+ optionalA: String?,
+ optionalB: NSString?,
+ optionalC: Any?) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $NSIdLover,
+ // CHECK: debug_value [[STRING:%.*]] : $String
+ // CHECK: debug_value [[NSSTRING:%.*]] : $NSString
+ // CHECK: debug_value [[OBJECT:%.*]] : $AnyObject
+ // CHECK: debug_value [[CLASS_GENERIC:%.*]] : $T
+ // CHECK: debug_value [[CLASS_EXISTENTIAL:%.*]] : $CP
+ // CHECK: debug_value_addr [[GENERIC:%.*]] : $*U
+ // CHECK: debug_value_addr [[EXISTENTIAL:%.*]] : $*P
+ // CHECK: debug_value [[ERROR:%.*]] : $Error
+ // CHECK: debug_value_addr [[ANY:%.*]] : $*Any
+ // CHECK: debug_value [[KNOWN_UNBRIDGED:%.*]] : $KnownUnbridged
+ // CHECK: debug_value [[OPT_STRING:%.*]] : $Optional<String>
+ // CHECK: debug_value [[OPT_NSSTRING:%.*]] : $Optional<NSString>
+ // CHECK: debug_value_addr [[OPT_ANY:%.*]] : $*Optional<Any>
+
+ // CHECK: [[STRING_COPY:%.*]] = copy_value [[STRING]]
+ // CHECK: [[BRIDGE_STRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_STRING_COPY:%.*]] = begin_borrow [[STRING_COPY]]
+ // CHECK: [[BRIDGED:%.*]] = apply [[BRIDGE_STRING]]([[BORROWED_STRING_COPY]])
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[BRIDGED]] : $NSString : $NSString, $AnyObject
+ // CHECK: end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
+ // CHECK: destroy_value [[STRING_COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]]
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(string)
+
+ // CHECK: [[NSSTRING_COPY:%.*]] = copy_value [[NSSTRING]]
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING_COPY]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(nsString)
+
+ // CHECK: [[CLASS_GENERIC_COPY:%.*]] = copy_value [[CLASS_GENERIC]]
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC_COPY]] : $T : $T, $AnyObject
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(classGeneric)
+
+ // CHECK: [[OBJECT_COPY:%.*]] = copy_value [[OBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[OBJECT_COPY]], [[SELF]])
+ // CHECK: destroy_value [[OBJECT_COPY]]
+ receiver.takesId(object)
+
+ // CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[CLASS_EXISTENTIAL]]
+ // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(classExistential)
+
+ // These cases perform a universal bridging conversion.
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $U
+ // CHECK: copy_addr [[GENERIC]] to [initialization] [[COPY]]
+ // CHECK: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<U>([[COPY]])
+ // CHECK: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(generic)
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $P
+ // CHECK: copy_addr [[EXISTENTIAL]] to [initialization] [[COPY]]
+ // CHECK: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*P to $*[[OPENED_TYPE:@opened.*P]],
+ // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]]
+ // CHECK: copy_addr [[OPENED_COPY]] to [initialization] [[TMP]]
+ // CHECK: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: destroy_addr [[COPY]]
+ // CHECK: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(existential)
+
+ // CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $Error
+ // CHECK: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
+ // CHECK: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]]) Error
+ // CHECK: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
+ // CHECK: [[BRIDGE_FUNCTION:%[0-9]+]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]]) Error>([[ERROR_STACK]])
+ // CHECK: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
+ // CHECK: destroy_value [[ERROR_COPY]] : $Error
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[BRIDGED_ERROR]], [[SELF]])
+ // CHECK: destroy_value [[BRIDGED_ERROR]] : $AnyObject
+ receiver.takesId(error)
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $Any
+ // CHECK: copy_addr [[ANY]] to [initialization] [[COPY]]
+ // CHECK: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*Any to $*[[OPENED_TYPE:@opened.*Any]],
+ // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]]
+ // CHECK: copy_addr [[OPENED_COPY]] to [initialization] [[TMP]]
+ // CHECK: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
+ // CHECK: destroy_addr [[COPY]]
+ // CHECK: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[ANYOBJECT]]
+ receiver.takesId(any)
+
+ // CHECK: [[TMP:%.*]] = alloc_stack $KnownUnbridged
+ // CHECK: store [[KNOWN_UNBRIDGED]] to [trivial] [[TMP]]
+ // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveC{{.*}}F
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<KnownUnbridged>([[TMP]])
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ receiver.takesId(knownUnbridged)
+
+ // These cases bridge using Optional's _ObjectiveCBridgeable conformance.
+
+ // CHECK: [[OPT_STRING_COPY:%.*]] = copy_value [[OPT_STRING]]
+ // CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+ // CHECK: [[TMP:%.*]] = alloc_stack $Optional<String>
+ // CHECK: [[BORROWED_OPT_STRING_COPY:%.*]] = begin_borrow [[OPT_STRING_COPY]]
+ // CHECK: store_borrow [[BORROWED_OPT_STRING_COPY]] to [[TMP]]
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<String>([[TMP]])
+ // CHECK: end_borrow [[BORROWED_OPT_STRING_COPY]] from [[OPT_STRING_COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ receiver.takesId(optionalA)
+
+ // CHECK: [[OPT_NSSTRING_COPY:%.*]] = copy_value [[OPT_NSSTRING]]
+ // CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+ // CHECK: [[TMP:%.*]] = alloc_stack $Optional<NSString>
+ // CHECK: [[BORROWED_OPT_NSSTRING_COPY:%.*]] = begin_borrow [[OPT_NSSTRING_COPY]]
+ // CHECK: store_borrow [[BORROWED_OPT_NSSTRING_COPY]] to [[TMP]]
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<NSString>([[TMP]])
+ // CHECK: end_borrow [[BORROWED_OPT_NSSTRING_COPY]] from [[OPT_NSSTRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ receiver.takesId(optionalB)
+
+ // CHECK: [[TMP:%.*]] = alloc_stack $Optional<Any>
+ // CHECK: copy_addr [[OPT_ANY]] to [initialization] [[TMP]]
+ // CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<Any>([[TMP]])
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
+ receiver.takesId(optionalC)
+
+ // TODO: Property and subscript setters
+}
+
+// Once upon a time, as a workaround for rdar://problem/28318984, we had
+// to skip the peephole for types with nontrivial SIL lowerings because we
+// didn't correctly form the substitutions for a generic
+// _bridgeAnythingToObjectiveC call. That's not true anymore.
+func zim() {}
+struct Zang {}
+// CHECK-LABEL: sil hidden @$S17objc_bridging_any27typesWithNontrivialLowering8receiverySo9NSIdLoverC_tF
+func typesWithNontrivialLowering(receiver: NSIdLover) {
+ // CHECK: apply {{.*}}<() -> ()>
+ receiver.takesId(zim)
+ // CHECK: apply {{.*}}<Zang.Type>
+ receiver.takesId(Zang.self)
+ // CHECK: apply {{.*}}<(() -> (), Zang.Type)>
+ receiver.takesId((zim, Zang.self))
+ // CHECK: apply {{%.*}}<(Int, String)>
+ receiver.takesId((0, "one"))
+}
+
+// CHECK-LABEL: sil hidden @$S17objc_bridging_any19passingToNullableId{{.*}}F
+func passingToNullableId<T: CP, U>(receiver: NSIdLover,
+ string: String,
+ nsString: NSString,
+ object: AnyObject,
+ classGeneric: T,
+ classExistential: CP,
+ generic: U,
+ existential: P,
+ error: Error,
+ any: Any,
+ knownUnbridged: KnownUnbridged,
+ optString: String?,
+ optNSString: NSString?,
+ optObject: AnyObject?,
+ optClassGeneric: T?,
+ optClassExistential: CP?,
+ optGeneric: U?,
+ optExistential: P?,
+ optAny: Any?,
+ optKnownUnbridged: KnownUnbridged?,
+ optOptA: String??,
+ optOptB: NSString??,
+ optOptC: Any??)
+{
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $NSIdLover,
+ // CHECK: [[STRING:%.*]] : $String,
+ // CHECK: [[NSSTRING:%.*]] : $NSString
+ // CHECK: [[OBJECT:%.*]] : $AnyObject
+ // CHECK: [[CLASS_GENERIC:%.*]] : $T
+ // CHECK: [[CLASS_EXISTENTIAL:%.*]] : $CP
+ // CHECK: [[GENERIC:%.*]] : $*U
+ // CHECK: [[EXISTENTIAL:%.*]] : $*P
+ // CHECK: [[ERROR:%.*]] : $Error
+ // CHECK: [[ANY:%.*]] : $*Any,
+ // CHECK: [[KNOWN_UNBRIDGED:%.*]] : $KnownUnbridged,
+ // CHECK: [[OPT_STRING:%.*]] : $Optional<String>,
+ // CHECK: [[OPT_NSSTRING:%.*]] : $Optional<NSString>
+ // CHECK: [[OPT_OBJECT:%.*]] : $Optional<AnyObject>
+ // CHECK: [[OPT_CLASS_GENERIC:%.*]] : $Optional<T>
+ // CHECK: [[OPT_CLASS_EXISTENTIAL:%.*]] : $Optional<CP>
+ // CHECK: [[OPT_GENERIC:%.*]] : $*Optional<U>
+ // CHECK: [[OPT_EXISTENTIAL:%.*]] : $*Optional<P>
+ // CHECK: [[OPT_ANY:%.*]] : $*Optional<Any>
+ // CHECK: [[OPT_KNOWN_UNBRIDGED:%.*]] : $Optional<KnownUnbridged>
+ // CHECK: [[OPT_OPT_A:%.*]] : $Optional<Optional<String>>
+ // CHECK: [[OPT_OPT_B:%.*]] : $Optional<Optional<NSString>>
+ // CHECK: [[OPT_OPT_C:%.*]] : $*Optional<Optional<Any>>
+
+ // CHECK: [[STRING_COPY:%.*]] = copy_value [[STRING]]
+ // CHECK: [[BRIDGE_STRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_STRING_COPY:%.*]] = begin_borrow [[STRING_COPY]]
+ // CHECK: [[BRIDGED:%.*]] = apply [[BRIDGE_STRING]]([[BORROWED_STRING_COPY]])
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[BRIDGED]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
+ // CHECK: destroy_value [[STRING_COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]]
+ // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[OPT_ANYOBJECT]]
+ receiver.takesNullableId(string)
+
+ // CHECK: [[NSSTRING_COPY:%.*]] = copy_value [[NSSTRING]]
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING_COPY]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ receiver.takesNullableId(nsString)
+
+ // CHECK: [[OBJECT_COPY:%.*]] = copy_value [[OBJECT]]
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[OBJECT_COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ receiver.takesNullableId(object)
+
+ // CHECK: [[CLASS_GENERIC_COPY:%.*]] = copy_value [[CLASS_GENERIC]]
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC_COPY]] : $T : $T, $AnyObject
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ receiver.takesNullableId(classGeneric)
+
+ // CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[CLASS_EXISTENTIAL]]
+ // CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ // CHECK: destroy_value [[OPT_ANYOBJECT]]
+ receiver.takesNullableId(classExistential)
+
+ // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $U
+ // CHECK-NEXT: copy_addr [[GENERIC]] to [initialization] [[COPY]]
+ // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK-NEXT: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<U>([[COPY]])
+ // CHECK-NEXT: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK-NEXT: destroy_addr [[COPY]]
+ // CHECK-NEXT: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
+ receiver.takesNullableId(generic)
+
+ // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $P
+ // CHECK-NEXT: copy_addr [[EXISTENTIAL]] to [initialization] [[COPY]]
+ // CHECK-NEXT: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*P to $*[[OPENED_TYPE:@opened.*P]],
+ // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]]
+ // CHECK: copy_addr [[OPENED_COPY]] to [initialization] [[TMP]]
+ // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK-NEXT: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
+ // CHECK-NEXT: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK-NEXT: destroy_addr [[TMP]]
+ // CHECK-NEXT: dealloc_stack [[TMP]]
+ // CHECK-NEXT: destroy_addr [[COPY]]
+ // CHECK-NEXT: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
+ receiver.takesNullableId(existential)
+
+ // CHECK-NEXT: [[ERROR_COPY:%.*]] = copy_value [[ERROR]] : $Error
+ // CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
+ // CHECK-NEXT: [[ERROR_STACK:%[0-9]+]] = alloc_stack $@opened([[ERROR_ARCHETYPE]]) Error
+ // CHECK-NEXT: copy_addr [[ERROR_BOX]] to [initialization] [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
+ // CHECK: [[BRIDGE_FUNCTION:%[0-9]+]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[BRIDGED_ERROR:%[0-9]+]] = apply [[BRIDGE_FUNCTION]]<@opened([[ERROR_ARCHETYPE]]) Error>([[ERROR_STACK]])
+ // CHECK-NEXT: [[BRIDGED_ERROR_OPT:%[0-9]+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1, [[BRIDGED_ERROR]] : $AnyObject
+ // CHECK-NEXT: destroy_addr [[ERROR_STACK]]
+ // CHECK-NEXT: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
+ // CHECK-NEXT: destroy_value [[ERROR_COPY]] : $Error
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK-NEXT: apply [[METHOD]]([[BRIDGED_ERROR_OPT]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[BRIDGED_ERROR_OPT]]
+ receiver.takesNullableId(error)
+
+ // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [[ANY]] to [initialization] [[COPY]]
+ // CHECK-NEXT: [[OPENED_COPY:%.*]] = open_existential_addr immutable_access [[COPY]] : $*Any to $*[[OPENED_TYPE:@opened.*Any]],
+ // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]]
+ // CHECK: copy_addr [[OPENED_COPY]] to [initialization] [[TMP]]
+ // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK-NEXT: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
+ // CHECK-NEXT: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK-NEXT: destroy_addr [[TMP]]
+ // CHECK-NEXT: dealloc_stack [[TMP]]
+ // CHECK-NEXT: destroy_addr [[COPY]]
+ // CHECK-NEXT: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
+ receiver.takesNullableId(any)
+
+ // CHECK: [[TMP:%.*]] = alloc_stack $KnownUnbridged
+ // CHECK: store [[KNOWN_UNBRIDGED]] to [trivial] [[TMP]]
+ // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveC{{.*}}F
+ // CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<KnownUnbridged>([[TMP]])
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $NSIdLover,
+ // CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[SELF]])
+ receiver.takesNullableId(knownUnbridged)
+
+ // CHECK: [[OPT_STRING_COPY:%.*]] = copy_value [[OPT_STRING]]
+ // CHECK: switch_enum [[OPT_STRING_COPY]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+ //
+ // CHECK: [[SOME_BB]]([[STRING_DATA:%.*]] : @owned $String):
+ // CHECK: [[BRIDGE_STRING:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK: [[BORROWED_STRING_DATA:%.*]] = begin_borrow [[STRING_DATA]]
+ // CHECK: [[BRIDGED:%.*]] = apply [[BRIDGE_STRING]]([[BORROWED_STRING_DATA]])
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[BRIDGED]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: end_borrow [[BORROWED_STRING_DATA]] from [[STRING_DATA]]
+ // CHECK: destroy_value [[STRING_DATA]]
+ // CHECK: br [[JOIN:bb.*]]([[OPT_ANYOBJECT]]
+ //
+ // CHECK: [[NONE_BB]]:
+ // CHECK: [[OPT_NONE:%.*]] = enum $Optional<AnyObject>, #Optional.none!enumelt
+ // CHECK: br [[JOIN]]([[OPT_NONE]]
+ //
+ // CHECK: [[JOIN]]([[PHI:%.*]] : @owned $Optional<AnyObject>):
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]]
+ // CHECK: apply [[METHOD]]([[PHI]], [[SELF]])
+ // CHECK: destroy_value [[PHI]]
+ receiver.takesNullableId(optString)
+
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]]
+ receiver.takesNullableId(optNSString)
+
+ // CHECK: [[OPT_OBJECT_COPY:%.*]] = copy_value [[OPT_OBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]]
+ // CHECK: apply [[METHOD]]([[OPT_OBJECT_COPY]], [[SELF]])
+ receiver.takesNullableId(optObject)
+ receiver.takesNullableId(optClassGeneric)
+ receiver.takesNullableId(optClassExistential)
+ receiver.takesNullableId(optGeneric)
+ receiver.takesNullableId(optExistential)
+ receiver.takesNullableId(optAny)
+ receiver.takesNullableId(optKnownUnbridged)
+
+ receiver.takesNullableId(optOptA)
+ receiver.takesNullableId(optOptB)
+ receiver.takesNullableId(optOptC)
+}
+
+protocol Anyable {
+ init(any: Any)
+ init(anyMaybe: Any?)
+ var anyProperty: Any { get }
+ var maybeAnyProperty: Any? { get }
+}
+
+// Make sure we generate correct bridging thunks
+class SwiftIdLover : NSObject, Anyable {
+
+ func methodReturningAny() -> Any {}
+ // SEMANTIC ARC TODO: This is another case of pattern matching the body of one
+ // function in a different function... Just pattern match the unreachable case
+ // to preserve behavior. We should check if it is correct.
+
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC18methodReturningAnyypyF : $@convention(method) (@guaranteed SwiftIdLover) -> @out Any
+ // CHECK: unreachable
+ // CHECK: } // end sil function '$S17objc_bridging_any12SwiftIdLoverC18methodReturningAnyypyF'
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC18methodReturningAnyypyFTo : $@convention(objc_method) (SwiftIdLover) -> @autoreleased AnyObject {
+ // CHECK: bb0([[SELF:%[0-9]+]] : @unowned $SwiftIdLover):
+ // CHECK: [[NATIVE_RESULT:%.*]] = alloc_stack $Any
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $SwiftIdLover
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NATIVE_IMP:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC18methodReturningAnyypyF
+ // CHECK: apply [[NATIVE_IMP]]([[NATIVE_RESULT]], [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: [[OPEN_RESULT:%.*]] = open_existential_addr immutable_access [[NATIVE_RESULT]]
+ // CHECK: [[TMP:%.*]] = alloc_stack
+ // CHECK: copy_addr [[OPEN_RESULT]] to [initialization] [[TMP]]
+ // CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveC{{.*}}F
+ // CHECK: [[OBJC_RESULT:%.*]] = apply [[BRIDGE_ANYTHING]]<{{.*}}>([[TMP]])
+ // CHECK: return [[OBJC_RESULT]]
+ // CHECK: } // end sil function '$S17objc_bridging_any12SwiftIdLoverC18methodReturningAnyypyFTo'
+
+ func methodReturningOptionalAny() -> Any? {}
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC26methodReturningOptionalAnyypSgyF
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC26methodReturningOptionalAnyypSgyFTo
+ // CHECK: function_ref @$Ss27_bridgeAnythingToObjectiveC{{.*}}F
+
+ @objc func methodTakingAny(a: Any) {}
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC15methodTakingAny1ayyp_tFTo : $@convention(objc_method) (AnyObject, SwiftIdLover) -> ()
+ // CHECK: bb0([[ARG:%.*]] : @unowned $AnyObject, [[SELF:%.*]] : @unowned $SwiftIdLover):
+ // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK-NEXT: [[OPENED_SELF:%.*]] = open_existential_ref [[ARG_COPY]]
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: [[INIT:%.*]] = init_existential_addr [[RESULT]] : $*Any
+ // CHECK-NEXT: store [[OPENED_SELF]] to [init] [[INIT]]
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC15methodTakingAny1ayyp_tF
+ // CHECK-NEXT: apply [[METHOD]]([[RESULT]], [[BORROWED_SELF_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_addr [[RESULT]]
+ // CHECK-NEXT: dealloc_stack [[RESULT]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: return
+
+ func methodTakingOptionalAny(a: Any?) {}
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC23methodTakingOptionalAny1ayypSg_tF
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC23methodTakingOptionalAny1ayypSg_tFTo
+
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC017methodTakingBlockH3AnyyyyypXEF : $@convention(method) (@noescape @callee_guaranteed (@in_guaranteed Any) -> (), @guaranteed SwiftIdLover) -> ()
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC017methodTakingBlockH3AnyyyyypXEFTo : $@convention(objc_method) (@convention(block) @noescape (AnyObject) -> (), SwiftIdLover) -> ()
+ // CHECK: bb0([[BLOCK:%.*]] : @unowned $@convention(block) @noescape (AnyObject) -> (), [[SELF:%.*]] : @unowned $SwiftIdLover):
+ // CHECK-NEXT: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SyXlIyBy_ypIegn_TR
+ // CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[BLOCK_COPY]])
+ // CHECK-NEXT: [[THUNK_CVT:%.*]] = convert_escape_to_noescape [[THUNK]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC017methodTakingBlockH3AnyyyyypXEF
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[THUNK_CVT]], [[BORROWED_SELF_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[THUNK]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: return [[RESULT]]
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SyXlIyBy_ypIegn_TR
+ // CHECK: bb0([[ANY:%.*]] : @trivial $*Any, [[BLOCK:%.*]] : @guaranteed $@convention(block) @noescape (AnyObject) -> ()):
+ // CHECK-NEXT: [[OPENED_ANY:%.*]] = open_existential_addr immutable_access [[ANY]] : $*Any to $*[[OPENED_TYPE:@opened.*Any]],
+ // CHECK: [[TMP:%.*]] = alloc_stack
+ // CHECK: copy_addr [[OPENED_ANY]] to [initialization] [[TMP]]
+ // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK-NEXT: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK-NEXT: [[BRIDGED:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
+ // CHECK-NEXT: apply [[BLOCK]]([[BRIDGED]])
+ // CHECK-NEXT: [[VOID:%.*]] = tuple ()
+ // CHECK-NEXT: destroy_value [[BRIDGED]]
+ // CHECK-NEXT: destroy_addr [[TMP]]
+ // CHECK-NEXT: dealloc_stack [[TMP]]
+ // CHECK-NEXT: return [[VOID]]
+
+ @objc func methodTakingBlockTakingAny(_: (Any) -> ()) {}
+
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC29methodReturningBlockTakingAnyyypcyF : $@convention(method) (@guaranteed SwiftIdLover) -> @owned @callee_guaranteed (@in_guaranteed Any) -> ()
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC29methodReturningBlockTakingAnyyypcyFTo : $@convention(objc_method) (SwiftIdLover) -> @autoreleased @convention(block) (AnyObject) -> ()
+ // CHECK: bb0([[SELF:%.*]] : @unowned $SwiftIdLover):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC29methodReturningBlockTakingAnyyypcyF
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD:%.*]]([[BORROWED_SELF_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage @callee_guaranteed (@in_guaranteed Any) -> ()
+ // CHECK-NEXT: [[BLOCK_STORAGE_ADDR:%.*]] = project_block_storage [[BLOCK_STORAGE]]
+ // CHECK-NEXT: store [[RESULT:%.*]] to [init] [[BLOCK_STORAGE_ADDR]]
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SypIegn_yXlIeyBy_TR
+ // CHECK-NEXT: [[BLOCK_HEADER:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] : $*@block_storage @callee_guaranteed (@in_guaranteed Any) -> (), invoke [[THUNK_FN]]
+ // CHECK-NEXT: [[BLOCK:%.*]] = copy_block [[BLOCK_HEADER]]
+ // CHECK-NEXT: destroy_addr [[BLOCK_STORAGE_ADDR]]
+ // CHECK-NEXT: dealloc_stack [[BLOCK_STORAGE]]
+ // CHECK-NEXT: return [[BLOCK]]
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypIegn_yXlIeyBy_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed (@in_guaranteed Any) -> (), AnyObject) -> ()
+ // CHECK: bb0([[BLOCK_STORAGE:%.*]] : @trivial $*@block_storage @callee_guaranteed (@in_guaranteed Any) -> (), [[ANY:%.*]] : @unowned $AnyObject):
+ // CHECK-NEXT: [[BLOCK_STORAGE_ADDR:%.*]] = project_block_storage [[BLOCK_STORAGE]]
+ // CHECK-NEXT: [[FUNCTION:%.*]] = load [copy] [[BLOCK_STORAGE_ADDR]]
+ // CHECK-NEXT: [[ANY_COPY:%.*]] = copy_value [[ANY]]
+ // CHECK-NEXT: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY_COPY]]
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: [[INIT:%.*]] = init_existential_addr [[RESULT]] : $*Any
+ // CHECK-NEXT: store [[OPENED_ANY]] to [init] [[INIT]]
+ // CHECK-NEXT: [[BORROW_FUN:%.*]] = begin_borrow [[FUNCTION]]
+ // CHECK-NEXT: apply [[BORROW_FUN]]([[RESULT]])
+ // CHECK-NEXT: end_borrow [[BORROW_FUN]] from [[FUNCTION]]
+ // CHECK-NEXT: [[VOID:%.*]] = tuple ()
+ // CHECK-NEXT: destroy_addr [[RESULT]]
+ // CHECK-NEXT: dealloc_stack [[RESULT]]
+ // CHECK-NEXT: destroy_value [[FUNCTION]]
+ // CHECK-NEXT: return [[VOID]] : $()
+
+ @objc func methodTakingBlockTakingOptionalAny(_: (Any?) -> ()) {}
+
+ @objc func methodReturningBlockTakingAny() -> ((Any) -> ()) {}
+
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC29methodTakingBlockReturningAnyyyypyXEF : $@convention(method) (@noescape @callee_guaranteed () -> @out Any, @guaranteed SwiftIdLover) -> () {
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC29methodTakingBlockReturningAnyyyypyXEFTo : $@convention(objc_method) (@convention(block) @noescape () -> @autoreleased AnyObject, SwiftIdLover) -> ()
+ // CHECK: bb0([[BLOCK:%.*]] : @unowned $@convention(block) @noescape () -> @autoreleased AnyObject, [[ANY:%.*]] : @unowned $SwiftIdLover):
+ // CHECK-NEXT: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ // CHECK-NEXT: [[ANY_COPY:%.*]] = copy_value [[ANY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[THUNK_FN:%.*]] = function_ref @$SyXlIyBa_ypIegr_TR
+ // CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]([[BLOCK_COPY]])
+ // CHECK-NEXT: [[THUNK_CVT:%.*]] = convert_escape_to_noescape [[THUNK]]
+ // CHECK-NEXT: [[BORROWED_ANY_COPY:%.*]] = begin_borrow [[ANY_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC29methodTakingBlockReturningAnyyyypyXEF
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[THUNK_CVT]], [[BORROWED_ANY_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_ANY_COPY]] from [[ANY_COPY]]
+ // CHECK-NEXT: destroy_value [[THUNK]]
+ // CHECK-NEXT: destroy_value [[ANY_COPY]]
+ // CHECK-NEXT: return [[RESULT]]
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SyXlIyBa_ypIegr_TR : $@convention(thin) (@guaranteed @convention(block) @noescape () -> @autoreleased AnyObject) -> @out Any
+ // CHECK: bb0([[ANY_ADDR:%.*]] : @trivial $*Any, [[BLOCK:%.*]] : @guaranteed $@convention(block) @noescape () -> @autoreleased AnyObject):
+ // CHECK-NEXT: [[BRIDGED:%.*]] = apply [[BLOCK]]()
+ // CHECK-NEXT: [[OPTIONAL:%.*]] = unchecked_ref_cast [[BRIDGED]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[BRIDGE_TO_ANY:%.*]] = function_ref [[BRIDGE_TO_ANY_FUNC:@.*]] :
+ // CHECK-NEXT: [[BORROWED_OPTIONAL:%.*]] = begin_borrow [[OPTIONAL]]
+ // CHECK-NEXT: [[RESULT_VAL:%.*]] = apply [[BRIDGE_TO_ANY]]([[ANY_ADDR]], [[BORROWED_OPTIONAL]])
+ // CHECK-NEXT: [[EMPTY:%.*]] = tuple ()
+ // CHECK-NEXT: end_borrow [[BORROWED_OPTIONAL]]
+ // CHECK-NEXT: destroy_value [[OPTIONAL]]
+ // CHECK-NEXT: return [[EMPTY]]
+
+ @objc func methodReturningBlockTakingOptionalAny() -> ((Any?) -> ()) {}
+
+ @objc func methodTakingBlockReturningAny(_: () -> Any) {}
+
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any12SwiftIdLoverC020methodReturningBlockH3AnyypycyF : $@convention(method) (@guaranteed SwiftIdLover) -> @owned @callee_guaranteed () -> @out Any
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_bridging_any12SwiftIdLoverC020methodReturningBlockH3AnyypycyFTo : $@convention(objc_method) (SwiftIdLover) -> @autoreleased @convention(block) () -> @autoreleased AnyObject
+ // CHECK: bb0([[SELF:%.*]] : @unowned $SwiftIdLover):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[METHOD:%.*]] = function_ref @$S17objc_bridging_any12SwiftIdLoverC020methodReturningBlockH3AnyypycyF
+ // CHECK-NEXT: [[FUNCTION:%.*]] = apply [[METHOD]]([[BORROWED_SELF_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage @callee_guaranteed () -> @out Any
+ // CHECK-NEXT: [[BLOCK_STORAGE_ADDR:%.*]] = project_block_storage [[BLOCK_STORAGE]]
+ // CHECK-NEXT: store [[FUNCTION]] to [init] [[BLOCK_STORAGE_ADDR]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[THUNK_FN:%.*]] = function_ref @$SypIegr_yXlIeyBa_TR
+ // CHECK-NEXT: [[BLOCK_HEADER:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] : $*@block_storage @callee_guaranteed () -> @out Any, invoke [[THUNK_FN]]
+ // CHECK-NEXT: [[BLOCK:%.*]] = copy_block [[BLOCK_HEADER]]
+ // CHECK-NEXT: destroy_addr [[BLOCK_STORAGE_ADDR]]
+ // CHECK-NEXT: dealloc_stack [[BLOCK_STORAGE]]
+ // CHECK-NEXT: return [[BLOCK]]
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypIegr_yXlIeyBa_TR : $@convention(c) (@inout_aliasable @block_storage @callee_guaranteed () -> @out Any) -> @autoreleased AnyObject
+ // CHECK: bb0(%0 : @trivial $*@block_storage @callee_guaranteed () -> @out Any):
+ // CHECK-NEXT: [[BLOCK_STORAGE_ADDR:%.*]] = project_block_storage %0
+ // CHECK-NEXT: [[FUNCTION:%.*]] = load [copy] [[BLOCK_STORAGE_ADDR]]
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: [[BORROW_FUN:%.*]] = begin_borrow [[FUNCTION]]
+ // CHECK-NEXT: apply [[BORROW_FUN]]([[RESULT]])
+ // CHECK-NEXT: end_borrow [[BORROW_FUN]] from [[FUNCTION]]
+ // CHECK-NEXT: [[OPENED:%.*]] = open_existential_addr immutable_access [[RESULT]] : $*Any to $*[[OPENED_TYPE:@opened.*Any]],
+ // CHECK: [[TMP:%.*]] = alloc_stack $[[OPENED_TYPE]]
+ // CHECK: copy_addr [[OPENED]] to [initialization] [[TMP]]
+ // CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
+ // CHECK-NEXT: [[BRIDGE_ANYTHING:%.*]] = function_ref
+ // CHECK-NEXT: [[BRIDGED:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
+ // CHECK-NEXT: destroy_addr [[TMP]]
+ // CHECK-NEXT: dealloc_stack [[TMP]]
+ // CHECK-NEXT: destroy_addr [[RESULT]]
+ // CHECK-NEXT: dealloc_stack [[RESULT]]
+ // CHECK-NEXT: destroy_value [[FUNCTION]]
+ // CHECK-NEXT: return [[BRIDGED]]
+
+ @objc func methodTakingBlockReturningOptionalAny(_: () -> Any?) {}
+
+ @objc func methodReturningBlockReturningAny() -> (() -> Any) {}
+
+ @objc func methodReturningBlockReturningOptionalAny() -> (() -> Any?) {}
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypSgIegr_yXlSgIeyBa_TR
+ // CHECK: function_ref @$Ss27_bridgeAnythingToObjectiveC{{.*}}F
+
+ override init() { super.init() }
+ @objc dynamic required convenience init(any: Any) { self.init() }
+ @objc dynamic required convenience init(anyMaybe: Any?) { self.init() }
+ @objc dynamic var anyProperty: Any
+ @objc dynamic var maybeAnyProperty: Any?
+
+ subscript(_: IndexForAnySubscript) -> Any { get {} set {} }
+
+ @objc func methodReturningAnyOrError() throws -> Any {}
+}
+
+class IndexForAnySubscript {}
+
+func dynamicLookup(x: AnyObject) {
+ _ = x.anyProperty
+ _ = x[IndexForAnySubscript()]
+}
+
+extension GenericClass {
+ // CHECK-LABEL: sil hidden @$SSo12GenericClassC17objc_bridging_anyE23pseudogenericAnyErasure1xypx_tF :
+ func pseudogenericAnyErasure(x: T) -> Any {
+ // CHECK: bb0([[ANY_OUT:%.*]] : @trivial $*Any, [[ARG:%.*]] : @guaranteed $T, [[SELF:%.*]] : @guaranteed $GenericClass<T>
+ // CHECK: [[ANY_BUF:%.*]] = init_existential_addr [[ANY_OUT]] : $*Any, $AnyObject
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[ARG_COPY]] : $T : $T, $AnyObject
+ // CHECK: store [[ANYOBJECT]] to [init] [[ANY_BUF]]
+ return x
+ }
+ // CHECK: } // end sil function '$SSo12GenericClassC17objc_bridging_anyE23pseudogenericAnyErasure1xypx_tF'
+}
+
+// Make sure AnyHashable erasure marks Hashable conformance as used
+class AnyHashableClass : NSObject {
+ // CHECK-LABEL: sil hidden @$S17objc_bridging_any16AnyHashableClassC07returnsdE0s0dE0VyF
+ // CHECK: [[FN:%.*]] = function_ref @$Ss21_convertToAnyHashableys0cD0Vxs0D0RzlF
+ // CHECK: apply [[FN]]<GenericOption>({{.*}})
+ func returnsAnyHashable() -> AnyHashable {
+ return GenericOption.multithreaded
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S17objc_bridging_any33bridgeOptionalFunctionToAnyObject2fnyXlyycSg_tF : $@convention(thin) (@guaranteed Optional<@callee_guaranteed () -> ()>) -> @owned AnyObject
+// CHECK: [[BRIDGE:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+// CHECK: [[FN:%.*]] = function_ref @$SIeg_ytytIegnr_TR
+// CHECK: partial_apply [callee_guaranteed] [[FN]]
+// CHECK: [[SELF:%.*]] = alloc_stack $Optional<@callee_guaranteed (@in_guaranteed ()) -> @out ()>
+// CHECK: apply [[BRIDGE]]<() -> ()>([[SELF]])
+func bridgeOptionalFunctionToAnyObject(fn: (() -> ())?) -> AnyObject {
+ return fn as AnyObject
+}
+
+// CHECK-LABEL: sil_witness_table shared [serialized] GenericOption: Hashable module objc_generics {
+// CHECK-NEXT: base_protocol Equatable: GenericOption: Equatable module objc_generics
+// CHECK-NEXT: method #Hashable.hashValue!getter.1: {{.*}} : @$SSo13GenericOptionas8HashableSCsACP9hashValueSivgTW
+// CHECK-NEXT: method #Hashable._hash!1: {{.*}} : @$SSo13GenericOptionas8HashableSCsACP5_hash4intoys7_HasherVz_tFTW
+// CHECK-NEXT: }
diff --git a/test/SILGen/plus_zero_objc_bridging_peephole.swift b/test/SILGen/plus_zero_objc_bridging_peephole.swift
new file mode 100644
index 0000000..8797bc5
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_bridging_peephole.swift
@@ -0,0 +1,617 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+import Foundation
+import OtherSubscripts
+import objc_generics
+
+func useNS(_ : NSString) {}
+func useOptNS(_ : NSString?) {}
+func makeNS() -> NSString { return "help" as NSString }
+func makeOptNS() -> NSString? { return nil }
+
+func useAnyObject(_: AnyObject) {}
+func useOptAnyObject(_: AnyObject?) {}
+
+/*** Return values ***********************************************************/
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole16testMethodResult5dummyySo10DummyClassC_tF
+func testMethodResult(dummy: DummyClass) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $DummyClass, #DummyClass.fetchNullableString!1.foreign
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(dummy.fetchNullableString() as NSString?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $DummyClass, #DummyClass.fetchNullproneString!1.foreign
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(dummy.fetchNullproneString() as NSString?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $DummyClass, #DummyClass.fetchNonnullString!1.foreign
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(dummy.fetchNonnullString() as NSString?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK-NEXT: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole15useOptAnyObjectyyyXlSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useOptAnyObject(dummy.fetchNullableString() as AnyObject?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole15useOptAnyObjectyyyXlSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useOptAnyObject(dummy.fetchNullproneString() as AnyObject?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole15useOptAnyObjectyyyXlSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useOptAnyObject(dummy.fetchNonnullString() as AnyObject?)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole23testNonNullMethodResult5dummyySo10DummyClassC_tF
+func testNonNullMethodResult(dummy: DummyClass) {
+ // CHECK: bb0([[ARG:%.*]] @guaranteed $DummyClass):
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: switch_enum [[RESULT]]
+ //
+ // CHECK: bb1:
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole5useNSyySo8NSStringCF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useNS(dummy.fetchNonnullString() as NSString)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: switch_enum [[RESULT]]
+ // CHECK: bb3:
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+ // CHECK-NEXT: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole12useAnyObjectyyyXlF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useAnyObject(dummy.fetchNonnullString() as AnyObject)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole22testForcedMethodResult5dummyySo10DummyClassC_tF
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $DummyClass):
+func testForcedMethodResult(dummy: DummyClass) {
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: switch_enum [[RESULT]]
+ // CHECK: bb1:
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole5useNSyySo8NSStringCF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useNS(dummy.fetchNullproneString() as NSString)
+
+ // This is not a force.
+ // TODO: we could do it more efficiently than this, though
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: switch_enum [[RESULT]]
+ //
+ // CHECK: bb3([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ //
+ // CHECK: bb4:
+ // CHECK: enum $Optional<String>, #Optional.none
+ //
+ // CHECK: bb5([[OPTSTRING:%.*]] : @owned $Optional<String>):
+ // CHECK: [[BRIDGE:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+ // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Optional<String>
+ // CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[OPTSTRING]]
+ // CHECK-NEXT: store_borrow [[BORROW]] to [[TEMP]] : $*Optional<String>
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]<String>([[TEMP]])
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole12useAnyObjectyyyXlF
+ // CHECK: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useAnyObject(dummy.fetchNullproneString() as AnyObject)
+
+ // CHECK: return
+}
+
+/*** Property loads **********************************************************/
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole17testPropertyValue5dummyySo10DummyClassC_tF
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $DummyClass):
+func testPropertyValue(dummy: DummyClass) {
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(dummy.nullableStringProperty as NSString?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(dummy.nullproneStringProperty as NSString?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(dummy.nonnullStringProperty as NSString?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole15useOptAnyObjectyyyXlSgF
+ // CHECK: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useOptAnyObject(dummy.nullableStringProperty as AnyObject?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole15useOptAnyObjectyyyXlSgF
+ // CHECK: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useOptAnyObject(dummy.nullproneStringProperty as AnyObject?)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole15useOptAnyObjectyyyXlSgF
+ // CHECK: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useOptAnyObject(dummy.nonnullStringProperty as AnyObject?)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole24testNonNullPropertyValue5dummyySo10DummyClassC_tF
+func testNonNullPropertyValue(dummy: DummyClass) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: switch_enum [[RESULT]]
+ // CHECK: bb1:
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole5useNSyySo8NSStringCF
+ // CHECK: apply [[USE]]([[BORROWED_RESULT]])
+ useNS(dummy.nonnullStringProperty as NSString)
+
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: switch_enum [[RESULT]]
+ // CHECK: bb3:
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole12useAnyObjectyyyXlF
+ // CHECK: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ useAnyObject(dummy.nonnullStringProperty as AnyObject)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole23testForcedPropertyValue5dummyySo10DummyClassC_tF
+func testForcedPropertyValue(dummy: DummyClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: switch_enum [[RESULT]]
+ // CHECK: bb1:
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole5useNSyySo8NSStringCF
+ // CHECK: apply [[USE]]([[BORROWED_RESULT]])
+ useNS(dummy.nullproneStringProperty as NSString)
+
+ // This is not a force.
+ // TODO: we could do it more efficiently than this, though
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: switch_enum [[RESULT]]
+ // CHECK: bb3([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+ // CHECK: bb4:
+ // CHECK: enum $Optional<String>, #Optional.none
+ // CHECK: bb5([[OPTSTRING:%.*]] : @owned $Optional<String>):
+ // CHECK: [[BRIDGE:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+ // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Optional<String>
+ // CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[OPTSTRING]]
+ // CHECK-NEXT: store_borrow [[BORROW]] to [[TEMP]] : $*Optional<String>
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]<String>([[TEMP]])
+ // CHECK: [[BORROWED_ANYOBJECT:%.*]] = begin_borrow [[ANYOBJECT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole12useAnyObjectyyyXlF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_ANYOBJECT]])
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: destroy_value [[OPTSTRING]]
+ useAnyObject(dummy.nullproneStringProperty as AnyObject)
+
+ // CHECK: return
+}
+
+/*** Subscript loads *********************************************************/
+
+// FIXME: apply peepholes to indices, too!
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole23testNonnullSubscriptGet6object5indexySo0eF0C_yXltF
+func testNonnullSubscriptGet(object: NonnullSubscript, index: AnyObject) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $NonnullSubscript,
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(object[index] as NSString?)
+
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK-NEXT: switch_enum [[RESULT]]
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb{{[0-9]+}}([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole5useNSyySo8NSStringCF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useNS(object[index] as NSString)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole24testNullableSubscriptGet6object5indexySo0eF0C_yXltF
+func testNullableSubscriptGet(object: NullableSubscript, index: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $NullableSubscript,
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(object[index] as NSString?)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole25testNullproneSubscriptGet6object5indexySo0eF0C_yXltF
+func testNullproneSubscriptGet(object: NullproneSubscript, index: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $NullproneSubscript,
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole8useOptNSyySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useOptNS(object[index] as NSString?)
+
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK-NEXT: switch_enum [[RESULT]]
+ // CHECK: function_ref @$Ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_lineyBp_BwBi1_BwtF
+ // CHECK: bb{{[0-9]+}}([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK: [[USE:%.*]] = function_ref @$S22objc_bridging_peephole5useNSyySo8NSStringCF
+ // CHECK-NEXT: apply [[USE]]([[BORROWED_RESULT]])
+ useNS(object[index] as NSString)
+
+ // CHECK: return
+}
+
+/*** Call arguments **********************************************************/
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole18testMethodArgument5dummyySo10DummyClassC_tF
+func testMethodArgument(dummy: DummyClass) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $DummyClass):
+ // CHECK: // function_ref
+ // CHECK-NEXT: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[ARG]]
+ dummy.takeNonnullString(makeNS() as String)
+
+ // CHECK: // function_ref
+ // CHECK-NEXT: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.takeNullableString(makeNS() as String)
+
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.takeNullproneString(makeNS() as String)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole28testValueToOptMethodArgument5dummyySo10DummyClassC_tF
+func testValueToOptMethodArgument(dummy: DummyClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.takeNullableString(makeNS() as String?)
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.takeNullproneString(makeNS() as String?)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole09testOptToE14MethodArgument5dummyySo10DummyClassC_tF
+func testOptToOptMethodArgument(dummy: DummyClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[ARG]]
+ dummy.takeNullableString(makeOptNS() as String?)
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[ARG]]
+ dummy.takeNullproneString(makeOptNS() as String?)
+
+ // CHECK: return
+}
+
+/*** Property assignments ****************************************************/
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole18testPropertySetter5dummyySo10DummyClassC_tF
+func testPropertySetter(dummy: DummyClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[ARG]]
+ dummy.nonnullStringProperty = makeNS() as String
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.nullableStringProperty = makeNS() as String
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.nullproneStringProperty = makeNS() as String
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole28testValueToOptPropertySetter5dummyySo10DummyClassC_tF
+func testValueToOptPropertySetter(dummy: DummyClass) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.nullableStringProperty = makeNS() as String?
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]] : $NSString
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[OPTARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[OPTARG]]
+ dummy.nullproneStringProperty = makeNS() as String?
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole09testOptToE14PropertySetter5dummyySo10DummyClassC_tF
+func testOptToOptPropertySetter(dummy: DummyClass) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $DummyClass):
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[ARG]]
+ dummy.nullableStringProperty = makeOptNS() as String?
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
+ // CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
+ // CHECK-NEXT: destroy_value [[ARG]]
+ dummy.nullproneStringProperty = makeOptNS() as String?
+
+ // CHECK: return
+}
+
+/*** Subscript assignments ***************************************************/
+
+// FIXME: apply peepholes to indices, too!
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole23testNonnullSubscriptSet6object5indexySo0eF0C_yXltF
+func testNonnullSubscriptSet(object: NonnullSubscript, index: AnyObject) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $NonnullSubscript,
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[ARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[ARG]]
+ object[index] = makeNS() as String
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole24testNullableSubscriptSet6object5indexySo0eF0C_yXltF
+func testNullableSubscriptSet(object: NullableSubscript, index: AnyObject) {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $NullableSubscript,
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[OPTARG]]
+ object[index] = makeNS() as String
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[OPTARG]]
+ object[index] = makeNS() as String?
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[ARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[ARG]]
+ object[index] = makeOptNS() as String?
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole25testNullproneSubscriptSet6object5indexySo0eF0C_yXltF
+func testNullproneSubscriptSet(object: NullproneSubscript, index: AnyObject) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $NullproneSubscript,
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[OPTARG]]
+ object[index] = makeNS() as String
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole6makeNSSo8NSStringCyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[OPTARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[OPTARG]]
+ object[index] = makeNS() as String?
+
+ // CHECK: [[MAKE:%.*]] = function_ref @$S22objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
+ // CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF
+ // CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: apply [[METHOD]]([[ARG]], [[INDEX]], [[SELF]])
+ // CHECK: destroy_value [[INDEX]]
+ // CHECK: destroy_value [[ARG]]
+ object[index] = makeOptNS() as String?
+
+ // CHECK: return
+}
+
+/*** Bugfixes ***************************************************************/
+
+protocol P {
+ var title : String { get }
+}
+
+func foo(p: P) {
+ DummyClass().takeNullableString(p.title)
+}
+
+// rdar://35402853
+// Make sure that we don't peephole AnyObject? -> Any? -> AnyObject naively.
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole017testOptionalToNonE6BridgeyyF
+func testOptionalToNonOptionalBridge() {
+ // CHECK: apply {{.*}}() : $@convention(c) () -> @autoreleased Optional<AnyObject>
+ // CHECK: function_ref @$Ss018_bridgeAnyObjectToB0yypyXlSgF :
+ // CHECK: [[T0:%.*]] = function_ref @$SSq19_bridgeToObjectiveCyXlyF
+ // CHECK: apply [[T0]]<Any>
+ useAnyObject(returnNullableId() as AnyObject)
+} // CHECK: end sil function '$S22objc_bridging_peephole017testOptionalToNonE6BridgeyyF'
+
+// CHECK-LABEL: sil hidden @$S22objc_bridging_peephole34testBlockToOptionalAnyObjectBridge5blockyyyXB_tF
+func testBlockToOptionalAnyObjectBridge(block: @escaping @convention(block) () -> ()) {
+ // CHECK: [[T0:%.*]] = begin_borrow {{%.*}} : $@convention(block) () -> ()
+ // CHECK-NEXT: [[T1:%.*]] = copy_value [[T0]]
+ // CHECK-NEXT: [[REF:%.*]] = unchecked_ref_cast [[T1]] : $@convention(block) () -> () to $AnyObject
+ // CHECK-NEXT: [[OPTREF:%.*]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1, [[REF]] : $AnyObject
+ // CHECK-NEXT: end_borrow [[T0]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[FN:%.*]] = function_ref @takeNullableId : $@convention(c) (Optional<AnyObject>) -> ()
+ // CHECK-NEXT: apply [[FN]]([[OPTREF]])
+ // CHECK-NEXT: destroy_value [[OPTREF]]
+ takeNullableId(block as Any)
+}
diff --git a/test/SILGen/plus_zero_objc_currying.swift b/test/SILGen/plus_zero_objc_currying.swift
new file mode 100644
index 0000000..8094585
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_currying.swift
@@ -0,0 +1,212 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -enable-sil-ownership -emit-silgen %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+import gizmo
+
+func curry_pod(_ x: CurryTest) -> (Int) -> Int {
+ return x.pod
+}
+// CHECK-LABEL: sil hidden @$S13objc_currying9curry_podyS2icSo9CurryTestCF : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed (Int) -> Int
+// CHECK: bb0([[ARG1:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_FOO_1:\$SSo9CurryTestC3podyS2iFTcTO]] : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed (Int) -> Int
+// CHECK: [[FN:%.*]] = apply [[THUNK]]([[ARG1]])
+// CHECK-NOT: destroy_value
+// CHECK: return [[FN]]
+// CHECK: } // end sil function '$S13objc_currying9curry_podyS2icSo9CurryTestCF'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK_FOO_1]] : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed (Int) -> Int
+// CHECK: bb0([[ARG1:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_FOO_2:\$SSo9CurryTestC3podyS2iFTO]]
+// CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]]
+// CHECK: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[ARG1_COPY]])
+// CHECK-NOT: destroy_value
+// CHECK: return [[FN]]
+// CHECK: } // end sil function '[[THUNK_FOO_1]]'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK_FOO_2]] : $@convention(method) (Int, @guaranteed CurryTest) -> Int
+// CHECK: bb0([[ARG1:%.*]] : @trivial $Int, [[ARG2:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[COPIED_ARG2:%.*]] = copy_value [[ARG2]]
+// CHECK: [[METHOD:%.*]] = objc_method [[COPIED_ARG2]] : $CurryTest, #CurryTest.pod!1.foreign
+// CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[ARG1]], [[COPIED_ARG2]])
+// CHECK: destroy_value [[COPIED_ARG2]]
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function '[[THUNK_FOO_2]]'
+
+func curry_bridged(_ x: CurryTest) -> (String?) -> String? {
+ return x.bridged
+}
+// CHECK-LABEL: sil hidden @$S13objc_currying13curry_bridgedySSSgACcSo9CurryTestCF : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>
+// CHECK: bb0([[ARG1:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_BAR_1:\$SSo9CurryTestC7bridgedySSSgADFTcTO]]
+// CHECK: [[FN:%.*]] = apply [[THUNK]]([[ARG1]])
+// CHECK-NOT: destroy_value [[ARG1]]
+// CHECK: return [[FN]]
+// CHECK: } // end sil function '$S13objc_currying13curry_bridgedySSSgACcSo9CurryTestCF'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK_BAR_1]] : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>
+// CHECK: bb0([[ARG1:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_BAR_2:\$SSo9CurryTestC7bridgedySSSgADFTO]]
+// CHECK: [[COPY_ARG1:%.*]] = copy_value [[ARG1]]
+// CHECK: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[COPY_ARG1]])
+// CHECK: return [[FN]]
+// CHECK: } // end sil function '[[THUNK_BAR_1]]'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK_BAR_2]] : $@convention(method) (@guaranteed Optional<String>, @guaranteed CurryTest) -> @owned Optional<String>
+// CHECK: bb0([[OPT_STRING:%.*]] : @guaranteed $Optional<String>, [[SELF:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[COPY_OPT_STRING:%.*]] = copy_value [[OPT_STRING]]
+// CHECK: switch_enum [[COPY_OPT_STRING]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]],
+//
+// CHECK: [[SOME_BB]]([[STRING:%.*]] : @owned $String):
+// CHECK: [[BRIDGING_FUNC:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+// CHECK: [[BORROWED_STRING:%.*]] = begin_borrow [[STRING]]
+// CHECK: [[NSSTRING:%.*]] = apply [[BRIDGING_FUNC]]([[BORROWED_STRING]])
+// CHECK: [[OPT_NSSTRING:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[NSSTRING]] : $NSString
+// CHECK: end_borrow [[BORROWED_STRING]] from [[STRING]]
+// CHECK: destroy_value [[STRING]]
+// CHECK: br bb3([[OPT_NSSTRING]] : $Optional<NSString>)
+
+// CHECK: bb2:
+// CHECK: [[OPT_NONE:%.*]] = enum $Optional<NSString>, #Optional.none!enumelt
+// CHECK: br bb3([[OPT_NONE]] : $Optional<NSString>)
+
+// CHECK: bb3([[OPT_NSSTRING:%.*]] : @owned $Optional<NSString>):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: [[METHOD:%.*]] = objc_method [[SELF_COPY]] : $CurryTest, #CurryTest.bridged!1.foreign
+// CHECK: [[RESULT_OPT_NSSTRING:%.*]] = apply [[METHOD]]([[OPT_NSSTRING]], [[SELF_COPY]]) : $@convention(objc_method) (Optional<NSString>, CurryTest) -> @autoreleased Optional<NSString>
+// CHECK: switch_enum [[RESULT_OPT_NSSTRING]] : $Optional<NSString>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]],
+
+// CHECK: [[SOME_BB]]([[RESULT_NSSTRING:%.*]] : @owned $NSString):
+// CHECK: [[BRIDGE_FUNC:%.*]] = function_ref @$SSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
+// CHECK: [[REWRAP_RESULT_NSSTRING:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[RESULT_NSSTRING]]
+// CHECK: [[RESULT_STRING:%.*]] = apply [[BRIDGE_FUNC]]([[REWRAP_RESULT_NSSTRING]]
+// CHECK: [[WRAPPED_RESULT_STRING:%.*]] = enum $Optional<String>, #Optional.some!enumelt.1, [[RESULT_STRING]]
+// CHECK: br bb6([[WRAPPED_RESULT_STRING]] : $Optional<String>)
+
+// CHECK: bb5:
+// CHECK: [[OPT_NONE:%.*]] = enum $Optional<String>, #Optional.none!enumelt
+// CHECK: br bb6([[OPT_NONE]] : $Optional<String>)
+
+// CHECK: bb6([[FINAL_RESULT:%.*]] : @owned $Optional<String>):
+// CHECK: destroy_value [[SELF_COPY]]
+// CHECK: destroy_value [[OPT_NSSTRING]]
+// CHECK: return [[FINAL_RESULT]] : $Optional<String>
+// CHECK: } // end sil function '[[THUNK_BAR_2]]'
+
+func curry_returnsInnerPointer(_ x: CurryTest) -> () -> UnsafeMutableRawPointer? {
+ return x.returnsInnerPointer
+}
+// CHECK-LABEL: sil hidden @$S13objc_currying25curry_returnsInnerPointerySvSgycSo9CurryTestCF : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed () -> Optional<UnsafeMutableRawPointer> {
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER:\$SSo9CurryTestC19returnsInnerPointerSvSgyFTcTO]]
+// CHECK: [[FN:%.*]] = apply [[THUNK]]([[SELF]])
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK: return [[FN]]
+// CHECK: } // end sil function '$S13objc_currying25curry_returnsInnerPointerySvSgycSo9CurryTestCF'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK_RETURNSINNERPOINTER]] : $@convention(thin) (@guaranteed CurryTest) -> @owned @callee_guaranteed () -> Optional<UnsafeMutableRawPointer>
+// CHECK: bb0([[ARG1:%.*]] : @guaranteed
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER_2:\$SSo9CurryTestC19returnsInnerPointerSvSgyFTO]]
+// CHECK: [[COPY_ARG1:%.*]] = copy_value [[ARG1]]
+// CHECK: [[FN:%.*]] = partial_apply [callee_guaranteed] [[THUNK]]([[COPY_ARG1]])
+// CHECK: return [[FN]]
+// CHECK: } // end sil function '[[THUNK_RETURNSINNERPOINTER]]'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK_RETURNSINNERPOINTER_2]] : $@convention(method) (@guaranteed CurryTest) -> Optional<UnsafeMutableRawPointer>
+// CHECK: bb0([[ARG1:%.*]] : @guaranteed $CurryTest):
+// CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]]
+// CHECK: [[METHOD:%.*]] = objc_method [[ARG1_COPY]] : $CurryTest, #CurryTest.returnsInnerPointer!1.foreign
+// CHECK: [[RES:%.*]] = apply [[METHOD]]([[ARG1_COPY]]) : $@convention(objc_method) (CurryTest) -> @unowned_inner_pointer Optional<UnsafeMutableRawPointer>
+// CHECK: autorelease_value
+// CHECK: return [[RES]]
+// CHECK: } // end sil function '[[THUNK_RETURNSINNERPOINTER_2]]'
+
+// CHECK-LABEL: sil hidden @$S13objc_currying19curry_pod_AnyObjectyS2icyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned @callee_guaranteed (Int) -> Int
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.pod!1.foreign, [[HAS_METHOD:bb[0-9]+]]
+// CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (Int, @opened({{.*}}) AnyObject) -> Int):
+// CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]]
+// CHECK: partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]])
+// CHECK: } // end sil function '$S13objc_currying19curry_pod_AnyObjectyS2icyXlF'
+func curry_pod_AnyObject(_ x: AnyObject) -> (Int) -> Int {
+ return x.pod!
+}
+
+// normalOwnership requires a thunk to bring the method to Swift conventions
+// CHECK-LABEL: sil hidden @$S13objc_currying31curry_normalOwnership_AnyObjectySo9CurryTestCSgAEcyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned @callee_guaranteed (@guaranteed Optional<CurryTest>) -> @owned Optional<CurryTest> {
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.normalOwnership!1.foreign, [[HAS_METHOD:bb[0-9]+]]
+// CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (Optional<CurryTest>, @opened({{.*}}) AnyObject) -> @autoreleased Optional<CurryTest>):
+// CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]]
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]])
+// CHECK: [[THUNK:%.*]] = function_ref @$SSo9CurryTestCSgACIegyo_A2CIeggo_TR
+// CHECK: partial_apply [callee_guaranteed] [[THUNK]]([[PA]])
+// CHECK: } // end sil function '$S13objc_currying31curry_normalOwnership_AnyObjectySo9CurryTestCSgAEcyXlF'
+func curry_normalOwnership_AnyObject(_ x: AnyObject) -> (CurryTest?) -> CurryTest? {
+ return x.normalOwnership!
+}
+
+// weirdOwnership is NS_RETURNS_RETAINED and NS_CONSUMES_SELF so already
+// follows Swift conventions
+// CHECK-LABEL: sil hidden @$S13objc_currying30curry_weirdOwnership_AnyObjectySo9CurryTestCSgAEcyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned @callee_guaranteed (@guaranteed Optional<CurryTest>) -> @owned Optional<CurryTest>
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[SELF:%.*]] : $@opened({{.*}}) AnyObject, #CurryTest.weirdOwnership!1.foreign, [[HAS_METHOD:bb[0-9]+]]
+//
+// CHECK: bb1([[METHOD:%.*]] : @trivial $@convention(objc_method) (@owned Optional<CurryTest>, @owned @opened({{.*}}) AnyObject) -> @owned Optional<CurryTest>):
+// CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]]
+// CHECK: partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]])
+// CHECK: } // end sil function '$S13objc_currying30curry_weirdOwnership_AnyObjectySo9CurryTestCSgAEcyXlF'
+func curry_weirdOwnership_AnyObject(_ x: AnyObject) -> (CurryTest?) -> CurryTest? {
+ return x.weirdOwnership!
+}
+
+// bridged requires a thunk to handle bridging conversions
+// CHECK-LABEL: sil hidden @$S13objc_currying23curry_bridged_AnyObjectySSSgACcyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned @callee_guaranteed (@guaranteed Optional<String>) -> @owned Optional<String>
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.bridged!1.foreign, [[HAS_METHOD:bb[0-9]+]]
+// CHECK: } // end sil function '$S13objc_currying23curry_bridged_AnyObjectySSSgACcyXlF'
+func curry_bridged_AnyObject(_ x: AnyObject) -> (String?) -> String? {
+ return x.bridged!
+}
+
+// check that we substitute Self = AnyObject correctly for Self-returning
+// methods
+// CHECK-LABEL: sil hidden @$S13objc_currying27curry_returnsSelf_AnyObjectyyXlSgycyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned @callee_guaranteed () -> @owned Optional<AnyObject> {
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.returnsSelf!1.foreign, [[HAS_METHOD:bb[0-9]+]]
+// CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (@opened({{.*}}) AnyObject) -> @autoreleased Optional<AnyObject>):
+// CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]]
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]])
+// CHECK: } // end sil function '$S13objc_currying27curry_returnsSelf_AnyObjectyyXlSgycyXlF'
+func curry_returnsSelf_AnyObject(_ x: AnyObject) -> () -> AnyObject? {
+ return x.returnsSelf!
+}
+
+// CHECK-LABEL: sil hidden @$S13objc_currying35curry_returnsInnerPointer_AnyObjectySvSgycyXlF : $@convention(thin) (@guaranteed AnyObject) -> @owned @callee_guaranteed () -> Optional<UnsafeMutableRawPointer> {
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened({{.*}}) AnyObject, #CurryTest.returnsInnerPointer!1.foreign, [[HAS_METHOD:bb[0-9]+]]
+// CHECK: [[HAS_METHOD]]([[METHOD:%.*]] : @trivial $@convention(objc_method) (@opened({{.*}}) AnyObject) -> @unowned_inner_pointer Optional<UnsafeMutableRawPointer>):
+// CHECK: [[OPENED_ANY_COPY_2:%.*]] = copy_value [[OPENED_ANY_COPY]]
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[METHOD]]([[OPENED_ANY_COPY_2]])
+// CHECK: } // end sil function '$S13objc_currying35curry_returnsInnerPointer_AnyObjectySvSgycyXlF'
+
+func curry_returnsInnerPointer_AnyObject(_ x: AnyObject) -> () -> UnsafeMutableRawPointer? {
+ return x.returnsInnerPointer!
+}
+
diff --git a/test/SILGen/plus_zero_objc_dictionary_bridging.swift b/test/SILGen/plus_zero_objc_dictionary_bridging.swift
new file mode 100644
index 0000000..cee9ad3
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_dictionary_bridging.swift
@@ -0,0 +1,96 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+import gizmo
+
+@objc class Foo : NSObject {
+ // Bridging dictionary parameters
+ // CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC23bridge_Dictionary_param{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
+ func bridge_Dictionary_param(_ dict: Dictionary<Foo, Foo>) {
+ // CHECK: bb0([[NSDICT:%[0-9]+]] : @unowned $NSDictionary, [[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[NSDICT_COPY:%.*]] = copy_value [[NSDICT]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss10DictionaryV10FoundationE36_unconditionallyBridgeFromObjectiveCyAByxq_GSo12NSDictionaryCSgFZ
+ // CHECK: [[OPT_NSDICT:%[0-9]+]] = enum $Optional<NSDictionary>, #Optional.some!enumelt.1, [[NSDICT_COPY]] : $NSDictionary
+ // CHECK: [[DICT_META:%[0-9]+]] = metatype $@thin Dictionary<Foo, Foo>.Type
+ // CHECK: [[DICT:%[0-9]+]] = apply [[CONVERTER]]<Foo, Foo>([[OPT_NSDICT]], [[DICT_META]])
+ // CHECK: [[BORROWED_DICT:%.*]] = begin_borrow [[DICT]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SWIFT_FN:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC23bridge_Dictionary_param{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[SWIFT_FN]]([[BORROWED_DICT]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: return [[RESULT]] : $()
+ }
+ // CHECK: } // end sil function '$S24objc_dictionary_bridging3FooC23bridge_Dictionary_param{{[_0-9a-zA-Z]*}}FTo'
+
+ // Bridging dictionary results
+ // CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC24bridge_Dictionary_result{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
+ func bridge_Dictionary_result() -> Dictionary<Foo, Foo> {
+ // CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SWIFT_FN:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC24bridge_Dictionary_result{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
+ // CHECK: [[DICT:%[0-9]+]] = apply [[SWIFT_FN]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss10DictionaryV10FoundationE19_bridgeToObjectiveCSo12NSDictionaryCyF
+ // CHECK: [[BORROWED_DICT:%.*]] = begin_borrow [[DICT]]
+ // CHECK: [[NSDICT:%[0-9]+]] = apply [[CONVERTER]]<Foo, Foo>([[BORROWED_DICT]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned NSDictionary
+ // CHECK: end_borrow [[BORROWED_DICT]] from [[DICT]]
+ // CHECK: destroy_value [[DICT]]
+ // CHECK: return [[NSDICT]] : $NSDictionary
+ }
+ // CHECK: } // end sil function '$S24objc_dictionary_bridging3FooC24bridge_Dictionary_result{{[_0-9a-zA-Z]*}}FTo'
+
+ var property: Dictionary<Foo, Foo> = [:]
+
+ // Property getter
+ // CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_GvgTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
+ // @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_Gvpfi
+ // CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[GETTER:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_Gvg : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
+ // CHECK: [[DICT:%[0-9]+]] = apply [[GETTER]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Foo) -> @owned Dictionary<Foo, Foo>
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss10DictionaryV10FoundationE19_bridgeToObjectiveCSo12NSDictionaryCyF
+ // CHECK: [[BORROWED_DICT:%.*]] = begin_borrow [[DICT]]
+ // CHECK: [[NSDICT:%[0-9]+]] = apply [[CONVERTER]]<Foo, Foo>([[BORROWED_DICT]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned NSDictionary
+ // CHECK: end_borrow [[BORROWED_DICT]] from [[DICT]]
+ // CHECK: destroy_value [[DICT]]
+ // CHECK: return [[NSDICT]] : $NSDictionary
+ // CHECK: } // end sil function
+
+ // Property setter
+ // CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_GvsTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
+ // CHECK: bb0([[NSDICT:%[0-9]+]] : @unowned $NSDictionary, [[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[NSDICT_COPY:%.*]] = copy_value [[NSDICT]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss10DictionaryV10FoundationE36_unconditionallyBridgeFromObjectiveCyAByxq_GSo12NSDictionaryCSgFZ
+ // CHECK: [[OPT_NSDICT:%[0-9]+]] = enum $Optional<NSDictionary>, #Optional.some!enumelt.1, [[NSDICT_COPY]] : $NSDictionary
+ // CHECK: [[DICT_META:%[0-9]+]] = metatype $@thin Dictionary<Foo, Foo>.Type
+ // CHECK: [[DICT:%[0-9]+]] = apply [[CONVERTER]]<Foo, Foo>([[OPT_NSDICT]], [[DICT_META]])
+
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SETTER:%[0-9]+]] = function_ref @$S24objc_dictionary_bridging3FooC8propertys10DictionaryVyA2CSo8NSObjectCs8Hashable10Foundationg_Gvs : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[SETTER]]([[DICT]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@owned Dictionary<Foo, Foo>, @guaranteed Foo) -> ()
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: return [[RESULT]] : $()
+
+ // CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC19nonVerbatimProperty{{[_0-9a-zA-Z]*}}vgTo : $@convention(objc_method) (Foo) -> @autoreleased NSDictionary
+
+ // CHECK-LABEL: sil hidden [thunk] @$S24objc_dictionary_bridging3FooC19nonVerbatimProperty{{[_0-9a-zA-Z]*}}vsTo : $@convention(objc_method) (NSDictionary, Foo) -> ()
+ @objc var nonVerbatimProperty: Dictionary<String, Int> = [:]
+}
+
+func ==(x: Foo, y: Foo) -> Bool { }
diff --git a/test/SILGen/plus_zero_objc_error.swift b/test/SILGen/plus_zero_objc_error.swift
new file mode 100644
index 0000000..e48d19c
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_error.swift
@@ -0,0 +1,173 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-clang-importer-objc-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+// CHECK-LABEL: sil hidden @$S10objc_error20NSErrorError_erasureys0D0_pSo0C0CF : $@convention(thin) (@guaranteed NSError) -> @owned Error {
+// CHECK: bb0([[ERROR:%.*]] : @guaranteed $NSError):
+// CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]]
+// CHECK: [[ERROR_TYPE:%.*]] = init_existential_ref [[ERROR_COPY]] : $NSError : $NSError, $Error
+// CHECK-NOT: destroy_value [[ERROR]]
+// CHECK: return [[ERROR_TYPE]]
+// CHECK: } // end sil function '$S10objc_error20NSErrorError_erasureys0D0_pSo0C0CF'
+func NSErrorError_erasure(_ x: NSError) -> Error {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S10objc_error30NSErrorError_archetype_erasureys0D0_pxSo0C0CRbzlF : $@convention(thin) <T where T : NSError> (@guaranteed T) -> @owned Error {
+// CHECK: bb0([[ERROR:%.*]] : @guaranteed $T):
+// CHECK: [[ERROR_COPY:%.*]] = copy_value [[ERROR]]
+// CHECK: [[T0:%.*]] = upcast [[ERROR_COPY]] : $T to $NSError
+// CHECK: [[ERROR_TYPE:%.*]] = init_existential_ref [[T0]] : $NSError : $NSError, $Error
+// CHECK-NOT: destroy_value [[ERROR]]
+// CHECK: return [[ERROR_TYPE]]
+// CHECK: } // end sil function '$S10objc_error30NSErrorError_archetype_erasureys0D0_pxSo0C0CRbzlF'
+func NSErrorError_archetype_erasure<T : NSError>(_ t: T) -> Error {
+ return t
+}
+
+// Test patterns that are non-trivial, but irrefutable. SILGen shouldn't crash
+// on these.
+func test_doesnt_throw() {
+ do {
+ throw NSError(domain: "", code: 1, userInfo: [:])
+ } catch is Error { // expected-warning {{'is' test is always true}}
+ }
+
+ do {
+ throw NSError(domain: "", code: 1, userInfo: [:])
+ } catch let e as NSError { // ok.
+ _ = e
+ }
+}
+
+class ErrorClass: Error {
+ let _domain = ""
+ let _code = 0
+}
+
+// Class-to-NSError casts must be done as indirect casts since they require
+// a representation change, and checked_cast_br currently doesn't allow that.
+
+// CHECK-LABEL: sil hidden @$S10objc_error20test_cast_to_nserroryyF
+func test_cast_to_nserror() {
+ let e = ErrorClass()
+
+ // CHECK: function_ref @$S10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF
+ let nsCoerced = e as Error as NSError
+
+ // CHECK: unconditional_checked_cast_addr AnyObject in {{%.*}} : $*AnyObject to NSError in {{%.*}} : $*NSError
+ let nsForcedCast = (e as AnyObject) as! NSError
+
+ // CHECK: checked_cast_addr_br {{.*}} Error in {{%.*}} : $*Error to NSError in {{%.*}} : $*NSError, bb3, bb4
+ do {
+ throw e
+ } catch _ as NSError {
+
+ }
+}
+
+// A class-constrained archetype may be NSError, so we can't use scalar casts
+// in that case either.
+// CHECK-LABEL: sil hidden @$S10objc_error28test_cast_to_class_archetype{{[_0-9a-zA-Z]*}}F
+func test_cast_to_class_archetype<T: AnyObject>(_: T) {
+ // CHECK: unconditional_checked_cast_addr ErrorClass in {{%.*}} : $*ErrorClass to T in {{.*}} : $*T
+ let e = ErrorClass()
+ let forcedCast = e as! T
+}
+
+// CHECK-LABEL: sil hidden @$S10objc_error15testAcceptError{{[_0-9a-zA-Z]*}}F
+func testAcceptError(error: Error) {
+ // CHECK-NOT: return
+ // CHECK: function_ref @$S10Foundation22_convertErrorToNSErrorySo0E0Cs0C0_pF
+ acceptError(error)
+}
+
+// CHECK-LABEL: sil hidden @$S10objc_error16testProduceError{{[_0-9a-zA-Z]*}}F
+func testProduceError() -> Error {
+ // CHECK: function_ref @produceError : $@convention(c) () -> @autoreleased NSError
+ // CHECK: init_existential_ref {{.*}} : $NSError : $NSError, $Error
+ return produceError()
+}
+
+// CHECK-LABEL: sil hidden @$S10objc_error24testProduceOptionalError{{[_0-9a-zA-Z]*}}F
+func testProduceOptionalError() -> Error? {
+ // CHECK: function_ref @produceOptionalError
+ // CHECK: init_existential_ref {{.*}} : $NSError : $NSError, $Error
+ return produceOptionalError();
+}
+
+class MyNSError : NSError {
+ override init() {
+ super.init(domain: "MyNSError", code: 0, userInfo: [:])
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10objc_error14eraseMyNSError{{[_0-9a-zA-Z]*}}F : $@convention(thin) () -> @owned Error {
+// CHECK: bb0:
+// CHECK: [[NSERROR_SUBCLASS:%.*]] = apply {{.*}}({{.*}}) : $@convention(method) (@thick MyNSError.Type) -> @owned MyNSError
+// CHECK: [[UPCAST:%.*]] = upcast [[NSERROR_SUBCLASS]] : $MyNSError to $NSError
+// CHECK: [[EXISTENTIAL_REF:%.*]] = init_existential_ref [[UPCAST]]
+// CHECK: [[BORROWED_EXISTENTIAL_REF:%.*]] = begin_borrow [[EXISTENTIAL_REF]]
+// CHECK: [[COPY_BORROWED_EXISTENTIAL_REF:%.*]] = copy_value [[BORROWED_EXISTENTIAL_REF]]
+// CHECK: end_borrow [[BORROWED_EXISTENTIAL_REF]] from [[EXISTENTIAL_REF]]
+// CHECK: destroy_value [[EXISTENTIAL_REF]]
+// CHECK: return [[COPY_BORROWED_EXISTENTIAL_REF]]
+// CHECK: } // end sil function '$S10objc_error14eraseMyNSError{{[_0-9a-zA-Z]*}}F'
+func eraseMyNSError() -> Error {
+ let x: Error = MyNSError()
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S10objc_error25eraseFictionalServerErrors0F0_pyF
+func eraseFictionalServerError() -> Error {
+ // CHECK-NOT: return
+ // CHECK: [[NSERROR:%[0-9]+]] = struct_extract {{.*}} : $FictionalServerError, #FictionalServerError._nsError
+ // CHECK: [[NSERROR_COPY:%.*]] = copy_value [[NSERROR]]
+ // CHECK: [[ERROR:%[0-9]+]] = init_existential_ref [[NSERROR_COPY]]
+ // CHECK: return [[ERROR]]
+ return FictionalServerError(.meltedDown)
+}
+// CHECK: } // end sil function '$S10objc_error25eraseFictionalServerErrors0F0_pyF'
+
+// SR-1562
+extension Error {
+ // CHECK-LABEL: sil hidden @$Ss5ErrorP10objc_errorE16convertToNSErrorSo0F0CyF
+ // CHECK: bb0([[SELF:%[0-9]+]] : @trivial $*Self)
+ func convertToNSError() -> NSError {
+ // CHECK: [[COPY:%.*]] = alloc_stack $Self
+ // CHECK: copy_addr [[SELF]] to [initialization] [[COPY]]
+ // CHECK: [[COPY2:%.*]] = alloc_stack $Self
+ // CHECK: copy_addr [[COPY]] to [initialization] [[COPY2]]
+ // CHECK: [[GET_EMBEDDED_FN:%[0-9]+]] = function_ref @$Ss24_getErrorEmbeddedNSErroryyXlSgxs0B0RzlF
+ // CHECK: [[EMBEDDED_RESULT_OPT:%[0-9]+]] = apply [[GET_EMBEDDED_FN]]<Self>([[COPY2]])
+ // CHECK: switch_enum [[EMBEDDED_RESULT_OPT]] : $Optional<AnyObject>,
+ // CHECK-SAME: case #Optional.some!enumelt.1: [[SUCCESS:bb[0-9]+]],
+ // CHECK-SAME: case #Optional.none!enumelt: [[FAILURE:bb[0-9]+]]
+
+ // CHECK: [[SUCCESS]]([[EMBEDDED_RESULT:%.*]] : @owned $AnyObject):
+ // CHECK: [[EMBEDDED_NSERROR:%[0-9]+]] = unchecked_ref_cast [[EMBEDDED_RESULT]] : $AnyObject to $NSError
+ // CHECK: [[ERROR:%[0-9]+]] = init_existential_ref [[EMBEDDED_NSERROR]] : $NSError : $NSError, $Error
+ // CHECK: destroy_addr [[COPY]] : $*Self
+ // CHECK: br [[CONTINUATION:bb[0-9]+]]([[ERROR]] : $Error)
+
+ // CHECK: [[FAILURE]]:
+ // CHECK: [[ERROR_BOX:%[0-9]+]] = alloc_existential_box $Error, $Self
+ // CHECK: [[ERROR_PROJECTED:%[0-9]+]] = project_existential_box $Self in [[ERROR_BOX]] : $Error
+ // CHECK: copy_addr [take] [[COPY]] to [initialization] [[ERROR_PROJECTED]] : $*Self
+ // CHECK: br [[CONTINUATION]]([[ERROR_BOX]] : $Error)
+
+ // CHECK: [[CONTINUATION]]([[ERROR_ARG:%[0-9]+]] : @owned $Error):
+ return self as NSError
+ }
+}
+
+class Gizmoid : NSObject {
+ // CHECK-LABEL: sil hidden [thunk] @$S10objc_error7GizmoidC3fooACyt_tKcfcTo : $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @owned Gizmoid) -> @owned Optional<Gizmoid>
+ @objc init(foo: ()) throws {}
+}
diff --git a/test/SILGen/plus_zero_objc_extensions.swift b/test/SILGen/plus_zero_objc_extensions.swift
new file mode 100644
index 0000000..96a4c49
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_extensions.swift
@@ -0,0 +1,187 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -sdk %S/Inputs/ -I %S/Inputs -enable-source-import %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+import objc_extensions_helper
+
+class Sub : Base {}
+
+extension Sub {
+ override var prop: String! {
+ didSet {
+ // Ignore it.
+ }
+
+ // Make sure that we are generating the @objc thunk and are calling the actual method.
+ //
+ // CHECK-LABEL: sil hidden [thunk] @$S15objc_extensions3SubC4propSSSgvgTo : $@convention(objc_method) (Sub) -> @autoreleased Optional<NSString> {
+ // CHECK: bb0([[SELF:%.*]] : @unowned $Sub):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[GETTER_FUNC:%.*]] = function_ref @$S15objc_extensions3SubC4propSSSgvg : $@convention(method) (@guaranteed Sub) -> @owned Optional<String>
+ // CHECK: apply [[GETTER_FUNC]]([[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: } // end sil function '$S15objc_extensions3SubC4propSSSgvgTo'
+
+ // Then check the body of the getter calls the super_method.
+ // CHECK-LABEL: sil hidden @$S15objc_extensions3SubC4propSSSgvg : $@convention(method) (@guaranteed Sub) -> @owned Optional<String> {
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $Sub):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[SELF_COPY_CAST:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
+ // CHECK: [[BORROWED_SELF_COPY_CAST:%.*]] = begin_borrow [[SELF_COPY_CAST]]
+ // CHECK: [[CAST_BACK:%.*]] = unchecked_ref_cast [[BORROWED_SELF_COPY_CAST]] : $Base to $Sub
+ // CHECK: [[SUPER_METHOD:%.*]] = objc_super_method [[CAST_BACK]] : $Sub, #Base.prop!getter.1.foreign
+ // CHECK: end_borrow [[BORROWED_SELF_COPY_CAST]]
+ // CHECK: [[RESULT:%.*]] = apply [[SUPER_METHOD]]([[SELF_COPY_CAST]])
+ // CHECK: bb3(
+ // CHECK: destroy_value [[SELF_COPY_CAST]]
+ // CHECK: } // end sil function '$S15objc_extensions3SubC4propSSSgvg'
+
+ // Then check the setter @objc thunk.
+ //
+ // CHECK-LABEL: sil hidden [thunk] @$S15objc_extensions3SubC4propSSSgvsTo : $@convention(objc_method) (Optional<NSString>, Sub) -> () {
+ // CHECK: bb0([[NEW_VALUE:%.*]] : @unowned $Optional<NSString>, [[SELF:%.*]] : @unowned $Sub):
+ // CHECK: [[NEW_VALUE_COPY:%.*]] = copy_value [[NEW_VALUE]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Sub
+ // CHECK: switch_enum [[NEW_VALUE_COPY]] : $Optional<NSString>, case #Optional.some!enumelt.1: [[SUCC_BB:bb[0-9]+]], case #Optional.none!enumelt: [[FAIL_BB:bb[0-9]+]]
+ // CHECK: [[SUCC_BB]]([[STR:%.*]] : @owned $NSString):
+ // CHECK: [[FAIL_BB]]:
+ // CHECK: bb3([[BRIDGED_NEW_VALUE:%.*]] : @owned $Optional<String>):
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NORMAL_FUNC:%.*]] = function_ref @$S15objc_extensions3SubC4propSSSgvs : $@convention(method) (@owned Optional<String>, @guaranteed Sub) -> ()
+ // CHECK: apply [[NORMAL_FUNC]]([[BRIDGED_NEW_VALUE]], [[BORROWED_SELF_COPY]])
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: } // end sil function '$S15objc_extensions3SubC4propSSSgvsTo'
+
+ // Then check the body of the actually setter value and make sure that we
+ // call the didSet function.
+ // CHECK-LABEL: sil hidden @$S15objc_extensions3SubC4propSSSgvs : $@convention(method) (@owned Optional<String>, @guaranteed Sub) -> () {
+
+ // First we get the old value.
+ // CHECK: bb0([[NEW_VALUE:%.*]] : @owned $Optional<String>, [[SELF:%.*]] : @guaranteed $Sub):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
+ // CHECK: [[BORROWED_UPCAST_SELF_COPY:%.*]] = begin_borrow [[UPCAST_SELF_COPY]]
+ // CHECK: [[CAST_BACK:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY]] : $Base to $Sub
+ // CHECK: [[GET_SUPER_METHOD:%.*]] = objc_super_method [[CAST_BACK]] : $Sub, #Base.prop!getter.1.foreign : (Base) -> () -> String?, $@convention(objc_method) (Base) -> @autoreleased Optional<NSString>
+ // CHECK: end_borrow [[BORROWED_UPCAST_SELF_COPY]] from [[UPCAST_SELF_COPY]]
+ // CHECK: [[OLD_NSSTRING:%.*]] = apply [[GET_SUPER_METHOD]]([[UPCAST_SELF_COPY]])
+
+ // CHECK: bb3([[OLD_NSSTRING_BRIDGED:%.*]] : @owned $Optional<String>):
+ // This next line is completely not needed. But we are emitting it now.
+ // CHECK: destroy_value [[UPCAST_SELF_COPY]]
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
+ // CHECK: [[BORROWED_NEW_VALUE:%.*]] = begin_borrow [[NEW_VALUE]]
+ // CHECK: [[NEW_VALUE_COPY:%.*]] = copy_value [[BORROWED_NEW_VALUE]]
+ // CHECK: switch_enum [[NEW_VALUE_COPY]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+ //
+ // CHECK: bb4([[OLD_STRING:%.*]] : @owned $String):
+ // CHECK: bb6([[BRIDGED_NEW_STRING:%.*]] : @owned $Optional<NSString>):
+ // CHECK: end_borrow [[BORROWED_NEW_VALUE]]
+ // CHECK: [[BORROWED_UPCAST_SELF:%.*]] = begin_borrow [[UPCAST_SELF_COPY]] : $Base
+ // CHECK: [[SUPERREF_DOWNCAST:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF]] : $Base to $Sub
+ // CHECK: [[SET_SUPER_METHOD:%.*]] = objc_super_method [[SUPERREF_DOWNCAST]] : $Sub, #Base.prop!setter.1.foreign : (Base) -> (String?) -> (), $@convention(objc_method) (Optional<NSString>, Base) -> ()
+ // CHECK: apply [[SET_SUPER_METHOD]]([[BRIDGED_NEW_STRING]], [[UPCAST_SELF_COPY]])
+ // CHECK: destroy_value [[BRIDGED_NEW_STRING]]
+ // CHECK: destroy_value [[UPCAST_SELF_COPY]]
+ // CHECK: [[BORROWED_OLD_NSSTRING_BRIDGED:%.*]] = begin_borrow [[OLD_NSSTRING_BRIDGED]]
+ // This is an identity cast that should be eliminated by SILGen peepholes.
+ // CHECK: [[DIDSET_NOTIFIER:%.*]] = function_ref @$S15objc_extensions3SubC4propSSSgvW : $@convention(method) (@guaranteed Optional<String>, @guaranteed Sub) -> ()
+ // CHECK: apply [[DIDSET_NOTIFIER]]([[BORROWED_OLD_NSSTRING_BRIDGED]], [[SELF]])
+ // CHECK: end_borrow [[BORROWED_OLD_NSSTRING_BRIDGED]] from [[OLD_NSSTRING_BRIDGED]]
+ // CHECK: destroy_value [[OLD_NSSTRING_BRIDGED]]
+ // CHECK: destroy_value [[NEW_VALUE]]
+ // CHECK: } // end sil function '$S15objc_extensions3SubC4propSSSgvs'
+
+ }
+
+ func foo() {
+ }
+
+ override func objCBaseMethod() {}
+}
+
+// CHECK-LABEL: sil hidden @$S15objc_extensions20testOverridePropertyyyAA3SubCF
+func testOverrideProperty(_ obj: Sub) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Sub):
+ // CHECK: = objc_method [[ARG]] : $Sub, #Sub.prop!setter.1.foreign : (Sub) -> (String?) -> ()
+ obj.prop = "abc"
+} // CHECK: } // end sil function '$S15objc_extensions20testOverridePropertyyyAA3SubCF'
+
+testOverrideProperty(Sub())
+
+// CHECK-LABEL: sil shared [thunk] @$S15objc_extensions3SubC3fooyyFTc
+// CHECK: function_ref @$S15objc_extensions3SubC3fooyyFTD
+// CHECK: } // end sil function '$S15objc_extensions3SubC3fooyyFTc'
+// CHECK: sil shared [transparent] [serializable] [thunk] @$S15objc_extensions3SubC3fooyyFTD
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $Sub):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: objc_method [[SELF_COPY]] : $Sub, #Sub.foo!1.foreign
+// CHECK: } // end sil function '$S15objc_extensions3SubC3fooyyFTD'
+func testCurry(_ x: Sub) {
+ _ = x.foo
+}
+
+extension Sub {
+ var otherProp: String {
+ get { return "hello" }
+ set { }
+ }
+}
+
+class SubSub : Sub {
+ // CHECK-LABEL: sil hidden @$S15objc_extensions03SubC0C14objCBaseMethodyyF :
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $SubSub):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $SubSub to $Sub
+ // CHECK: [[BORROWED_UPCAST_SELF_COPY:%.*]] = begin_borrow [[UPCAST_SELF_COPY]]
+ // CHECK: [[DOWNCAST:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY]] : $Sub to $SubSub
+ // CHECK: objc_super_method [[DOWNCAST]] : $SubSub, #Sub.objCBaseMethod!1.foreign : (Sub) -> () -> (), $@convention(objc_method) (Sub) -> ()
+ // CHECK: end_borrow [[BORROWED_UPCAST_SELF_COPY]] from [[UPCAST_SELF_COPY]]
+ // CHECK: } // end sil function '$S15objc_extensions03SubC0C14objCBaseMethodyyF'
+ override func objCBaseMethod() {
+ super.objCBaseMethod()
+ }
+}
+
+extension SubSub {
+ // CHECK-LABEL: sil hidden @$S15objc_extensions03SubC0C9otherPropSSvs
+ // CHECK: bb0([[NEW_VALUE:%.*]] : @owned $String, [[SELF:%.*]] : @guaranteed $SubSub):
+ // CHECK: [[SELF_COPY_1:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_SELF_COPY_1:%.*]] = upcast [[SELF_COPY_1]] : $SubSub to $Sub
+ // CHECK: [[BORROWED_UPCAST_SELF_COPY_1:%.*]] = begin_borrow [[UPCAST_SELF_COPY_1]]
+ // CHECK: [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_1:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY_1]] : $Sub to $SubSub
+ // CHECK: = objc_super_method [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_1]] : $SubSub, #Sub.otherProp!getter.1.foreign
+ // CHECK: end_borrow [[BORROWED_UPCAST_SELF_COPY_1]] from [[UPCAST_SELF_COPY_1]]
+
+ // CHECK: [[SELF_COPY_2:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_SELF_COPY_2:%.*]] = upcast [[SELF_COPY_2]] : $SubSub to $Sub
+ // CHECK: [[BORROWED_UPCAST_SELF_COPY_2:%.*]] = begin_borrow [[UPCAST_SELF_COPY_2]]
+ // CHECK: [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_2:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_SELF_COPY_2]] : $Sub to $SubSub
+ // CHECK: = objc_super_method [[DOWNCAST_BORROWED_UPCAST_SELF_COPY_2]] : $SubSub, #Sub.otherProp!setter.1.foreign
+ // CHECK: end_borrow [[BORROWED_UPCAST_SELF_COPY_2]] from [[UPCAST_SELF_COPY_2]]
+ // CHECK: } // end sil function '$S15objc_extensions03SubC0C9otherPropSSvs'
+ override var otherProp: String {
+ didSet {
+ // Ignore it.
+ }
+ }
+}
+
+// SR-1025
+extension Base {
+ fileprivate static var x = 1
+}
+
+// CHECK-LABEL: sil hidden @$S15objc_extensions19testStaticVarAccessyyF
+func testStaticVarAccess() {
+ // CHECK: [[F:%.*]] = function_ref @$SSo4BaseC15objc_extensionsE1x33_1F05E59585E0BB585FCA206FBFF1A92DLLSivau
+ // CHECK: [[PTR:%.*]] = apply [[F]]()
+ // CHECK: [[ADDR:%.*]] = pointer_to_address [[PTR]]
+ _ = Base.x
+}
diff --git a/test/SILGen/plus_zero_objc_imported_generic.swift b/test/SILGen/plus_zero_objc_imported_generic.swift
new file mode 100644
index 0000000..f874ba7
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_imported_generic.swift
@@ -0,0 +1,144 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %s -enable-sil-ownership | %FileCheck %s
+// For integration testing, ensure we get through IRGen too.
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-ir -verify -DIRGEN_INTEGRATION_TEST %s
+
+// REQUIRES: objc_interop
+
+import objc_generics
+
+func callInitializer() {
+ _ = GenericClass(thing: NSObject())
+}
+
+// CHECK-LABEL: sil shared [serializable] @$SSo12GenericClassC5thingAByxGSgxSg_tcfC
+// CHECK: thick_to_objc_metatype {{%.*}} : $@thick GenericClass<T>.Type to $@objc_metatype GenericClass<T>.Type
+
+public func genericMethodOnAnyObject(o: AnyObject, b: Bool) -> AnyObject {
+ return o.thing!()!
+}
+
+// CHECK-LABEL: sil @$S21objc_imported_generic0C17MethodOnAnyObject{{[_0-9a-zA-Z]*}}F
+// CHECK: objc_method {{%.*}} : $@opened([[TAG:.*]]) AnyObject, #GenericClass.thing!1.foreign : <T where T : AnyObject> (GenericClass<T>) -> () -> T?, $@convention(objc_method) @pseudogeneric (@opened([[TAG]]) AnyObject) -> @autoreleased Optional<AnyObject>
+
+public func genericMethodOnAnyObjectChained(o: AnyObject, b: Bool) -> AnyObject? {
+ return o.thing?()
+}
+
+// CHECK-LABEL: sil @$S21objc_imported_generic0C24MethodOnAnyObjectChained1o1byXlSgyXl_SbtF
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject, [[BOOL:%.*]] : @trivial $Bool):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened([[TAG:.*]]) AnyObject, #GenericClass.thing!1.foreign, bb1
+// CHECK: bb1({{%.*}} : @trivial $@convention(objc_method) @pseudogeneric (@opened([[TAG]]) AnyObject) -> @autoreleased Optional<AnyObject>):
+// CHECK: } // end sil function '$S21objc_imported_generic0C24MethodOnAnyObjectChained1o1byXlSgyXl_SbtF'
+
+public func genericSubscriptOnAnyObject(o: AnyObject, b: Bool) -> AnyObject? {
+ return o[0 as UInt16]
+}
+
+// CHECK-LABEL: sil @$S21objc_imported_generic0C20SubscriptOnAnyObject1o1byXlSgyXl_SbtF
+// CHECK: bb0([[ANY:%.*]]
+// CHCEK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened([[TAG:.*]]) AnyObject, #GenericClass.subscript!getter.1.foreign, bb1
+// CHECK: bb1({{%.*}} : @trivial $@convention(objc_method) @pseudogeneric (UInt16, @opened([[TAG]]) AnyObject) -> @autoreleased AnyObject):
+// CHECK: } // end sil function '$S21objc_imported_generic0C20SubscriptOnAnyObject1o1byXlSgyXl_SbtF'
+
+public func genericPropertyOnAnyObject(o: AnyObject, b: Bool) -> AnyObject?? {
+ return o.propertyThing
+}
+
+// CHECK-LABEL: sil @$S21objc_imported_generic0C19PropertyOnAnyObject1o1byXlSgSgyXl_SbtF
+// CHECK: bb0([[ANY:%.*]] : @guaranteed $AnyObject, [[BOOL:%.*]] : @trivial $Bool):
+// CHECK: [[OPENED_ANY:%.*]] = open_existential_ref [[ANY]]
+// CHECK: [[OPENED_ANY_COPY:%.*]] = copy_value [[OPENED_ANY]]
+// CHECK: dynamic_method_br [[OPENED_ANY_COPY]] : $@opened([[TAG:.*]]) AnyObject, #GenericClass.propertyThing!getter.1.foreign, bb1
+// CHECK: bb1({{%.*}} : @trivial $@convention(objc_method) @pseudogeneric (@opened([[TAG]]) AnyObject) -> @autoreleased Optional<AnyObject>):
+// CHECK: } // end sil function '$S21objc_imported_generic0C19PropertyOnAnyObject1o1byXlSgSgyXl_SbtF'
+
+public protocol ThingHolder {
+ associatedtype Thing
+
+ init!(thing: Thing!)
+ func thing() -> Thing?
+ func arrayOfThings() -> [Thing]
+ func setArrayOfThings(_: [Thing])
+ static func classThing() -> Thing?
+
+ var propertyThing: Thing? { get set }
+ var propertyArrayOfThings: [Thing]? { get set }
+}
+
+// TODO: Crashes in IRGen because the type metadata for `T` is not found in
+// the witness thunk to satisfy the associated type requirement. This could be
+// addressed by teaching IRGen to fulfill erased type parameters from protocol
+// witness tables (rdar://problem/26602097).
+#if !IRGEN_INTEGRATION_TEST
+extension GenericClass: ThingHolder {}
+#endif
+
+public protocol Ansible: class {
+ associatedtype Anser: ThingHolder
+}
+
+public func genericBlockBridging<T: Ansible>(x: GenericClass<T>) {
+ let block = x.blockForPerformingOnThings()
+ x.performBlock(onThings: block)
+}
+
+// CHECK-LABEL: sil @$S21objc_imported_generic0C13BlockBridging{{[_0-9a-zA-Z]*}}F
+// CHECK: [[BLOCK_TO_FUNC:%.*]] = function_ref @$SxxIeyBya_xxIeggo_21objc_imported_generic7AnsibleRzlTR
+// CHECK: partial_apply [callee_guaranteed] [[BLOCK_TO_FUNC]]<T>
+// CHECK: [[FUNC_TO_BLOCK:%.*]] = function_ref @$SxxIeggo_xxIeyBya_21objc_imported_generic7AnsibleRzlTR
+// CHECK: init_block_storage_header {{.*}} invoke [[FUNC_TO_BLOCK]]<T>
+
+// CHECK-LABEL: sil @$S21objc_imported_generic20arraysOfGenericParam{{[_0-9a-zA-Z]*}}F
+public func arraysOfGenericParam<T: AnyObject>(y: Array<T>) {
+ // CHECK: function_ref @$SSo12GenericClassC13arrayOfThingsAByxGSgSayxG_tcfC : $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@owned Array<τ_0_0>, @thick GenericClass<τ_0_0>.Type) -> @owned Optional<GenericClass<τ_0_0>>
+ let x = GenericClass<T>(arrayOfThings: y)!
+ // CHECK: objc_method {{%.*}} : $GenericClass<T>, #GenericClass.setArrayOfThings!1.foreign {{.*}}, $@convention(objc_method) @pseudogeneric <τ_0_0 where τ_0_0 : AnyObject> (NSArray, GenericClass<τ_0_0>) -> ()
+ x.setArrayOfThings(y)
+ // CHECK: objc_method {{%.*}} : $GenericClass<T>, #GenericClass.propertyArrayOfThings!getter.1.foreign {{.*}}, $@convention(objc_method) @pseudogeneric <τ_0_0 where τ_0_0 : AnyObject> (GenericClass<τ_0_0>) -> @autoreleased Optional<NSArray>
+ _ = x.propertyArrayOfThings
+ // CHECK: objc_method {{%.*}} : $GenericClass<T>, #GenericClass.propertyArrayOfThings!setter.1.foreign {{.*}}, $@convention(objc_method) @pseudogeneric <τ_0_0 where τ_0_0 : AnyObject> (Optional<NSArray>, GenericClass<τ_0_0>) -> ()
+ x.propertyArrayOfThings = y
+}
+
+// CHECK-LABEL: sil private @$S21objc_imported_generic0C4FuncyyxmRlzClFyycfU_ : $@convention(thin) <V where V : AnyObject> () -> () {
+// CHECK: [[META:%.*]] = metatype $@thick GenericClass<V>.Type
+// CHECK: [[INIT:%.*]] = function_ref @$SSo12GenericClassCAByxGycfC : $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@thick GenericClass<τ_0_0>.Type) -> @owned GenericClass<τ_0_0>
+// CHECK: apply [[INIT]]<V>([[META]])
+// CHECK: return
+func genericFunc<V: AnyObject>(_ v: V.Type) {
+ let _ = {
+ var _ = GenericClass<V>()
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S21objc_imported_generic23configureWithoutOptionsyyF : $@convention(thin) () -> ()
+// CHECK: [[NIL_FN:%.*]] = function_ref @$SSq10nilLiteralxSgyt_tcfC : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
+// CHECK: apply [[NIL_FN]]<[GenericOption : Any]>({{.*}})
+// CHECK: return
+func configureWithoutOptions() {
+ _ = GenericClass<NSObject>(options: nil)
+}
+
+// This gets emitted down here for some reason
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @$SSo12GenericClassC13arrayOfThingsAByxGSgSayxG_tcfcTO
+// CHECK: objc_method {{%.*}} : $GenericClass<T>, #GenericClass.init!initializer.1.foreign {{.*}}, $@convention(objc_method) @pseudogeneric <τ_0_0 where τ_0_0 : AnyObject> (NSArray, @owned GenericClass<τ_0_0>) -> @owned Optional<GenericClass<τ_0_0>>
+
+// foreign to native thunk for init(options:), uses GenericOption : Hashable
+// conformance
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @$SSo12GenericClassC7optionsAByxGSgs10DictionaryVySo0A6OptionaypGSg_tcfcTO : $@convention(method) <T where T : AnyObject> (@owned Optional<Dictionary<GenericOption, Any>>, @owned GenericClass<T>) -> @owned Optional<GenericClass<T>>
+// CHECK: [[FN:%.*]] = function_ref @$Ss10DictionaryV10FoundationE19_bridgeToObjectiveCSo12NSDictionaryCyF : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned NSDictionary
+// CHECK: apply [[FN]]<GenericOption, Any>({{.*}}) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed Dictionary<τ_0_0, τ_0_1>) -> @owned NSDictionary
+// CHECK: return
+
+// Make sure we emitted the witness table for the above conformance
+
+// CHECK-LABEL: sil_witness_table shared [serialized] GenericOption: Hashable module objc_generics {
+// CHECK: method #Hashable.hashValue!getter.1: {{.*}}: @$SSo13GenericOptionas8HashableSCsACP9hashValueSivgTW
+// CHECK: }
diff --git a/test/SILGen/plus_zero_objc_ownership_conventions.swift b/test/SILGen/plus_zero_objc_ownership_conventions.swift
new file mode 100644
index 0000000..3ef9bb6
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_ownership_conventions.swift
@@ -0,0 +1,226 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import gizmo
+
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions5test3So8NSObjectCyF
+func test3() -> NSObject {
+ // initializer returns at +1
+ return Gizmo()
+ // CHECK: [[GIZMO_META:%[0-9]+]] = metatype $@thick Gizmo.Type
+ // CHECK: [[CTOR:%[0-9]+]] = function_ref @$SSo5GizmoC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick Gizmo.Type) -> @owned Optional<Gizmo>
+ // CHECK-NEXT: [[GIZMO:%[0-9]+]] = apply [[CTOR]]([[GIZMO_META]]) : $@convention(method) (@thick Gizmo.Type) -> @owned Optional<Gizmo>
+ // CHECK: [[GIZMO_NS:%[0-9]+]] = upcast [[GIZMO:%[0-9]+]] : $Gizmo to $NSObject
+ // CHECK: return [[GIZMO_NS]] : $NSObject
+
+ // CHECK-LABEL: sil shared [serializable] @$SSo5GizmoC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick Gizmo.Type) -> @owned Optional<Gizmo>
+ // alloc is implicitly ns_returns_retained
+ // init is implicitly ns_consumes_self and ns_returns_retained
+ // CHECK: bb0([[GIZMO_META:%[0-9]+]] : @trivial $@thick Gizmo.Type):
+ // CHECK-NEXT: [[GIZMO_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[GIZMO_META]] : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
+ // CHECK-NEXT: [[GIZMO:%[0-9]+]] = alloc_ref_dynamic [objc] [[GIZMO_META_OBJC]] : $@objc_metatype Gizmo.Type, $Gizmo
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[INIT_CTOR:%[0-9]+]] = function_ref @$SSo5GizmoC{{[_0-9a-zA-Z]*}}fcTO
+ // CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[INIT_CTOR]]([[GIZMO]]) : $@convention(method) (@owned Gizmo) -> @owned Optional<Gizmo>
+ // CHECK-NEXT: return [[RESULT]] : $Optional<Gizmo>
+}
+
+
+
+// Normal message send with argument, no transfers.
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions5test5{{[_0-9a-zA-Z]*}}F
+func test5(_ g: Gizmo) {
+ var g = g
+ Gizmo.inspect(g)
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: [[GIZMO_BOX:%.*]] = alloc_box ${ var Gizmo }
+ // CHECK: [[GIZMO_BOX_PB:%.*]] = project_box [[GIZMO_BOX]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
+ // CHECK: [[CLASS:%.*]] = metatype $@objc_metatype Gizmo.Type
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
+ // CHECK: [[V:%.*]] = load [copy] [[READ]]
+ // CHECK: [[G:%.*]] = enum $Optional<Gizmo>, #Optional.some!enumelt.1, [[V]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.inspect!1.foreign
+ // CHECK: apply [[METHOD]]([[G]], [[CLASS]])
+ // CHECK: destroy_value [[G]]
+ // CHECK: destroy_value [[GIZMO_BOX]]
+ // CHECK-NOT: destroy_value [[ARG]]
+}
+// CHECK: } // end sil function '$S26objc_ownership_conventions5test5{{[_0-9a-zA-Z]*}}F'
+
+// The argument to consume is __attribute__((ns_consumed)).
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions5test6{{[_0-9a-zA-Z]*}}F
+func test6(_ g: Gizmo) {
+ var g = g
+ Gizmo.consume(g)
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: [[GIZMO_BOX:%.*]] = alloc_box ${ var Gizmo }
+ // CHECK: [[GIZMO_BOX_PB:%.*]] = project_box [[GIZMO_BOX]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
+ // CHECK: [[CLASS:%.*]] = metatype $@objc_metatype Gizmo.Type
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
+ // CHECK: [[V:%.*]] = load [copy] [[READ]]
+ // CHECK: [[G:%.*]] = enum $Optional<Gizmo>, #Optional.some!enumelt.1, [[V]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.consume!1.foreign
+ // CHECK: apply [[METHOD]]([[G]], [[CLASS]])
+ // CHECK-NOT: destroy_value [[G]]
+ // CHECK: destroy_value [[GIZMO_BOX]]
+ // CHECK-NOT: destroy_value [[G]]
+ // CHECK-NOT: destroy_value [[ARG]]
+ // CHECK-NOT: destroy_value [[G]]
+}
+// CHECK: } // end sil function '$S26objc_ownership_conventions5test6{{[_0-9a-zA-Z]*}}F'
+
+// fork is __attribute__((ns_consumes_self)).
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions5test7{{[_0-9a-zA-Z]*}}F
+func test7(_ g: Gizmo) {
+ var g = g
+ g.fork()
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: [[GIZMO_BOX:%.*]] = alloc_box ${ var Gizmo }
+ // CHECK: [[GIZMO_BOX_PB:%.*]] = project_box [[GIZMO_BOX]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
+ // CHECK: [[G:%.*]] = load [copy] [[READ]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[G]] : {{.*}}, #Gizmo.fork!1.foreign
+ // CHECK: apply [[METHOD]]([[G]])
+ // CHECK-NOT: destroy_value [[G]]
+ // CHECK: destroy_value [[GIZMO_BOX]]
+ // CHECK-NOT: destroy_value [[G]]
+ // CHECK-NOT: destroy_value [[ARG]]
+ // CHECK-NOT: destroy_value [[G]]
+}
+// CHECK: } // end sil function '$S26objc_ownership_conventions5test7{{[_0-9a-zA-Z]*}}F'
+
+// clone is __attribute__((ns_returns_retained)).
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions5test8{{[_0-9a-zA-Z]*}}F
+func test8(_ g: Gizmo) -> Gizmo {
+ return g.clone()
+ // CHECK: bb0([[G:%.*]] : @guaranteed $Gizmo):
+ // CHECK-NOT: copy_value
+ // CHECK: [[METHOD:%.*]] = objc_method [[G]] : {{.*}}, #Gizmo.clone!1.foreign
+ // CHECK-NOT: copy_value [[RESULT]]
+ // CHECK: bb2([[RESULT:%.*]] : @owned $Gizmo):
+ // CHECK-NOT: copy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[G]]
+ // CHECK-NEXT: return [[RESULT]]
+}
+// duplicate returns an autoreleased object at +0.
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions5test9{{[_0-9a-zA-Z]*}}F
+func test9(_ g: Gizmo) -> Gizmo {
+ return g.duplicate()
+ // CHECK: bb0([[G:%.*]] : @guaranteed $Gizmo):
+ // CHECK-NOT: copy_value [[G:%0]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[G]] : {{.*}}, #Gizmo.duplicate!1.foreign
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[G]])
+ // CHECK-NOT: copy_value [[RESULT]]
+ // CHECK: bb2([[RESULT:%.*]] : @owned $Gizmo):
+ // CHECK-NOT: copy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[G]]
+ // CHECK-NEXT: return [[RESULT]]
+}
+
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions6test10{{[_0-9a-zA-Z]*}}F
+func test10(_ g: Gizmo) -> AnyClass {
+ // CHECK: bb0([[G:%[0-9]+]] : @guaranteed $Gizmo):
+ // CHECK: [[G_COPY:%.*]] = copy_value [[G]]
+ // CHECK-NEXT: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY]] : $Gizmo to $NSObject
+ // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_COPY]] : $NSObject, #NSObject.classProp!getter.1.foreign : (NSObject) -> () -> AnyObject.Type?, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type>
+ // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_COPY]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type>
+ // CHECK-NEXT: switch_enum [[OPT_OBJC]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+ //
+ // CHECK: [[SOME_BB]]([[OBJC:%.*]] : @trivial $@objc_metatype AnyObject.Type):
+ // CHECK-NEXT: [[THICK:%.*]] = objc_to_thick_metatype [[OBJC]]
+ // CHECK: [[T0:%.*]] = enum $Optional<@thick AnyObject.Type>, #Optional.some!enumelt.1, [[THICK]]
+ // CHECK: bb{{.*}}(%{{.*}} : @trivial $Optional<@thick AnyObject.Type>):
+ // CHECK: destroy_value [[NS_G_COPY]] : $NSObject
+ // CHECK: bb{{.*}}([[RES:%.*]] : @trivial $@thick AnyObject.Type):
+ // CHECK-NOT: destroy_value [[G]] : $Gizmo
+ // CHECK-NEXT: return [[RES]] : $@thick AnyObject.Type
+ return g.classProp
+}
+
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions6test11{{[_0-9a-zA-Z]*}}F
+func test11(_ g: Gizmo) -> AnyClass {
+ // CHECK: bb0([[G:%[0-9]+]] : @guaranteed $Gizmo):
+ // CHECK: [[G_COPY:%.*]] = copy_value [[G]]
+ // CHECK: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY:%[0-9]+]] : $Gizmo to $NSObject
+ // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[NS_G_COPY]] : $NSObject, #NSObject.qualifiedClassProp!getter.1.foreign : (NSObject) -> () -> NSAnsing.Type?, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type>
+ // CHECK-NEXT: [[OPT_OBJC:%.*]] = apply [[GETTER]]([[NS_G_COPY]]) : $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type>
+ // CHECK-NEXT: switch_enum [[OPT_OBJC]] : $Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+ //
+ // CHECK: [[SOME_BB]]([[OBJC:%.*]] : @trivial $@objc_metatype NSAnsing.Type):
+ // CHECK-NEXT: [[THICK:%.*]] = objc_to_thick_metatype [[OBJC]]
+ // CHECK: [[T0:%.*]] = enum $Optional<@thick NSAnsing.Type>, #Optional.some!enumelt.1, [[THICK]]
+ // CHECK: bb{{.*}}(%{{.*}} : @trivial $Optional<@thick NSAnsing.Type>):
+ // CHECK: destroy_value [[NS_G_COPY]] : $NSObject
+ // CHECK: bb{{.*}}([[RES:%.*]] : @trivial $@thick NSAnsing.Type):
+ // CHECK: [[OPENED:%.*]] = open_existential_metatype [[RES]]
+ // CHECK: [[RES_ANY:%.*]] = init_existential_metatype [[OPENED]]
+ // CHECK-NOT: destroy_value [[G]] : $Gizmo
+ // CHECK-NEXT: return [[RES_ANY]] : $@thick AnyObject.Type
+ return g.qualifiedClassProp
+}
+
+// ObjC blocks should have cdecl calling convention and follow C/ObjC
+// ownership conventions, where the callee, arguments, and return are all +0.
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions10applyBlock{{[_0-9a-zA-Z]*}}F
+func applyBlock(_ f: @convention(block) (Gizmo) -> Gizmo, x: Gizmo) -> Gizmo {
+ // CHECK: bb0([[BLOCK:%.*]] : @guaranteed $@convention(block) @noescape (Gizmo) -> @autoreleased Gizmo, [[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ // CHECK: [[BORROWED_BLOCK_COPY:%.*]] = begin_borrow [[BLOCK_COPY]]
+ // CHECK: [[BLOCK_COPY_COPY:%.*]] = copy_value [[BORROWED_BLOCK_COPY]]
+ // CHECK: [[RESULT:%.*]] = apply [[BLOCK_COPY_COPY]]([[ARG]])
+ // CHECK: destroy_value [[BLOCK_COPY_COPY]]
+ // CHECK: end_borrow [[BORROWED_BLOCK_COPY]] from [[BLOCK_COPY]]
+ // CHECK-NOT: destroy_value [[ARG]]
+ // CHECK: destroy_value [[BLOCK_COPY]]
+ // CHECK-NOT: destroy_value [[BLOCK]]
+ // CHECK: return [[RESULT]]
+ return f(x)
+}
+
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions15maybeApplyBlock{{[_0-9a-zA-Z]*}}F
+func maybeApplyBlock(_ f: (@convention(block) (Gizmo) -> Gizmo)?, x: Gizmo) -> Gizmo? {
+ // CHECK: bb0([[BLOCK:%.*]] : @guaranteed $Optional<@convention(block) (Gizmo) -> @autoreleased Gizmo>, [[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: [[BLOCK_COPY:%.*]] = copy_block [[BLOCK]]
+ return f?(x)
+}
+
+func useInnerPointer(_ p: UnsafeMutableRawPointer) {}
+
+// Handle inner-pointer methods by autoreleasing self after the call.
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions18innerPointerMethodyySo5GizmoCF : $@convention(thin) (@guaranteed Gizmo) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+// CHECK: [[METHOD:%.*]] = objc_method [[ARG]] : $Gizmo, #Gizmo.getBytes!1.foreign : (Gizmo) -> () -> UnsafeMutableRawPointer, $@convention(objc_method) (Gizmo) -> @unowned_inner_pointer UnsafeMutableRawPointer
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// => SEMANTIC ARC TODO: The apply below /should/ be on ARG_COPY. It is safe how
+// it is today though since we are using a reference type.
+// CHECK: [[PTR:%.*]] = apply [[METHOD]]([[ARG]])
+// CHECK: autorelease_value [[ARG_COPY]]
+// CHECK: [[USE:%.*]] = function_ref @$S26objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[USE]]([[PTR]])
+// CHECK-NOT: destroy_value [[ARG]]
+func innerPointerMethod(_ g: Gizmo) {
+ useInnerPointer(g.getBytes())
+}
+
+// CHECK-LABEL: sil hidden @$S26objc_ownership_conventions20innerPointerPropertyyySo5GizmoCF : $@convention(thin) (@guaranteed Gizmo) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+// CHECK: [[METHOD:%.*]] = objc_method [[ARG]] : $Gizmo, #Gizmo.innerProperty!getter.1.foreign : (Gizmo) -> () -> UnsafeMutableRawPointer, $@convention(objc_method) (Gizmo) -> @unowned_inner_pointer UnsafeMutableRawPointer
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// => SEMANTIC ARC TODO: The apply below should be on ARG_COPY. It is benign since objc objects are reference types.
+// CHECK: [[PTR:%.*]] = apply [[METHOD]]([[ARG]])
+// CHECK: autorelease_value [[ARG_COPY]]
+// CHECK: [[USE:%.*]] = function_ref @$S26objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[USE]]([[PTR]])
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: } // end sil function '$S26objc_ownership_conventions20innerPointerPropertyyySo5GizmoCF'
+func innerPointerProperty(_ g: Gizmo) {
+ useInnerPointer(g.innerProperty)
+}
diff --git a/test/SILGen/plus_zero_objc_protocol_native_thunk.swift b/test/SILGen/plus_zero_objc_protocol_native_thunk.swift
new file mode 100644
index 0000000..3d75ecf
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_protocol_native_thunk.swift
@@ -0,0 +1,17 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+import Foundation
+
+@objc protocol P {
+ func p(_: String)
+}
+@objc class C: NSObject {
+ func c(_: String) {}
+}
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @$S{{.*}}1P{{.*}}1p{{.*}} : $@convention(method) <Self where Self : P> (@guaranteed String, @guaranteed Self) -> ()
+func foo(x: Bool, y: C & P) -> (String) -> () {
+ return x ? y.c : y.p
+}
diff --git a/test/SILGen/plus_zero_objc_protocols.swift b/test/SILGen/plus_zero_objc_protocols.swift
new file mode 100644
index 0000000..5052509
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_protocols.swift
@@ -0,0 +1,293 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import gizmo
+import objc_protocols_Bas
+
+@objc protocol NSRuncing {
+ func runce() -> NSObject
+ func copyRuncing() -> NSObject
+
+ func foo()
+
+ static func mince() -> NSObject
+}
+
+@objc protocol NSFunging {
+ func funge()
+
+ func foo()
+}
+
+protocol Ansible {
+ func anse()
+}
+
+// CHECK-LABEL: sil hidden @$S14objc_protocols0A8_generic{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[THIS:%.*]] : @guaranteed $T):
+// -- Result of runce is autoreleased according to default objc conv
+// CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : {{\$.*}}, #NSRuncing.runce!1.foreign
+// CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<T>([[THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @autoreleased NSObject
+
+// -- Result of copyRuncing is received copy_valued according to -copy family
+// CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : {{\$.*}}, #NSRuncing.copyRuncing!1.foreign
+// CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<T>([[THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @owned NSObject
+
+// -- Arguments are not consumed by objc calls
+// CHECK-NOT: destroy_value [[THIS]]
+func objc_generic<T : NSRuncing>(_ x: T) -> (NSObject, NSObject) {
+ return (x.runce(), x.copyRuncing())
+}
+
+// CHECK-LABEL: sil hidden @$S14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlF : $@convention(thin) <T where T : NSRuncing> (@guaranteed T) -> () {
+func objc_generic_partial_apply<T : NSRuncing>(_ x: T) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $T):
+ // CHECK: [[FN:%.*]] = function_ref @[[THUNK1:\$S14objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO]] :
+ // CHECK: [[METHOD:%.*]] = apply [[FN]]<T>([[ARG]])
+ // CHECK: destroy_value [[METHOD]]
+ _ = x.runce
+
+ // CHECK: [[FN:%.*]] = function_ref @[[THUNK1]] :
+ // CHECK: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]]<T>()
+ // CHECK: destroy_value [[METHOD]]
+ _ = T.runce
+
+ // CHECK: [[METATYPE:%.*]] = metatype $@thick T.Type
+ // CHECK: [[FN:%.*]] = function_ref @[[THUNK2:\$S14objc_protocols9NSRuncingP5minceSo8NSObjectCyFZTcTO]]
+ // CHECK: [[METHOD:%.*]] = apply [[FN]]<T>([[METATYPE]])
+ // CHECK: destroy_value [[METHOD:%.*]]
+ _ = T.mince
+ // CHECK-NOT: destroy_value [[ARG]]
+}
+// CHECK: } // end sil function '$S14objc_protocols0A22_generic_partial_applyyyxAA9NSRuncingRzlF'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK1]] :
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $Self):
+// CHECK: [[FN:%.*]] = function_ref @[[THUNK1_THUNK:\$S14objc_protocols9NSRuncingP5runceSo8NSObjectCyFTO]] :
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]]<Self>([[SELF_COPY]])
+// CHECK: return [[METHOD]]
+// CHECK: } // end sil function '[[THUNK1]]'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK1_THUNK]]
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $Self):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+// CHECK: [[FN:%.*]] = objc_method [[SELF_COPY]] : $Self, #NSRuncing.runce!1.foreign
+// CHECK: [[RESULT:%.*]] = apply [[FN]]<Self>([[SELF_COPY]])
+// CHECK: destroy_value [[SELF_COPY]]
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function '[[THUNK1_THUNK]]'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK2]] :
+// CHECK: [[FN:%.*]] = function_ref @[[THUNK2_THUNK:\$S14objc_protocols9NSRuncingP5minceSo8NSObjectCyFZTO]]
+// CHECK: [[METHOD:%.*]] = partial_apply [callee_guaranteed] [[FN]]<Self>(%0)
+// CHECK: return [[METHOD]]
+// CHECK: } // end sil function '[[THUNK2]]'
+
+// CHECK: sil shared [serializable] [thunk] @[[THUNK2_THUNK]] :
+// CHECK: [[FN:%.*]] = objc_method %0 : $@thick Self.Type, #NSRuncing.mince!1.foreign
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Self>(%0)
+// CHECK-NEXT: return [[RESULT]]
+// CHECK: } // end sil function '[[THUNK2_THUNK]]'
+
+// CHECK-LABEL: sil hidden @$S14objc_protocols0A9_protocol{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[THIS:%.*]] : @guaranteed $NSRuncing):
+// -- Result of runce is autoreleased according to default objc conv
+// CHECK: [[THIS1:%.*]] = open_existential_ref [[THIS]] : $NSRuncing to $[[OPENED:@opened(.*) NSRuncing]]
+// CHECK: [[METHOD:%.*]] = objc_method [[THIS1]] : $[[OPENED]], #NSRuncing.runce!1.foreign
+// CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<[[OPENED]]>([[THIS1]])
+
+// -- Result of copyRuncing is received copy_valued according to -copy family
+// CHECK: [[THIS2:%.*]] = open_existential_ref [[THIS]] : $NSRuncing to $[[OPENED2:@opened(.*) NSRuncing]]
+// CHECK: [[METHOD:%.*]] = objc_method [[THIS2]] : $[[OPENED2]], #NSRuncing.copyRuncing!1.foreign
+// CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<[[OPENED2]]>([[THIS2:%.*]])
+
+// -- Arguments are not consumed by objc calls
+// CHECK-NOT: destroy_value [[THIS]]
+func objc_protocol(_ x: NSRuncing) -> (NSObject, NSObject) {
+ return (x.runce(), x.copyRuncing())
+}
+
+// CHECK-LABEL: sil hidden @$S14objc_protocols0A23_protocol_partial_applyyyAA9NSRuncing_pF : $@convention(thin) (@guaranteed NSRuncing) -> () {
+func objc_protocol_partial_apply(_ x: NSRuncing) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $NSRuncing):
+ // CHECK: [[OPENED_ARG:%.*]] = open_existential_ref [[ARG]] : $NSRuncing to $[[OPENED:@opened(.*) NSRuncing]]
+ // CHECK: [[FN:%.*]] = function_ref @$S14objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO
+ // CHECK: [[RESULT:%.*]] = apply [[FN]]<[[OPENED]]>([[OPENED_ARG]])
+ // CHECK: destroy_value [[RESULT]]
+ // CHECK-NOT: destroy_value [[ARG]]
+ _ = x.runce
+
+ // FIXME: rdar://21289579
+ // _ = NSRuncing.runce
+}
+// CHECK : } // end sil function '$S14objc_protocols0A23_protocol_partial_applyyyAA9NSRuncing_pF'
+
+// CHECK-LABEL: sil hidden @$S14objc_protocols0A21_protocol_composition{{[_0-9a-zA-Z]*}}F
+func objc_protocol_composition(_ x: NSRuncing & NSFunging) {
+ // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $NSFunging & NSRuncing to $[[OPENED:@opened(.*) NSFunging & NSRuncing]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : $[[OPENED]], #NSRuncing.runce!1.foreign
+ // CHECK: apply [[METHOD]]<[[OPENED]]>([[THIS]])
+ x.runce()
+
+ // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $NSFunging & NSRuncing to $[[OPENED:@opened(.*) NSFunging & NSRuncing]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : $[[OPENED]], #NSFunging.funge!1.foreign
+ // CHECK: apply [[METHOD]]<[[OPENED]]>([[THIS]])
+ x.funge()
+}
+// -- ObjC thunks get emitted for ObjC protocol conformances
+
+class Foo : NSRuncing, NSFunging, Ansible {
+ // -- NSRuncing
+ @objc func runce() -> NSObject { return NSObject() }
+ @objc func copyRuncing() -> NSObject { return NSObject() }
+
+ @objc static func mince() -> NSObject { return NSObject() }
+
+ // -- NSFunging
+ @objc func funge() {}
+
+ // -- Both NSRuncing and NSFunging
+ @objc func foo() {}
+
+ // -- Ansible
+ func anse() {}
+}
+
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3FooC5runce{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3FooC11copyRuncing{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3FooC5funge{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3FooC3foo{{[_0-9a-zA-Z]*}}FTo
+// CHECK-NOT: sil hidden @_TToF{{.*}}anse{{.*}}
+
+class Bar { }
+
+extension Bar : NSRuncing {
+ @objc func runce() -> NSObject { return NSObject() }
+ @objc func copyRuncing() -> NSObject { return NSObject() }
+ @objc func foo() {}
+ @objc static func mince() -> NSObject { return NSObject() }
+}
+
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3BarC5runce{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3BarC11copyRuncing{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3BarC3foo{{[_0-9a-zA-Z]*}}FTo
+
+// class Bas from objc_protocols_Bas module
+extension Bas : NSRuncing {
+ // runce() implementation from the original definition of Bas
+ @objc func copyRuncing() -> NSObject { return NSObject() }
+ @objc func foo() {}
+ @objc static func mince() -> NSObject { return NSObject() }
+}
+
+// CHECK-LABEL: sil hidden [thunk] @$S18objc_protocols_Bas0C0C0a1_B0E11copyRuncing{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S18objc_protocols_Bas0C0C0a1_B0E3foo{{[_0-9a-zA-Z]*}}FTo
+
+// -- Inherited objc protocols
+
+protocol Fungible : NSFunging { }
+
+class Zim : Fungible {
+ @objc func funge() {}
+ @objc func foo() {}
+}
+
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3ZimC5funge{{[_0-9a-zA-Z]*}}FTo
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols3ZimC3foo{{[_0-9a-zA-Z]*}}FTo
+
+// class Zang from objc_protocols_Bas module
+extension Zang : Fungible {
+ // funge() implementation from the original definition of Zim
+ @objc func foo() {}
+}
+
+// CHECK-LABEL: sil hidden [thunk] @$S18objc_protocols_Bas4ZangC0a1_B0E3foo{{[_0-9a-zA-Z]*}}FTo
+
+// -- objc protocols with property requirements in extensions
+// <rdar://problem/16284574>
+
+@objc protocol NSCounting {
+ var count: Int {get}
+}
+
+class StoredPropertyCount {
+ @objc let count = 0
+}
+
+extension StoredPropertyCount: NSCounting {}
+// CHECK-LABEL: sil hidden [transparent] [thunk] @$S14objc_protocols19StoredPropertyCountC5countSivgTo
+
+class ComputedPropertyCount {
+ @objc var count: Int { return 0 }
+}
+
+extension ComputedPropertyCount: NSCounting {}
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols21ComputedPropertyCountC5countSivgTo
+
+// -- adding @objc protocol conformances to native ObjC classes should not
+// emit thunks since the methods are already available to ObjC.
+
+// Gizmo declared in Inputs/usr/include/Gizmo.h
+extension Gizmo : NSFunging { }
+
+// CHECK-NOT: _TTo{{.*}}5Gizmo{{.*}}
+
+@objc class InformallyFunging {
+ @objc func funge() {}
+ @objc func foo() {}
+}
+
+extension InformallyFunging: NSFunging { }
+
+@objc protocol Initializable {
+ init(int: Int)
+}
+
+// CHECK-LABEL: sil hidden @$S14objc_protocols28testInitializableExistential_1iAA0D0_pAaD_pXp_SitF : $@convention(thin) (@thick Initializable.Type, Int) -> @owned Initializable {
+func testInitializableExistential(_ im: Initializable.Type, i: Int) -> Initializable {
+ // CHECK: bb0([[META:%[0-9]+]] : @trivial $@thick Initializable.Type, [[I:%[0-9]+]] : @trivial $Int):
+ // CHECK: [[I2_BOX:%[0-9]+]] = alloc_box ${ var Initializable }
+ // CHECK: [[PB:%.*]] = project_box [[I2_BOX]]
+ // CHECK: [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[META]] : $@thick Initializable.Type to $@thick (@opened([[N:".*"]]) Initializable).Type
+ // CHECK: [[ARCHETYPE_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[ARCHETYPE_META]] : $@thick (@opened([[N]]) Initializable).Type to $@objc_metatype (@opened([[N]]) Initializable).Type
+ // CHECK: [[I2_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[ARCHETYPE_META_OBJC]] : $@objc_metatype (@opened([[N]]) Initializable).Type, $@opened([[N]]) Initializable
+ // CHECK: [[INIT_WITNESS:%[0-9]+]] = objc_method [[I2_ALLOC]] : $@opened([[N]]) Initializable, #Initializable.init!initializer.1.foreign : {{.*}}
+ // CHECK: [[I2:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]]) Initializable>([[I]], [[I2_ALLOC]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0
+ // CHECK: [[I2_EXIST_CONTAINER:%[0-9]+]] = init_existential_ref [[I2]] : $@opened([[N]]) Initializable : $@opened([[N]]) Initializable, $Initializable
+ // CHECK: store [[I2_EXIST_CONTAINER]] to [init] [[PB]] : $*Initializable
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*Initializable
+ // CHECK: [[I2:%[0-9]+]] = load [copy] [[READ]] : $*Initializable
+ // CHECK: destroy_value [[I2_BOX]] : ${ var Initializable }
+ // CHECK: return [[I2]] : $Initializable
+ var i2 = im.init(int: i)
+ return i2
+}
+// CHECK: } // end sil function '$S14objc_protocols28testInitializableExistential_1iAA0D0_pAaD_pXp_SitF'
+
+class InitializableConformer: Initializable {
+ @objc required init(int: Int) {}
+}
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols22InitializableConformerC{{[_0-9a-zA-Z]*}}fcTo
+
+final class InitializableConformerByExtension {
+ init() {}
+}
+
+extension InitializableConformerByExtension: Initializable {
+ @objc convenience init(int: Int) {
+ self.init()
+ }
+}
+// CHECK-LABEL: sil hidden [thunk] @$S14objc_protocols33InitializableConformerByExtensionC{{[_0-9a-zA-Z]*}}fcTo
+
+// Make sure we're crashing from trying to use materializeForSet here.
+@objc protocol SelectionItem {
+ var time: Double { get set }
+}
+
+func incrementTime(contents: SelectionItem) {
+ contents.time += 1.0
+}
diff --git a/test/SILGen/plus_zero_objc_set_bridging.swift b/test/SILGen/plus_zero_objc_set_bridging.swift
new file mode 100644
index 0000000..3c790c1
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_set_bridging.swift
@@ -0,0 +1,92 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %build-silgen-test-overlays
+
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-silgen %s -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+import gizmo
+
+@objc class Foo : NSObject {
+ // Bridging set parameters
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_set_bridging3FooC16bridge_Set_param{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (NSSet, Foo) -> ()
+ func bridge_Set_param(_ s: Set<Foo>) {
+ // CHECK: bb0([[NSSET:%[0-9]+]] : @unowned $NSSet, [[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[NSSET_COPY:%.*]] = copy_value [[NSSET]] : $NSSet
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Foo
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss3SetV10FoundationE36_unconditionallyBridgeFromObjectiveCyAByxGSo5NSSetCSgFZ
+ // CHECK: [[OPT_NSSET:%[0-9]+]] = enum $Optional<NSSet>, #Optional.some!enumelt.1, [[NSSET_COPY]] : $NSSet
+ // CHECK: [[SET_META:%[0-9]+]] = metatype $@thin Set<Foo>.Type
+ // CHECK: [[SET:%[0-9]+]] = apply [[CONVERTER]]<Foo>([[OPT_NSSET]], [[SET_META]])
+ // CHECK: [[BORROWED_SET:%.*]] = begin_borrow [[SET]]
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SWIFT_FN:%[0-9]+]] = function_ref @$S17objc_set_bridging3FooC16bridge_Set_param{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed Set<Foo>, @guaranteed Foo) -> ()
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[SWIFT_FN]]([[BORROWED_SET]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Set<Foo>, @guaranteed Foo) -> ()
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: return [[RESULT]] : $()
+ }
+ // CHECK: // end sil function '$S17objc_set_bridging3FooC16bridge_Set_param{{[_0-9a-zA-Z]*}}FTo'
+
+ // Bridging set results
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_set_bridging3FooC17bridge_Set_result{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (Foo) -> @autoreleased NSSet {
+ func bridge_Set_result() -> Set<Foo> {
+ // CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Foo
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SWIFT_FN:%[0-9]+]] = function_ref @$S17objc_set_bridging3FooC17bridge_Set_result{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed Foo) -> @owned Set<Foo>
+ // CHECK: [[SET:%[0-9]+]] = apply [[SWIFT_FN]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Foo) -> @owned Set<Foo>
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss3SetV10FoundationE19_bridgeToObjectiveCSo5NSSetCyF
+ // CHECK: [[BORROWED_SET:%.*]] = begin_borrow [[SET]]
+ // CHECK: [[NSSET:%[0-9]+]] = apply [[CONVERTER]]<Foo>([[BORROWED_SET]]) : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned NSSet
+ // CHECK: end_borrow [[BORROWED_SET]] from [[SET]]
+ // CHECK: destroy_value [[SET]]
+ // CHECK: return [[NSSET]] : $NSSet
+ }
+ // CHECK: } // end sil function '$S17objc_set_bridging3FooC17bridge_Set_result{{[_0-9a-zA-Z]*}}FTo'
+
+ var property: Set<Foo> = Set()
+
+ // Property getter
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_set_bridging3FooC8property{{[_0-9a-zA-Z]*}}vgTo : $@convention(objc_method) (Foo) -> @autoreleased NSSet
+ // CHECK: bb0([[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[SELF_COPY]] = copy_value [[SELF]] : $Foo
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[GETTER:%[0-9]+]] = function_ref @$S17objc_set_bridging3FooC8property{{[_0-9a-zA-Z]*}}vg : $@convention(method) (@guaranteed Foo) -> @owned Set<Foo>
+ // CHECK: [[SET:%[0-9]+]] = apply [[GETTER]]([[BORROWED_SELF_COPY]]) : $@convention(method) (@guaranteed Foo) -> @owned Set<Foo>
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss3SetV10FoundationE19_bridgeToObjectiveCSo5NSSetCyF
+ // CHECK: [[BORROWED_SET:%.*]] = begin_borrow [[SET]]
+ // CHECK: [[NSSET:%[0-9]+]] = apply [[CONVERTER]]<Foo>([[BORROWED_SET]]) : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed Set<τ_0_0>) -> @owned NSSet
+ // CHECK: end_borrow [[BORROWED_SET]] from [[SET]]
+ // CHECK: destroy_value [[SET]]
+ // CHECK: return [[NSSET]] : $NSSet
+ // CHECK: } // end sil function '$S17objc_set_bridging3FooC8property{{[_0-9a-zA-Z]*}}vgTo'
+
+ // Property setter
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_set_bridging3FooC8property{{[_0-9a-zA-Z]*}}vsTo : $@convention(objc_method) (NSSet, Foo) -> () {
+ // CHECK: bb0([[NSSET:%[0-9]+]] : @unowned $NSSet, [[SELF:%[0-9]+]] : @unowned $Foo):
+ // CHECK: [[NSSET_COPY:%.*]] = copy_value [[NSSET]] : $NSSet
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Foo
+ // CHECK: [[CONVERTER:%[0-9]+]] = function_ref @$Ss3SetV10FoundationE36_unconditionallyBridgeFromObjectiveCyAByxGSo5NSSetCSgFZ
+ // CHECK: [[OPT_NSSET:%[0-9]+]] = enum $Optional<NSSet>, #Optional.some!enumelt.1, [[NSSET_COPY]] : $NSSet
+ // CHECK: [[SET_META:%[0-9]+]] = metatype $@thin Set<Foo>.Type
+ // CHECK: [[SET:%[0-9]+]] = apply [[CONVERTER]]<Foo>([[OPT_NSSET]], [[SET_META]])
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[SETTER:%[0-9]+]] = function_ref @$S17objc_set_bridging3FooC8property{{[_0-9a-zA-Z]*}}vs : $@convention(method) (@owned Set<Foo>, @guaranteed Foo) -> ()
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[SETTER]]([[SET]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@owned Set<Foo>, @guaranteed Foo) -> ()
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]] : $Foo
+ // CHECK: return [[RESULT]] : $()
+
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_set_bridging3FooC19nonVerbatimProperty{{[_0-9a-zA-Z]*}}vgTo : $@convention(objc_method) (Foo) -> @autoreleased NSSet
+ // CHECK-LABEL: sil hidden [thunk] @$S17objc_set_bridging3FooC19nonVerbatimProperty{{[_0-9a-zA-Z]*}}vsTo : $@convention(objc_method) (NSSet, Foo) -> () {
+ @objc var nonVerbatimProperty: Set<String> = Set()
+}
+
+func ==(x: Foo, y: Foo) -> Bool { }
diff --git a/test/SILGen/plus_zero_objc_thunks.swift b/test/SILGen/plus_zero_objc_thunks.swift
new file mode 100644
index 0000000..0a40a32
--- /dev/null
+++ b/test/SILGen/plus_zero_objc_thunks.swift
@@ -0,0 +1,542 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -sdk %S/Inputs -I %S/Inputs -enable-source-import %s -emit-silgen -emit-verbose-sil -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import gizmo
+import ansible
+
+class Hoozit : Gizmo {
+ @objc func typical(_ x: Int, y: Gizmo) -> Gizmo { return y }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtFTo : $@convention(objc_method) (Int, Gizmo, Hoozit) -> @autoreleased Gizmo {
+ // CHECK: bb0([[X:%.*]] : @trivial $Int, [[Y:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[Y_COPY:%.*]] = copy_value [[Y]]
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_Y_COPY:%.*]] = begin_borrow [[Y_COPY]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref objc_thunks.Hoozit.typical
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtF : $@convention(method) (Int, @guaranteed Gizmo, @guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[X]], [[BORROWED_Y_COPY]], [[BORROWED_THIS_COPY]]) {{.*}} line:[[@LINE-9]]:14:auto_gen
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: end_borrow [[BORROWED_Y_COPY]] from [[Y_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]] : $Hoozit
+ // CHECK-NEXT: destroy_value [[Y_COPY]]
+ // CHECK-NEXT: return [[RES]] : $Gizmo{{.*}} line:[[@LINE-14]]:14:auto_gen
+ // CHECK-NEXT: } // end sil function '$S11objc_thunks6HoozitC7typical_1ySo5GizmoCSi_AGtFTo'
+
+ // NS_CONSUMES_SELF by inheritance
+ override func fork() { }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC4forkyyFTo : $@convention(objc_method) (@owned Hoozit) -> () {
+ // CHECK: bb0([[THIS:%.*]] : @owned $Hoozit):
+ // CHECK-NEXT: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC4forkyyF : $@convention(method) (@guaranteed Hoozit) -> ()
+ // CHECK-NEXT: apply [[NATIVE]]([[BORROWED_THIS]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS]] from [[THIS]]
+ // CHECK-NEXT: destroy_value [[THIS]]
+ // CHECK-NEXT: return
+ // CHECK-NEXT: }
+
+ // NS_CONSUMED 'gizmo' argument by inheritance
+ override class func consume(_ gizmo: Gizmo?) { }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC7consumeyySo5GizmoCSgFZTo : $@convention(objc_method) (@owned Optional<Gizmo>, @objc_metatype Hoozit.Type) -> () {
+ // CHECK: bb0([[GIZMO:%.*]] : @owned $Optional<Gizmo>, [[THIS:%.*]] : @trivial $@objc_metatype Hoozit.Type):
+ // CHECK-NEXT: [[BORROWED_GIZMO:%.*]] = begin_borrow [[GIZMO]]
+ // CHECK-NEXT: [[THICK_THIS:%[0-9]+]] = objc_to_thick_metatype [[THIS]] : $@objc_metatype Hoozit.Type to $@thick Hoozit.Type
+ // CHECK: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC7consumeyySo5GizmoCSgFZ : $@convention(method) (@guaranteed Optional<Gizmo>, @thick Hoozit.Type) -> ()
+ // CHECK-NEXT: apply [[NATIVE]]([[BORROWED_GIZMO]], [[THICK_THIS]])
+ // CHECK-NEXT: end_borrow [[BORROWED_GIZMO]]
+ // CHECK-NEXT: destroy_value [[GIZMO]]
+ // CHECK-NEXT: return
+ // CHECK-NEXT: }
+
+ // NS_RETURNS_RETAINED by family (-copy)
+ @objc func copyFoo() -> Gizmo { return self }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC7copyFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC7copyFooSo5GizmoCyF : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // NS_RETURNS_RETAINED by family (-copy)
+ @objc(copyDuplicate) func makeDuplicate() -> Gizmo { return self }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC13makeDuplicateSo5GizmoCyF : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // Override the normal family conventions to make this non-consuming and
+ // returning at +0.
+ @objc func initFoo() -> Gizmo { return self }
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC7initFooSo5GizmoCyFTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC7initFooSo5GizmoCyF : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ @objc var typicalProperty: Gizmo
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
+ // CHECK: bb0([[SELF:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref objc_thunks.Hoozit.typicalProperty.getter
+ // CHECK-NEXT: [[GETIMPL:%.*]] = function_ref @$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvg
+ // CHECK-NEXT: [[RES:%.*]] = apply [[GETIMPL]]([[BORROWED_SELF_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: return [[RES]] : $Gizmo
+ // CHECK-NEXT: }
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvg : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK: bb0(%0 : @guaranteed $Hoozit):
+ // CHECK-NEXT: debug_value %0
+ // CHECK-NEXT: [[ADDR:%.*]] = ref_element_addr %0 : {{.*}}, #Hoozit.typicalProperty
+ // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[ADDR]] : $*Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = load [copy] [[READ]] {{.*}}
+ // CHECK-NEXT: end_access [[READ]] : $*Gizmo
+ // CHECK-NEXT: return [[RES]]
+
+ // -- setter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvsTo : $@convention(objc_method) (Gizmo, Hoozit) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK: [[VALUE_COPY:%.*]] = copy_value [[VALUE]] : $Gizmo
+ // CHECK: [[THIS_COPY:%.*]] = copy_value [[THIS]] : $Hoozit
+ // CHECK: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK: // function_ref objc_thunks.Hoozit.typicalProperty.setter
+ // CHECK: [[FR:%.*]] = function_ref @$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvs
+ // CHECK: [[RES:%.*]] = apply [[FR]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
+ // CHECK: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK: destroy_value [[THIS_COPY]]
+ // CHECK: return [[RES]] : $(), loc {{.*}}, scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:13:auto_gen
+ // CHECK: } // end sil function '$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvsTo'
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvs
+ // CHECK: bb0([[ARG0:%.*]] : @owned $Gizmo, [[ARG1:%.*]] : @guaranteed $Hoozit):
+ // CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
+ // CHECK: [[ARG0_COPY:%.*]] = copy_value [[BORROWED_ARG0]]
+ // CHECK: [[ADDR:%.*]] = ref_element_addr [[ARG1]] : {{.*}}, #Hoozit.typicalProperty
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*Gizmo
+ // CHECK: assign [[ARG0_COPY]] to [[WRITE]] : $*Gizmo
+ // CHECK: end_access [[WRITE]] : $*Gizmo
+ // CHECK: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
+ // CHECK: destroy_value [[ARG0]]
+ // CHECK: } // end sil function '$S11objc_thunks6HoozitC15typicalPropertySo5GizmoCvs'
+
+ // NS_RETURNS_RETAINED getter by family (-copy)
+ @objc var copyProperty: Gizmo
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo {
+ // CHECK: bb0([[SELF:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref objc_thunks.Hoozit.copyProperty.getter
+ // CHECK-NEXT: [[FR:%.*]] = function_ref @$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvg
+ // CHECK-NEXT: [[RES:%.*]] = apply [[FR]]([[BORROWED_SELF_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvg
+ // CHECK: bb0(%0 : @guaranteed $Hoozit):
+ // CHECK: [[ADDR:%.*]] = ref_element_addr %0 : {{.*}}, #Hoozit.copyProperty
+ // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[ADDR]] : $*Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = load [copy] [[READ]]
+ // CHECK-NEXT: end_access [[READ]] : $*Gizmo
+ // CHECK-NEXT: return [[RES]]
+
+ // -- setter is normal
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvsTo : $@convention(objc_method) (Gizmo, Hoozit) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref objc_thunks.Hoozit.copyProperty.setter
+ // CHECK-NEXT: [[FR:%.*]] = function_ref @$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvs
+ // CHECK-NEXT: [[RES:%.*]] = apply [[FR]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvs
+ // CHECK: bb0([[ARG1:%.*]] : @owned $Gizmo, [[SELF:%.*]] : @guaranteed $Hoozit):
+ // CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
+ // CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
+ // CHECK: [[ADDR:%.*]] = ref_element_addr [[SELF]] : {{.*}}, #Hoozit.copyProperty
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*Gizmo
+ // CHECK: assign [[ARG1_COPY]] to [[WRITE]]
+ // CHECK: end_access [[WRITE]] : $*Gizmo
+ // CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
+ // CHECK: destroy_value [[ARG1]]
+ // CHECK: } // end sil function '$S11objc_thunks6HoozitC12copyPropertySo5GizmoCvs'
+
+ @objc var roProperty: Gizmo { return self }
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC10roPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC10roPropertySo5GizmoCvg : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]] : $Hoozit
+ // CHECK-NEXT: return [[RES]] : $Gizmo
+ // CHECK-NEXT: } // end sil function '$S11objc_thunks6HoozitC10roPropertySo5GizmoCvgTo'
+
+ // -- no setter
+ // CHECK-NOT: sil hidden [thunk] @$S11objc_thunks6HoozitC10roPropertySo5GizmoCvsTo
+
+ @objc var rwProperty: Gizmo {
+ get {
+ return self
+ }
+ set {}
+ }
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC10rwPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo
+
+ // -- setter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC10rwPropertySo5GizmoCvsTo : $@convention(objc_method) (Gizmo, Hoozit) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC10rwPropertySo5GizmoCvs : $@convention(method) (@owned Gizmo, @guaranteed Hoozit) -> ()
+ // CHECK-NEXT: apply [[NATIVE]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return
+ // CHECK-NEXT: }
+
+ @objc var copyRWProperty: Gizmo {
+ get {
+ return self
+ }
+ set {}
+ }
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC14copyRWPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @owned Gizmo {
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC14copyRWPropertySo5GizmoCvg : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NOT: return
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // -- setter is normal
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC14copyRWPropertySo5GizmoCvsTo : $@convention(objc_method) (Gizmo, Hoozit) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC14copyRWPropertySo5GizmoCvs : $@convention(method) (@owned Gizmo, @guaranteed Hoozit) -> ()
+ // CHECK-NEXT: apply [[NATIVE]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return
+ // CHECK-NEXT: }
+
+ @objc var initProperty: Gizmo
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC12initPropertySo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC12initPropertySo5GizmoCvg : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // -- setter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC12initPropertySo5GizmoCvsTo : $@convention(objc_method) (Gizmo, Hoozit) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC12initPropertySo5GizmoCvs : $@convention(method) (@owned Gizmo, @guaranteed Hoozit) -> ()
+ // CHECK-NEXT: apply [[NATIVE]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return
+ // CHECK-NEXT: }
+
+ @objc var propComputed: Gizmo {
+ @objc(initPropComputedGetter) get { return self }
+ @objc(initPropComputedSetter:) set {}
+ }
+ // -- getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC12propComputedSo5GizmoCvgTo : $@convention(objc_method) (Hoozit) -> @autoreleased Gizmo {
+ // CHECK: bb0([[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC12propComputedSo5GizmoCvg : $@convention(method) (@guaranteed Hoozit) -> @owned Gizmo
+ // CHECK-NEXT: [[RES:%.*]] = apply [[NATIVE]]([[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return [[RES]]
+ // CHECK-NEXT: }
+
+ // -- setter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC12propComputedSo5GizmoCvsTo : $@convention(objc_method) (Gizmo, Hoozit) -> () {
+ // CHECK: bb0([[VALUE:%.*]] : @unowned $Gizmo, [[THIS:%.*]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[VALUE_COPY:%.*]] = copy_value [[VALUE]]
+ // CHECK-NEXT: [[THIS_COPY:%.*]] = copy_value [[THIS]]
+ // CHECK-NEXT: [[BORROWED_THIS_COPY:%.*]] = begin_borrow [[THIS_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6HoozitC12propComputedSo5GizmoCvs : $@convention(method) (@owned Gizmo, @guaranteed Hoozit) -> ()
+ // CHECK-NEXT: apply [[NATIVE]]([[VALUE_COPY]], [[BORROWED_THIS_COPY]])
+ // CHECK-NEXT: end_borrow [[BORROWED_THIS_COPY]] from [[THIS_COPY]]
+ // CHECK-NEXT: destroy_value [[THIS_COPY]]
+ // CHECK-NEXT: return
+ // CHECK-NEXT: }
+
+ // Don't export generics to ObjC yet
+ func generic<T>(_ x: T) {}
+ // CHECK-NOT: sil hidden [thunk] @_TToFC11objc_thunks6Hoozit7generic{{.*}}
+
+ // Constructor.
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC7bellsOnACSi_tcfc : $@convention(method) (Int, @owned Hoozit) -> @owned Hoozit {
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Hoozit }
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [derivedself] [[SELF_BOX]]
+ // CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+ // CHECK: [[GIZMO:%[0-9]+]] = upcast [[SELF:%[0-9]+]] : $Hoozit to $Gizmo
+ // CHECK: [[BORROWED_GIZMO:%.*]] = begin_borrow [[GIZMO]]
+ // CHECK: [[CAST_BORROWED_GIZMO:%.*]] = unchecked_ref_cast [[BORROWED_GIZMO]] : $Gizmo to $Hoozit
+ // CHECK: [[SUPERMETHOD:%[0-9]+]] = objc_super_method [[CAST_BORROWED_GIZMO]] : $Hoozit, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo?, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+ // CHECK-NEXT: end_borrow [[BORROWED_GIZMO]] from [[GIZMO]]
+ // CHECK-NEXT: [[SELF_REPLACED:%[0-9]+]] = apply [[SUPERMETHOD]](%0, [[X:%[0-9]+]]) : $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+ // CHECK-NOT: unconditional_checked_cast downcast [[SELF_REPLACED]] : $Gizmo to $Hoozit
+ // CHECK: unchecked_ref_cast
+ // CHECK: return
+ override init(bellsOn x : Int) {
+ super.init(bellsOn: x)
+ other()
+ }
+
+ // Subscript
+ @objc subscript (i: Int) -> Hoozit {
+ // Getter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitCyACSicigTo : $@convention(objc_method) (Int, Hoozit) -> @autoreleased Hoozit
+ // CHECK: bb0([[I:%[0-9]+]] : @trivial $Int, [[SELF:%[0-9]+]] : @unowned $Hoozit):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Hoozit
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%[0-9]+]] = function_ref @$S11objc_thunks6HoozitCyACSicig : $@convention(method) (Int, @guaranteed Hoozit) -> @owned Hoozit
+ // CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[NATIVE]]([[I]], [[BORROWED_SELF_COPY]]) : $@convention(method) (Int, @guaranteed Hoozit) -> @owned Hoozit
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]]
+ // CHECK-NEXT: return [[RESULT]] : $Hoozit
+ get {
+ return self
+ }
+
+ // Setter
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitCyACSicisTo : $@convention(objc_method) (Hoozit, Int, Hoozit) -> ()
+ // CHECK: bb0([[VALUE:%[0-9]+]] : @unowned $Hoozit, [[I:%[0-9]+]] : @trivial $Int, [[SELF:%[0-9]+]] : @unowned $Hoozit):
+ // CHECK: [[VALUE_COPY:%.*]] = copy_value [[VALUE]] : $Hoozit
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Hoozit
+ // CHECK: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK: [[NATIVE:%[0-9]+]] = function_ref @$S11objc_thunks6HoozitCyACSicis : $@convention(method) (@owned Hoozit, Int, @guaranteed Hoozit) -> ()
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[NATIVE]]([[VALUE_COPY]], [[I]], [[BORROWED_SELF_COPY]]) : $@convention(method) (@owned Hoozit, Int, @guaranteed Hoozit) -> ()
+ // CHECK: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK: destroy_value [[SELF_COPY]]
+ // CHECK: return [[RESULT]] : $()
+ // CHECK: } // end sil function '$S11objc_thunks6HoozitCyACSicisTo'
+ set {}
+ }
+}
+
+class Wotsit<T> : Gizmo {
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6WotsitC5plainyyFTo : $@convention(objc_method) <T> (Wotsit<T>) -> () {
+ // CHECK: bb0([[SELF:%.*]] : @unowned $Wotsit<T>):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Wotsit<T>
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6WotsitC5plainyyF : $@convention(method) <τ_0_0> (@guaranteed Wotsit<τ_0_0>) -> ()
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[NATIVE]]<T>([[BORROWED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed Wotsit<τ_0_0>) -> ()
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]] : $Wotsit<T>
+ // CHECK-NEXT: return [[RESULT]] : $()
+ // CHECK-NEXT: }
+ @objc func plain() { }
+
+ func generic<U>(_ x: U) {}
+
+ var property : T
+
+ init(t: T) {
+ self.property = t
+ super.init()
+ }
+
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6WotsitC11descriptionSSvgTo : $@convention(objc_method) <T> (Wotsit<T>) -> @autoreleased NSString {
+ // CHECK: bb0([[SELF:%.*]] : @unowned $Wotsit<T>):
+ // CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $Wotsit<T>
+ // CHECK-NEXT: [[BORROWED_SELF_COPY:%.*]] = begin_borrow [[SELF_COPY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[NATIVE:%.*]] = function_ref @$S11objc_thunks6WotsitC11descriptionSSvg : $@convention(method) <τ_0_0> (@guaranteed Wotsit<τ_0_0>) -> @owned String
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[NATIVE:%.*]]<T>([[BORROWED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed Wotsit<τ_0_0>) -> @owned String
+ // CHECK-NEXT: end_borrow [[BORROWED_SELF_COPY]] from [[SELF_COPY]]
+ // CHECK-NEXT: destroy_value [[SELF_COPY]] : $Wotsit<T>
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[BRIDGE:%.*]] = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
+ // CHECK-NEXT: [[BORROWED_RESULT:%.*]] = begin_borrow [[RESULT]]
+ // CHECK-NEXT: [[NSRESULT:%.*]] = apply [[BRIDGE]]([[BORROWED_RESULT]]) : $@convention(method) (@guaranteed String) -> @owned NSString
+ // CHECK-NEXT: end_borrow [[BORROWED_RESULT]] from [[RESULT]]
+ // CHECK-NEXT: destroy_value [[RESULT]]
+ // CHECK-NEXT: return [[NSRESULT]] : $NSString
+ // CHECK-NEXT: }
+ override var description : String {
+ return "Hello, world."
+ }
+
+ // Ivar destroyer
+ // CHECK: sil hidden @$S11objc_thunks6WotsitCfETo
+
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6WotsitCACyxGSgycfcTo : $@convention(objc_method) <T> (@owned Wotsit<T>) -> @owned Optional<Wotsit<T>>
+
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6WotsitC7bellsOnACyxGSgSi_tcfcTo : $@convention(objc_method) <T> (Int, @owned Wotsit<T>) -> @owned Optional<Wotsit<T>>
+}
+
+// CHECK-NOT: sil hidden [thunk] @_TToF{{.*}}Wotsit{{.*}}
+
+// Extension initializers, properties and methods need thunks too.
+extension Hoozit {
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC3intACSi_tcfcTo : $@convention(objc_method) (Int, @owned Hoozit) -> @owned Hoozit
+ @objc dynamic convenience init(int i: Int) { self.init(bellsOn: i) }
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC6doubleACSd_tcfc : $@convention(method) (Double, @owned Hoozit) -> @owned Hoozit
+ convenience init(double d: Double) {
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var Hoozit }
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+ // CHECK: [[X_BOX:%[0-9]+]] = alloc_box ${ var X }
+ var x = X()
+ // CHECK: [[CTOR:%[0-9]+]] = objc_method [[SELF:%[0-9]+]] : $Hoozit, #Hoozit.init!initializer.1.foreign : (Hoozit.Type) -> (Int) -> Hoozit, $@convention(objc_method) (Int, @owned Hoozit) -> @owned Hoozit
+ // CHECK: [[NEW_SELF:%[0-9]+]] = apply [[CTOR]]
+ // CHECK: store [[NEW_SELF]] to [init] [[PB_BOX]] : $*Hoozit
+ // CHECK: return
+ self.init(int:Int(d))
+ other()
+ }
+
+ func foof() {}
+ // CHECK-LABEL: sil hidden [thunk] @$S11objc_thunks6HoozitC4foofyyFTo : $@convention(objc_method) (Hoozit) -> () {
+
+ var extensionProperty: Int { return 0 }
+ // CHECK-LABEL: sil hidden @$S11objc_thunks6HoozitC17extensionPropertySivg : $@convention(method) (@guaranteed Hoozit) -> Int
+}
+
+// Calling objc methods of subclass should go through native entry points
+func useHoozit(_ h: Hoozit) {
+// sil @$S11objc_thunks9useHoozit1hyAA0D0C_tF
+ // In the class decl, overrides importd method, 'dynamic' was inferred
+ h.fork()
+ // CHECK: objc_method {{%.*}} : {{.*}}, #Hoozit.fork!1.foreign
+
+ // In an extension, 'dynamic' was inferred.
+ h.foof()
+ // CHECK: objc_method {{%.*}} : {{.*}}, #Hoozit.foof!1.foreign
+}
+
+func useWotsit(_ w: Wotsit<String>) {
+// sil @$S11objc_thunks9useWotsit1wySo0D0CySSG_tF
+ w.plain()
+ // CHECK: class_method {{%.*}} : {{.*}}, #Wotsit.plain!1 :
+ w.generic(2)
+ // CHECK: class_method {{%.*}} : {{.*}}, #Wotsit.generic!1 :
+
+ // Inherited methods only have objc entry points
+ w.clone()
+ // CHECK: objc_method {{%.*}} : {{.*}}, #Gizmo.clone!1.foreign
+}
+
+func other() { }
+
+class X { }
+
+// CHECK-LABEL: sil hidden @$S11objc_thunks8propertyySiSo5GizmoCF
+func property(_ g: Gizmo) -> Int {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: objc_method [[ARG]] : $Gizmo, #Gizmo.count!getter.1.foreign
+ return g.count
+}
+
+// CHECK-LABEL: sil hidden @$S11objc_thunks13blockPropertyyySo5GizmoCF
+func blockProperty(_ g: Gizmo) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $Gizmo):
+ // CHECK: objc_method [[ARG]] : $Gizmo, #Gizmo.block!setter.1.foreign
+ g.block = { }
+ // CHECK: objc_method [[ARG]] : $Gizmo, #Gizmo.block!getter.1.foreign
+ g.block()
+}
+
+class DesignatedStubs : Gizmo {
+ var i: Int
+
+ override init() { i = 5 }
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks15DesignatedStubsC7bellsOnACSgSi_tcfc
+ // CHECK: string_literal utf8 "objc_thunks.DesignatedStubs"
+ // CHECK: string_literal utf8 "init(bellsOn:)"
+ // CHECK: string_literal utf8 "{{.*}}objc_thunks.swift"
+ // CHECK: function_ref @$Ss25_unimplementedInitializer9className04initD04file4line6columns5NeverOs12StaticStringV_A2JS2utF
+ // CHECK: return
+
+ // CHECK-NOT: sil hidden @_TFCSo15DesignatedStubsc{{.*}}
+}
+
+class DesignatedOverrides : Gizmo {
+ var i: Int = 5
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks19DesignatedOverridesCACSgycfc
+ // CHECK-NOT: return
+ // CHECK: function_ref @$S11objc_thunks19DesignatedOverridesC1iSivpfi : $@convention(thin) () -> Int
+ // CHECK: objc_super_method [[SELF:%[0-9]+]] : $DesignatedOverrides, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> () -> Gizmo?, $@convention(objc_method) (@owned Gizmo) -> @owned Optional<Gizmo>
+ // CHECK: return
+
+ // CHECK-LABEL: sil hidden @$S11objc_thunks19DesignatedOverridesC7bellsOnACSgSi_tcfc
+ // CHECK: function_ref @$S11objc_thunks19DesignatedOverridesC1iSivpfi : $@convention(thin) () -> Int
+ // CHECK: objc_super_method [[SELF:%[0-9]+]] : $DesignatedOverrides, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo?, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+ // CHECK: return
+}
+
+// Make sure we copy blocks passed in as IUOs - <rdar://problem/22471309>
+
+func registerAnsible() {
+ // CHECK: function_ref @$S11objc_thunks15registerAnsibleyyFyyycSgcfU_
+ Ansible.anseAsync({ completion in completion!() })
+}
diff --git a/test/SILGen/plus_zero_opaque_ownership.swift b/test/SILGen/plus_zero_opaque_ownership.swift
new file mode 100644
index 0000000..622ffaf
--- /dev/null
+++ b/test/SILGen/plus_zero_opaque_ownership.swift
@@ -0,0 +1,257 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-opaque-values -enable-sil-ownership -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck %s
+// RUN: %target-swift-frontend -target x86_64-apple-macosx10.9 -enable-sil-opaque-values -enable-sil-ownership -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen -parse-stdlib -parse-as-library -module-name Swift %s | %FileCheck --check-prefix=CHECK-OSX %s
+
+public typealias AnyObject = Builtin.AnyObject
+
+precedencegroup AssignmentPrecedence {}
+precedencegroup CastingPrecedence {}
+precedencegroup ComparisonPrecedence {}
+
+public protocol _ObjectiveCBridgeable {}
+
+public protocol UnkeyedDecodingContainer {
+ var isAtEnd: Builtin.Int1 { get }
+}
+
+public protocol Decoder {
+ func unkeyedContainer() throws -> UnkeyedDecodingContainer
+}
+
+// Test open_existential_value ownership
+// ---
+// CHECK-LABEL: sil @$Ss11takeDecoder4fromBi1_s0B0_p_tKF : $@convention(thin) (@in_guaranteed Decoder) -> (Builtin.Int1, @error Error) {
+// CHECK: bb0(%0 : @guaranteed $Decoder):
+// CHECK: [[OPENED:%.*]] = open_existential_value %0 : $Decoder to $@opened("{{.*}}") Decoder
+// CHECK: [[WT:%.*]] = witness_method $@opened("{{.*}}") Decoder, #Decoder.unkeyedContainer!1 : <Self where Self : Decoder> (Self) -> () throws -> UnkeyedDecodingContainer, %3 : $@opened("{{.*}}") Decoder : $@convention(witness_method: Decoder) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Error)
+// CHECK: try_apply [[WT]]<@opened("{{.*}}") Decoder>([[OPENED]]) : $@convention(witness_method: Decoder) <τ_0_0 where τ_0_0 : Decoder> (@in_guaranteed τ_0_0) -> (@out UnkeyedDecodingContainer, @error Error), normal bb2, error bb1
+//
+// CHECK:bb{{.*}}([[RET1:%.*]] : @owned $UnkeyedDecodingContainer):
+// CHECK: [[BORROW2:%.*]] = begin_borrow [[RET1]] : $UnkeyedDecodingContainer
+// CHECK: [[OPENED2:%.*]] = open_existential_value [[BORROW2]] : $UnkeyedDecodingContainer to $@opened("{{.*}}") UnkeyedDecodingContainer
+// CHECK: [[WT2:%.*]] = witness_method $@opened("{{.*}}") UnkeyedDecodingContainer, #UnkeyedDecodingContainer.isAtEnd!getter.1 : <Self where Self : UnkeyedDecodingContainer> (Self) -> () -> Builtin.Int1, [[OPENED2]] : $@opened("{{.*}}") UnkeyedDecodingContainer : $@convention(witness_method: UnkeyedDecodingContainer) <τ_0_0 where τ_0_0 : UnkeyedDecodingContainer> (@in_guaranteed τ_0_0) -> Builtin.Int1
+// CHECK: [[RET2:%.*]] = apply [[WT2]]<@opened("{{.*}}") UnkeyedDecodingContainer>([[OPENED2]]) : $@convention(witness_method: UnkeyedDecodingContainer) <τ_0_0 where τ_0_0 : UnkeyedDecodingContainer> (@in_guaranteed τ_0_0) -> Builtin.Int1
+// CHECK: end_borrow [[BORROW2]] from [[RET1]] : $UnkeyedDecodingContainer, $UnkeyedDecodingContainer
+// CHECK: destroy_value [[RET1]] : $UnkeyedDecodingContainer
+// CHECK-NOT: destroy_value %0 : $Decoder
+// CHECK: return [[RET2]] : $Builtin.Int1
+// CHECK-LABEL: } // end sil function '$Ss11takeDecoder4fromBi1_s0B0_p_tKF'
+public func takeDecoder(from decoder: Decoder) throws -> Builtin.Int1 {
+ let container = try decoder.unkeyedContainer()
+ return container.isAtEnd
+}
+
+// Test unsafe_bitwise_cast nontrivial ownership.
+// ---
+// CHECK-LABEL: sil @$Ss13unsafeBitCast_2toq_x_q_mtr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @thick U.Type) -> @out U {
+// CHECK: bb0([[ARG0:%.*]] : @guaranteed $T, [[ARG1:%.*]] : @trivial $@thick U.Type):
+// CHECK: [[RESULT:%.*]] = unchecked_bitwise_cast [[ARG0]] : $T to $U
+// CHECK: [[RESULT_COPY:%.*]] = copy_value [[RESULT]] : $U
+// CHECK: return [[RESULT_COPY]] : $U
+// CHECK-LABEL: } // end sil function '$Ss13unsafeBitCast_2toq_x_q_mtr0_lF'
+public func unsafeBitCast<T, U>(_ x: T, to type: U.Type) -> U {
+ return Builtin.reinterpretCast(x)
+}
+
+// A lot of standard library support is necessary to support raw enums.
+// --------------------------------------------------------------------
+
+infix operator == : ComparisonPrecedence
+infix operator ~= : ComparisonPrecedence
+
+public struct Bool {
+ var _value: Builtin.Int1
+
+ public init() {
+ let zero: Int64 = 0
+ self._value = Builtin.trunc_Int64_Int1(zero._value)
+ }
+
+ internal init(_ v: Builtin.Int1) { self._value = v }
+
+ public init(_ value: Bool) {
+ self = value
+ }
+}
+
+extension Bool {
+ public func _getBuiltinLogicValue() -> Builtin.Int1 {
+ return _value
+ }
+}
+
+public protocol Equatable {
+ /// Returns a Boolean value indicating whether two values are equal.
+ ///
+ /// Equality is the inverse of inequality. For any values `a` and `b`,
+ /// `a == b` implies that `a != b` is `false`.
+ ///
+ /// - Parameters:
+ /// - lhs: A value to compare.
+ /// - rhs: Another value to compare.
+ static func == (lhs: Self, rhs: Self) -> Bool
+}
+
+public func ~= <T : Equatable>(a: T, b: T) -> Bool {
+ return a == b
+}
+
+public protocol RawRepresentable {
+ associatedtype RawValue
+
+ init?(rawValue: RawValue)
+
+ var rawValue: RawValue { get }
+}
+
+public func == <T : RawRepresentable>(lhs: T, rhs: T) -> Bool
+ where T.RawValue : Equatable {
+ return lhs.rawValue == rhs.rawValue
+}
+
+public typealias _MaxBuiltinIntegerType = Builtin.Int2048
+
+public protocol _ExpressibleByBuiltinIntegerLiteral {
+ init(_builtinIntegerLiteral value: _MaxBuiltinIntegerType)
+}
+
+public protocol ExpressibleByIntegerLiteral {
+ associatedtype IntegerLiteralType : _ExpressibleByBuiltinIntegerLiteral
+
+ init(integerLiteral value: IntegerLiteralType)
+}
+
+extension ExpressibleByIntegerLiteral
+ where Self : _ExpressibleByBuiltinIntegerLiteral {
+ @_transparent
+ public init(integerLiteral value: Self) {
+ self = value
+ }
+}
+
+public protocol ExpressibleByStringLiteral {}
+public protocol ExpressibleByFloatLiteral {}
+public protocol ExpressibleByUnicodeScalarLiteral {}
+public protocol ExpressibleByExtendedGraphemeClusterLiteral {}
+
+public struct Int64 : ExpressibleByIntegerLiteral, _ExpressibleByBuiltinIntegerLiteral, Equatable {
+ public var _value: Builtin.Int64
+ public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) {
+ _value = Builtin.s_to_s_checked_trunc_Int2048_Int64(x).0
+ }
+ public typealias IntegerLiteralType = Int64
+ public init(integerLiteral value: Int64) {
+ self = value
+ }
+ public static func ==(_ lhs: Int64, rhs: Int64) -> Bool {
+ return Bool(Builtin.cmp_eq_Int64(lhs._value, rhs._value))
+ }
+}
+
+// Test ownership of multi-case Enum values in the context of @trivial to @in thunks.
+// ---
+// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$Ss17FloatingPointSignOs9EquatablessACP2eeoiySbx_xtFZTW : $@convention(witness_method: Equatable) (@in_guaranteed FloatingPointSign, @in_guaranteed FloatingPointSign, @thick FloatingPointSign.Type) -> Bool {
+// CHECK: bb0(%0 : @trivial $FloatingPointSign, %1 : @trivial $FloatingPointSign, %2 : @trivial $@thick FloatingPointSign.Type):
+// CHECK: %3 = function_ref @$Ss2eeoiySbx_xts16RawRepresentableRzs9Equatable0B5ValueRpzlF : $@convention(thin) <τ_0_0 where τ_0_0 : RawRepresentable, τ_0_0.RawValue : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+// CHECK: %4 = apply %3<FloatingPointSign, Int64>(%0, %1) : $@convention(thin) <τ_0_0 where τ_0_0 : RawRepresentable, τ_0_0.RawValue : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+// CHECK: return %4 : $Bool
+// CHECK-LABEL: } // end sil function '$Ss17FloatingPointSignOs9EquatablessACP2eeoiySbx_xtFZTW'
+public enum FloatingPointSign: Int64 {
+ /// The sign for a positive value.
+ case plus
+
+ /// The sign for a negative value.
+ case minus
+}
+
+#if os(OSX)
+// Test open_existential_value used in a conversion context.
+// (the actual bridging call is dropped because we don't import Swift).
+// ---
+// CHECK-OSX-LABEL: sil @$Ss26_unsafeDowncastToAnyObject04fromD0yXlyp_tF : $@convention(thin) (@in_guaranteed Any) -> @owned AnyObject {
+// CHECK-OSX: bb0(%0 : @guaranteed $Any):
+// CHECK-OSX: [[COPY:%.*]] = copy_value %0 : $Any
+// CHECK-OSX: [[BORROW2:%.*]] = begin_borrow [[COPY]] : $Any
+// CHECK-OSX: [[VAL:%.*]] = open_existential_value [[BORROW2]] : $Any to $@opened
+// CHECK-OSX: [[COPY2:%.*]] = copy_value [[VAL]] : $@opened
+// CHECK-OSX: destroy_value [[COPY2]] : $@opened
+// CHECK-OSX: end_borrow [[BORROW2]] from [[COPY]] : $Any, $Any
+// CHECK-OSX: destroy_value [[COPY]] : $Any
+// CHECK-OSX-NOT: destroy_value %0 : $Any
+// CHECK-OSX: return undef : $AnyObject
+// CHECK-OSX-LABEL: } // end sil function '$Ss26_unsafeDowncastToAnyObject04fromD0yXlyp_tF'
+public func _unsafeDowncastToAnyObject(fromAny any: Any) -> AnyObject {
+ return any as AnyObject
+}
+#endif
+
+public protocol Error {}
+
+#if os(OSX)
+// Test open_existential_box_value in a conversion context.
+// ---
+// CHECK-OSX-LABEL: sil @$Ss3foo1eys5Error_pSg_tF : $@convention(thin) (@guaranteed Optional<Error>) -> () {
+// CHECK-OSX: [[BORROW:%.*]] = begin_borrow %{{.*}} : $Error
+// CHECK-OSX: [[VAL:%.*]] = open_existential_box_value [[BORROW]] : $Error to $@opened
+// CHECK-OSX: [[COPY:%.*]] = copy_value [[VAL]] : $@opened
+// CHECK-OSX: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened
+// CHECK-OSX: end_borrow [[BORROW]] from %{{.*}} : $Error, $Error
+// CHECK-OSX-LABEL: } // end sil function '$Ss3foo1eys5Error_pSg_tF'
+public func foo(e: Error?) {
+ if let u = e {
+ let a: Any = u
+ _ = a
+ }
+}
+#endif
+
+public enum Optional<Wrapped> {
+ case none
+ case some(Wrapped)
+}
+
+public protocol IP {}
+
+public protocol Seq {
+ associatedtype Iterator : IP
+
+ func makeIterator() -> Iterator
+}
+
+extension Seq where Self.Iterator == Self {
+ public func makeIterator() -> Self {
+ return self
+ }
+}
+
+public struct EnumIter<Base : IP> : IP, Seq {
+ internal var _base: Base
+
+ public typealias Iterator = EnumIter<Base>
+}
+
+// Test passing a +1 RValue to @in_guaranteed.
+// ---
+// CHECK-LABEL: sil @$Ss7EnumSeqV12makeIterators0A4IterVy0D0QzGyF : $@convention(method) <Base where Base : Seq> (@in_guaranteed EnumSeq<Base>) -> @out EnumIter<Base.Iterator> {
+// CHECK: bb0(%0 : @guaranteed $EnumSeq<Base>):
+// CHECK: [[MT:%.*]] = metatype $@thin EnumIter<Base.Iterator>.Type
+// CHECK: [[FIELD:%.*]] = struct_extract %0 : $EnumSeq<Base>, #EnumSeq._base
+// CHECK: [[COPY:%.*]] = copy_value [[FIELD]] : $Base
+// CHECK: [[BORROW:%.*]] = begin_borrow [[COPY]] : $Base
+// CHECK: [[WT:%.*]] = witness_method $Base, #Seq.makeIterator!1 : <Self where Self : Seq> (Self) -> () -> Self.Iterator : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
+// CHECK: [[ITER:%.*]] = apply [[WT]]<Base>([[BORROW]]) : $@convention(witness_method: Seq) <τ_0_0 where τ_0_0 : Seq> (@in_guaranteed τ_0_0) -> @out τ_0_0.Iterator
+// CHECK: end_borrow [[BORROW]] from [[COPY]] : $Base, $Base
+// CHECK: destroy_value [[COPY]] : $Base
+// CHECK: [[FN:%.*]] = function_ref @$Ss8EnumIterV5_baseAByxGx_tcfC : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
+// CHECK: [[RET:%.*]] = apply [[FN]]<Base.Iterator>([[ITER]], [[MT]]) : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
+// CHECK: return [[RET]] : $EnumIter<Base.Iterator>
+// CHECK-LABEL: } // end sil function '$Ss7EnumSeqV12makeIterators0A4IterVy0D0QzGyF'
+public struct EnumSeq<Base : Seq> : Seq {
+ public typealias Iterator = EnumIter<Base.Iterator>
+
+ internal var _base: Base
+
+ public func makeIterator() -> Iterator {
+ return EnumIter(_base: _base.makeIterator())
+ }
+}
diff --git a/test/SILGen/plus_zero_opaque_values_silgen.swift b/test/SILGen/plus_zero_opaque_values_silgen.swift
new file mode 100644
index 0000000..1c7f8f7
--- /dev/null
+++ b/test/SILGen/plus_zero_opaque_values_silgen.swift
@@ -0,0 +1,1236 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-opaque-values -emit-sorted-sil -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
+
+// UNSUPPORTED: resilient_stdlib
+
+struct TrivialStruct {
+ var x: Int
+}
+
+protocol Foo {
+ func foo()
+}
+
+protocol P {
+ var x : Int { get }
+}
+
+protocol P2 : P {}
+
+extension TrivialStruct : P2 {}
+
+struct Box<T> {
+ let t: T
+}
+
+protocol EmptyP {}
+
+struct AddressOnlyStruct : EmptyP {}
+
+struct AnyStruct {
+ let a: Any
+}
+
+protocol Clonable {
+ func maybeClone() -> Self?
+}
+
+indirect enum IndirectEnum<T> {
+ case Nil
+ case Node(T)
+}
+
+protocol SubscriptableGet {
+ subscript(a : Int) -> Int { get }
+}
+
+protocol SubscriptableGetSet {
+ subscript(a : Int) -> Int { get set }
+}
+
+var subscriptableGet : SubscriptableGet
+var subscriptableGetSet : SubscriptableGetSet
+
+class OpaqueClass<T> {
+ typealias ObnoxiousTuple = (T, (T.Type, (T) -> T))
+
+ func inAndOut(x: T) -> T { return x }
+ func variantOptionalityTuples(x: ObnoxiousTuple) -> ObnoxiousTuple? { return x }
+}
+
+class StillOpaqueClass<T>: OpaqueClass<T> {
+ override func variantOptionalityTuples(x: ObnoxiousTuple?) -> ObnoxiousTuple { return x! }
+}
+
+class OpaqueTupleClass<U>: OpaqueClass<(U, U)> {
+ override func inAndOut(x: (U, U)) -> (U, U) { return x }
+}
+
+func unreachableF<T>() -> (Int, T)? { }
+
+func s010_hasVarArg(_ args: Any...) {}
+
+// Tests Address only enums's construction
+// CHECK-LABEL: sil shared [transparent] @$S20opaque_values_silgen15AddressOnlyEnumO4mereyAcA6EmptyP_pcACmF : $@convention(method) (@in EmptyP, @thin AddressOnlyEnum.Type) -> @out AddressOnlyEnum {
+// CHECK: bb0([[ARG0:%.*]] : $EmptyP, [[ARG1:%.*]] : $@thin AddressOnlyEnum.Type):
+// CHECK: [[RETVAL:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.mere!enumelt.1, [[ARG0]] : $EmptyP
+// CHECK: return [[RETVAL]] : $AddressOnlyEnum
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen15AddressOnlyEnumO4mereyAcA6EmptyP_pcACmF'
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$S20opaque_values_silgen15AddressOnlyEnumO4mereyAcA6EmptyP_pcACmFTc : $@convention(thin) (@thin AddressOnlyEnum.Type) -> @owned @callee_guaranteed (@in_guaranteed EmptyP) -> @out AddressOnlyEnum {
+// CHECK: bb0([[ARG:%.*]] : $@thin AddressOnlyEnum.Type):
+// CHECK: [[RETVAL:%.*]] = partial_apply {{.*}}([[ARG]]) : $@convention(method) (@in EmptyP, @thin AddressOnlyEnum.Type) -> @out AddressOnlyEnum
+// CHECK: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$S20opaque_values_silgen6EmptyP_pAA15AddressOnlyEnumOIegir_AaB_pADIegnr_TR : $@convention(thin) (@in_guaranteed EmptyP, @guaranteed @callee_guaranteed (@in EmptyP) -> @out AddressOnlyEnum) -> @out AddressOnlyEnum
+// CHECK: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[RETVAL]])
+// CHECK: return [[CANONICAL_THUNK]] : $@callee_guaranteed (@in_guaranteed EmptyP) -> @out AddressOnlyEnum
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen15AddressOnlyEnumO4mereyAcA6EmptyP_pcACmFTc'
+enum AddressOnlyEnum {
+ case nought
+ case mere(EmptyP)
+ case phantom(AddressOnlyStruct)
+}
+
+// Test vtables - OpaqueTupleClass
+// ---
+// CHECK-LABEL: sil private @$S20opaque_values_silgen16OpaqueTupleClassC8inAndOut1xx_xtx_xt_tFAA0dF0CAdExx_tFTV : $@convention(method) <U> (@in_guaranteed (U, U), @guaranteed OpaqueTupleClass<U>) -> @out (U, U) {
+// CHECK: bb0([[ARG0:%.*]] : $(U, U), [[ARG1:%.*]] : $OpaqueTupleClass<U>):
+// CHECK: ([[TELEM0:%.*]], [[TELEM1:%.*]]) = destructure_tuple [[ARG0]] : $(U, U)
+// CHECK: [[APPLY:%.*]] = apply {{.*}}<U>([[TELEM0]], [[TELEM1]], [[ARG1]]) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, @guaranteed OpaqueTupleClass<τ_0_0>) -> (@out τ_0_0, @out τ_0_0)
+// CHECK: [[BORROWED_CALL:%.*]] = begin_borrow [[APPLY]]
+// CHECK: [[BORROWED_CALL_EXT0:%.*]] = tuple_extract [[BORROWED_CALL]] : $(U, U), 0
+// CHECK: [[RETVAL0:%.*]] = copy_value [[BORROWED_CALL_EXT0]] : $U
+// CHECK: [[BORROWED_CALL_EXT1:%.*]] = tuple_extract [[BORROWED_CALL]] : $(U, U), 1
+// CHECK: [[RETVAL1:%.*]] = copy_value [[BORROWED_CALL_EXT1]] : $U
+// CHECK: end_borrow [[BORROWED_CALL]]
+// CHECK: [[RETVAL:%.*]] = tuple ([[RETVAL0]] : $U, [[RETVAL1]] : $U)
+// CHECK: return [[RETVAL]]
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen16OpaqueTupleClassC8inAndOut1xx_xtx_xt_tFAA0dF0CAdExx_tFTV'
+
+// Test vtables - StillOpaqueClass
+// ---
+// CHECK-LABEL: sil private @$S20opaque_values_silgen16StillOpaqueClassC24variantOptionalityTuples1xx_xm_xxcttx_xm_xxcttSg_tFAA0eF0CAdeFx_xm_xxctt_tFTV : $@convention(method) <T> (@in_guaranteed T, @thick T.Type, @guaranteed @callee_guaranteed (@in_guaranteed T) -> @out T, @guaranteed StillOpaqueClass<T>) -> @out Optional<(T, (@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))> {
+// CHECK: bb0([[ARG0:%.*]] : $T, [[ARG1:%.*]] : $@thick T.Type, [[ARG2:%.*]] : $@callee_guaranteed (@in_guaranteed T) -> @out T, [[ARG3:%.*]] : $StillOpaqueClass<T>):
+// CHECK: [[TELEM0:%.*]] = tuple ([[ARG1]] : $@thick T.Type, [[ARG2]] : $@callee_guaranteed (@in_guaranteed T) -> @out T)
+// CHECK: [[TELEM1:%.*]] = tuple ([[ARG0]] : $T, [[TELEM0]] : $(@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))
+// CHECK: [[ENUMOPT0:%.*]] = enum $Optional<(T, (@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))>, #Optional.some!enumelt.1, [[TELEM1]] : $(T, (@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))
+// CHECK: [[APPLY:%.*]] = apply {{.*}}<T>([[ENUMOPT0]], [[ARG3]]) : $@convention(method) <τ_0_0> (@in_guaranteed Optional<(τ_0_0, (@thick τ_0_0.Type, @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_0_0))>, @guaranteed StillOpaqueClass<τ_0_0>) -> (@out τ_0_0, @thick τ_0_0.Type, @owned @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_0_0)
+// CHECK: [[BORROWED_T:%.*]] = begin_borrow [[APPLY]]
+// CHECK: [[BORROWED_T_EXT0:%.*]] = tuple_extract [[BORROWED_T]] : $(T, @thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T), 0
+// CHECK: [[RETVAL0:%.*]] = copy_value [[BORROWED_T_EXT0]]
+// CHECK: [[BORROWED_T_EXT1:%.*]] = tuple_extract [[BORROWED_T]] : $(T, @thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T), 1
+// CHECK: [[BORROWED_T_EXT2:%.*]] = tuple_extract [[BORROWED_T]] : $(T, @thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T), 2
+// CHECK: [[RETVAL1:%.*]] = copy_value [[BORROWED_T_EXT2]]
+// CHECK: end_borrow [[BORROWED_T]]
+// CHECK: [[RETTUPLE0:%.*]] = tuple ([[BORROWED_T_EXT1]] : $@thick T.Type, [[RETVAL1]] : $@callee_guaranteed (@in_guaranteed T) -> @out T)
+// CHECK: [[RETTUPLE1:%.*]] = tuple ([[RETVAL0]] : $T, [[RETTUPLE0]] : $(@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))
+// CHECK: [[RETVAL:%.*]] = enum $Optional<(T, (@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))>, #Optional.some!enumelt.1, [[RETTUPLE1]] : $(T, (@thick T.Type, @callee_guaranteed (@in_guaranteed T) -> @out T))
+// CHECK: return [[RETVAL]]
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen16StillOpaqueClassC24variantOptionalityTuples1xx_xm_xxcttx_xm_xxcttSg_tFAA0eF0CAdeFx_xm_xxctt_tFTV'
+
+
+// part of s280_convExistTrivial: conversion between existential types - reabstraction thunk
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S20opaque_values_silgen1P_pAA13TrivialStructVIegnd_AA2P2_pAaE_pIegnr_TR : $@convention(thin) (@in_guaranteed P2, @guaranteed @callee_guaranteed (@in_guaranteed P) -> TrivialStruct) -> @out P2 {
+// CHECK: bb0([[ARG0:%.*]] : $P2, [[ARG1:%.*]] : $@callee_guaranteed (@in_guaranteed P) -> TrivialStruct):
+// CHECK: [[OPENED_ARG:%.*]] = open_existential_value [[ARG]] : $P2 to $@opened({{.*}}) P2
+// CHECK: [[COPIED_VAL:%.*]] = copy_value [[OPENED_ARG]]
+// CHECK: [[INIT_P:%.*]] = init_existential_value [[COPIED_VAL]] : $@opened({{.*}}) P2, $@opened({{.*}}) P2, $P
+// CHECK: [[BORROWED_INIT_P:%.*]] = begin_borrow [[INIT_P]]
+// CHECK: [[APPLY_P:%.*]] = apply [[ARG1]]([[BORROWED_INIT_P]]) : $@callee_guaranteed (@in_guaranteed P) -> TrivialStruct
+// CHECK: [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $P2
+// CHECK: end_borrow [[BORROWED_INIT_P]]
+// CHECK-NOT: destroy_value [[ARG0]]
+// CHECK: return [[RETVAL]] : $P2
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen1P_pAA13TrivialStructVIegnd_AA2P2_pAaE_pIegnr_TR'
+
+// part of s290_convOptExistTriv: conversion between existential types - reabstraction thunk - optionals case
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S20opaque_values_silgen1P_pSgAA13TrivialStructVIegnd_AESgAA2P2_pIegyr_TR : $@convention(thin) (Optional<TrivialStruct>, @guaranteed @callee_guaranteed (@in_guaranteed Optional<P>) -> TrivialStruct) -> @out P2 {
+// CHECK: bb0([[ARG0:%.*]] : $Optional<TrivialStruct>, [[ARG1:%.*]] : $@callee_guaranteed (@in_guaranteed Optional<P>) -> TrivialStruct):
+// CHECK: switch_enum [[ARG0]] : $Optional<TrivialStruct>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb1:
+// CHECK: [[ONONE:%.*]] = enum $Optional<P>, #Optional.none!enumelt
+// CHECK: br bb3([[ONONE]] : $Optional<P>)
+// CHECK: bb2([[OSOME:%.*]] : $TrivialStruct):
+// CHECK: [[INIT_S:%.*]] = init_existential_value [[OSOME]] : $TrivialStruct, $TrivialStruct, $P
+// CHECK: [[ENUM_S:%.*]] = enum $Optional<P>, #Optional.some!enumelt.1, [[INIT_S]] : $P
+// CHECK: br bb3([[ENUM_S]] : $Optional<P>)
+// CHECK: bb3([[OPT_S:%.*]] : $Optional<P>):
+// CHECK: [[BORROWED_OPT_S:%.*]] = begin_borrow [[OPT_S]]
+// CHECK: [[APPLY_P:%.*]] = apply [[ARG1]]([[BORROWED_OPT_S]]) : $@callee_guaranteed (@in_guaranteed Optional<P>) -> TrivialStruct
+// CHECK: [[RETVAL:%.*]] = init_existential_value [[APPLY_P]] : $TrivialStruct, $TrivialStruct, $P2
+// CHECK: return [[RETVAL]] : $P2
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen1P_pSgAA13TrivialStructVIegnd_AESgAA2P2_pIegyr_TR'
+
+// Test array initialization - we are still (somewhat) using addresses
+// ---
+// CHECK-LABEL: sil @$S20opaque_values_silgen21s020_______callVarArgyyF : $@convention(thin) () -> () {
+// CHECK: %[[APY:.*]] = apply %{{.*}}<Any>(%{{.*}}) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer)
+// CHECK: %[[BRW:.*]] = begin_borrow %[[APY]]
+// CHECK: %[[TPL:.*]] = tuple_extract %[[BRW]] : $(Array<Any>, Builtin.RawPointer), 1
+// CHECK: end_borrow %[[BRW]] from %[[APY]] : $(Array<Any>, Builtin.RawPointer), $(Array<Any>, Builtin.RawPointer)
+// CHECK: destroy_value %[[APY]]
+// CHECK: %[[PTR:.*]] = pointer_to_address %[[TPL]] : $Builtin.RawPointer to [strict] $*Any
+// CHECK: [[IOPAQUE:%.*]] = init_existential_value %{{.*}} : $Int, $Int, $Any
+// CHECK: store [[IOPAQUE]] to [init] %[[PTR]] : $*Any
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s020_______callVarArgyyF'
+public func s020_______callVarArg() {
+ s010_hasVarArg(3)
+}
+
+// Test emitSemanticStore.
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s030______assigninoutyyxz_xtlF : $@convention(thin) <T> (@inout T, @in_guaranteed T) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $*T, [[ARG1:%.*]] : $T):
+// CHECK: [[CPY:%.*]] = copy_value [[ARG1]] : $T
+// CHECK: [[READ:%.*]] = begin_access [modify] [unknown] [[ARG0]] : $*T
+// CHECK: assign [[CPY]] to [[READ]] : $*T
+// CHECK-NOT: destroy_value [[ARG1]] : $T
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s030______assigninoutyyxz_xtlF'
+func s030______assigninout<T>(_ a: inout T, _ b: T) {
+ a = b
+}
+
+// Test that we no longer use copy_addr or tuple_element_addr when copy by value is possible
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s040___tupleReturnIntyS2i_xt_tlF : $@convention(thin) <T> (Int, @in_guaranteed T) -> Int {
+// CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $T):
+// CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]]
+// CHECK: [[TPL:%.*]] = tuple ([[ARG0]] : $Int, [[ARG1_COPY]] : $T)
+// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[TPL]] : $(Int, T)
+// CHECK: [[CPY:%.*]] = copy_value [[BORROWED_ARG1]] : $(Int, T)
+// CHECK: [[BORROWED_CPY:%.*]] = begin_borrow [[CPY]]
+// CHECK: [[INT:%.*]] = tuple_extract [[BORROWED_CPY]] : $(Int, T), 0
+// CHECK: [[GEN:%.*]] = tuple_extract [[BORROWED_CPY]] : $(Int, T), 1
+// CHECK: [[COPY_GEN:%.*]] = copy_value [[GEN]]
+// CHECK: destroy_value [[COPY_GEN]]
+// CHECK: end_borrow [[BORROWED_CPY]] from [[CPY]]
+// CHECK: destroy_value [[CPY]]
+// CHECK: end_borrow [[BORROWED_ARG1]] from [[TPL]] : $(Int, T), $(Int, T)
+// CHECK: destroy_value [[TPL]] : $(Int, T)
+// CHECK: return [[INT]]
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s040___tupleReturnIntyS2i_xt_tlF'
+func s040___tupleReturnInt<T>(_ x: (Int, T)) -> Int {
+ let y = x.0
+ return y
+}
+
+// Test returning an opaque tuple of tuples.
+// ---
+// CHECK-LABEL: sil hidden [noinline] @$S20opaque_values_silgen21s050______multiResultyx_x_xttxlF : $@convention(thin) <T> (@in_guaranteed T) -> (@out T, @out T, @out T) {
+// CHECK: bb0(%0 : $T):
+// CHECK: %[[CP1:.*]] = copy_value %{{.*}} : $T
+// CHECK: %[[CP2:.*]] = copy_value %{{.*}} : $T
+// CHECK: %[[CP3:.*]] = copy_value %{{.*}} : $T
+// CHECK-NOT: destroy_value %0 : $T
+// CHECK: %[[TPL:.*]] = tuple (%[[CP1]] : $T, %[[CP2]] : $T, %[[CP3]] : $T)
+// CHECK: return %[[TPL]] : $(T, T, T)
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s050______multiResultyx_x_xttxlF'
+@inline(never)
+func s050______multiResult<T>(_ t: T) -> (T, (T, T)) {
+ return (t, (t, t))
+}
+
+// Test returning an opaque tuple of tuples as a concrete tuple.
+// ---
+// CHECK-LABEL: sil @$S20opaque_values_silgen21s060__callMultiResult1iSi_Si_SittSi_tF : $@convention(thin) (Int) -> (Int, Int, Int) {
+// CHECK: bb0(%0 : $Int):
+// CHECK: %[[FN:.*]] = function_ref @$S20opaque_values_silgen21s050______multiResultyx_x_xttxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
+// CHECK: %[[TPL:.*]] = apply %[[FN]]<Int>(%0) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
+// CHECK: %[[I1:.*]] = tuple_extract %[[TPL]] : $(Int, Int, Int), 0
+// CHECK: %[[I2:.*]] = tuple_extract %[[TPL]] : $(Int, Int, Int), 1
+// CHECK: %[[I3:.*]] = tuple_extract %[[TPL]] : $(Int, Int, Int), 2
+// CHECK: %[[R:.*]] = tuple (%[[I1]] : $Int, %[[I2]] : $Int, %[[I3]] : $Int)
+// CHECK: return %[[R]] : $(Int, Int, Int)
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s060__callMultiResult1iSi_Si_SittSi_tF'
+public func s060__callMultiResult(i: Int) -> (Int, (Int, Int)) {
+ return s050______multiResult(i)
+}
+
+// SILGen, prepareArchetypeCallee. Materialize a
+// non-class-constrainted self from a class-constrained archetype.
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s070__materializeSelf1tyx_tRlzCAA3FooRzlF : $@convention(thin) <T where T : AnyObject, T : Foo> (@guaranteed T) -> () {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $T, #Foo.foo!1 : <Self where Self : Foo> (Self) -> () -> () : $@convention(witness_method: Foo) <τ_0_0 where τ_0_0 : Foo> (@in_guaranteed τ_0_0) -> ()
+// CHECK: apply [[WITNESS_METHOD]]<T>([[ARG]]) : $@convention(witness_method: Foo) <τ_0_0 where τ_0_0 : Foo> (@in_guaranteed τ_0_0) -> ()
+// CHECK-NOT: destroy_value [[ARG]] : $T
+// CHECK: return %{{[0-9]+}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s070__materializeSelf1tyx_tRlzCAA3FooRzlF'
+func s070__materializeSelf<T: Foo>(t: T) where T: AnyObject {
+ t.foo()
+}
+
+// Test open existential with opaque values
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s080______________bar1pSiAA1P_p_tF : $@convention(thin) (@in_guaranteed P) -> Int {
+// CHECK: bb0([[ARG:%.*]] : $P):
+// CHECK: [[OPENED_ARG:%.*]] = open_existential_value [[ARG]] : $P to $@opened
+// CHECK: [[WITNESS_FUNC:%.*]] = witness_method $@opened
+// CHECK: [[RESULT:%.*]] = apply [[WITNESS_FUNC]]<{{.*}}>([[OPENED_ARG]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int
+// CHECK-NOT: destroy_value [[ARG]] : $P
+// CHECK: return [[RESULT]] : $Int
+func s080______________bar(p: P) -> Int {
+ return p.x
+}
+
+// Test OpaqueTypeLowering copyValue and destroyValue.
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s090___________calleryxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK-NOT: copy_value
+// CHECK: [[RESULT:%.*]] = apply {{%.*}}<T>([[ARG]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+// CHECK-NOT: destroy_value [[ARG]] : $T
+// CHECK: return %{{.*}} : $T
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s090___________calleryxxlF'
+func s090___________caller<T>(_ t: T) -> T {
+ return s090___________caller(t)
+}
+
+// Test a simple opaque parameter and return value.
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s100_________identityyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] : $T
+// CHECK-NOT: destroy_value [[ARG]] : $T
+// CHECK: return [[COPY_ARG]] : $T
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s100_________identityyxxlF'
+func s100_________identity<T>(_ t: T) -> T {
+ return t
+}
+
+// Test a guaranteed opaque parameter.
+// ---
+// CHECK-LABEL: sil private [transparent] [thunk] @$S20opaque_values_silgen21s110___GuaranteedSelfVAA3FooA2aDP3fooyyFTW : $@convention(witness_method: Foo) (@in_guaranteed s110___GuaranteedSelf) -> () {
+// CHECK: bb0(%0 : $s110___GuaranteedSelf):
+// CHECK: %[[F:.*]] = function_ref @$S20opaque_values_silgen21s110___GuaranteedSelfV3fooyyF : $@convention(method) (s110___GuaranteedSelf) -> ()
+// CHECK: apply %[[F]](%0) : $@convention(method) (s110___GuaranteedSelf) -> ()
+// CHECK: return
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s110___GuaranteedSelfVAA3FooA2aDP3fooyyFTW'
+struct s110___GuaranteedSelf : Foo {
+ func foo() {}
+}
+
+// Tests a corner case wherein we used to do a temporary and return a pointer to T instead of T
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s120______returnValueyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[COPY_ARG1:%.*]] = copy_value [[ARG]] : $T
+// CHECK: [[BORROWED_ARG2:%.*]] = begin_borrow [[COPY_ARG1]]
+// CHECK: [[COPY_ARG2:%.*]] = copy_value [[BORROWED_ARG2]] : $T
+// CHECK: end_borrow [[BORROWED_ARG2]] from [[COPY_ARG1]]
+// CHECK: return [[COPY_ARG2]] : $T
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s120______returnValueyxxlF'
+func s120______returnValue<T>(_ x: T) -> T {
+ let y = x
+ return y
+}
+
+// Tests Optional initialization by value
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s130_____________wrapyxSgxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out Optional<T> {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] : $T
+// CHECK: [[OPTIONAL_ARG:%.*]] = enum $Optional<T>, #Optional.some!enumelt.1, [[COPY_ARG]] : $T
+// CHECK-NOT: destroy_value [[ARG]] : $T
+// CHECK: return [[OPTIONAL_ARG]] : $Optional<T>
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s130_____________wrapyxSgxlF'
+func s130_____________wrap<T>(_ x: T) -> T? {
+ return x
+}
+
+// Tests For-each statements
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s140______forEachStmtyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[PROJ_BOX_ARG:%.*]] = project_box %{{.*}} : ${ var IndexingIterator<Range<Int>> }
+// CHECK: [[APPLY_ARG1:%.*]] = apply
+// CHECK-NOT: alloc_stack $Int
+// CHECK-NOT: store [[APPLY_ARG1]] to [trivial]
+// CHECK-NOT: alloc_stack $Range<Int>
+// CHECK-NOT: dealloc_stack
+// CHECK: [[APPLY_ARG2:%.*]] = apply %{{.*}}<Range<Int>>
+// CHECK: store [[APPLY_ARG2]] to [trivial] [[PROJ_BOX_ARG]]
+// CHECK: br bb1
+// CHECK: bb1:
+// CHECK-NOT: alloc_stack $Optional<Int>
+// CHECK: [[APPLY_ARG3:%.*]] = apply %{{.*}}<Range<Int>>
+// CHECK-NOT: dealloc_stack
+// CHECK: switch_enum [[APPLY_ARG3]]
+// CHECK: bb2:
+// CHECK: br bb3
+// CHECK: bb3:
+// CHECK: return %{{.*}} : $()
+// CHECK: bb4([[ENUM_ARG:%.*]] : $Int):
+// CHECK-NOT: unchecked_enum_data
+// CHECK: br bb1
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s140______forEachStmtyyF'
+func s140______forEachStmt() {
+ for _ in 1..<42 {
+ }
+}
+
+func s150___________anyArg(_: Any) {}
+
+// Tests init of opaque existentials
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s160_______callAnyArgyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[INT_TYPE:%.*]] = metatype $@thin Int.Type
+// CHECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Int2048, 42
+// CHECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[INT_ARG]] : $Int, $Int, $Any
+// CHECK: apply %{{.*}}([[INIT_OPAQUE]]) : $@convention(thin) (@in_guaranteed Any) -> ()
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s160_______callAnyArgyyF'
+func s160_______callAnyArg() {
+ s150___________anyArg(42)
+}
+
+// Tests unconditional_checked_cast for opaque values
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s170____force_convertxylF : $@convention(thin) <T> () -> @out T {
+// CHECK: bb0:
+// CHECK-NOT: alloc_stack
+// CHECK: [[INT_TYPE:%.*]] = metatype $@thin Int.Type
+// CHECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Int2048, 42
+// CHECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value [[INT_ARG]] : $Int to $T
+// CHECK: [[CAST_BORROW:%.*]] = begin_borrow [[INT_CAST]] : $T
+// CHECK: [[RETURN_VAL:%.*]] = copy_value [[CAST_BORROW]] : $T
+// CHECK: end_borrow [[CAST_BORROW]] from [[INT_CAST]] : $T, $T
+// CHECK: destroy_value [[INT_CAST]] : $T
+// CHECK: return [[RETURN_VAL]] : $T
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s170____force_convertxylF'
+func s170____force_convert<T>() -> T {
+ let x : T = 42 as! T
+ return x
+}
+
+// Tests supporting function for s190___return_foo_var - cast and return of protocol
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s180_______return_fooAA3Foo_pyF : $@convention(thin) () -> @out Foo {
+// CHECK: bb0:
+// CHECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Int2048, 42
+// CHECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value [[INT_ARG]] : $Int to $Foo
+// CHECK: return [[INT_CAST]] : $Foo
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s180_______return_fooAA3Foo_pyF'
+func s180_______return_foo() -> Foo {
+ return 42 as! Foo
+}
+var foo_var : Foo = s180_______return_foo()
+
+// Tests return of global variables by doing a load of copy
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s190___return_foo_varAA3Foo_pyF : $@convention(thin) () -> @out Foo {
+// CHECK: bb0:
+// CHECK: [[GLOBAL:%.*]] = global_addr {{.*}} : $*Foo
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*Foo
+// CHECK: [[LOAD_GLOBAL:%.*]] = load [copy] [[READ]] : $*Foo
+// CHECK: return [[LOAD_GLOBAL]] : $Foo
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s190___return_foo_varAA3Foo_pyF'
+func s190___return_foo_var() -> Foo {
+ return foo_var
+}
+
+// Tests deinit of opaque existentials
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s200______use_foo_varyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[GLOBAL:%.*]] = global_addr {{.*}} : $*Foo
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL]] : $*Foo
+// CHECK: [[LOAD_GLOBAL:%.*]] = load [copy] [[READ]] : $*Foo
+// CHECK: [[BORROW:%.*]] = begin_borrow [[LOAD_GLOBAL]] : $Foo
+// CHECK: [[OPEN_VAR:%.*]] = open_existential_value [[BORROW]] : $Foo
+// CHECK: [[WITNESS:%.*]] = witness_method $@opened
+// CHECK: apply [[WITNESS]]
+// CHECK: end_borrow [[BORROW]]
+// CHECK: destroy_value [[LOAD_GLOBAL]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s200______use_foo_varyyF'
+func s200______use_foo_var() {
+ foo_var.foo()
+}
+
+// Tests composition erasure of opaque existentials + copy into of opaques
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s210______compErasureys5Error_psAC_AA3FoopF : $@convention(thin) (@in_guaranteed Error & Foo) -> @owned Error {
+// CHECK: bb0([[ARG:%.*]] : $Error & Foo):
+// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_value [[ARG]] : $Error & Foo to $@opened({{.*}}) Error & Foo
+// CHECK: [[EXIST_BOX:%.*]] = alloc_existential_box $Error, $@opened({{.*}}) Error & Foo
+// CHECK: [[PROJ_BOX:%.*]] = project_existential_box $@opened({{.*}}) Error & Foo in [[EXIST_BOX]]
+// CHECK: [[COPY_OPAQUE:%.*]] = copy_value [[OPAQUE_ARG]] : $@opened({{.*}}) Error & Foo
+// CHECK: store [[COPY_OPAQUE]] to [init] [[PROJ_BOX]] : $*@opened({{.*}}) Error & Foo
+// CHECK-NOT: destroy_value [[ARG]] : $Error & Foo
+// CHECK: return [[EXIST_BOX]] : $Error
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s210______compErasureys5Error_psAC_AA3FoopF'
+func s210______compErasure(_ x: Foo & Error) -> Error {
+ return x
+}
+
+// Tests that existential boxes can contain opaque types
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s220_____openExistBoxySSs5Error_pF : $@convention(thin) (@guaranteed Error) -> @owned String {
+// CHECK: bb0([[ARG:%.*]] : $Error):
+// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_box_value [[ARG]] : $Error to $@opened({{.*}}) Error
+// CHECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}) Error
+// CHECK: store_borrow [[OPAQUE_ARG]] to [[ALLOC_OPEN]]
+// CHECK: dealloc_stack [[ALLOC_OPEN]]
+// CHECK-NOT: destroy_value [[ARG]] : $Error
+// CHECK: return {{.*}} : $String
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s220_____openExistBoxySSs5Error_pF'
+func s220_____openExistBox(_ x: Error) -> String {
+ return x._domain
+}
+
+// Tests conditional value casts and correspondingly generated reabstraction thunk
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s230______condFromAnyyyypF : $@convention(thin) (@in_guaranteed Any) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Any):
+// CHECK: [[COPY__ARG:%.*]] = copy_value [[ARG]]
+// CHECK: checked_cast_value_br [[COPY__ARG]] : $Any to $@callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int), bb2, bb1
+// CHECK: bb2([[THUNK_PARAM:%.*]] : $@callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)):
+// CHECK: [[THUNK_REF:%.*]] = function_ref @{{.*}} : $@convention(thin) (Int, Int, Int, Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)) -> (Int, Int, Int, Int, Int)
+// CHECK: partial_apply [callee_guaranteed] [[THUNK_REF]]([[THUNK_PARAM]])
+// CHECK: bb6:
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s230______condFromAnyyyypF'
+func s230______condFromAny(_ x: Any) {
+ if let f = x as? (Int, (Int, (Int, Int)), Int) -> (Int, (Int, (Int, Int)), Int) {
+ _ = f(24, (4,(2, 42)), 42)
+ }
+}
+
+// Tests LValue of error types / existential boxes
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s240_____propOfLValueySSs5Error_pF : $@convention(thin) (@guaranteed Error) -> @owned String {
+// CHECK: bb0([[ARG:%.*]] : $Error):
+// CHECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var Error }
+// CHECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: store [[COPY_ARG]] to [init] [[PROJ_BOX]]
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*Error
+// CHECK: [[LOAD_BOX:%.*]] = load [copy] [[READ]]
+// CHECK: [[OPAQUE_ARG:%.*]] = open_existential_box [[LOAD_BOX]] : $Error to $*@opened({{.*}}) Error
+// CHECK: [[LOAD_OPAQUE:%.*]] = load [copy] [[OPAQUE_ARG]]
+// CHECK: [[ALLOC_OPEN:%.*]] = alloc_stack $@opened({{.*}}) Error
+// CHECK: store [[LOAD_OPAQUE]] to [init] [[ALLOC_OPEN]]
+// CHECK: [[RET_VAL:%.*]] = apply {{.*}}<@opened({{.*}}) Error>([[ALLOC_OPEN]])
+// CHECK: return [[RET_VAL]] : $String
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s240_____propOfLValueySSs5Error_pF'
+func s240_____propOfLValue(_ x: Error) -> String {
+ var x = x
+ return x._domain
+}
+
+// Tests Implicit Value Construction under Opaque value mode
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s250_________testBoxTyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[BOX_MTYPE:%.*]] = metatype $@thin Box<Int>.Type
+// CHECK: [[MTYPE:%.*]] = metatype $@thin Int.Type
+// CHECK: [[INTLIT:%.*]] = integer_literal $Builtin.Int2048, 42
+// CHECK: [[AINT:%.*]] = apply {{.*}}([[INTLIT]], [[MTYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+// CHECK: apply {{.*}}<Int>([[AINT]], [[BOX_MTYPE]]) : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Box<τ_0_0>.Type) -> @out Box<τ_0_0>
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s250_________testBoxTyyF'
+func s250_________testBoxT() {
+ let _ = Box(t: 42)
+}
+
+// Tests Address only enums
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s260_______AOnly_enumyyAA17AddressOnlyStructVF : $@convention(thin) (AddressOnlyStruct) -> () {
+// CHECK: bb0([[ARG:%.*]] : $AddressOnlyStruct):
+// CHECK: [[MTYPE1:%.*]] = metatype $@thin AddressOnlyEnum.Type
+// CHECK: [[APPLY1:%.*]] = apply {{.*}}([[MTYPE1]]) : $@convention(thin) (@thin AddressOnlyEnum.Type) -> @owned @callee_guaranteed (@in_guaranteed EmptyP) -> @out AddressOnlyEnum
+// CHECK: destroy_value [[APPLY1]]
+// CHECK: [[MTYPE2:%.*]] = metatype $@thin AddressOnlyEnum.Type
+// CHECK: [[ENUM1:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.nought!enumelt
+// CHECK: [[MTYPE3:%.*]] = metatype $@thin AddressOnlyEnum.Type
+// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[ARG]] : $AddressOnlyStruct, $AddressOnlyStruct, $EmptyP
+// CHECK: [[ENUM2:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.mere!enumelt.1, [[INIT_OPAQUE]] : $EmptyP
+// CHECK: destroy_value [[ENUM2]]
+// CHECK: [[MTYPE4:%.*]] = metatype $@thin AddressOnlyEnum.Type
+// CHECK: [[ENUM3:%.*]] = enum $AddressOnlyEnum, #AddressOnlyEnum.phantom!enumelt.1, [[ARG]] : $AddressOnlyStruct
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s260_______AOnly_enumyyAA17AddressOnlyStructVF'
+func s260_______AOnly_enum(_ s: AddressOnlyStruct) {
+ _ = AddressOnlyEnum.mere
+
+ _ = AddressOnlyEnum.nought
+
+ _ = AddressOnlyEnum.mere(s)
+
+ _ = AddressOnlyEnum.phantom(s)
+}
+
+// Tests InjectOptional for opaque value types + conversion of opaque structs
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s270_convOptAnyStructyyAA0gH0VADSgcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct) -> () {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (@in_guaranteed Optional<AnyStruct>, @guaranteed @callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct) -> @out Optional<AnyStruct>
+// CHECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out Optional<AnyStruct>
+// CHECK-NOT: destroy_value [[ARG]] : $@callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s270_convOptAnyStructyyAA0gH0VADSgcF'
+func s270_convOptAnyStruct(_ a1: @escaping (AnyStruct?) -> AnyStruct) {
+ let _: (AnyStruct?) -> AnyStruct? = a1
+}
+
+// Tests conversion between existential types
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s280_convExistTrivialyyAA0G6StructVAA1P_pcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed P) -> TrivialStruct) -> () {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed (@in_guaranteed P) -> TrivialStruct):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (@in_guaranteed P2, @guaranteed @callee_guaranteed (@in_guaranteed P) -> TrivialStruct) -> @out P2
+// CHECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (@in_guaranteed P2) -> @out P2
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s280_convExistTrivialyyAA0G6StructVAA1P_pcF'
+func s280_convExistTrivial(_ s: @escaping (P) -> TrivialStruct) {
+ let _: (P2) -> P2 = s
+}
+
+// Tests conversion between existential types - optionals case
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s290_convOptExistTrivyyAA13TrivialStructVAA1P_pSgcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed Optional<P>) -> TrivialStruct) -> () {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed (@in_guaranteed Optional<P>) -> TrivialStruct):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (Optional<TrivialStruct>, @guaranteed @callee_guaranteed (@in_guaranteed Optional<P>) -> TrivialStruct) -> @out P2
+// CHECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (Optional<TrivialStruct>) -> @out P2
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s290_convOptExistTrivyyAA13TrivialStructVAA1P_pSgcF'
+func s290_convOptExistTriv(_ s: @escaping (P?) -> TrivialStruct) {
+ let _: (TrivialStruct?) -> P2 = s
+}
+
+// Tests corner-case: reabstraction of an empty tuple to any
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s300__convETupleToAnyyyyycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> () {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> ()):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Any
+// CHECK: destroy_value [[PAPPLY]] : $@callee_guaranteed () -> @out Any
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s300__convETupleToAnyyyyycF'
+func s300__convETupleToAny(_ t: @escaping () -> ()) {
+ let _: () -> Any = t
+}
+
+// Tests corner-case: reabstraction of a non-empty tuple to any
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s310__convIntTupleAnyyySi_SitycF : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> () {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> (Int, Int)):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Any
+// CHECK: destroy_value [[PAPPLY]] : $@callee_guaranteed () -> @out Any
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s310__convIntTupleAnyyySi_SitycF'
+func s310__convIntTupleAny(_ t: @escaping () -> (Int, Int)) {
+ let _: () -> Any = t
+}
+
+// Tests translating and imploding into Any under opaque value mode
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s320__transImplodeAnyyyyypcF : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed Any) -> ()) -> () {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed (@in_guaranteed Any) -> ()):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[COPY_ARG]]) : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> ()) -> ()
+// CHECK: destroy_value [[PAPPLY]] : $@callee_guaranteed (Int, Int) -> ()
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s320__transImplodeAnyyyyypcF'
+func s320__transImplodeAny(_ t: @escaping (Any) -> ()) {
+ let _: ((Int, Int)) -> () = t
+}
+
+// Tests support for address only let closures under opaque value mode - they are not by-address anymore
+// ---
+// CHECK-LABEL: sil private @$S20opaque_values_silgen21s330___addrLetClosureyxxlFxyXEfU_xyXEfU_ : $@convention(thin) <T> (@in_guaranteed T) -> @out T {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]] : $T
+// CHECK: return [[COPY_ARG]] : $T
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s330___addrLetClosureyxxlFxyXEfU_xyXEfU_'
+func s330___addrLetClosure<T>(_ x:T) -> T {
+ return { { x }() }()
+}
+
+// Tests support for capture of a mutable opaque value type
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s340_______captureBoxyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var EmptyP }, var, name "mutableAddressOnly"
+// CHECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
+// CHECK: [[APPLY_FOR_BOX:%.*]] = apply %{{.*}}(%{{.*}}) : $@convention(method) (@thin AddressOnlyStruct.Type) -> AddressOnlyStruct
+// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[APPLY_FOR_BOX]] : $AddressOnlyStruct, $AddressOnlyStruct, $EmptyP
+// CHECK: store [[INIT_OPAQUE]] to [init] [[PROJ_BOX]] : $*EmptyP
+// CHECK: [[BORROW_BOX:%.*]] = begin_borrow [[ALLOC_OF_BOX]] : ${ var EmptyP }
+// CHECK: mark_function_escape [[PROJ_BOX]] : $*EmptyP
+// CHECK: apply %{{.*}}([[BORROW_BOX]]) : $@convention(thin) (@guaranteed { var EmptyP }) -> ()
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s340_______captureBoxyyF'
+func s340_______captureBox() {
+ var mutableAddressOnly: EmptyP = AddressOnlyStruct()
+
+ func captureEverything() {
+ _ = s100_________identity((mutableAddressOnly))
+ }
+
+ captureEverything()
+}
+
+// Tests support for if statements for opaque value(s) under new mode
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s350_______addrOnlyIf1xAA6EmptyP_pSb_tF : $@convention(thin) (Bool) -> @out EmptyP {
+// CHECK: bb0([[ARG:%.*]] : $Bool):
+// CHECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var EmptyP }, var
+// CHECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
+// CHECK: [[APPLY_FOR_BOX:%.*]] = apply %{{.*}}(%{{.*}}) : $@convention(method) (@thin AddressOnlyStruct.Type) -> AddressOnlyStruct
+// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[APPLY_FOR_BOX]] : $AddressOnlyStruct, $AddressOnlyStruct, $EmptyP
+// CHECK: store [[INIT_OPAQUE]] to [init] [[PROJ_BOX]] : $*EmptyP
+// CHECK: [[APPLY_FOR_BRANCH:%.*]] = apply %{{.*}}([[ARG]]) : $@convention(method) (Bool) -> Builtin.Int1
+// CHECK: cond_br [[APPLY_FOR_BRANCH]], bb2, bb1
+// CHECK: bb1:
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*EmptyP
+// CHECK: [[RETVAL1:%.*]] = load [copy] [[READ]] : $*EmptyP
+// CHECK: br bb3([[RETVAL1]] : $EmptyP)
+// CHECK: bb2:
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PROJ_BOX]] : $*EmptyP
+// CHECK: [[RETVAL2:%.*]] = load [copy] [[READ]] : $*EmptyP
+// CHECK: br bb3([[RETVAL2]] : $EmptyP)
+// CHECK: bb3([[RETVAL:%.*]] : $EmptyP):
+// CHECK: destroy_value [[ALLOC_OF_BOX]]
+// CHECK: return [[RETVAL]] : $EmptyP
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s350_______addrOnlyIf1xAA6EmptyP_pSb_tF'
+func s350_______addrOnlyIf(x: Bool) -> EmptyP {
+ var a : EmptyP = AddressOnlyStruct()
+
+ return x ? a : a
+}
+
+// Tests support for guards and indirect enums for opaque values
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s360________guardEnumyyAA08IndirectF0OyxGlF : $@convention(thin) <T> (@guaranteed IndirectEnum<T>) -> () {
+// CHECK: bb0([[ARG:%.*]] : $IndirectEnum<T>):
+// CHECK: [[COPY__ARG:%.*]] = copy_value [[ARG]]
+// CHECK: switch_enum [[COPY__ARG]] : $IndirectEnum<T>, case #IndirectEnum.Node!enumelt.1: [[NODE_BB:bb[0-9]+]], case #IndirectEnum.Nil!enumelt: [[NIL_BB:bb[0-9]+]]
+//
+// CHECK: [[NIL_BB]]:
+// CHECK: br [[NIL_TRAMPOLINE:bb[0-9]+]]
+//
+// CHECK: [[NIL_TRAMPOLINE]]:
+// CHECK: br [[EPILOG_BB:bb[0-9]+]]
+//
+// CHECK: [[NODE_BB]]([[EARG:%.*]] : $<τ_0_0> { var τ_0_0 } <T>):
+// CHECK: [[PROJ_BOX:%.*]] = project_box [[EARG]]
+// CHECK: [[LOAD_BOX:%.*]] = load [take] [[PROJ_BOX]] : $*T
+// CHECK: [[COPY_BOX:%.*]] = copy_value [[LOAD_BOX]] : $T
+// CHECK: destroy_value [[EARG]]
+// CHECK: br [[CONT_BB:bb[0-9]+]]
+//
+// CHECK: [[CONT_BB]]:
+// CHECK: destroy_value [[COPY_BOX]]
+// CHECK: br [[EPILOG_BB]]
+//
+// CHECK: [[EPILOG_BB]]:
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s360________guardEnumyyAA08IndirectF0OyxGlF'
+func s360________guardEnum<T>(_ e: IndirectEnum<T>) {
+ do {
+ guard case .Node(let x) = e else { return }
+ _ = x
+ }
+}
+
+// Tests contextual init() of opaque value types
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s370_____optToOptCastyxSgAClF : $@convention(thin) <T> (@in_guaranteed Optional<T>) -> @out Optional<T> {
+// CHECK: bb0([[ARG:%.*]] : $Optional<T>):
+// CHECK: [[COPY__ARG:%.*]] = copy_value [[ARG]]
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[COPY__ARG]] : $Optional<T>
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s370_____optToOptCastyxSgAClF'
+func s370_____optToOptCast<T>(_ x : T!) -> T? {
+ return x
+}
+
+// Tests casting optional opaques to optional opaques
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s380___contextualInityySiSgF : $@convention(thin) (Optional<Int>) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Optional<Int>):
+// CHECK: [[ALLOC_OF_BOX:%.*]] = alloc_box ${ var Optional<Int> }, var
+// CHECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
+// CHECK: store [[ARG]] to [trivial] [[PROJ_BOX]] : $*Optional<Int>
+// CHECK: destroy_value [[ALLOC_OF_BOX]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s380___contextualInityySiSgF'
+func s380___contextualInit(_ a : Int?) {
+ var x: Int! = a
+ _ = x
+}
+
+// Tests opaque call result types
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s390___addrCallResultyyxycSglF : $@convention(thin) <T> (@guaranteed Optional<@callee_guaranteed () -> @out T>) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Optional<@callee_guaranteed () -> @out T>):
+// CHECK: [[ALLOC_OF_BOX:%.*]] = alloc_box $<τ_0_0> { var Optional<τ_0_0> } <T>
+// CHECK: [[PROJ_BOX:%.*]] = project_box [[ALLOC_OF_BOX]]
+// CHECK: [[COPY__ARG:%.*]] = copy_value [[ARG]]
+// CHECK: [[SENUM:%.*]] = select_enum [[COPY__ARG]]
+// CHECK: cond_br [[SENUM]], bb3, bb1
+// CHECK: bb1:
+// CHECK: br bb2
+// CHECK: bb2:
+// CHECK: [[ONONE:%.*]] = enum $Optional<T>, #Optional.none!enumelt
+// CHECK: br bb4([[ONONE]] : $Optional<T>)
+// CHECK: bb4(%{{.*}} : $Optional<T>):
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s390___addrCallResultyyxycSglF'
+func s390___addrCallResult<T>(_ f: (() -> T)?) {
+ var x = f?()
+ _ = x
+}
+
+// Tests reabstraction / partial apply of protocols under opaque value mode
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s400______maybeCloneP1cyAA8Clonable_p_tF : $@convention(thin) (@in_guaranteed Clonable) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Clonable):
+// CHECK: [[OPEN_ARG:%.*]] = open_existential_value [[ARG]] : $Clonable
+// CHECK: [[APPLY_OPAQUE:%.*]] = apply %{{.*}}<@opened({{.*}}) Clonable>([[OPEN_ARG]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out Optional<τ_0_0>
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}<@opened({{.*}}) Clonable>([[APPLY_OPAQUE]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable>
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s400______maybeCloneP1cyAA8Clonable_p_tF'
+func s400______maybeCloneP(c: Clonable) {
+ let _: () -> Clonable? = c.maybeClone
+}
+
+// Tests global opaque values / subscript rvalues
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s410__globalRvalueGetyS2iF : $@convention(thin) (Int) -> Int {
+// CHECK: bb0([[ARG:%.*]] : $Int):
+// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$S20opaque_values_silgen16subscriptableGetAA013SubscriptableE0_pvp : $*SubscriptableGet
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]] : $*SubscriptableGet
+// CHECK: [[OPEN_ARG:%.*]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGet to $*@opened
+// CHECK: [[GET_OPAQUE:%.*]] = load [copy] [[OPEN_ARG]] : $*@opened
+// CHECK: [[RETVAL:%.*]] = apply %{{.*}}<@opened({{.*}}) SubscriptableGet>([[ARG]], [[GET_OPAQUE]]) : $@convention(witness_method: SubscriptableGet) <τ_0_0 where τ_0_0 : SubscriptableGet> (Int, @in_guaranteed τ_0_0) -> Int
+// CHECK: destroy_value [[GET_OPAQUE]]
+// CHECK: return [[RETVAL]] : $Int
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s410__globalRvalueGetyS2iF'
+func s410__globalRvalueGet(_ i : Int) -> Int {
+ return subscriptableGet[i]
+}
+
+// Tests global opaque values / subscript lvalues
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s420__globalLvalueGetyS2iF : $@convention(thin) (Int) -> Int {
+// CHECK: bb0([[ARG:%.*]] : $Int):
+// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @$S20opaque_values_silgen19subscriptableGetSetAA013SubscriptableeF0_pvp : $*SubscriptableGetSet
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]] : $*SubscriptableGetSet
+// CHECK: [[OPEN_ARG:%.*]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGetSet to $*@opened
+// CHECK: [[GET_OPAQUE:%.*]] = load [copy] [[OPEN_ARG]] : $*@opened
+// CHECK: [[RETVAL:%.*]] = apply %{{.*}}<@opened({{.*}}) SubscriptableGetSet>([[ARG]], [[GET_OPAQUE]]) : $@convention(witness_method: SubscriptableGetSet) <τ_0_0 where τ_0_0 : SubscriptableGetSet> (Int, @in_guaranteed τ_0_0) -> Int
+// CHECK: destroy_value [[GET_OPAQUE]]
+// CHECK: return [[RETVAL]] : $Int
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s420__globalLvalueGetyS2iF'
+func s420__globalLvalueGet(_ i : Int) -> Int {
+ return subscriptableGetSet[i]
+}
+
+// Tests tuple transformation
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s430_callUnreachableF1tyx_tlF : $@convention(thin) <T> (@in_guaranteed T) -> () {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[APPLY_T:%.*]] = apply %{{.*}}<((T) -> (), T)>() : $@convention(thin) <τ_0_0> () -> @out Optional<(Int, τ_0_0)>
+// CHECK: switch_enum [[APPLY_T]] : $Optional<(Int, (@callee_guaranteed (@in_guaranteed T) -> @out (), T))>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb2([[ENUMARG:%.*]] : $(Int, (@callee_guaranteed (@in_guaranteed T) -> @out (), T))):
+// CHECK: ([[TELEM0:%.*]], [[TELEM1:%.*]]) = destructure_tuple [[ENUMARG]] : $(Int, (@callee_guaranteed (@in_guaranteed T) -> @out (), T))
+// CHECK: ([[TELEM10:%.*]], [[TELEM11:%.*]]) = destructure_tuple [[TELEM1]] : $(@callee_guaranteed (@in_guaranteed T) -> @out (), T)
+// CHECK: [[PAPPLY:%.*]] = partial_apply [callee_guaranteed] %{{.*}}<T>([[TELEM10]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @out ()) -> ()
+// CHECK: [[NEWT0:%.*]] = tuple ([[PAPPLY]] : $@callee_guaranteed (@in_guaranteed T) -> (), [[TELEM11]] : $T)
+// CHECK: [[NEWT1:%.*]] = tuple ([[TELEM0]] : $Int, [[NEWT0]] : $(@callee_guaranteed (@in_guaranteed T) -> (), T))
+// CHECK: [[NEWENUM:%.*]] = enum $Optional<(Int, (@callee_guaranteed (@in_guaranteed T) -> (), T))>, #Optional.some!enumelt.1, [[NEWT1]] : $(Int, (@callee_guaranteed (@in_guaranteed T) -> (), T))
+// CHECK: br bb3([[NEWENUM]] : $Optional<(Int, (@callee_guaranteed (@in_guaranteed T) -> (), T))>)
+// CHECK: bb3([[ENUMIN:%.*]] : $Optional<(Int, (@callee_guaranteed (@in_guaranteed T) -> (), T))>):
+// CHECK: destroy_value [[ENUMIN]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s430_callUnreachableF1tyx_tlF'
+func s430_callUnreachableF<T>(t: T) {
+ let _: (Int, ((T) -> (), T))? = unreachableF()
+}
+
+// Further testing for conditional checked cast under opaque value mode - make sure we don't create a buffer for results
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s440__cleanupEmissionyyxlF : $@convention(thin) <T> (@in_guaranteed T) -> () {
+// CHECK: bb0([[ARG:%.*]] : $T):
+// CHECK: [[COPY_ARG:%.*]] = copy_value [[ARG]]
+// CHECK: checked_cast_value_br [[COPY_ARG]] : $T to $EmptyP, bb2, bb1
+//
+// CHECK: bb2([[PTYPE:%.*]] : $EmptyP):
+// CHECK: [[PSOME:%.*]] = enum $Optional<EmptyP>, #Optional.some!enumelt.1, [[PTYPE]] : $EmptyP
+// CHECK: br bb3([[PSOME]] : $Optional<EmptyP>)
+//
+// CHECK: bb3([[ENUMRES:%.*]] : $Optional<EmptyP>):
+// CHECK: switch_enum [[ENUMRES]] : $Optional<EmptyP>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+//
+// CHECK: [[NONE_BB]]:
+// CHECK: br [[NONE_TRAMPOLINE:bb[0-9]+]]
+//
+// CHECK: [[NONE_TRAMPOLINE]]:
+// CHECK: br [[EPILOG_BB:bb[0-9]+]]
+//
+// CHECK: [[SOME_BB]]([[ENUMRES2:%.*]] : $EmptyP):
+// CHECK: br [[CONT_BB:bb[0-9]+]]
+//
+// CHECK: [[CONT_BB]]:
+// CHECK: destroy_value [[ENUMRES2]]
+// CHECK: br [[EPILOG_BB]]
+//
+// CHECK: [[EPILOG_BB]]:
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s440__cleanupEmissionyyxlF'
+func s440__cleanupEmission<T>(_ x: T) {
+ guard let x2 = x as? EmptyP else { return }
+ _ = x2
+}
+
+// Test SILGenBuilder.loadCopy().
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s450__________lastValyxxd_tlF : $@convention(thin) <T> (@guaranteed Array<T>) -> @out T
+// CHECK: [[LOAD:%.*]] = load [copy] %{{.*}} : $*T
+// CHECK: return [[LOAD]] : $T
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s450__________lastValyxxd_tlF'
+func s450__________lastVal<T>(_ rest: T...) -> T {
+ var minValue: T
+ for value in rest {
+ minValue = value
+ }
+ return minValue
+}
+
+// Test SILGenFunction::emitPointerToPointer.
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s460______________foo1pSRyxGSPyxG_tlF : $@convention(thin) <Element> (UnsafePointer<Element>) -> UnsafeBufferPointer<Element> {
+// CHECK: [[F:%.*]] = function_ref @$Ss017_convertPointerToB8Argumentyq_xs01_B0RzsABR_r0_lF : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : _Pointer, τ_0_1 : _Pointer> (@in_guaranteed τ_0_0) -> @out τ_0_1
+// CHECK: apply [[F]]<UnsafePointer<Element>, UnsafePointer<Element>>(%0) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : _Pointer, τ_0_1 : _Pointer> (@in_guaranteed τ_0_0) -> @out τ_0_1
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s460______________foo1pSRyxGSPyxG_tlF'
+func s460______________foo<Element>(p: UnsafePointer<Element>) -> UnsafeBufferPointer<Element> {
+ return UnsafeBufferPointer(start: p, count: 1)
+}
+
+// Test emitNativeToCBridgedNonoptionalValue.
+// ---
+// CHECK-objc-LABEL: sil hidden @$S20opaque_values_silgen21s470________nativeToC7fromAnyyXlyp_tF : $@convention(thin) (@in_guaranteed Any) -> @owned AnyObject {
+// CHECK-objc bb0(%0 : $Any):
+// CHECK-objc [[BORROW:%.*]] = begin_borrow %0 : $Any
+// CHECK-objc [[SRC:%.*]] = copy_value [[BORROW]] : $Any
+// CHECK-objc [[OPEN:%.*]] = open_existential_opaque [[SRC]] : $Any to $@opened
+// CHECK-objc [[COPY:%.*]] = copy_value [[OPEN]] : $@opened
+// CHECK-objc [[F:%.*]] = function_ref @$Ss27_bridgeAnythingToObjectiveCyyXlxlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
+// CHECK-objc [[RET:%.*]] = apply [[F]]<@opened("{{.*}}") Any>([[COPY]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @owned AnyObject
+// CHECK-objc destroy_value [[SRC]] : $Any
+// CHECK-objc destroy_value %0 : $Any
+// CHECK-objc return [[RET]] : $AnyObject
+// CHECK-objc-LABEL: } // end sil function '$S20opaque_values_silgen21s470________nativeToC7fromAnyyXlyp_tF'
+#if _runtime(_ObjC)
+func s470________nativeToC(fromAny any: Any) -> AnyObject {
+ return any as AnyObject
+}
+#endif
+
+// Test emitOpenExistential.
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s480_________getError04someF0yps0F0_p_tF : $@convention(thin) (@guaranteed Error) -> @out Any {
+// CHECK: bb0([[ARG:%.*]] : $Error):
+// CHECK: [[VAL:%.*]] = open_existential_box_value [[ARG]] : $Error to $@opened("{{.*}}") Error
+// CHECK: [[COPY:%.*]] = copy_value [[VAL]] : $@opened("{{.*}}") Error
+// CHECK: [[ANY:%.*]] = init_existential_value [[COPY]] : $@opened("{{.*}}") Error, $@opened("{{.*}}") Error, $Any
+// CHECK-NOT: destroy_value [[ARG]] : $Error
+// CHECK: return [[ANY]] : $Any
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s480_________getError04someF0yps0F0_p_tF'
+func s480_________getError(someError: Error) -> Any {
+ return someError
+}
+
+// Test SILBuilder.createLoadBorrow.
+// ---
+// CHECK-LABEL: sil private @$S20opaque_values_silgen21s490_______loadBorrowyyF3FooL_V3foo3pos7ElementQzSg5IndexQz_tF : $@convention(method) <Elements where Elements : Collection> (@in_guaranteed Elements.Index, @inout Foo<Elements>) -> @out Optional<Elements.Element> {
+// CHECK: bb0([[ARG0:%.*]] : $Elements.Index, [[ARG1:%.*]] : $*Foo<Elements>):
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[ARG1]] : $*Foo<Elements>
+// CHECK: [[LOAD:%.*]] = load [copy] [[READ]] : $*Foo<Elements>
+// CHECK: end_access [[READ]] : $*Foo<Elements>
+// CHECK: [[BORROW_LOAD:%.*]] = begin_borrow [[LOAD]]
+// CHECK: [[EXTRACT:%.*]] = struct_extract [[BORROW_LOAD]] : $Foo<Elements>, #<abstract function>Foo._elements
+// CHECK: [[COPYELT:%.*]] = copy_value [[EXTRACT]] : $Elements
+// CHECK: [[COPYIDX:%.*]] = copy_value [[ARG0]] : $Elements.Index
+// CHECK: [[WT:%.*]] = witness_method $Elements, #Collection.subscript!getter.1 : <Self where Self : Collection> (Self) -> (Self.Index) -> Self.Element : $@convention(witness_method: Collection) <τ_0_0 where τ_0_0 : Collection> (@in_guaranteed τ_0_0.Index, @in_guaranteed τ_0_0) -> @out τ_0_0.Element
+// CHECK: [[RESULT:%.*]] = apply [[WT]]<Elements>([[COPYIDX]], [[COPYELT]]) : $@convention(witness_method: Collection) <τ_0_0 where τ_0_0 : Collection> (@in_guaranteed τ_0_0.Index, @in_guaranteed τ_0_0) -> @out τ_0_0.Element
+// CHECK: destroy_value [[COPYELT]] : $Elements
+// CHECK: [[ENUM_RESULT:%.*]] = enum $Optional<Elements.Element>, #Optional.some!enumelt.1, [[RESULT]] : $Elements.Element
+// CHECK: destroy_value [[LOAD]]
+// CHECK-NOT: destroy_value [[ARG0]] : $Elements.Index
+// CHECK: return [[ENUM_RESULT]] : $Optional<Elements.Element>
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s490_______loadBorrowyyF3FooL_V3foo3pos7ElementQzSg5IndexQz_tF'
+
+func s490_______loadBorrow() {
+ struct Foo<Elements : Collection> {
+ internal let _elements: Elements
+
+ public mutating func foo(pos: Elements.Index) -> Elements.Element? {
+ return _elements[pos]
+ }
+ }
+ var foo = Foo(_elements: [])
+ _ = foo.foo(pos: 1)
+}
+
+protocol ConvertibleToP {
+ func asP() -> P
+}
+
+// Test visitBindOptionalExpr
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s500_______getAnyHashyAA1P_pSgAA14ConvertibleToP_pSgF : $@convention(thin) (@in_guaranteed Optional<ConvertibleToP>) -> @out Optional<P> {
+// CHECK: bb0(%0 : $Optional<ConvertibleToP>):
+// CHECK: [[COPY:%.*]] = copy_value [[ARG]] : $Optional<ConvertibleToP>
+// CHECK: [[DATA:%.*]] = unchecked_enum_data [[COPY]] : $Optional<ConvertibleToP>, #Optional.some!enumelt.1
+// CHECK: [[BORROW_DATA:%.*]] = begin_borrow [[DATA]] : $ConvertibleToP
+// CHECK: [[VAL:%.*]] = open_existential_value [[BORROW_DATA]] : $ConvertibleToP to $@opened("{{.*}}") ConvertibleToP
+// CHECK: [[WT:%.*]] = witness_method $@opened("{{.*}}") ConvertibleToP, #ConvertibleToP.asP!1 : <Self where Self : ConvertibleToP> (Self) -> () -> P, [[VAL]] : $@opened("{{.*}}") ConvertibleToP : $@convention(witness_method: ConvertibleToP) <τ_0_0 where τ_0_0 : ConvertibleToP> (@in_guaranteed τ_0_0) -> @out P
+// CHECK: [[AS_P:%.*]] = apply [[WT]]<@opened("{{.*}}") ConvertibleToP>([[VAL]]) : $@convention(witness_method: ConvertibleToP) <τ_0_0 where τ_0_0 : ConvertibleToP> (@in_guaranteed τ_0_0) -> @out P
+// CHECK: [[ENUM:%.*]] = enum $Optional<P>, #Optional.some!enumelt.1, [[AS_P]] : $P
+// CHECK: destroy_value [[DATA]] : $ConvertibleToP
+// CHECK: br bb{{.*}}([[ENUM]] : $Optional<P>)
+// CHECK: // end sil function '$S20opaque_values_silgen21s500_______getAnyHashyAA1P_pSgAA14ConvertibleToP_pSgF'
+func s500_______getAnyHash(_ value: ConvertibleToP?) -> P? {
+ return value?.asP()
+}
+
+public protocol FooP {
+ func foo() -> Self
+}
+
+// Test emitting a protocol witness for a method (with @in_guaranteed self) on a dependent generic type.
+// ---
+// CHECK-LABEL: sil private [transparent] [thunk] @$S20opaque_values_silgen21s510_______OpaqueSelfVyxGAA4FooPA2aEP3fooxyFTW : $@convention(witness_method: FooP) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0> {
+// CHECK: bb0(%0 : $s510_______OpaqueSelf<τ_0_0>):
+// CHECK: [[FN:%.*]] = function_ref @$S20opaque_values_silgen21s510_______OpaqueSelfV3fooACyxGyF : $@convention(method) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0>
+// CHECK: [[RESULT:%.*]] = apply [[FN]]<τ_0_0>(%0) : $@convention(method) <τ_0_0> (@in_guaranteed s510_______OpaqueSelf<τ_0_0>) -> @out s510_______OpaqueSelf<τ_0_0>
+// CHECK: return [[RESULT]] : $s510_______OpaqueSelf<τ_0_0>
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s510_______OpaqueSelfVyxGAA4FooPA2aEP3fooxyFTW'
+struct s510_______OpaqueSelf<Base> : FooP {
+ var x: Base
+
+ func foo() -> s510_______OpaqueSelf<Base> {
+ return self
+ }
+}
+
+// Tests conditional value casts and correspondingly generated reabstraction thunk, with <T> types
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen21s999_____condTFromAnyyyyp_xtlF : $@convention(thin) <T> (@in_guaranteed Any, @in_guaranteed T) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Any, [[ARG1:%.*]] : $T):
+// CHECK: [[COPY__ARG:%.*]] = copy_value [[ARG]]
+// CHECK: checked_cast_value_br [[COPY__ARG]] : $Any to $@callee_guaranteed (@in_guaranteed (Int, T)) -> @out (Int, T), bb2, bb1
+// CHECK: bb2([[THUNK_PARAM:%.*]] : $@callee_guaranteed (@in_guaranteed (Int, T)) -> @out (Int, T)):
+// CHECK: [[THUNK_REF:%.*]] = function_ref @{{.*}} : $@convention(thin) <τ_0_0> (Int, @in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed (Int, τ_0_0)) -> @out (Int, τ_0_0)) -> (Int, @out τ_0_0)
+// CHECK: partial_apply [callee_guaranteed] [[THUNK_REF]]<T>([[THUNK_PARAM]])
+// CHECK: bb6:
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen21s999_____condTFromAnyyyyp_xtlF'
+func s999_____condTFromAny<T>(_ x: Any, _ y: T) {
+ if let f = x as? (Int, T) -> (Int, T) {
+ _ = f(42, y)
+ }
+}
+
+// Make sure that we insert a destroy of the box even though we used an Int type.
+// CHECK-LABEL: sil @$S20opaque_values_silgen22s020_______assignToVaryyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[Y_BOX:%.*]] = alloc_box ${ var Int }, var, name "y"
+// CHECK: [[PROJECT_Y_BOX:%.*]] = project_box [[Y_BOX]] : ${ var Int }, 0
+// CHECK: [[X_BOX:%.*]] = alloc_box ${ var Any }, var, name "x"
+// CHECK: [[PROJECT_X_BOX:%.*]] = project_box [[X_BOX]] : ${ var Any }, 0
+// CHECK: [[ACCESS_PROJECT_Y_BOX:%.*]] = begin_access [read] [unknown] [[PROJECT_Y_BOX]] : $*Int
+// CHECK: [[Y:%.*]] = load [trivial] [[ACCESS_PROJECT_Y_BOX]] : $*Int
+// CHECK: [[Y_ANY_FOR_X:%.*]] = init_existential_value [[Y]] : $Int, $Int, $Any
+// CHECK: store [[Y_ANY_FOR_X]] to [init] [[PROJECT_X_BOX]]
+// CHECK: [[ACCESS_PROJECT_Y_BOX:%.*]] = begin_access [read] [unknown] [[PROJECT_Y_BOX]] : $*Int
+// CHECK: [[Y:%.*]] = load [trivial] [[ACCESS_PROJECT_Y_BOX]] : $*Int
+// CHECK: [[Y_ANY_FOR_Z:%.*]] = init_existential_value [[Y]] : $Int, $Int, $Any
+// CHECK: destroy_value [[Y_ANY_FOR_Z]]
+// CEHCK: destroy_value [[X_BOX]]
+// CHECK: destroy_value [[Y_BOX]]
+// CHECK: } // end sil function '$S20opaque_values_silgen22s020_______assignToVaryyF'
+public func s020_______assignToVar() {
+ var y: Int = 3
+ var x: Any = y
+ let z: Any = y
+}
+
+// s250_________testBoxT continued Test Implicit Value Construction under Opaque value mode
+// ---
+// CHECK-LABEL: sil hidden @$S20opaque_values_silgen3BoxV1tACyxGx_tcfC : $@convention(method) <T> (@in T, @thin Box<T>.Type) -> @out Box<T> {
+// CHECK: bb0([[ARG0:%.*]] : $T, [[ARG1:%.*]] : $@thin Box<T>.Type):
+// CHECK: [[RETVAL:%.*]] = struct $Box<T> ([[ARG0]] : $T)
+// CHECK: return [[RETVAL]] : $Box<T>
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen3BoxV1tACyxGx_tcfC'
+
+// s270_convOptAnyStruct continued Test: reabstraction thunk helper
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S20opaque_values_silgen9AnyStructVSgACIegnr_A2DIegnr_TR : $@convention(thin) (@in_guaranteed Optional<AnyStruct>, @guaranteed @callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct) -> @out Optional<AnyStruct> {
+// CHECK: bb0([[ARG0:%.*]] : $Optional<AnyStruct>, [[ARG1:%.*]] : $@callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct):
+// CHECK: [[APPLYARG:%.*]] = apply [[ARG1]]([[ARG0]]) : $@callee_guaranteed (@in_guaranteed Optional<AnyStruct>) -> @out AnyStruct
+// CHECK: [[RETVAL:%.*]] = enum $Optional<AnyStruct>, #Optional.some!enumelt.1, [[APPLYARG]] : $AnyStruct
+// CHECK: return [[RETVAL]] : $Optional<AnyStruct>
+// CHECK-LABEL: } // end sil function '$S20opaque_values_silgen9AnyStructVSgACIegnr_A2DIegnr_TR'
+
+// s300__convETupleToAny continued Test: reabstraction of () to Any
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SIeg_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> ()) -> @out Any {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> ()):
+// CHECK: [[ASTACK:%.*]] = alloc_stack $Any
+// CHECK: [[IADDR:%.*]] = init_existential_addr [[ASTACK]] : $*Any, $()
+// CHECK: [[APPLYARG:%.*]] = apply [[ARG]]() : $@callee_guaranteed () -> ()
+// CHECK: [[LOAD_EXIST:%.*]] = load [trivial] [[IADDR]] : $*()
+// CHECK: [[RETVAL:%.*]] = init_existential_value [[LOAD_EXIST]] : $(), $(), $Any
+// CHECK: return [[RETVAL]] : $Any
+// CHECK-LABEL: } // end sil function '$SIeg_ypIegr_TR'
+
+// s310_convIntTupleAny continued Test: reabstraction of non-empty tuple to Any
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SS2iIegdd_ypIegr_TR : $@convention(thin) (@guaranteed @callee_guaranteed () -> (Int, Int)) -> @out Any {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> (Int, Int)):
+// CHECK: [[ASTACK:%.*]] = alloc_stack $Any
+// CHECK: [[IADDR:%.*]] = init_existential_addr [[ASTACK]] : $*Any, $(Int, Int)
+// CHECK: [[TADDR0:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 0
+// CHECK: [[TADDR1:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 1
+// CHECK: [[APPLYARG:%.*]] = apply [[ARG]]() : $@callee_guaranteed () -> (Int, Int)
+// CHECK: [[TEXTRACT0:%.*]] = tuple_extract [[APPLYARG]] : $(Int, Int), 0
+// CHECK: [[TEXTRACT1:%.*]] = tuple_extract [[APPLYARG]] : $(Int, Int), 1
+// CHECK: store [[TEXTRACT0]] to [trivial] [[TADDR0]] : $*Int
+// CHECK: store [[TEXTRACT1]] to [trivial] [[TADDR1]] : $*Int
+// CHECK: [[LOAD_EXIST:%.*]] = load [trivial] [[IADDR]] : $*(Int, Int)
+// CHECK: [[RETVAL:%.*]] = init_existential_value [[LOAD_EXIST]] : $(Int, Int), $(Int, Int), $Any
+// CHECK: dealloc_stack [[ASTACK]] : $*Any
+// CHECK: return [[RETVAL]] : $Any
+// CHECK-LABEL: } // end sil function '$SS2iIegdd_ypIegr_TR'
+
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @{{.*}} : $@convention(thin) (Int, Int, Int, Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)) -> (Int, Int, Int, Int, Int)
+// CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $Int, [[ARG3:%.*]] : $Int, [[ARG4:%.*]] : $Int, [[ARG5:%.*]] : $@callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)):
+// CHECK: [[TUPLE_TO_APPLY0:%.*]] = tuple ([[ARG2]] : $Int, [[ARG3]] : $Int)
+// CHECK: [[TUPLE_TO_APPLY1:%.*]] = tuple ([[ARG1]] : $Int, [[TUPLE_TO_APPLY0]] : $(Int, Int))
+// CHECK: [[TUPLE_TO_APPLY2:%.*]] = tuple ([[ARG0]] : $Int, [[TUPLE_TO_APPLY1]] : $(Int, (Int, Int)), [[ARG4]] : $Int)
+// CHECK: [[TUPLE_APPLY:%.*]] = apply [[ARG5]]([[TUPLE_TO_APPLY2]]) : $@callee_guaranteed (@in_guaranteed (Int, (Int, (Int, Int)), Int)) -> @out (Int, (Int, (Int, Int)), Int)
+// CHECK: [[RET_VAL0:%.*]] = tuple_extract [[TUPLE_APPLY]] : $(Int, (Int, (Int, Int)), Int), 0
+// CHECK: [[TUPLE_EXTRACT1:%.*]] = tuple_extract [[TUPLE_APPLY]] : $(Int, (Int, (Int, Int)), Int), 1
+// CHECK: [[RET_VAL1:%.*]] = tuple_extract [[TUPLE_EXTRACT1]] : $(Int, (Int, Int)), 0
+// CHECK: [[TUPLE_EXTRACT2:%.*]] = tuple_extract [[TUPLE_EXTRACT1]] : $(Int, (Int, Int)), 1
+// CHECK: [[RET_VAL2:%.*]] = tuple_extract [[TUPLE_EXTRACT2]] : $(Int, Int), 0
+// CHECK: [[RET_VAL3:%.*]] = tuple_extract [[TUPLE_EXTRACT2]] : $(Int, Int), 1
+// CHECK: [[RET_VAL4:%.*]] = tuple_extract [[TUPLE_APPLY]] : $(Int, (Int, (Int, Int)), Int), 2
+// CHECK: [[RET_VAL_TUPLE:%.*]] = tuple ([[RET_VAL0]] : $Int, [[RET_VAL1]] : $Int, [[RET_VAL2]] : $Int, [[RET_VAL3]] : $Int, [[RET_VAL4]] : $Int)
+// CHECK: return [[RET_VAL_TUPLE]] : $(Int, Int, Int, Int, Int)
+// CHECK-LABEL: } // end sil function '{{.*}}'
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @{{.*}} : $@convention(thin) <T> (Int, @in_guaranteed T, @guaranteed @callee_guaranteed (@in_guaranteed (Int, T)) -> @out (Int, T)) -> (Int, @out T) {
+// CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $T, [[ARG2:%.*]] : $@callee_guaranteed (@in_guaranteed (Int, T)) -> @out (Int, T)):
+// CHECK: [[TUPLE_TO_APPLY:%.*]] = tuple ([[ARG0]] : $Int, [[ARG1]] : $T)
+// CHECK: [[TUPLE_APPLY:%.*]] = apply [[ARG2]]([[TUPLE_TO_APPLY]]) : $@callee_guaranteed (@in_guaranteed (Int, T)) -> @out (Int, T)
+// CHECK: [[TUPLE_BORROW:%.*]] = begin_borrow [[TUPLE_APPLY]] : $(Int, T)
+// CHECK: [[RET_VAL0:%.*]] = tuple_extract [[TUPLE_BORROW]] : $(Int, T), 0
+// CHECK: [[TUPLE_EXTRACT:%.*]] = tuple_extract [[TUPLE_BORROW]] : $(Int, T), 1
+// CHECK: [[RET_VAL1:%.*]] = copy_value [[TUPLE_EXTRACT]] : $T
+// CHECK: end_borrow [[TUPLE_BORROW]] from [[TUPLE_APPLY]] : $(Int, T), $(Int, T)
+// CHECK: destroy_value [[TUPLE_APPLY]] : $(Int, T)
+// CHECK: [[RET_VAL_TUPLE:%.*]] = tuple ([[RET_VAL0]] : $Int, [[RET_VAL1]] : $T)
+// CHECK: return [[RET_VAL_TUPLE]] : $(Int, T)
+// CHECK-LABEL: } // end sil function '{{.*}}'
+
+
+// Tests LogicalPathComponent's writeback for opaque value types
+// ---
+// CHECK-LABEL: sil @$Ss10DictionaryV20opaque_values_silgenE22inoutAccessOfSubscript3keyyq__tF : $@convention(method) <Key, Value where Key : Hashable> (@in_guaranteed Value, @inout Dictionary<Key, Value>) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Value, [[ARG1:%.*]] : $*Dictionary<Key, Value>):
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*Dictionary<Key, Value>
+// CHECK: [[OPTIONAL_ALLOC:%.*]] = alloc_stack $Optional<Value>
+// CHECK: switch_enum_addr [[OPTIONAL_ALLOC]] : $*Optional<Value>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb2:
+// CHECK: [[OPTIONAL_LOAD:%.*]] = load [take] [[OPTIONAL_ALLOC]] : $*Optional<Value>
+// CHECK: apply {{.*}}<Key, Value>([[OPTIONAL_LOAD]], {{.*}}, [[WRITE]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_1, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$Ss10DictionaryV20opaque_values_silgenE22inoutAccessOfSubscript3keyyq__tF'
+
+// Tests materializeForSet's createSetterCallback for opaque values
+// ---
+// CHECK-LABEL: sil shared [transparent] [serialized] @$Ss10DictionaryV20opaque_values_silgenEyq_Sgq_cimytfU_ : $@convention(method) <Key, Value where Key : Hashable> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary<Key, Value>, @thick Dictionary<Key, Value>.Type) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.RawPointer, [[ARG1:%.*]] : $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : $*Dictionary<Key, Value>, [[ARG3:%.*]] : $@thick Dictionary<Key, Value>.Type):
+// CHECK: [[PROJ_VAL1:%.*]] = project_value_buffer $Value in [[ARG1]] : $*Builtin.UnsafeValueBuffer
+// CHECK: [[LOAD_VAL1:%.*]] = load [take] [[PROJ_VAL1]] : $*Value
+// CHECK: [[ADDR_VAL0:%.*]] = pointer_to_address [[ARG0]] : $Builtin.RawPointer to [strict] $*Optional<Value>
+// CHECK: [[LOAD_VAL0:%.*]] = load [take] [[ADDR_VAL0]] : $*Optional<Value>
+// CHECK: apply {{.*}}<Key, Value>([[LOAD_VAL0]], [[LOAD_VAL1]], [[ARG2]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_1, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$Ss10DictionaryV20opaque_values_silgenEyq_Sgq_cimytfU_'
+extension Dictionary {
+ public subscript(key: Value) -> Value? {
+ @inline(__always)
+ get {
+ return key
+ }
+ set(newValue) {
+ }
+ }
+
+ public mutating func inoutAccessOfSubscript(key: Value) {
+ func increment(x: inout Value) { }
+
+ increment(x: &self[key]!)
+ }
+}
+
+// s400______maybeCloneP continued Test: reabstraction thunk
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SxSgIegr_20opaque_values_silgen8Clonable_pSgIegr_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable> {
+// CHECK: bb0([[ARG:%.*]] : $@callee_guaranteed () -> @out Optional<τ_0_0>):
+// CHECK: [[APPLY_ARG:%.*]] = apply [[ARG]]() : $@callee_guaranteed () -> @out Optional<τ_0_0>
+// CHECK: switch_enum [[APPLY_ARG]] : $Optional<τ_0_0>, case #Optional.some!enumelt.1: bb2, case #Optional.none!enumelt: bb1
+// CHECK: bb1:
+// CHECK: [[ONONE:%.*]] = enum $Optional<Clonable>, #Optional.none!enumelt
+// CHECK: br bb3([[ONONE]] : $Optional<Clonable>)
+// CHECK: bb2([[ENUM_SOME:%.*]] : $τ_0_0):
+// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[ENUM_SOME]] : $τ_0_0, $τ_0_0, $Clonable
+// CHECK: [[OSOME:%.*]] = enum $Optional<Clonable>, #Optional.some!enumelt.1, [[INIT_OPAQUE]] : $Clonable
+// CHECK: br bb3([[OSOME]] : $Optional<Clonable>)
+// CHECK: bb3([[RETVAL:%.*]] : $Optional<Clonable>):
+// CHECK: return [[RETVAL]] : $Optional<Clonable>
+// CHECK-LABEL: } // end sil function '$SxSgIegr_20opaque_values_silgen8Clonable_pSgIegr_AbCRzlTR'
+
+// s320__transImplodeAny continued Test: reabstraction thunk
+// ---
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypIegn_S2iIegyy_TR : $@convention(thin) (Int, Int, @guaranteed @callee_guaranteed (@in_guaranteed Any) -> ()) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Int, [[ARG1:%.*]] : $Int, [[ARG2:%.*]] : $@callee_guaranteed (@in_guaranteed Any) -> ()):
+// CHECK: [[ASTACK:%.*]] = alloc_stack $Any
+// CHECK: [[IADDR:%.*]] = init_existential_addr [[ASTACK]] : $*Any, $(Int, Int)
+// CHECK: [[TADDR0:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 0
+// CHECK: store [[ARG0]] to [trivial] [[TADDR0]] : $*Int
+// CHECK: [[TADDR1:%.*]] = tuple_element_addr [[IADDR]] : $*(Int, Int), 1
+// CHECK: store [[ARG1]] to [trivial] [[TADDR1]] : $*Int
+// CHECK: [[LOAD_EXIST:%.*]] = load [trivial] [[IADDR]] : $*(Int, Int)
+// CHECK: [[INIT_OPAQUE:%.*]] = init_existential_value [[LOAD_EXIST]] : $(Int, Int), $(Int, Int), $Any
+// CHECK: [[BORROWED_INIT_OPAQUE:%.*]] = begin_borrow [[INIT_OPAQUE]]
+// CHECK: [[APPLYARG:%.*]] = apply [[ARG2]]([[BORROWED_INIT_OPAQUE]]) : $@callee_guaranteed (@in_guaranteed Any) -> ()
+// CHECK: dealloc_stack [[ASTACK]] : $*Any
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$SypIegn_S2iIegyy_TR'
diff --git a/test/SILGen/plus_zero_opaque_values_silgen_lib.swift b/test/SILGen/plus_zero_opaque_values_silgen_lib.swift
new file mode 100644
index 0000000..fa43ee0
--- /dev/null
+++ b/test/SILGen/plus_zero_opaque_values_silgen_lib.swift
@@ -0,0 +1,77 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -enable-sil-opaque-values -emit-sorted-sil -Xllvm -sil-full-demangle -parse-stdlib -parse-as-library -emit-silgen -module-name Swift %s | %FileCheck %s
+// UNSUPPORTED: resilient_stdlib
+
+precedencegroup AssignmentPrecedence { assignment: true }
+
+enum Optional<Wrapped> {
+ case none
+ case some(Wrapped)
+}
+
+protocol EmptyP {}
+
+struct String { var ptr: Builtin.NativeObject }
+
+// Tests Empty protocol + Builtin.NativeObject enum (including opaque tuples as a return value)
+// ---
+// CHECK-LABEL: sil hidden @$Ss21s010______PAndS_casesyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: [[MTYPE:%.*]] = metatype $@thin PAndSEnum.Type
+// CHECK: [[EAPPLY:%.*]] = apply {{.*}}([[MTYPE]]) : $@convention(thin) (@thin PAndSEnum.Type) -> @owned @callee_guaranteed (@in_guaranteed EmptyP, @guaranteed String) -> @out PAndSEnum
+// CHECK: destroy_value [[EAPPLY]]
+// CHECK: return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function '$Ss21s010______PAndS_casesyyF'
+func s010______PAndS_cases() {
+ _ = PAndSEnum.A
+}
+
+// Test emitBuiltinReinterpretCast.
+// ---
+// CHECK-LABEL: sil hidden @$Ss21s020__________bitCast_2toq_x_q_mtr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @thick U.Type) -> @out U {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T,
+// CHECK: [[CAST:%.*]] = unchecked_bitwise_cast [[ARG]] : $T to $U
+// CHECK: [[RET:%.*]] = copy_value [[CAST]] : $U
+// CHECK-NOT: destroy_value [[COPY]] : $T
+// CHECK: return [[RET]] : $U
+// CHECK-LABEL: } // end sil function '$Ss21s020__________bitCast_2toq_x_q_mtr0_lF'
+func s020__________bitCast<T, U>(_ x: T, to type: U.Type) -> U {
+ return Builtin.reinterpretCast(x)
+}
+
+// Test emitBuiltinCastReference
+// ---
+// CHECK-LABEL: sil hidden @$Ss21s030__________refCast_2toq_x_q_mtr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @thick U.Type) -> @out U {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $T, %1 : @trivial $@thick U.Type):
+// CHECK: [[COPY:%.*]] = copy_value [[ARG]] : $T
+// CHECK: [[SRC:%.*]] = alloc_stack $T
+// CHECK: store [[COPY]] to [init] [[SRC]] : $*T
+// CHECK: [[DEST:%.*]] = alloc_stack $U
+// CHECK: unchecked_ref_cast_addr T in [[SRC]] : $*T to U in [[DEST]] : $*U
+// CHECK: [[LOAD:%.*]] = load [take] [[DEST]] : $*U
+// CHECK: dealloc_stack [[DEST]] : $*U
+// CHECK: dealloc_stack [[SRC]] : $*T
+// CHECK-NOT: destroy_value [[ARG]] : $T
+// CHECK: return [[LOAD]] : $U
+// CHECK-LABEL: } // end sil function '$Ss21s030__________refCast_2toq_x_q_mtr0_lF'
+func s030__________refCast<T, U>(_ x: T, to: U.Type) -> U {
+ return Builtin.castReference(x)
+}
+
+// Init of Empty protocol + Builtin.NativeObject enum (including opaque tuples as a return value)
+// ---
+// CHECK-LABEL: sil shared [transparent] @$Ss9PAndSEnumO1AyABs6EmptyP_p_SStcABmF : $@convention(method) (@in EmptyP, @owned String, @thin PAndSEnum.Type) -> @out PAndSEnum {
+// CHECK: bb0([[ARG0:%.*]] : @owned $EmptyP, [[ARG1:%.*]] : @owned $String, [[ARG2:%.*]] : @trivial $@thin PAndSEnum.Type):
+// CHECK: [[RTUPLE:%.*]] = tuple ([[ARG0]] : $EmptyP, [[ARG1]] : $String)
+// CHECK: [[RETVAL:%.*]] = enum $PAndSEnum, #PAndSEnum.A!enumelt.1, [[RTUPLE]] : $(EmptyP, String)
+// CHECK: return [[RETVAL]] : $PAndSEnum
+// CHECK-LABEL: } // end sil function '$Ss9PAndSEnumO1AyABs6EmptyP_p_SStcABmF'
+// CHECK-LABEL: sil shared [transparent] [thunk] @$Ss9PAndSEnumO1AyABs6EmptyP_p_SStcABmFTc : $@convention(thin) (@thin PAndSEnum.Type) -> @owned @callee_guaranteed (@in_guaranteed EmptyP, @guaranteed String) -> @out PAndSEnum {
+// CHECK: bb0([[ARG:%.*]] : @trivial $@thin PAndSEnum.Type):
+// CHECK: [[RETVAL:%.*]] = partial_apply [callee_guaranteed] {{.*}}([[ARG]]) : $@convention(method) (@in EmptyP, @owned String, @thin PAndSEnum.Type) -> @out PAndSEnum
+// CHECK: [[CANONICAL_THUNK_FN:%.*]] = function_ref @$Ss6EmptyP_pSSs9PAndSEnumOIegixr_sAA_pSSACIegngr_TR : $@convention(thin) (@in_guaranteed EmptyP, @guaranteed String, @guaranteed @callee_guaranteed (@in EmptyP, @owned String) -> @out PAndSEnum) -> @out PAndSEnum
+// CHECK: [[CANONICAL_THUNK:%.*]] = partial_apply [callee_guaranteed] [[CANONICAL_THUNK_FN]]([[RETVAL]])
+// CHECK: return [[CANONICAL_THUNK]] : $@callee_guaranteed (@in_guaranteed EmptyP, @guaranteed String) -> @out PAndSEnum
+// CHECK-LABEL: } // end sil function '$Ss9PAndSEnumO1AyABs6EmptyP_p_SStcABmFTc'
+enum PAndSEnum { case A(EmptyP, String) }
+
diff --git a/test/SILGen/plus_zero_optional-cast.swift b/test/SILGen/plus_zero_optional-cast.swift
new file mode 100644
index 0000000..0c0ca83
--- /dev/null
+++ b/test/SILGen/plus_zero_optional-cast.swift
@@ -0,0 +1,226 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class A {}
+class B : A {}
+
+// CHECK-LABEL: sil hidden @$S4main3fooyyAA1ACSgF : $@convention(thin) (@guaranteed Optional<A>) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<A>):
+// CHECK: [[X:%.*]] = alloc_box ${ var Optional<B> }, var, name "x"
+// CHECK-NEXT: [[PB:%.*]] = project_box [[X]]
+// Check whether the temporary holds a value.
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[T1:%.*]] = select_enum [[ARG_COPY]]
+// CHECK-NEXT: cond_br [[T1]], [[IS_PRESENT:bb.*]], [[NOT_PRESENT:bb[0-9]+]]
+//
+// CHECK: [[NOT_PRESENT]]:
+// CHECK: br [[NOT_PRESENT_FINISH:bb[0-9]+]]
+//
+// If so, pull the value out and check whether it's a B.
+// CHECK: [[IS_PRESENT]]:
+// CHECK-NEXT: [[VAL:%.*]] = unchecked_enum_data [[ARG_COPY]] : $Optional<A>, #Optional.some!enumelt.1
+// CHECK-NEXT: [[X_VALUE:%.*]] = init_enum_data_addr [[PB]] : $*Optional<B>, #Optional.some
+// CHECK-NEXT: checked_cast_br [[VAL]] : $A to $B, [[IS_B:bb.*]], [[NOT_B:bb[0-9]+]]
+//
+// If so, materialize that and inject it into x.
+// CHECK: [[IS_B]]([[T0:%.*]] : @owned $B):
+// CHECK-NEXT: store [[T0]] to [init] [[X_VALUE]] : $*B
+// CHECK-NEXT: inject_enum_addr [[PB]] : $*Optional<B>, #Optional.some
+// CHECK-NEXT: br [[CONT:bb[0-9]+]]
+//
+// If not, destroy_value the A and inject nothing into x.
+// CHECK: [[NOT_B]]([[ORIGINAL_VALUE:%.*]] : @owned $A):
+// CHECK-NEXT: destroy_value [[ORIGINAL_VALUE]]
+// CHECK-NEXT: inject_enum_addr [[PB]] : $*Optional<B>, #Optional.none
+// CHECK-NEXT: br [[CONT]]
+//
+// Finish the present path.
+// CHECK: [[CONT]]:
+// CHECK-NEXT: br [[RETURN_BB:bb[0-9]+]]
+//
+// Finish.
+// CHECK: [[RETURN_BB]]:
+// CHECK-NEXT: destroy_value [[X]]
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK-NEXT: tuple
+// CHECK-NEXT: return
+//
+// Finish the not-present path.
+// CHECK: [[NOT_PRESENT_FINISH]]:
+// CHECK-NEXT: inject_enum_addr [[PB]] {{.*}}none
+// CHECK-NEXT: br [[RETURN_BB]]
+func foo(_ y : A?) {
+ var x = (y as? B)
+}
+
+// CHECK-LABEL: sil hidden @$S4main3baryyAA1ACSgSgSgSgF : $@convention(thin) (@guaranteed Optional<Optional<Optional<Optional<A>>>>) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<Optional<Optional<Optional<A>>>>):
+// CHECK: [[X:%.*]] = alloc_box ${ var Optional<Optional<Optional<B>>> }, var, name "x"
+// CHECK-NEXT: [[PB:%.*]] = project_box [[X]]
+// -- Check for some(...)
+// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[T1:%.*]] = select_enum [[ARG_COPY]]
+// CHECK-NEXT: cond_br [[T1]], [[P:bb.*]], [[NIL_DEPTH_1:bb[0-9]+]]
+//
+// CHECK: [[NIL_DEPTH_1]]:
+// CHECK: br [[FINISH_NIL_0:bb[0-9]+]]
+//
+// If so, drill down another level and check for some(some(...)).
+// CHECK: [[P]]:
+// CHECK-NEXT: [[VALUE_OOOA:%.*]] = unchecked_enum_data [[ARG_COPY]]
+// CHECK: [[T1:%.*]] = select_enum [[VALUE_OOOA]]
+// CHECK-NEXT: cond_br [[T1]], [[PP:bb.*]], [[NIL_DEPTH_2:bb[0-9]+]]
+//
+// CHECK: [[NIL_DEPTH_2]]:
+// CHECK: br [[FINISH_NIL_0]]
+//
+// If so, drill down another level and check for some(some(some(...))).
+// CHECK: [[PP]]:
+// CHECK-NEXT: [[VALUE_OOA:%.*]] = unchecked_enum_data [[VALUE_OOOA]]
+// CHECK: [[T1:%.*]] = select_enum [[VALUE_OOA]]
+// CHECK-NEXT: cond_br [[T1]], [[PPP:bb.*]], [[NIL_DEPTH_3:bb[0-9]+]]
+//
+// CHECK: [[NIL_DEPTH_3]]:
+// CHECK: br [[FINISH_NIL_1:bb[0-9]+]]
+//
+// If so, drill down another level and check for some(some(some(some(...)))).
+// CHECK: [[PPP]]:
+// CHECK-NEXT: [[VALUE_OA:%.*]] = unchecked_enum_data [[VALUE_OOA]]
+// CHECK: [[T1:%.*]] = select_enum [[VALUE_OA]]
+// CHECK-NEXT: cond_br [[T1]], [[PPPP:bb.*]], [[NIL_DEPTH_4:bb[0-9]+]]
+//
+// CHECK: [[NIL_DEPTH_4]]:
+// CHECK: br [[FINISH_NIL_2:bb[0-9]+]]
+//
+// If so, pull out the A and check whether it's a B.
+// CHECK: [[PPPP]]:
+// CHECK-NEXT: [[VAL:%.*]] = unchecked_enum_data [[VALUE_OA]]
+// CHECK-NEXT: checked_cast_br [[VAL]] : $A to $B, [[IS_B:bb.*]], [[NOT_B:bb[0-9]+]]
+//
+// If so, inject it back into an optional.
+// TODO: We're going to switch back out of this; we really should peephole it.
+// CHECK: [[IS_B]]([[T0:%.*]] : @owned $B):
+// CHECK-NEXT: enum $Optional<B>, #Optional.some!enumelt.1, [[T0]]
+// CHECK-NEXT: br [[SWITCH_OB2:bb[0-9]+]](
+//
+// If not, inject nothing into an optional.
+// CHECK: [[NOT_B]]([[ORIGINAL_VALUE:%.*]] : @owned $A):
+// CHECK-NEXT: destroy_value [[ORIGINAL_VALUE]]
+// CHECK-NEXT: enum $Optional<B>, #Optional.none!enumelt
+// CHECK-NEXT: br [[SWITCH_OB2]](
+//
+// Switch out on the value in [[OB2]].
+// CHECK: [[SWITCH_OB2]]([[VAL:%[0-9]+]] : @owned $Optional<B>):
+// CHECK: [[T0:%.*]] = select_enum [[VAL]]
+// CHECK: cond_br [[T0]], [[HAVE_B:bb[0-9]+]], [[FINISH_NIL_4:bb[0-9]+]]
+//
+// CHECK: [[FINISH_NIL_4]]:
+// CHECK: br [[FINISH_NIL_0]]
+//
+// CHECK: [[HAVE_B]]:
+// CHECK: [[UNWRAPPED_VAL:%.*]] = unchecked_enum_data [[VAL]]
+// CHECK: [[REWRAPPED_VAL:%.*]] = enum $Optional<B>, #Optional.some!enumelt.1, [[UNWRAPPED_VAL]]
+// CHECK: br [[DONE_DEPTH0:bb[0-9]+]]
+//
+// CHECK: [[DONE_DEPTH0]](
+// CHECK-NEXT: enum $Optional<Optional<B>>, #Optional.some!enumelt.1,
+// CHECK-NEXT: br [[DONE_DEPTH1:bb[0-9]+]]
+//
+// Set X := some(OOB).
+// CHECK: [[DONE_DEPTH1]]
+// CHECK-NEXT: enum $Optional<Optional<Optional<B>>>, #Optional.some!enumelt.1,
+// CHECK: br [[DONE_DEPTH2:bb[0-9]+]]
+// CHECK: [[DONE_DEPTH2]]
+// CHECK-NEXT: destroy_value [[X]]
+// CHECK-NOT: destroy_value %0
+// CHECK: return
+//
+// On various failure paths, set OOB := nil.
+// CHECK: [[FINISH_NIL_2]]:
+// CHECK-NEXT: enum $Optional<B>, #Optional.none!enumelt
+// CHECK-NEXT: br [[DONE_DEPTH0]]
+//
+// CHECK: [[FINISH_NIL_1]]:
+// CHECK-NEXT: enum $Optional<Optional<B>>, #Optional.none!enumelt
+// CHECK-NEXT: br [[DONE_DEPTH1]]
+//
+// On various failure paths, set X := nil.
+// CHECK: [[FINISH_NIL_0]]:
+// CHECK-NEXT: inject_enum_addr [[PB]] {{.*}}none
+// CHECK-NEXT: br [[DONE_DEPTH2]]
+// Done.
+func bar(_ y : A????) {
+ var x = (y as? B??)
+}
+
+
+// CHECK-LABEL: sil hidden @$S4main3bazyyyXlSgF : $@convention(thin) (@guaranteed Optional<AnyObject>) -> () {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<AnyObject>):
+// CHECK: [[X:%.*]] = alloc_box ${ var Optional<B> }, var, name "x"
+// CHECK-NEXT: [[PB:%.*]] = project_box [[X]]
+// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: [[T1:%.*]] = select_enum [[ARG_COPY]]
+// CHECK: bb1:
+// CHECK: [[VAL:%.*]] = unchecked_enum_data [[ARG_COPY]]
+// CHECK-NEXT: [[X_VALUE:%.*]] = init_enum_data_addr [[PB]] : $*Optional<B>, #Optional.some
+// CHECK-NEXT: checked_cast_br [[VAL]] : $AnyObject to $B, [[IS_B:bb.*]], [[NOT_B:bb[0-9]+]]
+// CHECK: [[IS_B]]([[CASTED_VALUE:%.*]] : @owned $B):
+// CHECK: store [[CASTED_VALUE]] to [init] [[X_VALUE]]
+// CHECK: [[NOT_B]]([[ORIGINAL_VALUE:%.*]] : @owned $AnyObject):
+// CHECK: destroy_value [[ORIGINAL_VALUE]]
+// CHECK: } // end sil function '$S4main3bazyyyXlSgF'
+func baz(_ y : AnyObject?) {
+ var x = (y as? B)
+}
+
+
+// <rdar://problem/17013042> T! <-> T? conversions should not produce a diamond
+
+// CHECK-LABEL: sil hidden @$S4main07opt_to_B8_trivialySiSgACF
+// CHECK: bb0(%0 : @trivial $Optional<Int>):
+// CHECK-NEXT: debug_value %0 : $Optional<Int>, let, name "x"
+// CHECK-NEXT: return %0 : $Optional<Int>
+// CHECK-NEXT:}
+func opt_to_opt_trivial(_ x: Int?) -> Int! {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S4main07opt_to_B10_referenceyAA1CCSgAEF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<C>):
+// CHECK: debug_value [[ARG]] : $Optional<C>, let, name "x"
+// CHECK: [[RESULT:%.*]] = copy_value [[ARG]]
+// CHECK-NOT: destroy_value [[ARG]]
+// CHECK: return [[RESULT]] : $Optional<C>
+// CHECK: } // end sil function '$S4main07opt_to_B10_referenceyAA1CCSgAEF'
+func opt_to_opt_reference(_ x : C!) -> C? { return x }
+
+// CHECK-LABEL: sil hidden @$S4main07opt_to_B12_addressOnly{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0(%0 : @trivial $*Optional<T>, %1 : @trivial $*Optional<T>):
+// CHECK-NEXT: debug_value_addr %1 : $*Optional<T>, let, name "x"
+// CHECK-NEXT: copy_addr %1 to [initialization] %0
+// CHECK-NOT: destroy_addr %1
+func opt_to_opt_addressOnly<T>(_ x : T!) -> T? { return x }
+
+class C {}
+
+public struct TestAddressOnlyStruct<T> {
+ func f(_ a : T?) {}
+
+ // CHECK-LABEL: sil hidden @$S4main21TestAddressOnlyStructV8testCall{{[_0-9a-zA-Z]*}}F
+ // CHECK: bb0(%0 : @trivial $*Optional<T>, %1 : @trivial $TestAddressOnlyStruct<T>):
+ // CHECK: apply {{.*}}<T>(%0, %1)
+ func testCall(_ a : T!) {
+ f(a)
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S4main35testContextualInitOfNonAddrOnlyTypeyySiSgF
+// CHECK: bb0(%0 : @trivial $Optional<Int>):
+// CHECK-NEXT: debug_value %0 : $Optional<Int>, let, name "a"
+// CHECK-NEXT: [[X:%.*]] = alloc_box ${ var Optional<Int> }, var, name "x"
+// CHECK-NEXT: [[PB:%.*]] = project_box [[X]]
+// CHECK-NEXT: store %0 to [trivial] [[PB]] : $*Optional<Int>
+// CHECK-NEXT: destroy_value [[X]] : ${ var Optional<Int> }
+func testContextualInitOfNonAddrOnlyType(_ a : Int?) {
+ var x: Int! = a
+}
diff --git a/test/SILGen/plus_zero_optional.swift b/test/SILGen/plus_zero_optional.swift
new file mode 100644
index 0000000..038a0ab
--- /dev/null
+++ b/test/SILGen/plus_zero_optional.swift
@@ -0,0 +1,105 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func testCall(_ f: (() -> ())?) {
+ f?()
+}
+// CHECK: sil hidden @{{.*}}testCall{{.*}}
+// CHECK: bb0([[T0:%.*]] : @guaranteed $Optional<@callee_guaranteed () -> ()>):
+// CHECK: [[T0_COPY:%.*]] = copy_value [[T0]]
+// CHECK: [[T1:%.*]] = select_enum [[T0_COPY]]
+// CHECK-NEXT: cond_br [[T1]], [[SOME:bb[0-9]+]], [[NONE:bb[0-9]+]]
+
+// CHECK: [[NONE]]:
+// CHECK: br [[NOTHING_BLOCK_EXIT:bb[0-9]+]]
+
+// If it does, project and load the value out of the implicitly unwrapped
+// optional...
+
+// CHECK: [[SOME]]:
+// CHECK-NEXT: [[FN0:%.*]] = unchecked_enum_data [[T0_COPY]] : $Optional<@callee_guaranteed () -> ()>, #Optional.some!enumelt.1
+// .... then call it
+// CHECK-NEXT: [[B:%.*]] = begin_borrow [[FN0]]
+// CHECK-NEXT: apply [[B]]()
+// CHECK: destroy_value [[FN0]]
+// CHECK: br [[EXIT:bb[0-9]+]](
+
+// (first nothing block)
+// CHECK: [[NOTHING_BLOCK_EXIT]]:
+// CHECK-NEXT: enum $Optional<()>, #Optional.none!enumelt
+// CHECK-NEXT: br [[EXIT]]
+// CHECK: } // end sil function '$S8optional8testCallyyyycSgF'
+
+func testAddrOnlyCallResult<T>(_ f: (() -> T)?) {
+ var f = f
+ var x = f?()
+}
+// CHECK-LABEL: sil hidden @{{.*}}testAddrOnlyCallResult{{.*}} : $@convention(thin) <T> (@guaranteed Optional<@callee_guaranteed () -> @out T>) -> ()
+// CHECK: bb0([[T0:%.*]] : @guaranteed $Optional<@callee_guaranteed () -> @out T>):
+// CHECK: [[F:%.*]] = alloc_box $<τ_0_0> { var Optional<@callee_guaranteed () -> @out τ_0_0> } <T>, var, name "f"
+// CHECK-NEXT: [[PBF:%.*]] = project_box [[F]]
+// CHECK: [[T0_COPY:%.*]] = copy_value [[T0]]
+// CHECK: store [[T0_COPY]] to [init] [[PBF]]
+// CHECK-NEXT: [[X:%.*]] = alloc_box $<τ_0_0> { var Optional<τ_0_0> } <T>, var, name "x"
+// CHECK-NEXT: [[PBX:%.*]] = project_box [[X]]
+// CHECK-NEXT: [[TEMP:%.*]] = init_enum_data_addr [[PBX]]
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[PBF]]
+// Check whether 'f' holds a value.
+// CHECK: [[T1:%.*]] = select_enum_addr [[READ]]
+// CHECK-NEXT: cond_br [[T1]], bb2, bb1
+// If so, pull out the value...
+// CHECK: bb2:
+// CHECK-NEXT: [[T1:%.*]] = unchecked_take_enum_data_addr [[READ]]
+// CHECK-NEXT: [[T0:%.*]] = load [copy] [[T1]]
+// CHECK-NEXT: end_access [[READ]]
+// ...evaluate the rest of the suffix...
+// CHECK: [[B:%.*]] = begin_borrow [[T0]]
+// CHECK-NEXT: apply [[B]]([[TEMP]])
+// ...and coerce to T?
+// CHECK: inject_enum_addr [[PBX]] {{.*}}some
+// CHECK: destroy_value [[T0]]
+// CHECK-NEXT: br bb3
+// Continuation block.
+// CHECK: bb3
+// CHECK-NEXT: destroy_value [[X]]
+// CHECK-NEXT: destroy_value [[F]]
+// CHECK-NOT: destroy_value %0
+// CHECK-NEXT: [[T0:%.*]] = tuple ()
+// CHECK-NEXT: return [[T0]] : $()
+
+// Nothing block.
+// CHECK: bb4:
+// CHECK-NEXT: inject_enum_addr [[PBX]] {{.*}}none
+// CHECK-NEXT: br bb3
+
+
+// <rdar://problem/15180622>
+
+func wrap<T>(_ x: T) -> T? { return x }
+
+// CHECK-LABEL: sil hidden @$S8optional16wrap_then_unwrap{{[_0-9a-zA-Z]*}}F
+func wrap_then_unwrap<T>(_ x: T) -> T {
+ // CHECK: switch_enum_addr {{.*}}, case #Optional.some!enumelt.1: [[OK:bb[0-9]+]], case #Optional.none!enumelt: [[FAIL:bb[0-9]+]]
+ // CHECK: [[FAIL]]:
+ // CHECK: unreachable
+ // CHECK: [[OK]]:
+ // CHECK: unchecked_take_enum_data_addr
+ return wrap(x)!
+}
+
+// CHECK-LABEL: sil hidden @$S8optional10tuple_bind{{[_0-9a-zA-Z]*}}F
+func tuple_bind(_ x: (Int, String)?) -> String? {
+ return x?.1
+ // CHECK: cond_br {{%.*}}, [[NONNULL:bb[0-9]+]], [[NULL:bb[0-9]+]]
+ // CHECK: [[NONNULL]]:
+ // CHECK: [[STRING:%.*]] = tuple_extract {{%.*}} : $(Int, String), 1
+ // CHECK-NOT: destroy_value [[STRING]]
+}
+
+// rdar://21883752 - We were crashing on this function because the deallocation happened
+// out of scope.
+// CHECK-LABEL: sil hidden @$S8optional16crash_on_deallocyys10DictionaryVySiSaySiGGFfA_
+func crash_on_dealloc(_ dict : [Int : [Int]] = [:]) {
+ var dict = dict
+ dict[1]?.append(2)
+}
diff --git a/test/SILGen/plus_zero_optional_lvalue.swift b/test/SILGen/plus_zero_optional_lvalue.swift
new file mode 100644
index 0000000..d2a4f17
--- /dev/null
+++ b/test/SILGen/plus_zero_optional_lvalue.swift
@@ -0,0 +1,74 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+// CHECK-LABEL: sil hidden @$S15optional_lvalue07assign_a1_B0yySiSgz_SitF
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Optional<Int>
+// CHECK: [[PRECOND:%.*]] = function_ref @$Ss30_diagnoseUnexpectedNilOptional{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[PRECOND]](
+// CHECK: [[PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[WRITE]] : $*Optional<Int>, #Optional.some!enumelt.1
+// CHECK: assign {{%.*}} to [[PAYLOAD]]
+func assign_optional_lvalue(_ x: inout Int?, _ y: Int) {
+ x! = y
+}
+
+// CHECK-LABEL: sil hidden @$S15optional_lvalue011assign_iuo_B0yySiSgz_SitF
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Optional<Int>
+// CHECK: [[PRECOND:%.*]] = function_ref @$Ss30_diagnoseUnexpectedNilOptional{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[PRECOND]](
+// CHECK: [[PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[WRITE]] : $*Optional<Int>, #Optional.some!enumelt.1
+// CHECK: assign {{%.*}} to [[PAYLOAD]]
+func assign_iuo_lvalue(_ x: inout Int!, _ y: Int) {
+ x! = y
+}
+
+struct S {
+ var x: Int
+
+ var computed: Int {
+ get {}
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S15optional_lvalue011assign_iuo_B9_implicityyAA1SVSgz_SitF
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Optional<S>
+// CHECK: [[SOME:%.*]] = unchecked_take_enum_data_addr [[WRITE]]
+// CHECK: [[X:%.*]] = struct_element_addr [[SOME]]
+func assign_iuo_lvalue_implicit(_ s: inout S!, _ y: Int) {
+ s.x = y
+}
+
+struct Struct<T> {
+ var value: T?
+}
+
+// CHECK-LABEL: sil hidden @$S15optional_lvalue07assign_a1_B13_reabstractedyyAA6StructVyS2icGz_S2ictF
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$SS2iIegyd_S2iIegnr_TR
+// CHECK: [[REABSTRACTED:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]
+// CHECK: assign [[REABSTRACTED]] to {{%.*}} : $*@callee_guaranteed (@in_guaranteed Int) -> @out Int
+func assign_optional_lvalue_reabstracted(_ x: inout Struct<(Int) -> Int>,
+ _ y: @escaping (Int) -> Int) {
+ x.value! = y
+}
+
+// CHECK-LABEL: sil hidden @$S15optional_lvalue07assign_a1_B9_computedySiAA1SVSgz_SitF
+// CHECK: function_ref @$S15optional_lvalue1SV8computedSivs
+// CHECK: function_ref @$S15optional_lvalue1SV8computedSivg
+func assign_optional_lvalue_computed(_ x: inout S?, _ y: Int) -> Int {
+ x!.computed = y
+ return x!.computed
+}
+
+func generate_int() -> Int { return 0 }
+
+// CHECK-LABEL: sil hidden @$S15optional_lvalue013assign_bound_a1_B0yySiSgzF
+// CHECK: select_enum_addr
+// CHECK: cond_br {{%.*}}, [[SOME:bb[0-9]+]], [[NONE:bb[0-9]+]]
+// CHECK: [[SOME]]:
+// CHECK: [[PAYLOAD:%.*]] = unchecked_take_enum_data_addr
+// CHECK: [[FN:%.*]] = function_ref
+// CHECK: [[T0:%.*]] = apply [[FN]]()
+// CHECK: assign [[T0]] to [[PAYLOAD]]
+func assign_bound_optional_lvalue(_ x: inout Int?) {
+ x? = generate_int()
+}
diff --git a/test/SILGen/plus_zero_partial_apply_generic.swift b/test/SILGen/plus_zero_partial_apply_generic.swift
new file mode 100644
index 0000000..dc1f4c5
--- /dev/null
+++ b/test/SILGen/plus_zero_partial_apply_generic.swift
@@ -0,0 +1,91 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol Panda {
+ associatedtype Cuddles : Foo
+}
+
+protocol Foo {
+ static func staticFunc()
+ func instanceFunc()
+
+ func makesSelfNonCanonical<T : Panda>(_: T) where T.Cuddles == Self
+}
+
+// CHECK-LABEL: sil hidden @$S21partial_apply_generic14getStaticFunc1{{[_0-9a-zA-Z]*}}F
+func getStaticFunc1<T: Foo>(t: T.Type) -> () -> () {
+// CHECK: [[REF:%.*]] = function_ref @$S21partial_apply_generic3FooP10staticFunc{{[_0-9a-zA-Z]*}}FZ
+// CHECK-NEXT: apply [[REF]]<T>(%0)
+ return t.staticFunc
+// CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil shared [thunk] @$S21partial_apply_generic3FooP10staticFunc{{[_0-9a-zA-Z]*}}FZ
+// CHECK: [[REF:%.*]] = witness_method $Self, #Foo.staticFunc!1
+// CHECK-NEXT: partial_apply [callee_guaranteed] [[REF]]<Self>(%0)
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil hidden @$S21partial_apply_generic14getStaticFunc2{{[_0-9a-zA-Z]*}}F
+func getStaticFunc2<T: Foo>(t: T) -> () -> () {
+// CHECK: [[REF:%.*]] = function_ref @$S21partial_apply_generic3FooP10staticFunc{{[_0-9a-zA-Z]*}}FZ
+// CHECK: apply [[REF]]<T>
+ return T.staticFunc
+// CHECK-NOT: destroy_addr %0 : $*T
+// CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S21partial_apply_generic16getInstanceFunc1{{[_0-9a-zA-Z]*}}F
+func getInstanceFunc1<T: Foo>(t: T) -> () -> () {
+// CHECK-NOT: alloc_stack $T
+// CHECK-NOT: copy_addr %0 to [initialization]
+// CHECK: [[REF:%.*]] = function_ref @$S21partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: apply [[REF]]<T>
+ return t.instanceFunc
+// CHECK-NOT: dealloc_stack
+// CHECK-NOT: destroy_addr %0 : $*T
+// CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil shared [thunk] @$S21partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG:%.*]] : @trivial $*Self):
+// CHECK: [[REF:%.*]] = witness_method $Self, #Foo.instanceFunc!1
+// CHECK-NEXT: [[STACK:%.*]] = alloc_stack $Self
+// CHECK-NEXT: copy_addr [[ARG]] to [initialization] [[STACK]]
+// CHECK-NEXT: partial_apply [callee_guaranteed] [[REF]]<Self>([[STACK]])
+// CHECK-NEXT: dealloc_stack
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil hidden @$S21partial_apply_generic16getInstanceFunc2{{[_0-9a-zA-Z]*}}F
+func getInstanceFunc2<T: Foo>(t: T) -> (T) -> () -> () {
+// CHECK: [[REF:%.*]] = function_ref @$S21partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: partial_apply [callee_guaranteed] [[REF]]<T>(
+ return T.instanceFunc
+// CHECK-NOT: destroy_addr %0 : $*
+// CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S21partial_apply_generic16getInstanceFunc3{{[_0-9a-zA-Z]*}}F
+func getInstanceFunc3<T: Foo>(t: T.Type) -> (T) -> () -> () {
+// CHECK: [[REF:%.*]] = function_ref @$S21partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: partial_apply [callee_guaranteed] [[REF]]<T>(
+ return t.instanceFunc
+// CHECK-NEXT: return
+}
+
+// CHECK-LABEL: sil hidden @$S21partial_apply_generic23getNonCanonicalSelfFunc1tyq_cxcxm_t7CuddlesQy_RszAA5PandaR_r0_lF : $@convention(thin) <T, U where T == U.Cuddles, U : Panda> (@thick T.Type) -> @owned @callee_guaranteed (@in_guaranteed T) -> @owned @callee_guaranteed (@in_guaranteed U) -> () {
+func getNonCanonicalSelfFunc<T : Foo, U : Panda>(t: T.Type) -> (T) -> (U) -> () where U.Cuddles == T {
+// CHECK: [[REF:%.*]] = function_ref @$S21partial_apply_generic3FooP21makesSelfNonCanonicalyyqd__7CuddlesQyd__RszAA5PandaRd__lFTc : $@convention(thin) <τ_0_0><τ_1_0 where τ_0_0 == τ_1_0.Cuddles, τ_1_0 : Panda> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed (@in_guaranteed τ_1_0) -> ()
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[REF]]<T, U>()
+ return t.makesSelfNonCanonical
+// CHECK-NEXT: return [[CLOSURE]]
+}
+
+// curry thunk of Foo.makesSelfNonCanonical<A where ...> (A1) -> ()
+// CHECK-LABEL: sil shared [thunk] @$S21partial_apply_generic3FooP21makesSelfNonCanonicalyyqd__7CuddlesQyd__RszAA5PandaRd__lFTc : $@convention(thin) <Self><T where Self == T.Cuddles, T : Panda> (@in_guaranteed Self) -> @owned @callee_guaranteed (@in_guaranteed T) -> () {
+// CHECK: bb0([[ARG:%.*]] : @trivial $*Self):
+// CHECK: [[REF:%.*]] = witness_method $Self, #Foo.makesSelfNonCanonical!1 : <Self><T where Self == T.Cuddles, T : Panda> (Self) -> (T) -> () : $@convention(witness_method: Foo) <τ_0_0><τ_1_0 where τ_0_0 == τ_1_0.Cuddles, τ_1_0 : Panda> (@in_guaranteed τ_1_0, @in_guaranteed τ_0_0) -> ()
+// CHECK-NEXT: [[STACK:%.*]] = alloc_stack $Self
+// CHECK-NEXT: copy_addr [[ARG]] to [initialization] [[STACK]] : $*Self
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[REF]]<Self, T>([[STACK]])
+// CHECK-NEXT: dealloc_stack
+// CHECK-NEXT: return [[CLOSURE]]
diff --git a/test/SILGen/plus_zero_partial_apply_protocol.swift b/test/SILGen/plus_zero_partial_apply_protocol.swift
new file mode 100644
index 0000000..ba46add
--- /dev/null
+++ b/test/SILGen/plus_zero_partial_apply_protocol.swift
@@ -0,0 +1,159 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -primary-file %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-ir -primary-file %s
+
+protocol Clonable {
+ func clone() -> Self
+ func maybeClone() -> Self?
+ func cloneMetatype() -> Self.Type
+ func getCloneFn() -> () -> Self
+
+ func genericClone<T>(t: T) -> Self
+ func genericGetCloneFn<T>(t: T) -> () -> Self
+}
+
+//===----------------------------------------------------------------------===//
+// Partial apply of methods returning Self-derived types
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: sil hidden @$S22partial_apply_protocol12testClonable1cyAA0E0_p_tF : $@convention(thin) (@in_guaranteed Clonable) -> ()
+func testClonable(c: Clonable) {
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}})
+ let _: () -> Clonable = c.clone
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxSgIegr_22partial_apply_protocol8Clonable_pSgIegr_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable>
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}})
+ let _: () -> Clonable? = c.maybeClone
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxXMTIegd_22partial_apply_protocol8Clonable_pXmTIegd_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @thick τ_0_0.Type) -> @thick Clonable.Type
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @thick τ_0_0.Type) -> @thick Clonable.Type
+ let _: () -> Clonable.Type = c.cloneMetatype
+
+ // CHECK: [[METHOD_FN:%.*]] = witness_method $@opened("{{.*}}") Clonable, #Clonable.getCloneFn!1 : {{.*}}, {{.*}} : $*@opened("{{.*}}") Clonable : $@convention(witness_method: Clonable) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_0_0
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD_FN]]<@opened("{{.*}}") Clonable>({{.*}}) : $@convention(witness_method: Clonable) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_0_0
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>([[RESULT]])
+ let _: () -> Clonable = c.getCloneFn()
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_Iego_22partial_apply_protocol8Clonable_pIegr_Iego_AaBRzlTR
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}})
+ let _: () -> () -> Clonable = c.getCloneFn
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
+// CHECK: bb0(%0 : @trivial $*Clonable, %1 : @guaranteed $@callee_guaranteed () -> @out τ_0_0):
+// CHECK-NEXT: [[INNER_RESULT:%.*]] = alloc_stack $τ_0_0
+// CHECK-NEXT: apply %1([[INNER_RESULT]])
+// CHECK-NEXT: [[OUTER_RESULT:%.*]] = init_existential_addr %0
+// CHECK-NEXT: copy_addr [take] [[INNER_RESULT]] to [initialization] [[OUTER_RESULT]]
+// CHECK-NEXT: [[EMPTY:%.*]] = tuple ()
+// CHECK-NEXT: dealloc_stack [[INNER_RESULT]]
+// CHECK-NEXT: return [[EMPTY]]
+
+// FIXME: This is horribly inefficient, too much alloc_stack / copy_addr!
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SxSgIegr_22partial_apply_protocol8Clonable_pSgIegr_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable>
+// CHECK: bb0(%0 : @trivial $*Optional<Clonable>, %1 : @guaranteed $@callee_guaranteed () -> @out Optional<τ_0_0>):
+// CHECK-NEXT: [[INNER_RESULT:%.*]] = alloc_stack $Optional<τ_0_0>
+// CHECK-NEXT: apply %1([[INNER_RESULT]])
+// CHECK-NEXT: [[OUTER_RESULT:%.*]] = alloc_stack $Optional<Clonable>
+// CHECK-NEXT: switch_enum_addr [[INNER_RESULT]] : $*Optional<{{.*}}>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]],
+// CHECK: [[SOME_BB]]:
+// CHECK-NEXT: [[INNER_RESULT_ADDR:%.*]] = unchecked_take_enum_data_addr [[INNER_RESULT]]
+// CHECK-NEXT: [[SOME_PAYLOAD:%.*]] = alloc_stack $Clonable
+// CHECK-NEXT: [[SOME_PAYLOAD_ADDR:%.*]] = init_existential_addr [[SOME_PAYLOAD]]
+// CHECK-NEXT: copy_addr [take] [[INNER_RESULT_ADDR]] to [initialization] [[SOME_PAYLOAD_ADDR]]
+// CHECK-NEXT: [[OUTER_RESULT_ADDR:%.*]] = init_enum_data_addr [[OUTER_RESULT]]
+// CHECK-NEXT: copy_addr [take] [[SOME_PAYLOAD]] to [initialization] [[OUTER_RESULT_ADDR]]
+// CHECK-NEXT: inject_enum_addr [[OUTER_RESULT]]
+// CHECK-NEXT: dealloc_stack [[SOME_PAYLOAD]]
+// CHECK-NEXT: br bb3
+// CHECK: bb2:
+// CHECK-NEXT: inject_enum_addr [[OUTER_RESULT]]
+// CHECK-NEXT: br bb3
+// CHECK: bb3:
+// CHECK-NEXT: copy_addr [take] [[OUTER_RESULT]] to [initialization] %0
+// CHECK-NEXT: [[EMPTY:%.*]] = tuple ()
+// CHECK-NEXT: dealloc_stack [[OUTER_RESULT]]
+// CHECK-NEXT: dealloc_stack [[INNER_RESULT]]
+// CHECK-NEXT: return [[EMPTY]]
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SxXMTIegd_22partial_apply_protocol8Clonable_pXmTIegd_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @thick τ_0_0.Type) -> @thick Clonable.Type
+// CHECK: bb0(%0 : @guaranteed $@callee_guaranteed () -> @thick τ_0_0.Type):
+// CHECK-NEXT: [[INNER_RESULT:%.*]] = apply %0()
+// CHECK-NEXT: [[OUTER_RESULT:%.*]] = init_existential_metatype [[INNER_RESULT]]
+// CHECK-NEXT: return [[OUTER_RESULT]]
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SxIegr_Iego_22partial_apply_protocol8Clonable_pIegr_Iego_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @owned @callee_guaranteed () -> @out τ_0_0) -> @owned @callee_guaranteed () -> @out Clonable
+// CHECK: bb0(%0 : @guaranteed $@callee_guaranteed () -> @owned @callee_guaranteed () -> @out τ_0_0):
+// CHECK-NEXT: [[INNER_RESULT:%.*]] = apply %0()
+// CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR
+// CHECK-NEXT: [[OUTER_RESULT:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<τ_0_0>([[INNER_RESULT]])
+// CHECK-NEXT: return [[OUTER_RESULT]]
+
+//===----------------------------------------------------------------------===//
+// Partial apply of methods returning Self-derived types from generic context
+//
+// Make sure the thunk only has the context generic parameters if needed!
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: sil hidden @$S22partial_apply_protocol28testClonableInGenericContext1c1tyAA0E0_p_xtlF : $@convention(thin) <T> (@in_guaranteed Clonable, @in_guaranteed T) -> ()
+func testClonableInGenericContext<T>(c: Clonable, t: T) {
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}})
+ let _: () -> Clonable = c.clone
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxSgIegr_22partial_apply_protocol8Clonable_pSgIegr_AbCRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable>
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out Optional<τ_0_0>) -> @out Optional<Clonable>
+ let _: () -> Clonable? = c.maybeClone
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxXMTIegd_22partial_apply_protocol8Clonable_pXmTIegd_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @thick τ_0_0.Type) -> @thick Clonable.Type
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @thick τ_0_0.Type) -> @thick Clonable.Type
+ let _: () -> Clonable.Type = c.cloneMetatype
+
+ // CHECK: [[METHOD_FN:%.*]] = witness_method $@opened("{{.*}}") Clonable, #Clonable.getCloneFn!1 : {{.*}}, {{.*}} : $*@opened("{{.*}}") Clonable : $@convention(witness_method: Clonable) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_0_0
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD_FN]]<@opened("{{.*}}") Clonable>({{.*}}) : $@convention(witness_method: Clonable) <τ_0_0 where τ_0_0 : Clonable> (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_0_0
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_22partial_apply_protocol8Clonable_pIegr_AaBRzlTR : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>([[RESULT]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_0_0) -> @out Clonable
+ let _: () -> Clonable = c.getCloneFn()
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$SxIegr_Iego_22partial_apply_protocol8Clonable_pIegr_Iego_AaBRzlTR
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<@opened("{{.*}}") Clonable>({{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : Clonable> (@guaranteed @callee_guaranteed () -> @owned @callee_guaranteed () -> @out τ_0_0) -> @owned @callee_guaranteed () -> @out Clonable
+ let _: () -> () -> Clonable = c.getCloneFn
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$Sxqd__Iegnr_x22partial_apply_protocol8Clonable_pIegnr_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_1_0) -> @out Clonable
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<T, @opened("{{.*}}") Clonable>({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_1_0) -> @out Clonable
+ let _: (T) -> Clonable = c.genericClone
+
+ // CHECK: [[THUNK_FN:%.*]] = function_ref @$Sxqd__Iegr_Iegno_x22partial_apply_protocol8Clonable_pIegr_Iegno_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_1_0) -> @owned @callee_guaranteed () -> @out Clonable
+ // CHECK: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<T, @opened("{{.*}}") Clonable>({{.*}}) : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_1_0) -> @owned @callee_guaranteed () -> @out Clonable
+ let _: (T) -> () -> Clonable = c.genericGetCloneFn
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$Sxqd__Iegnr_x22partial_apply_protocol8Clonable_pIegnr_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_1_0) -> @out Clonable
+// CHECK: bb0(%0 : @trivial $*Clonable, %1 : @trivial $*τ_0_0, %2 : @guaranteed $@callee_guaranteed (@in_guaranteed τ_0_0) -> @out τ_1_0):
+// CHECK-NEXT: [[INNER_RESULT:%.*]] = alloc_stack $τ_1_0
+// CHECK-NEXT: apply %2([[INNER_RESULT]], %1)
+// CHECK-NEXT: [[OUTER_RESULT:%.*]] = init_existential_addr %0
+// CHECK-NEXT: copy_addr [take] [[INNER_RESULT]] to [initialization] [[OUTER_RESULT]]
+// CHECK-NEXT: [[EMPTY:%.*]] = tuple ()
+// CHECK-NEXT: dealloc_stack [[INNER_RESULT]]
+// CHECK-NEXT: return [[EMPTY]]
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$Sxqd__Iegr_Iegno_x22partial_apply_protocol8Clonable_pIegr_Iegno_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@in_guaranteed τ_0_0, @guaranteed @callee_guaranteed (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_1_0) -> @owned @callee_guaranteed () -> @out Clonable
+// CHECK: bb0(%0 : @trivial $*τ_0_0, %1 : @guaranteed $@callee_guaranteed (@in_guaranteed τ_0_0) -> @owned @callee_guaranteed () -> @out τ_1_0):
+// CHECK-NEXT: [[RES:%.*]] = apply %1(%0)
+// CHECK: [[THUNK_FN:%.*]] = function_ref @$Sqd__Iegr_22partial_apply_protocol8Clonable_pIegr_AaBRd__r__lTR
+// CHECK-NEXT: [[RESULT:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<τ_0_0, τ_1_0>([[RES]])
+// CHECK-NEXT: return [[RESULT]]
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$Sqd__Iegr_22partial_apply_protocol8Clonable_pIegr_AaBRd__r__lTR : $@convention(thin) <τ_0_0><τ_1_0 where τ_1_0 : Clonable> (@guaranteed @callee_guaranteed () -> @out τ_1_0) -> @out Clonable {
+// CHECK: bb0(%0 : @trivial $*Clonable, %1 : @guaranteed $@callee_guaranteed () -> @out τ_1_0):
+// CHECK-NEXT: [[INNER_RESULT:%.*]] = alloc_stack $τ_1_0
+// CHECK-NEXT: apply %1([[INNER_RESULT]])
+// CHECK-NEXT: [[OUTER_RESULT:%.*]] = init_existential_addr %0
+// CHECK-NEXT: copy_addr [take] [[INNER_RESULT]] to [initialization] [[OUTER_RESULT]]
+// CHECK-NEXT: [[EMPTY:%.*]] = tuple ()
+// CHECK-NEXT: dealloc_stack [[INNER_RESULT:%.*]]
+// CHECK-NEXT: return [[EMPTY]]
diff --git a/test/SILGen/plus_zero_partial_apply_protocol_class_refinement_method.swift b/test/SILGen/plus_zero_partial_apply_protocol_class_refinement_method.swift
new file mode 100644
index 0000000..ec4c8be
--- /dev/null
+++ b/test/SILGen/plus_zero_partial_apply_protocol_class_refinement_method.swift
@@ -0,0 +1,16 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol P { func foo() }
+protocol Q: class, P {}
+
+// CHECK-LABEL: sil hidden @$S46partial_apply_protocol_class_refinement_method0A5ApplyyyycAA1Q_pF : $@convention
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Q):
+func partialApply(_ q: Q) -> () -> () {
+ // CHECK: [[OPENED:%.*]] = open_existential_ref [[ARG]]
+ // CHECK: [[TMP:%.*]] = alloc_stack
+ // CHECK: store_borrow [[OPENED]] to [[TMP:%.*]] :
+ // CHECK: apply {{%.*}}<{{.*}}>([[TMP]])
+ // CHECK-NEXT: dealloc_stack [[TMP]]
+ return q.foo
+}
diff --git a/test/SILGen/plus_zero_partial_apply_super.swift b/test/SILGen/plus_zero_partial_apply_super.swift
new file mode 100644
index 0000000..0a823f1
--- /dev/null
+++ b/test/SILGen/plus_zero_partial_apply_super.swift
@@ -0,0 +1,320 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -enable-sil-ownership -I %t -emit-module -emit-module-path=%t/resilient_struct.swiftmodule -module-name resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -enable-sil-ownership -I %t -emit-module -emit-module-path=%t/resilient_class.swiftmodule -module-name resilient_class %S/../Inputs/resilient_class.swift
+// RUN: %target-swift-frontend -enable-sil-ownership -enable-resilience -emit-silgen -parse-as-library -I %t %s | %FileCheck %s
+
+import resilient_class
+
+func doFoo(_ f: () -> ()) {
+ f()
+}
+
+public class Parent {
+ public init() {}
+ public func method() {}
+ public final func finalMethod() {}
+ public class func classMethod() {}
+ public final class func finalClassMethod() {}
+}
+
+public class GenericParent<A> {
+ let a: A
+ public init(a: A) {
+ self.a = a
+ }
+ public func method() {}
+ public final func finalMethod() {}
+ public class func classMethod() {}
+ public final class func finalClassMethod() {}
+}
+
+class Child : Parent {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super5ChildC6methodyyF : $@convention(method) (@guaranteed Child) -> ()
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $Child):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Child to $Parent
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC6methodyyFTcTd : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]([[BORROWED_CASTED_SELF_COPY]]) : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super5ChildC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super5ChildC11classMethodyyFZ : $@convention(method) (@thick Child.Type) -> () {
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick Child.Type to $@thick Parent.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC11classMethodyyFZTcTd : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super5ChildC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super5ChildC20callFinalSuperMethodyyF : $@convention(method) (@guaranteed Child) -> ()
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $Child):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Child to $Parent
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC11finalMethodyyFTc : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[APPLIED_SELF:%.*]] = apply [[SUPER_METHOD]]([[BORROWED_CASTED_SELF_COPY]]) : $@convention(thin) (@guaranteed Parent) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[APPLIED_SELF]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super5ChildC20callFinalSuperMethodyyF'
+ func callFinalSuperMethod() {
+ doFoo(super.finalMethod)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super5ChildC25callFinalSuperClassMethodyyFZ : $@convention(method) (@thick Child.Type) -> ()
+ // CHECK: bb0([[ARG:%.*]] : @trivial $@thick Child.Type):
+ // CHECK: [[CASTED_SELF:%.*]] = upcast [[ARG]] : $@thick Child.Type to $@thick Parent.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super6ParentC16finalClassMethodyyFZTc : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[APPLIED_SELF:%.*]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[APPLIED_SELF]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super5ChildC25callFinalSuperClassMethodyyFZ'
+ class func callFinalSuperClassMethod() {
+ doFoo(super.finalClassMethod)
+ }
+}
+
+class GenericChild<A> : GenericParent<A> {
+ override init(a: A) {
+ super.init(a: a)
+ }
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super12GenericChildC6methodyyF : $@convention(method) <A> (@guaranteed GenericChild<A>) -> ()
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $GenericChild<A>):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $GenericChild<A> to $GenericParent<A>
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super13GenericParentC6methodyyFTcTd : $@convention(thin) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]<A>([[BORROWED_CASTED_SELF_COPY]]) : $@convention(thin) <τ_0_0> (@guaranteed GenericParent<τ_0_0>) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super12GenericChildC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super12GenericChildC11classMethodyyFZ : $@convention(method) <A> (@thick GenericChild<A>.Type) -> ()
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GenericChild<A>.Type to $@thick GenericParent<A>.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @$S19partial_apply_super13GenericParentC11classMethodyyFZTcTd : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_guaranteed () -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super12GenericChildC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
+
+class ChildToFixedOutsideParent : OutsideParent {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super25ChildToFixedOutsideParentC6methodyyF
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $ChildToFixedOutsideParent):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $ChildToFixedOutsideParent to $OutsideParent
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = copy_value [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+ // Semantic SIL TODO: This super_method used to take
+ // ChildToFixedOutsideParent. Since super_method IIRC goes through
+ // objc_runtime, this shouldn't matter, but we should look into it before we
+ // turn on +0.
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $OutsideParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideParent) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super25ChildToFixedOutsideParentC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super25ChildToFixedOutsideParentC11classMethodyyFZ
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick ChildToFixedOutsideParent.Type to $@thick OutsideParent.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick ChildToFixedOutsideParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> (){{.*}}
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideParent.Type) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super25ChildToFixedOutsideParentC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
+
+class ChildToResilientOutsideParent : ResilientOutsideParent {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super29ChildToResilientOutsideParentC6methodyyF : $@convention
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $ChildToResilientOutsideParent):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $ChildToResilientOutsideParent to $ResilientOutsideParent
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = copy_value [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ResilientOutsideParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+ // CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super29ChildToResilientOutsideParentC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super29ChildToResilientOutsideParentC11classMethodyyFZ
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick ChildToResilientOutsideParent.Type to $@thick ResilientOutsideParent.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick ChildToResilientOutsideParent.Type, #ResilientOutsideParent.classMethod!1 : (ResilientOutsideParent.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super29ChildToResilientOutsideParentC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
+
+class GrandchildToFixedOutsideChild : OutsideChild {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $GrandchildToFixedOutsideChild):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $GrandchildToFixedOutsideChild to $OutsideChild
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = copy_value [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $OutsideChild, #OutsideChild.method!1 : (OutsideChild) -> () -> (), $@convention(method) (@guaranteed OutsideChild) -> ()
+ // CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideChild) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super29GrandchildToFixedOutsideChildC11classMethodyyFZ
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GrandchildToFixedOutsideChild.Type to $@thick OutsideChild.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GrandchildToFixedOutsideChild.Type, #OutsideChild.classMethod!1 : (OutsideChild.Type) -> () -> (), $@convention(method) (@thick OutsideChild.Type) -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideChild.Type) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super29GrandchildToFixedOutsideChildC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
+
+class GrandchildToResilientOutsideChild : ResilientOutsideChild {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $GrandchildToResilientOutsideChild):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $GrandchildToResilientOutsideChild to $ResilientOutsideChild
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = copy_value [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ResilientOutsideChild, #ResilientOutsideChild.method!1 : (ResilientOutsideChild) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
+ // CHEC: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super33GrandchildToResilientOutsideChildC11classMethodyyFZ
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GrandchildToResilientOutsideChild.Type to $@thick ResilientOutsideChild.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GrandchildToResilientOutsideChild.Type, #ResilientOutsideChild.classMethod!1 : (ResilientOutsideChild.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super33GrandchildToResilientOutsideChildC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
+
+class GenericChildToFixedGenericOutsideParent<A> : GenericOutsideParent<A> {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $GenericChildToFixedGenericOutsideParent<A>):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $GenericChildToFixedGenericOutsideParent<A> to $GenericOutsideParent<A>
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = copy_value [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $GenericOutsideParent<A>, #GenericOutsideParent.method!1 : <A> (GenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
+ // CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super019GenericChildToFixedD13OutsideParentC11classMethodyyFZ
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type to $@thick GenericOutsideParent<A>.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type, #GenericOutsideParent.classMethod!1 : <A> (GenericOutsideParent<A>.Type) -> () -> (), $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super019GenericChildToFixedD13OutsideParentC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
+
+class GenericChildToResilientGenericOutsideParent<A> : ResilientGenericOutsideParent<A> {
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF
+ // CHECK: bb0([[SELF:%.*]] : @guaranteed $GenericChildToResilientGenericOutsideParent<A>):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $GenericChildToResilientGenericOutsideParent<A> to $ResilientGenericOutsideParent<A>
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[CASTED_SELF_COPY:%.*]] = copy_value [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
+ // CHECK: [[DOWNCAST_BORROWED_CASTED_SELF_COPY:%.*]] = unchecked_ref_cast [[BORROWED_CASTED_SELF_COPY]]
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_CASTED_SELF_COPY]] : $ResilientGenericOutsideParent<A>, #ResilientGenericOutsideParent.method!1 : <A> (ResilientGenericOutsideParent<A>) -> () -> (), $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
+ // CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF'
+ override func method() {
+ doFoo(super.method)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19partial_apply_super023GenericChildToResilientD13OutsideParentC11classMethodyyFZ
+ // CHECK: [[CASTED_SELF:%.*]] = upcast %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type to $@thick ResilientGenericOutsideParent<A>.Type
+ // CHECK: [[SUPER_METHOD:%.*]] = super_method %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type, #ResilientGenericOutsideParent.classMethod!1 : <A> (ResilientGenericOutsideParent<A>.Type) -> () -> (), $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
+ // CHECK: [[PARTIAL_APPLY:%.*]] = partial_apply [callee_guaranteed] [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%.*]] = function_ref @$S19partial_apply_super5doFooyyyyXEF : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
+ // CHECK: } // end sil function '$S19partial_apply_super023GenericChildToResilientD13OutsideParentC11classMethodyyFZ'
+ override class func classMethod() {
+ doFoo(super.classMethod)
+ }
+}
diff --git a/test/SILGen/plus_zero_pgo_checked_cast.swift b/test/SILGen/plus_zero_pgo_checked_cast.swift
new file mode 100644
index 0000000..a479e87
--- /dev/null
+++ b/test/SILGen/plus_zero_pgo_checked_cast.swift
@@ -0,0 +1,72 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift %s -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_checked_cast -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-sorted-sil -emit-sil -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=SIL
+// need to lower checked_cast_addr_br(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=IR
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to lower checked_cast_addr_br(addr) into IR for this
+// %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_checked_cast -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+// SIL-LABEL: // pgo_checked_cast.check1<A>(Any, A) -> A
+// SIL-LABEL: sil @$S16pgo_checked_cast6check1yxyp_xtlF : $@convention(thin) <T> (@in_guaranteed Any, @in_guaranteed T) -> @out T !function_entry_count(5001) {
+// IR-LABEL: define swiftcc i32 @$S6pgo_checked_cast6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @$S6pgo_checked_cast6guess1s5Int32VAD1x_tF
+public func check1<T>(_ a : Any, _ t : T) -> T {
+ // SIL: checked_cast_addr_br take_always Any in {{.*}} : $*Any to T in {{.*}} : $*T, {{.*}}, {{.*}} !true_count(5000) !false_count(1)
+ // SIL-OPT: checked_cast_addr_br take_always Any in {{.*}} : $*Any to T in {{.*}} : $*T, {{.*}}, {{.*}} !true_count(5000) !false_count(1)
+ if let x = a as? T {
+ return x
+ } else {
+ return t
+ }
+}
+
+public class B {}
+public class C : B {}
+public class D : C {}
+
+// SIL-LABEL: // pgo_checked_cast.check2(pgo_checked_cast.B) -> Swift.Int32
+// SIL-LABEL: sil @$S16pgo_checked_cast6check2ys5Int32VAA1BCF : $@convention(thin) (@guaranteed B) -> Int32 !function_entry_count(5003) {
+// IR-LABEL: define swiftcc i32 @$S6pgo_checked_cast6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @$S6pgo_checked_cast6guess1s5Int32VAD1x_tF
+public func check2(_ a : B) -> Int32 {
+ // SIL: checked_cast_br %0 : $B to $D, {{.*}}, {{.*}} !true_count(5000)
+ // SIL: checked_cast_br %0 : $B to $C, {{.*}}, {{.*}} !true_count(2)
+ // SIL-OPT: checked_cast_br %0 : $B to $D, {{.*}}, {{.*}} !true_count(5000)
+ // SIL-OPT: checked_cast_br %0 : $B to $C, {{.*}}, {{.*}} !true_count(2)
+ switch a {
+ case is D:
+ return 42
+ case is C:
+ return 23
+ default:
+ return 13
+ }
+}
+
+func main() {
+ let answer : Int32 = 42
+ var sum : Int32 = 0
+
+ sum += check1("The answer to the life, the universe, and everything", answer)
+
+ sum += check2(B())
+ sum += check2(C())
+ sum += check2(C())
+
+ for i : Int32 in 1...5000 {
+ sum += check1(i, answer)
+ sum += check2(D())
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 5001, i32 2}
+// IR-OPT: !{!"branch_weights", i32 5001, i32 2}
diff --git a/test/SILGen/plus_zero_pgo_switchenum.swift b/test/SILGen/plus_zero_pgo_switchenum.swift
new file mode 100644
index 0000000..405912d
--- /dev/null
+++ b/test/SILGen/plus_zero_pgo_switchenum.swift
@@ -0,0 +1,100 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift %s -Xfrontend -enable-sil-ownership -profile-generate -Xfrontend -disable-incremental-llvm-codegen -module-name pgo_switchenum -o %t/main
+// RUN: env LLVM_PROFILE_FILE=%t/default.profraw %target-run %t/main
+// RUN: %llvm-profdata merge %t/default.profraw -o %t/default.profdata
+// need to move counts attached to expr for this
+// RUN: %target-swift-frontend %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -enable-sil-ownership -emit-sorted-sil -emit-sil -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=SIL
+// need to lower switch_enum(addr) into IR for this
+// %target-swift-frontend %s -enable-sil-ownership -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -emit-ir -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=IR
+// need to check Opt support
+// %target-swift-frontend %s -enable-sil-ownership -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-sorted-sil -emit-sil -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=SIL-OPT
+// need to lower switch_enum(addr) into IR for this
+// %target-swift-frontend -enable-sil-ownership %s -Xllvm -sil-full-demangle -profile-use=%t/default.profdata -O -emit-ir -module-name pgo_switchenum -o - | %FileCheck %s --check-prefix=IR-OPT
+
+// REQUIRES: profile_runtime
+// REQUIRES: OS=macosx
+
+public enum MaybePair {
+ case Neither
+ case Left(Int32)
+ case Right(String)
+ case Both(Int32, String)
+}
+
+// SIL-LABEL: // pgo_switchenum.guess1
+// SIL-LABEL: sil @$S14pgo_switchenum6guess11xs5Int32VAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> Int32 !function_entry_count(5011) {
+// IR-LABEL: define swiftcc i32 @$S9pgo_switchenum6guess1s5Int32VAD1x_tF
+// IR-OPT-LABEL: define swiftcc i32 @$S9pgo_switchenum6guess1s5Int32VAD1x_tF
+
+public func guess1(x: MaybePair) -> Int32 {
+ // SIL: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), case #MaybePair.Right!enumelt.1: {{.*}} !case_count(3), case #MaybePair.Both!enumelt.1: {{.*}} !case_count(5)
+ // SIL-OPT: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), case #MaybePair.Right!enumelt.1: {{.*}} !case_count(3), case #MaybePair.Both!enumelt.1: {{.*}} !case_count(5)
+ switch x {
+ case .Neither:
+ return 1
+ case let .Left(val):
+ return val*2
+ case let .Right(val):
+ return Int32(val.count)
+ case let .Both(valNum, valStr):
+ return valNum + Int32(valStr.count)
+ }
+}
+
+// SIL-LABEL: // pgo_switchenum.guess2
+// SIL-LABEL: sil @$S14pgo_switchenum6guess21xs5Int32VAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> Int32 !function_entry_count(5011) {
+public func guess2(x: MaybePair) -> Int32 {
+ // SIL: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), default {{.*}} !default_count(8)
+ // SIL-OPT: switch_enum {{.*}} : $MaybePair, case #MaybePair.Neither!enumelt: {{.*}} !case_count(2), case #MaybePair.Left!enumelt.1: {{.*}} !case_count(5001), default {{.*}} !default_count(8)
+ switch x {
+ case .Neither:
+ return 1
+ case let .Left(val):
+ return val*2
+ default:
+ return 42;
+ }
+}
+
+
+func main() {
+ var guesses : Int32 = 0;
+
+ guesses += guess1(x: MaybePair.Neither)
+ guesses += guess1(x: MaybePair.Neither)
+ guesses += guess1(x: MaybePair.Left(42))
+ guesses += guess1(x: MaybePair.Right("The Answer"))
+ guesses += guess1(x: MaybePair.Right("The Answer"))
+ guesses += guess1(x: MaybePair.Right("The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess1(x: MaybePair.Both(42, "The Answer"))
+
+ for _ in 1...5000 {
+ guesses += guess1(x: MaybePair.Left(10))
+ }
+
+ guesses += guess2(x: MaybePair.Neither)
+ guesses += guess2(x: MaybePair.Neither)
+ guesses += guess2(x: MaybePair.Left(42))
+ guesses += guess2(x: MaybePair.Right("The Answer"))
+ guesses += guess2(x: MaybePair.Right("The Answer"))
+ guesses += guess2(x: MaybePair.Right("The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+ guesses += guess2(x: MaybePair.Both(42, "The Answer"))
+
+ for _ in 1...5000 {
+ guesses += guess2(x: MaybePair.Left(10))
+ }
+}
+
+main()
+
+// IR: !{!"branch_weights", i32 5001, i32 3}
+// IR-OPT: !{!"branch_weights", i32 5001, i32 3}
diff --git a/test/SILGen/plus_zero_pointer_conversion.swift b/test/SILGen/plus_zero_pointer_conversion.swift
new file mode 100644
index 0000000..a07a9cf
--- /dev/null
+++ b/test/SILGen/plus_zero_pointer_conversion.swift
@@ -0,0 +1,457 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
+
+// FIXME: rdar://problem/19648117 Needs splitting objc parts out
+// XFAIL: linux
+
+import Foundation
+
+func sideEffect1() -> Int { return 1 }
+func sideEffect2() -> Int { return 2 }
+func takesMutablePointer(_ x: UnsafeMutablePointer<Int>) {}
+func takesConstPointer(_ x: UnsafePointer<Int>) {}
+func takesOptConstPointer(_ x: UnsafePointer<Int>?, and: Int) {}
+func takesOptOptConstPointer(_ x: UnsafePointer<Int>??, and: Int) {}
+func takesMutablePointer(_ x: UnsafeMutablePointer<Int>, and: Int) {}
+func takesConstPointer(_ x: UnsafePointer<Int>, and: Int) {}
+func takesMutableVoidPointer(_ x: UnsafeMutableRawPointer) {}
+func takesConstVoidPointer(_ x: UnsafeRawPointer) {}
+func takesMutableRawPointer(_ x: UnsafeMutableRawPointer) {}
+func takesConstRawPointer(_ x: UnsafeRawPointer) {}
+func takesOptConstRawPointer(_ x: UnsafeRawPointer?, and: Int) {}
+func takesOptOptConstRawPointer(_ x: UnsafeRawPointer??, and: Int) {}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion0A9ToPointeryySpySiG_SPySiGSvtF
+// CHECK: bb0([[MP:%.*]] : $UnsafeMutablePointer<Int>, [[CP:%.*]] : $UnsafePointer<Int>, [[MRP:%.*]] : $UnsafeMutableRawPointer):
+func pointerToPointer(_ mp: UnsafeMutablePointer<Int>,
+ _ cp: UnsafePointer<Int>, _ mrp: UnsafeMutableRawPointer) {
+
+ // There should be no conversion here
+ takesMutablePointer(mp)
+ // CHECK: [[TAKES_MUTABLE_POINTER:%.*]] = function_ref @$S18pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE_POINTER]]([[MP]])
+
+ takesMutableVoidPointer(mp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeMutableRawPointer>
+ // CHECK: [[TAKES_MUTABLE_VOID_POINTER:%.*]] = function_ref @$S18pointer_conversion23takesMutableVoidPointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE_VOID_POINTER]]
+
+ takesMutableRawPointer(mp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeMutableRawPointer>
+ // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion22takesMutableRawPointeryySvF :
+ // CHECK: apply [[TAKES_MUTABLE_RAW_POINTER]]
+
+ takesConstPointer(mp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafePointer<Int>>
+ // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @$S18pointer_conversion17takesConstPointeryySPySiGF
+ // CHECK: apply [[TAKES_CONST_POINTER]]
+
+ takesConstVoidPointer(mp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @$S18pointer_conversion21takesConstVoidPointeryySVF
+ // CHECK: apply [[TAKES_CONST_VOID_POINTER]]
+
+ takesConstRawPointer(mp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion20takesConstRawPointeryySVF :
+ // CHECK: apply [[TAKES_CONST_RAW_POINTER]]
+
+ takesConstPointer(cp)
+ // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @$S18pointer_conversion17takesConstPointeryySPySiGF
+ // CHECK: apply [[TAKES_CONST_POINTER]]([[CP]])
+
+ takesConstVoidPointer(cp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @$S18pointer_conversion21takesConstVoidPointeryySVF
+ // CHECK: apply [[TAKES_CONST_VOID_POINTER]]
+
+ takesConstRawPointer(cp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion20takesConstRawPointeryySVF
+ // CHECK: apply [[TAKES_CONST_RAW_POINTER]]
+
+ takesConstRawPointer(mrp)
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion20takesConstRawPointeryySVF
+ // CHECK: apply [[TAKES_CONST_RAW_POINTER]]
+}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion14arrayToPointeryyF
+func arrayToPointer() {
+ var ints = [1,2,3]
+
+ takesMutablePointer(&ints)
+ // CHECK: [[CONVERT_MUTABLE:%.*]] = function_ref @$Ss37_convertMutableArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_MUTABLE]]<Int, UnsafeMutablePointer<Int>>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeMutablePointer<Int> on [[OWNER]]
+ // CHECK: [[TAKES_MUTABLE_POINTER:%.*]] = function_ref @$S18pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE_POINTER]]([[DEPENDENT]])
+ // CHECK: destroy_value [[OWNER]]
+
+ takesConstPointer(ints)
+ // CHECK: [[CONVERT_CONST:%.*]] = function_ref @$Ss35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_CONST]]<Int, UnsafePointer<Int>>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafePointer<Int> on [[OWNER]]
+ // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @$S18pointer_conversion17takesConstPointeryySPySiGF
+ // CHECK: apply [[TAKES_CONST_POINTER]]([[DEPENDENT]])
+ // CHECK: destroy_value [[OWNER]]
+
+ takesMutableRawPointer(&ints)
+ // CHECK: [[CONVERT_MUTABLE:%.*]] = function_ref @$Ss37_convertMutableArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_MUTABLE]]<Int, UnsafeMutableRawPointer>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeMutableRawPointer on [[OWNER]]
+ // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion22takesMutableRawPointeryySvF :
+ // CHECK: apply [[TAKES_MUTABLE_RAW_POINTER]]([[DEPENDENT]])
+ // CHECK: destroy_value [[OWNER]]
+
+ takesConstRawPointer(ints)
+ // CHECK: [[CONVERT_CONST:%.*]] = function_ref @$Ss35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_CONST]]<Int, UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion20takesConstRawPointeryySVF :
+ // CHECK: apply [[TAKES_CONST_RAW_POINTER]]([[DEPENDENT]])
+ // CHECK: destroy_value [[OWNER]]
+
+ takesOptConstPointer(ints, and: sideEffect1())
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[CONVERT_CONST:%.*]] = function_ref @$Ss35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_CONST]]<Int, UnsafePointer<Int>>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafePointer<Int> on [[OWNER]]
+ // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafePointer<Int>>, #Optional.some!enumelt.1, [[DEPENDENT]]
+ // CHECK: [[TAKES_OPT_CONST_POINTER:%.*]] = function_ref @$S18pointer_conversion20takesOptConstPointer_3andySPySiGSg_SitF :
+ // CHECK: apply [[TAKES_OPT_CONST_POINTER]]([[OPTPTR]], [[RESULT1]])
+ // CHECK: destroy_value [[OWNER]]
+}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion15stringToPointeryySSF
+func stringToPointer(_ s: String) {
+ takesConstVoidPointer(s)
+ // CHECK: [[CONVERT_STRING:%.*]] = function_ref @$Ss40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_STRING]]<UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+ // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @$S18pointer_conversion21takesConstVoidPointeryySV{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_CONST_VOID_POINTER]]([[DEPENDENT]])
+ // CHECK: destroy_value [[OWNER]]
+
+ takesConstRawPointer(s)
+ // CHECK: [[CONVERT_STRING:%.*]] = function_ref @$Ss40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_STRING]]<UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion20takesConstRawPointeryySV{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_CONST_RAW_POINTER]]([[DEPENDENT]])
+ // CHECK: destroy_value [[OWNER]]
+
+ takesOptConstRawPointer(s, and: sideEffect1())
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[CONVERT_STRING:%.*]] = function_ref @$Ss40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT_STRING]]<UnsafeRawPointer>([[POINTER_BUF:%[0-9]*]],
+ // CHECK: [[POINTER:%.*]] = load [trivial] [[POINTER_BUF]]
+ // CHECK: [[DEPENDENT:%.*]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]]
+ // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafeRawPointer>, #Optional.some!enumelt.1, [[DEPENDENT]]
+ // CHECK: [[TAKES_OPT_CONST_RAW_POINTER:%.*]] = function_ref @$S18pointer_conversion23takesOptConstRawPointer_3andySVSg_SitF :
+ // CHECK: apply [[TAKES_OPT_CONST_RAW_POINTER]]([[OPTPTR]], [[RESULT1]])
+ // CHECK: destroy_value [[OWNER]]
+}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion14inoutToPointeryyF
+func inoutToPointer() {
+ var int = 0
+ // CHECK: [[INT:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[PB:%.*]] = project_box [[INT]]
+ takesMutablePointer(&int)
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @$S18pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE]]
+
+ var logicalInt: Int {
+ get { return 0 }
+ set { }
+ }
+ takesMutablePointer(&logicalInt)
+ // CHECK: [[GETTER:%.*]] = function_ref @$S18pointer_conversion14inoutToPointeryyF10logicalIntL_Sivg
+ // CHECK: apply [[GETTER]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>>
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @$S18pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE]]
+ // CHECK: [[SETTER:%.*]] = function_ref @$S18pointer_conversion14inoutToPointeryyF10logicalIntL_Sivs
+ // CHECK: apply [[SETTER]]
+
+ takesMutableRawPointer(&int)
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @$S18pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE]]
+
+ takesMutableRawPointer(&logicalInt)
+ // CHECK: [[GETTER:%.*]] = function_ref @$S18pointer_conversion14inoutToPointeryyF10logicalIntL_Sivg
+ // CHECK: apply [[GETTER]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer>
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @$S18pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_MUTABLE]]
+ // CHECK: [[SETTER:%.*]] = function_ref @$S18pointer_conversion14inoutToPointeryyF10logicalIntL_Sivs
+ // CHECK: apply [[SETTER]]
+}
+
+class C {}
+
+func takesPlusOnePointer(_ x: UnsafeMutablePointer<C>) {}
+func takesPlusZeroPointer(_ x: AutoreleasingUnsafeMutablePointer<C>) {}
+func takesPlusZeroOptionalPointer(_ x: AutoreleasingUnsafeMutablePointer<C?>) {}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion19classInoutToPointeryyF
+func classInoutToPointer() {
+ var c = C()
+ // CHECK: [[VAR:%.*]] = alloc_box ${ var C }
+ // CHECK: [[PB:%.*]] = project_box [[VAR]]
+ takesPlusOnePointer(&c)
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<UnsafeMutablePointer<C>>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_PLUS_ONE:%.*]] = function_ref @$S18pointer_conversion19takesPlusOnePointer{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[TAKES_PLUS_ONE]]
+
+ takesPlusZeroPointer(&c)
+ // CHECK: [[WRITEBACK:%.*]] = alloc_stack $@sil_unmanaged C
+ // CHECK: [[OWNED:%.*]] = load_borrow [[PB]]
+ // CHECK: [[UNOWNED:%.*]] = ref_to_unmanaged [[OWNED]]
+ // CHECK: store [[UNOWNED]] to [trivial] [[WRITEBACK]]
+ // CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITEBACK]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[CONVERT]]<AutoreleasingUnsafeMutablePointer<C>>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_PLUS_ZERO:%.*]] = function_ref @$S18pointer_conversion20takesPlusZeroPointeryys026AutoreleasingUnsafeMutableF0VyAA1CCGF
+ // CHECK: apply [[TAKES_PLUS_ZERO]]
+ // CHECK: [[UNOWNED_OUT:%.*]] = load [trivial] [[WRITEBACK]]
+ // CHECK: [[OWNED_OUT:%.*]] = unmanaged_to_ref [[UNOWNED_OUT]]
+ // CHECK: [[OWNED_OUT_COPY:%.*]] = copy_value [[OWNED_OUT]]
+ // CHECK: assign [[OWNED_OUT_COPY]] to [[PB]]
+
+ var cq: C? = C()
+ takesPlusZeroOptionalPointer(&cq)
+}
+
+// Check that pointer types don't bridge anymore.
+@objc class ObjCMethodBridging : NSObject {
+ // CHECK-LABEL: sil hidden [thunk] @$S18pointer_conversion18ObjCMethodBridgingC0A4Args{{[_0-9a-zA-Z]*}}FTo : $@convention(objc_method) (UnsafeMutablePointer<Int>, UnsafePointer<Int>, AutoreleasingUnsafeMutablePointer<ObjCMethodBridging>, ObjCMethodBridging)
+ @objc func pointerArgs(_ x: UnsafeMutablePointer<Int>,
+ y: UnsafePointer<Int>,
+ z: AutoreleasingUnsafeMutablePointer<ObjCMethodBridging>) {}
+}
+
+// rdar://problem/21505805
+// CHECK-LABEL: sil hidden @$S18pointer_conversion22functionInoutToPointeryyF
+func functionInoutToPointer() {
+ // CHECK: [[BOX:%.*]] = alloc_box ${ var @callee_guaranteed () -> () }
+ var f: () -> () = {}
+
+ // CHECK: [[REABSTRACT_BUF:%.*]] = alloc_stack $@callee_guaranteed (@in_guaranteed ()) -> @out ()
+ // CHECK: address_to_pointer [[REABSTRACT_BUF]]
+ takesMutableVoidPointer(&f)
+}
+
+// rdar://problem/31781386
+// CHECK-LABEL: sil hidden @$S18pointer_conversion20inoutPointerOrderingyyF
+func inoutPointerOrdering() {
+ // CHECK: [[ARRAY_BOX:%.*]] = alloc_box ${ var Array<Int> }
+ // CHECK: [[ARRAY:%.*]] = project_box [[ARRAY_BOX]] :
+ // CHECK: store {{.*}} to [init] [[ARRAY]]
+ var array = [Int]()
+
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[SIDE2:%.*]] = function_ref @$S18pointer_conversion11sideEffect2SiyF
+ // CHECK: [[RESULT2:%.*]] = apply [[SIDE2]]()
+ // CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[ARRAY]] : $*Array<Int>
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @$S18pointer_conversion19takesMutablePointer_3andySpySiG_SitF
+ // CHECK: apply [[TAKES_MUTABLE]]({{.*}}, [[RESULT2]])
+ // CHECK: strong_unpin
+ // CHECK: end_access [[ACCESS]]
+ takesMutablePointer(&array[sideEffect1()], and: sideEffect2())
+
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[SIDE2:%.*]] = function_ref @$S18pointer_conversion11sideEffect2SiyF
+ // CHECK: [[RESULT2:%.*]] = apply [[SIDE2]]()
+ // CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[ARRAY]] : $*Array<Int>
+ // CHECK: [[TAKES_CONST:%.*]] = function_ref @$S18pointer_conversion17takesConstPointer_3andySPySiG_SitF
+ // CHECK: apply [[TAKES_CONST]]({{.*}}, [[RESULT2]])
+ // CHECK: end_access [[ACCESS]]
+ takesConstPointer(&array[sideEffect1()], and: sideEffect2())
+}
+
+// rdar://problem/31542269
+// CHECK-LABEL: sil hidden @$S18pointer_conversion20optArrayToOptPointer5arrayySaySiGSg_tF
+func optArrayToOptPointer(array: [Int]?) {
+ // CHECK: [[COPY:%.*]] = copy_value %0
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[T0:%.*]] = select_enum [[COPY]]
+ // CHECK: cond_br [[T0]], [[SOME_BB:bb[0-9]+]], [[NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_BB]]:
+ // CHECK: [[SOME_VALUE:%.*]] = unchecked_enum_data [[COPY]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss35_convertConstArrayToPointerArgumentyyXlSg_q_tSayxGs01_E0R_r0_lF
+ // CHECK: [[TEMP:%.*]] = alloc_stack $UnsafePointer<Int>
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT]]<Int, UnsafePointer<Int>>([[TEMP:%.*]], [[SOME_VALUE]])
+ // CHECK: [[PTR:%.*]] = load [trivial] [[TEMP]]
+ // CHECK: [[DEP:%.*]] = mark_dependence [[PTR]] : $UnsafePointer<Int> on [[OWNER]]
+ // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafePointer<Int>>, #Optional.some!enumelt.1, [[DEP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: br [[CONT_BB:bb[0-9]+]]([[OPTPTR]] : $Optional<UnsafePointer<Int>>, [[OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[CONT_BB]]([[OPTPTR:%.*]] : $Optional<UnsafePointer<Int>>, [[OWNER:%.*]] : $Optional<AnyObject>):
+ // CHECK: [[OPTDEP:%.*]] = mark_dependence [[OPTPTR]] : $Optional<UnsafePointer<Int>> on [[OWNER]]
+ // CHECK: [[TAKES:%.*]] = function_ref @$S18pointer_conversion20takesOptConstPointer_3andySPySiGSg_SitF
+ // CHECK: apply [[TAKES]]([[OPTDEP]], [[RESULT1]])
+ // CHECK: destroy_value [[OWNER]]
+ // CHECK-NOT: destroy_value %0
+ // CHECK: [[NONE_BB]]:
+ // CHECK: [[NO_VALUE:%.*]] = enum $Optional<UnsafePointer<Int>>, #Optional.none
+ // CHECK: [[NO_OWNER:%.*]] = enum $Optional<AnyObject>, #Optional.none
+ // CHECK: br [[CONT_BB]]([[NO_VALUE]] : $Optional<UnsafePointer<Int>>, [[NO_OWNER]] : $Optional<AnyObject>)
+ takesOptConstPointer(array, and: sideEffect1())
+}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion013optOptArrayTodD7Pointer5arrayySaySiGSgSg_tF
+func optOptArrayToOptOptPointer(array: [Int]??) {
+ // CHECK: [[COPY:%.*]] = copy_value %0
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[T0:%.*]] = select_enum [[COPY]]
+ // CHECK: cond_br [[T0]], [[SOME_BB:bb[0-9]+]], [[NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_BB]]:
+ // CHECK: [[SOME_VALUE:%.*]] = unchecked_enum_data [[COPY]]
+ // CHECK: [[T0:%.*]] = select_enum [[SOME_VALUE]]
+ // CHECK: cond_br [[T0]], [[SOME_SOME_BB:bb[0-9]+]], [[SOME_NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_NONE_BB]]:
+ // CHECK: destroy_value [[SOME_VALUE]]
+ // CHECK: br [[SOME_NONE_BB2:bb[0-9]+]]
+ // CHECK: [[SOME_SOME_BB]]:
+ // CHECK: [[SOME_SOME_VALUE:%.*]] = unchecked_enum_data [[SOME_VALUE]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss35_convertConstArrayToPointerArgumentyyXlSg_q_tSayxGs01_E0R_r0_lF
+ // CHECK: [[TEMP:%.*]] = alloc_stack $UnsafePointer<Int>
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT]]<Int, UnsafePointer<Int>>([[TEMP:%.*]], [[SOME_SOME_VALUE]])
+ // CHECK: [[PTR:%.*]] = load [trivial] [[TEMP]]
+ // CHECK: [[DEP:%.*]] = mark_dependence [[PTR]] : $UnsafePointer<Int> on [[OWNER]]
+ // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafePointer<Int>>, #Optional.some!enumelt.1, [[DEP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: br [[SOME_SOME_CONT_BB:bb[0-9]+]]([[OPTPTR]] : $Optional<UnsafePointer<Int>>, [[OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[SOME_SOME_CONT_BB]]([[OPTPTR:%.*]] : $Optional<UnsafePointer<Int>>, [[OWNER:%.*]] : $Optional<AnyObject>):
+ // CHECK: [[OPTDEP:%.*]] = mark_dependence [[OPTPTR]] : $Optional<UnsafePointer<Int>> on [[OWNER]]
+ // CHECK: [[OPTOPTPTR:%.*]] = enum $Optional<Optional<UnsafePointer<Int>>>, #Optional.some!enumelt.1, [[OPTDEP]]
+ // CHECK: br [[SOME_CONT_BB:bb[0-9]+]]([[OPTOPTPTR]] : $Optional<Optional<UnsafePointer<Int>>>, [[OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[SOME_CONT_BB]]([[OPTOPTPTR:%.*]] : $Optional<Optional<UnsafePointer<Int>>>, [[OWNER:%.*]] : $Optional<AnyObject>):
+ // CHECK: [[OPTOPTDEP:%.*]] = mark_dependence [[OPTOPTPTR]] : $Optional<Optional<UnsafePointer<Int>>> on [[OWNER]]
+ // CHECK: [[TAKES:%.*]] = function_ref @$S18pointer_conversion08takesOptD12ConstPointer_3andySPySiGSgSg_SitF
+ // CHECK: apply [[TAKES]]([[OPTOPTDEP]], [[RESULT1]])
+ // CHECK: destroy_value [[OWNER]]
+ // CHECK-NOT: destroy_value %0
+ // CHECK: [[SOME_NONE_BB2]]:
+ // CHECK: [[NO_VALUE:%.*]] = enum $Optional<UnsafePointer<Int>>, #Optional.none
+ // CHECK: [[NO_OWNER:%.*]] = enum $Optional<AnyObject>, #Optional.none
+ // CHECK: br [[SOME_SOME_CONT_BB]]([[NO_VALUE]] : $Optional<UnsafePointer<Int>>, [[NO_OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[NONE_BB]]:
+ // CHECK: [[NO_VALUE:%.*]] = enum $Optional<Optional<UnsafePointer<Int>>>, #Optional.none
+ // CHECK: [[NO_OWNER:%.*]] = enum $Optional<AnyObject>, #Optional.none
+ // CHECK: br [[SOME_CONT_BB]]([[NO_VALUE]] : $Optional<Optional<UnsafePointer<Int>>>, [[NO_OWNER]] : $Optional<AnyObject>)
+ takesOptOptConstPointer(array, and: sideEffect1())
+}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion21optStringToOptPointer6stringySSSg_tF
+func optStringToOptPointer(string: String?) {
+ // CHECK: [[COPY:%.*]] = copy_value %0
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[T0:%.*]] = select_enum [[COPY]]
+ // CHECK: cond_br [[T0]], [[SOME_BB:bb[0-9]+]], [[NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_BB]]:
+ // CHECK: [[SOME_VALUE:%.*]] = unchecked_enum_data [[COPY]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss40_convertConstStringToUTF8PointerArgumentyyXlSg_xtSSs01_F0RzlF
+ // CHECK: [[TEMP:%.*]] = alloc_stack $UnsafeRawPointer
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT]]<UnsafeRawPointer>([[TEMP:%.*]], [[SOME_VALUE]])
+ // CHECK: [[PTR:%.*]] = load [trivial] [[TEMP]]
+ // CHECK: [[DEP:%.*]] = mark_dependence [[PTR]] : $UnsafeRawPointer on [[OWNER]]
+ // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafeRawPointer>, #Optional.some!enumelt.1, [[DEP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: br [[CONT_BB:bb[0-9]+]]([[OPTPTR]] : $Optional<UnsafeRawPointer>, [[OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[CONT_BB]]([[OPTPTR:%.*]] : $Optional<UnsafeRawPointer>, [[OWNER:%.*]] : $Optional<AnyObject>):
+ // CHECK: [[OPTDEP:%.*]] = mark_dependence [[OPTPTR]] : $Optional<UnsafeRawPointer> on [[OWNER]]
+ // CHECK: [[TAKES:%.*]] = function_ref @$S18pointer_conversion23takesOptConstRawPointer_3andySVSg_SitF
+ // CHECK: apply [[TAKES]]([[OPTDEP]], [[RESULT1]])
+ // CHECK: destroy_value [[OWNER]]
+ // CHECK-NOT: destroy_value %0
+ // CHECK: [[NONE_BB]]:
+ // CHECK: [[NO_VALUE:%.*]] = enum $Optional<UnsafeRawPointer>, #Optional.none
+ // CHECK: [[NO_OWNER:%.*]] = enum $Optional<AnyObject>, #Optional.none
+ // CHECK: br [[CONT_BB]]([[NO_VALUE]] : $Optional<UnsafeRawPointer>, [[NO_OWNER]] : $Optional<AnyObject>)
+ takesOptConstRawPointer(string, and: sideEffect1())
+}
+
+// CHECK-LABEL: sil hidden @$S18pointer_conversion014optOptStringTodD7Pointer6stringySSSgSg_tF
+func optOptStringToOptOptPointer(string: String??) {
+ // CHECK: [[COPY:%.*]] = copy_value %0
+ // CHECK: [[SIDE1:%.*]] = function_ref @$S18pointer_conversion11sideEffect1SiyF
+ // CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
+ // CHECK: [[T0:%.*]] = select_enum [[COPY]]
+ // FIXME: this should really go somewhere that will make nil, not some(nil)
+ // CHECK: cond_br [[T0]], [[SOME_BB:bb[0-9]+]], [[NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_BB]]:
+ // CHECK: [[SOME_VALUE:%.*]] = unchecked_enum_data [[COPY]]
+ // CHECK: [[T0:%.*]] = select_enum [[SOME_VALUE]]
+ // CHECK: cond_br [[T0]], [[SOME_SOME_BB:bb[0-9]+]], [[SOME_NONE_BB:bb[0-9]+]]
+ // CHECK: [[SOME_NONE_BB]]:
+ // CHECK: destroy_value [[SOME_VALUE]]
+ // CHECK: br [[SOME_NONE_BB2:bb[0-9]+]]
+ // CHECK: [[SOME_SOME_BB]]:
+ // CHECK: [[SOME_SOME_VALUE:%.*]] = unchecked_enum_data [[SOME_VALUE]]
+ // CHECK: [[CONVERT:%.*]] = function_ref @$Ss40_convertConstStringToUTF8PointerArgumentyyXlSg_xtSSs01_F0RzlF
+ // CHECK: [[TEMP:%.*]] = alloc_stack $UnsafeRawPointer
+ // CHECK: [[OWNER:%.*]] = apply [[CONVERT]]<UnsafeRawPointer>([[TEMP:%.*]], [[SOME_SOME_VALUE]])
+ // CHECK: [[PTR:%.*]] = load [trivial] [[TEMP]]
+ // CHECK: [[DEP:%.*]] = mark_dependence [[PTR]] : $UnsafeRawPointer on [[OWNER]]
+ // CHECK: [[OPTPTR:%.*]] = enum $Optional<UnsafeRawPointer>, #Optional.some!enumelt.1, [[DEP]]
+ // CHECK: dealloc_stack [[TEMP]]
+ // CHECK: br [[SOME_SOME_CONT_BB:bb[0-9]+]]([[OPTPTR]] : $Optional<UnsafeRawPointer>, [[OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[SOME_SOME_CONT_BB]]([[OPTPTR:%.*]] : $Optional<UnsafeRawPointer>, [[OWNER:%.*]] : $Optional<AnyObject>):
+ // CHECK: [[OPTDEP:%.*]] = mark_dependence [[OPTPTR]] : $Optional<UnsafeRawPointer> on [[OWNER]]
+ // CHECK: [[OPTOPTPTR:%.*]] = enum $Optional<Optional<UnsafeRawPointer>>, #Optional.some!enumelt.1, [[OPTDEP]]
+ // CHECK: br [[SOME_CONT_BB:bb[0-9]+]]([[OPTOPTPTR]] : $Optional<Optional<UnsafeRawPointer>>, [[OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[SOME_CONT_BB]]([[OPTOPTPTR:%.*]] : $Optional<Optional<UnsafeRawPointer>>, [[OWNER:%.*]] : $Optional<AnyObject>):
+ // CHECK: [[OPTOPTDEP:%.*]] = mark_dependence [[OPTOPTPTR]] : $Optional<Optional<UnsafeRawPointer>> on [[OWNER]]
+ // CHECK: [[TAKES:%.*]] = function_ref @$S18pointer_conversion08takesOptD15ConstRawPointer_3andySVSgSg_SitF
+ // CHECK: apply [[TAKES]]([[OPTOPTDEP]], [[RESULT1]])
+ // CHECK: destroy_value [[OWNER]]
+ // CHECK: end_borrow [[BORROW]]
+ // CHECK: destroy_value %0
+ // CHECK: [[SOME_NONE_BB2]]:
+ // CHECK: [[NO_VALUE:%.*]] = enum $Optional<UnsafeRawPointer>, #Optional.none
+ // CHECK: [[NO_OWNER:%.*]] = enum $Optional<AnyObject>, #Optional.none
+ // CHECK: br [[SOME_SOME_CONT_BB]]([[NO_VALUE]] : $Optional<UnsafeRawPointer>, [[NO_OWNER]] : $Optional<AnyObject>)
+ // CHECK: [[NONE_BB]]:
+ // CHECK: [[NO_VALUE:%.*]] = enum $Optional<Optional<UnsafeRawPointer>>, #Optional.none
+ // CHECK: [[NO_OWNER:%.*]] = enum $Optional<AnyObject>, #Optional.none
+ // CHECK: br [[SOME_CONT_BB]]([[NO_VALUE]] : $Optional<Optional<UnsafeRawPointer>>, [[NO_OWNER]] : $Optional<AnyObject>)
+ takesOptOptConstRawPointer(string, and: sideEffect1())
+}
diff --git a/test/SILGen/plus_zero_properties.swift b/test/SILGen/plus_zero_properties.swift
new file mode 100644
index 0000000..76dd9c9
--- /dev/null
+++ b/test/SILGen/plus_zero_properties.swift
@@ -0,0 +1,1191 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
+
+var zero: Int = 0
+
+func use(_: Int) {}
+func use(_: Double) {}
+func getInt() -> Int { return zero }
+
+// CHECK-LABEL: sil hidden @{{.*}}physical_tuple_lvalue
+// CHECK: bb0(%0 : $Int):
+func physical_tuple_lvalue(_ c: Int) {
+ var x : (Int, Int)
+ // CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[MARKED_BOX:%[0-9]+]] = mark_uninitialized [var] [[BOX]]
+ // CHECK: [[XADDR:%.*]] = project_box [[MARKED_BOX]]
+ x.1 = c
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[XADDR]]
+ // CHECK: [[X_1:%[0-9]+]] = tuple_element_addr [[WRITE]] : {{.*}}, 1
+ // CHECK: assign %0 to [[X_1]]
+}
+
+func tuple_rvalue() -> (Int, Int) {}
+
+// CHECK-LABEL: sil hidden @{{.*}}physical_tuple_rvalue
+func physical_tuple_rvalue() -> Int {
+ return tuple_rvalue().1
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S10properties12tuple_rvalue{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[TUPLE:%[0-9]+]] = apply [[FUNC]]()
+ // CHECK: [[RET:%[0-9]+]] = tuple_extract [[TUPLE]] : {{.*}}, 1
+ // CHECK: return [[RET]]
+}
+
+// CHECK-LABEL: sil hidden @$S10properties16tuple_assignment{{[_0-9a-zA-Z]*}}F
+func tuple_assignment(_ a: inout Int, b: inout Int) {
+ // CHECK: bb0([[A_ADDR:%[0-9]+]] : $*Int, [[B_ADDR:%[0-9]+]] : $*Int):
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[B_ADDR]]
+ // CHECK: [[B:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[A_ADDR]]
+ // CHECK: [[A:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[A_ADDR]]
+ // CHECK: assign [[B]] to [[WRITE]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[B_ADDR]]
+ // CHECK: assign [[A]] to [[WRITE]]
+ (a, b) = (b, a)
+}
+
+// CHECK-LABEL: sil hidden @$S10properties18tuple_assignment_2{{[_0-9a-zA-Z]*}}F
+func tuple_assignment_2(_ a: inout Int, b: inout Int, xy: (Int, Int)) {
+ // CHECK: bb0([[A_ADDR:%[0-9]+]] : $*Int, [[B_ADDR:%[0-9]+]] : $*Int, [[X:%[0-9]+]] : $Int, [[Y:%[0-9]+]] : $Int):
+ (a, b) = xy
+ // CHECK: [[XY2:%[0-9]+]] = tuple ([[X]] : $Int, [[Y]] : $Int)
+ // CHECK: [[X:%[0-9]+]] = tuple_extract [[XY2]] : {{.*}}, 0
+ // CHECK: [[Y:%[0-9]+]] = tuple_extract [[XY2]] : {{.*}}, 1
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[A_ADDR]]
+ // CHECK: assign [[X]] to [[WRITE]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[B_ADDR]]
+ // CHECK: assign [[Y]] to [[WRITE]]
+}
+
+class Ref {
+ var x, y : Int
+ var ref : Ref
+
+ var z: Int { get {} set {} }
+
+ var val_prop: Val { get {} set {} }
+
+ subscript(i: Int) -> Float { get {} set {} }
+
+ init(i: Int) {
+ x = i
+ y = i
+ ref = self
+ }
+}
+
+class RefSubclass : Ref {
+ var w : Int
+
+ override init (i: Int) {
+ w = i
+ super.init(i: i)
+ }
+}
+
+struct Val {
+ var x, y : Int
+ var ref : Ref
+
+ var z: Int { get {} set {} }
+
+ var z_tuple: (Int, Int) { get {} set {} }
+
+ subscript(i: Int) -> Float { get {} set {} }
+}
+
+// CHECK-LABEL: sil hidden @$S10properties22physical_struct_lvalue{{[_0-9a-zA-Z]*}}F
+func physical_struct_lvalue(_ c: Int) {
+ var v : Val
+ // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
+ v.y = c
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown]
+ // CHECK: [[YADDR:%.*]] = struct_element_addr [[WRITE]]
+ // CHECK: assign %0 to [[YADDR]]
+}
+
+// CHECK-LABEL: sil hidden @$S10properties21physical_class_lvalue{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed Ref, Int) -> ()
+// CHECK: bb0([[ARG0:%.*]] : $Ref,
+ func physical_class_lvalue(_ r: Ref, a: Int) {
+ r.y = a
+ // CHECK: [[FN:%[0-9]+]] = class_method [[ARG0]] : $Ref, #Ref.y!setter.1
+ // CHECK: apply [[FN]](%1, [[ARG0]]) : $@convention(method) (Int, @guaranteed Ref) -> ()
+ }
+
+
+// CHECK-LABEL: sil hidden @$S10properties24physical_subclass_lvalue{{[_0-9a-zA-Z]*}}F
+func physical_subclass_lvalue(_ r: RefSubclass, a: Int) {
+ // CHECK: bb0([[ARG1:%.*]] : $RefSubclass, [[ARG2:%.*]] : $Int):
+ r.y = a
+ // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] : $RefSubclass
+ // CHECK: [[R_SUP:%[0-9]+]] = upcast [[ARG1_COPY]] : $RefSubclass to $Ref
+ // CHECK: [[FN:%[0-9]+]] = class_method [[R_SUP]] : $Ref, #Ref.y!setter.1 : (Ref) -> (Int) -> (), $@convention(method) (Int, @guaranteed Ref) -> ()
+ // CHECK: apply [[FN]]([[ARG2]], [[R_SUP]]) :
+ // CHECK: destroy_value [[R_SUP]]
+ r.w = a
+
+ // CHECK: [[FN:%[0-9]+]] = class_method [[ARG1]] : $RefSubclass, #RefSubclass.w!setter.1
+ // CHECK: apply [[FN]](%1, [[ARG1]]) : $@convention(method) (Int, @guaranteed RefSubclass) -> ()
+ // CHECK-NOT: destroy_value [[ARG1]]
+ // CHECK: } // end sil function '$S10properties24physical_subclass_lvalue{{[_0-9a-zA-Z]*}}F'
+}
+
+
+
+func struct_rvalue() -> Val {}
+
+// CHECK-LABEL: sil hidden @$S10properties22physical_struct_rvalue{{[_0-9a-zA-Z]*}}F
+func physical_struct_rvalue() -> Int {
+ return struct_rvalue().y
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S10properties13struct_rvalueAA3ValVyF
+ // CHECK: [[STRUCT:%[0-9]+]] = apply [[FUNC]]()
+ // CHECK: [[BORROWED_STRUCT:%.*]] = begin_borrow [[STRUCT]]
+ // CHECK: [[RET:%[0-9]+]] = struct_extract [[BORROWED_STRUCT]] : $Val, #Val.y
+ // CHECK: end_borrow [[BORROWED_STRUCT]] from [[STRUCT]]
+ // CHECK: destroy_value [[STRUCT]]
+ // CHECK: return [[RET]]
+}
+
+func class_rvalue() -> Ref {}
+
+// CHECK-LABEL: sil hidden @$S10properties21physical_class_rvalue{{[_0-9a-zA-Z]*}}F
+func physical_class_rvalue() -> Int {
+ return class_rvalue().y
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @$S10properties12class_rvalueAA3RefCyF
+ // CHECK: [[CLASS:%[0-9]+]] = apply [[FUNC]]()
+ // CHECK: [[FN:%[0-9]+]] = class_method [[CLASS]] : $Ref, #Ref.y!getter.1
+ // CHECK: [[RET:%[0-9]+]] = apply [[FN]]([[CLASS]])
+ // CHECK: return [[RET]]
+}
+
+// CHECK-LABEL: sil hidden @$S10properties18logical_struct_get{{[_0-9a-zA-Z]*}}F
+func logical_struct_get() -> Int {
+ return struct_rvalue().z
+ // CHECK: [[GET_RVAL:%[0-9]+]] = function_ref @$S10properties13struct_rvalue{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[STRUCT:%[0-9]+]] = apply [[GET_RVAL]]()
+ // CHECK: [[GET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV1z{{[_0-9a-zA-Z]*}}vg
+ // CHECK: [[VALUE:%[0-9]+]] = apply [[GET_METHOD]]([[STRUCT]])
+ // CHECK: return [[VALUE]]
+}
+
+// CHECK-LABEL: sil hidden @$S10properties18logical_struct_set{{[_0-9a-zA-Z]*}}F
+func logical_struct_set(_ value: inout Val, z: Int) {
+ // CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z:%[0-9]+]] : $Int):
+ value.z = z
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
+ // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV1z{{[_0-9a-zA-Z]*}}vs
+ // CHECK: apply [[Z_SET_METHOD]]([[Z]], [[WRITE]])
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S10properties27logical_struct_in_tuple_set{{[_0-9a-zA-Z]*}}F
+func logical_struct_in_tuple_set(_ value: inout (Int, Val), z: Int) {
+ // CHECK: bb0([[VAL:%[0-9]+]] : $*(Int, Val), [[Z:%[0-9]+]] : $Int):
+ value.1.z = z
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
+ // CHECK: [[VAL_1:%[0-9]+]] = tuple_element_addr [[WRITE]] : {{.*}}, 1
+ // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV1z{{[_0-9a-zA-Z]*}}vs
+ // CHECK: apply [[Z_SET_METHOD]]([[Z]], [[VAL_1]])
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S10properties29logical_struct_in_reftype_set{{[_0-9a-zA-Z]*}}F
+func logical_struct_in_reftype_set(_ value: inout Val, z1: Int) {
+ // CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z1:%[0-9]+]] : $Int):
+ value.ref.val_prop.z_tuple.1 = z1
+ // -- val.ref
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[VAL]]
+ // CHECK: [[VAL_REF_ADDR:%[0-9]+]] = struct_element_addr [[READ]] : $*Val, #Val.ref
+ // CHECK: [[VAL_REF:%[0-9]+]] = load [copy] [[VAL_REF_ADDR]]
+ // -- getters and setters
+ // -- val.ref.val_prop
+ // CHECK: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
+ // CHECK: [[VAL_REF_VAL_PROP_TEMP:%.*]] = alloc_stack $Val
+ // CHECK: [[VAL_REF_BORROWED:%.*]] = begin_borrow [[VAL_REF]]
+ // CHECK: [[T0:%.*]] = address_to_pointer [[VAL_REF_VAL_PROP_TEMP]] : $*Val to $Builtin.RawPointer
+ // CHECK: [[MAT_VAL_PROP_METHOD:%[0-9]+]] = class_method {{.*}} : $Ref, #Ref.val_prop!materializeForSet.1 : (Ref) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?)
+ // CHECK: [[MAT_RESULT:%[0-9]+]] = apply [[MAT_VAL_PROP_METHOD]]([[T0]], [[STORAGE]], [[VAL_REF_BORROWED]])
+ // CHECK: [[T0:%.*]] = tuple_extract [[MAT_RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
+ // CHECK: [[OPT_CALLBACK:%.*]] = tuple_extract [[MAT_RESULT]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 1
+ // CHECK: [[T1:%[0-9]+]] = pointer_to_address [[T0]] : $Builtin.RawPointer to [strict] $*Val
+ // CHECK: [[VAL_REF_VAL_PROP_MAT:%.*]] = mark_dependence [[T1]] : $*Val on [[VAL_REF]]
+ // CHECK: end_borrow [[VAL_REF_BORROWED]] from [[VAL_REF]]
+ // -- val.ref.val_prop.z_tuple
+ // CHECK: [[V_R_VP_Z_TUPLE_MAT:%[0-9]+]] = alloc_stack $(Int, Int)
+ // CHECK: [[LD:%[0-9]+]] = load_borrow [[VAL_REF_VAL_PROP_MAT]]
+ // CHECK: [[A0:%.*]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 0
+ // CHECK: [[A1:%.*]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 1
+ // CHECK: [[GET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV7z_tupleSi_Sitvg
+ // CHECK: [[V_R_VP_Z_TUPLE:%[0-9]+]] = apply [[GET_Z_TUPLE_METHOD]]([[LD]])
+ // CHECK: [[T0:%.*]] = tuple_extract [[V_R_VP_Z_TUPLE]] : {{.*}}, 0
+ // CHECK: [[T1:%.*]] = tuple_extract [[V_R_VP_Z_TUPLE]] : {{.*}}, 1
+ // CHECK: store [[T0]] to [trivial] [[A0]]
+ // CHECK: store [[T1]] to [trivial] [[A1]]
+ // CHECK: end_borrow [[LD]] from [[VAL_REF_VAL_PROP_MAT]]
+ // -- write to val.ref.val_prop.z_tuple.1
+ // CHECK: [[V_R_VP_Z_TUPLE_1:%[0-9]+]] = tuple_element_addr [[V_R_VP_Z_TUPLE_MAT]] : {{.*}}, 1
+ // CHECK: assign [[Z1]] to [[V_R_VP_Z_TUPLE_1]]
+ // -- writeback to val.ref.val_prop.z_tuple
+ // CHECK: [[WB_V_R_VP_Z_TUPLE:%[0-9]+]] = load [trivial] [[V_R_VP_Z_TUPLE_MAT]]
+ // CHECK: [[SET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV7z_tupleSi_Sitvs
+ // CHECK: apply [[SET_Z_TUPLE_METHOD]]({{%[0-9]+, %[0-9]+}}, [[VAL_REF_VAL_PROP_MAT]])
+ // -- writeback to val.ref.val_prop
+ // CHECK: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
+ // CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
+ // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Ref, @thick Ref.Type) -> ()
+ // CHECK: [[REF_MAT:%.*]] = alloc_stack $Ref
+ // CHECK: store [[VAL_REF]] to [init] [[REF_MAT]]
+ // CHECK: [[T0:%.*]] = metatype $@thick Ref.Type
+ // CHECK: [[T1:%.*]] = address_to_pointer [[VAL_REF_VAL_PROP_MAT]]
+ // CHECK: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[REF_MAT]], [[T0]])
+ // CHECK: br [[CONT]]
+ // CHECK: [[CONT]]:
+ // -- cleanup
+ // CHECK: dealloc_stack [[V_R_VP_Z_TUPLE_MAT]]
+ // CHECK: dealloc_stack [[VAL_REF_VAL_PROP_TEMP]]
+ // -- don't need to write back to val.ref because it's a ref type
+}
+
+func reftype_rvalue() -> Ref {}
+
+// CHECK-LABEL: sil hidden @$S10properties18reftype_rvalue_set{{[_0-9a-zA-Z]*}}F
+func reftype_rvalue_set(_ value: Val) {
+ reftype_rvalue().val_prop = value
+}
+
+// CHECK-LABEL: sil hidden @$S10properties27tuple_in_logical_struct_set{{[_0-9a-zA-Z]*}}F
+func tuple_in_logical_struct_set(_ value: inout Val, z1: Int) {
+ // CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z1:%[0-9]+]] : $Int):
+ value.z_tuple.1 = z1
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
+ // CHECK: [[Z_TUPLE_MATERIALIZED:%[0-9]+]] = alloc_stack $(Int, Int)
+ // CHECK: [[VAL1:%[0-9]+]] = load_borrow [[WRITE]]
+ // CHECK: [[A0:%.*]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 0
+ // CHECK: [[A1:%.*]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 1
+ // CHECK: [[Z_GET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV7z_tupleSi_Sitvg
+ // CHECK: [[Z_TUPLE:%[0-9]+]] = apply [[Z_GET_METHOD]]([[VAL1]])
+ // CHECK: [[T0:%.*]] = tuple_extract [[Z_TUPLE]] : {{.*}}, 0
+ // CHECK: [[T1:%.*]] = tuple_extract [[Z_TUPLE]] : {{.*}}, 1
+ // CHECK: store [[T0]] to [trivial] [[A0]]
+ // CHECK: store [[T1]] to [trivial] [[A1]]
+ // CHECK: end_borrow [[VAL1]] from [[WRITE]]
+ // CHECK: [[Z_TUPLE_1:%[0-9]+]] = tuple_element_addr [[Z_TUPLE_MATERIALIZED]] : {{.*}}, 1
+ // CHECK: assign [[Z1]] to [[Z_TUPLE_1]]
+ // CHECK: [[Z_TUPLE_MODIFIED:%[0-9]+]] = load [trivial] [[Z_TUPLE_MATERIALIZED]]
+ // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV7z_tupleSi_Sitvs
+ // CHECK: apply [[Z_SET_METHOD]]({{%[0-9]+, %[0-9]+}}, [[WRITE]])
+ // CHECK: dealloc_stack [[Z_TUPLE_MATERIALIZED]]
+ // CHECK: return
+}
+
+var global_prop : Int {
+ // CHECK-LABEL: sil hidden @$S10properties11global_prop{{[_0-9a-zA-Z]*}}vg
+ get {
+ return zero
+ }
+ // CHECK-LABEL: sil hidden @$S10properties11global_prop{{[_0-9a-zA-Z]*}}vs
+ set {
+ use(newValue)
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10properties18logical_global_get{{[_0-9a-zA-Z]*}}F
+func logical_global_get() -> Int {
+ return global_prop
+ // CHECK: [[GET:%[0-9]+]] = function_ref @$S10properties11global_prop{{[_0-9a-zA-Z]*}}vg
+ // CHECK: [[VALUE:%[0-9]+]] = apply [[GET]]()
+ // CHECK: return [[VALUE]]
+}
+
+// CHECK-LABEL: sil hidden @$S10properties18logical_global_set{{[_0-9a-zA-Z]*}}F
+func logical_global_set(_ x: Int) {
+ global_prop = x
+ // CHECK: [[SET:%[0-9]+]] = function_ref @$S10properties11global_prop{{[_0-9a-zA-Z]*}}vs
+ // CHECK: apply [[SET]](%0)
+}
+
+// CHECK-LABEL: sil hidden @$S10properties17logical_local_get{{[_0-9a-zA-Z]*}}F
+func logical_local_get(_ x: Int) -> Int {
+ var prop : Int {
+ get {
+ return x
+ }
+ }
+ // CHECK: [[GET_REF:%[0-9]+]] = function_ref [[PROP_GET_CLOSURE:@\$S10properties17logical_local_getyS2iF4propL_Sivg]]
+ // CHECK: apply [[GET_REF]](%0)
+ return prop
+}
+// CHECK-: sil private [[PROP_GET_CLOSURE]]
+// CHECK: bb0(%{{[0-9]+}} : $Int):
+
+func logical_generic_local_get<T>(_ x: Int, _: T) {
+ var prop1: Int {
+ get {
+ return x
+ }
+ }
+
+ _ = prop1
+
+ var prop2: Int {
+ get {
+ _ = T.self
+ return x
+ }
+ }
+
+ _ = prop2
+}
+
+// CHECK-LABEL: sil hidden @$S10properties26logical_local_captured_get{{[_0-9a-zA-Z]*}}F
+func logical_local_captured_get(_ x: Int) -> Int {
+ var prop : Int {
+ get {
+ return x
+ }
+ }
+ func get_prop() -> Int {
+ return prop
+ }
+
+ return get_prop()
+ // CHECK: [[FUNC_REF:%[0-9]+]] = function_ref @$S10properties26logical_local_captured_getyS2iF0E5_propL_SiyF
+ // CHECK: apply [[FUNC_REF]](%0)
+}
+// CHECK: sil private @$S10properties26logical_local_captured_get{{.*}}vg
+// CHECK: bb0(%{{[0-9]+}} : $Int):
+
+func inout_arg(_ x: inout Int) {}
+
+// CHECK-LABEL: sil hidden @$S10properties14physical_inout{{[_0-9a-zA-Z]*}}F
+func physical_inout(_ x: Int) {
+ var x = x
+ // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[PB:%.*]] = project_box [[XADDR]]
+ inout_arg(&x)
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @$S10properties9inout_arg{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[INOUT_ARG]]([[WRITE]])
+}
+
+
+/* TODO check writeback to more complex logical prop, check that writeback
+ * reuses temporaries */
+
+// CHECK-LABEL: sil hidden @$S10properties17val_subscript_get{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@guaranteed Val, Int) -> Float
+// CHECK: bb0([[VVAL:%[0-9]+]] : $Val, [[I:%[0-9]+]] : $Int):
+func val_subscript_get(_ v: Val, i: Int) -> Float {
+ return v[i]
+ // CHECK: [[SUBSCRIPT_GET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV{{[_0-9a-zA-Z]*}}ig
+ // CHECK: [[RET:%[0-9]+]] = apply [[SUBSCRIPT_GET_METHOD]]([[I]], [[VVAL]]) : $@convention(method) (Int, @guaranteed Val)
+ // CHECK: return [[RET]]
+}
+
+// CHECK-LABEL: sil hidden @$S10properties17val_subscript_set{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0(%0 : $Val, [[I:%[0-9]+]] : $Int, [[X:%[0-9]+]] : $Float):
+func val_subscript_set(_ v: Val, i: Int, x: Float) {
+ var v = v
+ v[i] = x
+ // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
+ // CHECK: [[PB:%.*]] = project_box [[VADDR]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[SUBSCRIPT_SET_METHOD:%[0-9]+]] = function_ref @$S10properties3ValV{{[_0-9a-zA-Z]*}}is
+ // CHECK: apply [[SUBSCRIPT_SET_METHOD]]([[X]], [[I]], [[WRITE]])
+}
+
+struct Generic<T> {
+ var mono_phys:Int
+ var mono_log: Int { get {} set {} }
+ var typevar_member:T
+
+ subscript(x: Int) -> Float { get {} set {} }
+
+ subscript(x: T) -> T { get {} set {} }
+
+ // CHECK-LABEL: sil hidden @$S10properties7GenericV19copy_typevar_member{{[_0-9a-zA-Z]*}}F
+ mutating
+ func copy_typevar_member(_ x: Generic<T>) {
+ typevar_member = x.typevar_member
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10properties21generic_mono_phys_get{{[_0-9a-zA-Z]*}}F
+func generic_mono_phys_get<T>(_ g: Generic<T>) -> Int {
+ return g.mono_phys
+ // CHECK: struct_element_addr %{{.*}}, #Generic.mono_phys
+}
+
+// CHECK-LABEL: sil hidden @$S10properties20generic_mono_log_get{{[_0-9a-zA-Z]*}}F
+func generic_mono_log_get<T>(_ g: Generic<T>) -> Int {
+ return g.mono_log
+ // CHECK: [[GENERIC_GET_METHOD:%[0-9]+]] = function_ref @$S10properties7GenericV8mono_log{{[_0-9a-zA-Z]*}}vg
+ // CHECK: apply [[GENERIC_GET_METHOD]]<
+}
+
+// CHECK-LABEL: sil hidden @$S10properties20generic_mono_log_set{{[_0-9a-zA-Z]*}}F
+func generic_mono_log_set<T>(_ g: Generic<T>, x: Int) {
+ var g = g
+ g.mono_log = x
+ // CHECK: [[GENERIC_SET_METHOD:%[0-9]+]] = function_ref @$S10properties7GenericV8mono_log{{[_0-9a-zA-Z]*}}vs
+ // CHECK: apply [[GENERIC_SET_METHOD]]<
+}
+
+// CHECK-LABEL: sil hidden @$S10properties26generic_mono_subscript_get{{[_0-9a-zA-Z]*}}F
+func generic_mono_subscript_get<T>(_ g: Generic<T>, i: Int) -> Float {
+ return g[i]
+ // CHECK: [[GENERIC_GET_METHOD:%[0-9]+]] = function_ref @$S10properties7GenericV{{[_0-9a-zA-Z]*}}ig
+ // CHECK: apply [[GENERIC_GET_METHOD]]<
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}generic_mono_subscript_set
+func generic_mono_subscript_set<T>(_ g: inout Generic<T>, i: Int, x: Float) {
+ g[i] = x
+ // CHECK: [[GENERIC_SET_METHOD:%[0-9]+]] = function_ref @$S10properties7GenericV{{[_0-9a-zA-Z]*}}is
+ // CHECK: apply [[GENERIC_SET_METHOD]]<
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}bound_generic_mono_phys_get
+func bound_generic_mono_phys_get(_ g: inout Generic<UnicodeScalar>, x: Int) -> Int {
+ return g.mono_phys
+ // CHECK: struct_element_addr %{{.*}}, #Generic.mono_phys
+}
+
+// CHECK-LABEL: sil hidden @$S10properties26bound_generic_mono_log_get{{[_0-9a-zA-Z]*}}F
+func bound_generic_mono_log_get(_ g: Generic<UnicodeScalar>, x: Int) -> Int {
+ return g.mono_log
+// CHECK: [[GENERIC_GET_METHOD:%[0-9]+]] = function_ref @$S10properties7GenericV8mono_log{{[_0-9a-zA-Z]*}}vg
+ // CHECK: apply [[GENERIC_GET_METHOD]]<
+}
+
+// CHECK-LABEL: sil hidden @$S10properties22generic_subscript_type{{[_0-9a-zA-Z]*}}F
+func generic_subscript_type<T>(_ g: Generic<T>, i: T, x: T) -> T {
+ var g = g
+ g[i] = x
+ return g[i]
+}
+
+/*TODO: archetype and existential properties and subscripts */
+
+struct StaticProperty {
+ static var foo: Int {
+ get {
+ return zero
+ }
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10properties10static_get{{[_0-9a-zA-Z]*}}F
+// CHECK: function_ref @$S10properties14StaticPropertyV3foo{{[_0-9a-zA-Z]*}}vgZ : $@convention(method) (@thin StaticProperty.Type) -> Int
+func static_get() -> Int {
+ return StaticProperty.foo
+}
+
+// CHECK-LABEL: sil hidden @$S10properties10static_set{{[_0-9a-zA-Z]*}}F
+// CHECK: function_ref @$S10properties14StaticPropertyV3foo{{[_0-9a-zA-Z]*}}vsZ : $@convention(method) (Int, @thin StaticProperty.Type) -> ()
+func static_set(_ x: Int) {
+ StaticProperty.foo = x
+}
+
+func takeInt(_ a : Int) {}
+
+protocol ForceAccessors {
+ var a: Int { get set }
+}
+
+struct DidSetWillSetTests: ForceAccessors {
+ var a: Int {
+ willSet(newA) {
+ // CHECK-LABEL: // {{.*}}.DidSetWillSetTests.a.willset
+ // CHECK-NEXT: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+ // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
+ // CHECK-NEXT: debug_value %0
+ // CHECK-NEXT: debug_value_addr %1 : $*DidSetWillSetTests
+
+ takeInt(a)
+
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %1
+ // CHECK-NEXT: [[FIELDPTR:%.*]] = struct_element_addr [[READ]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: [[A:%.*]] = load [trivial] [[FIELDPTR]] : $*Int
+ // CHECK-NEXT: end_access [[READ]]
+ // CHECK: [[TAKEINTFN:%.*]] = function_ref @$S10properties7takeInt{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply [[TAKEINTFN]]([[A]]) : $@convention(thin) (Int) -> ()
+
+ takeInt(newA)
+
+ // CHECK-NEXT: // function_ref properties.takeInt(Swift.Int) -> ()
+ // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @$S10properties7takeInt{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply [[TAKEINTFN]](%0) : $@convention(thin) (Int) -> ()
+ }
+
+ didSet {
+ // CHECK-LABEL: // {{.*}}.DidSetWillSetTests.a.didset
+ // CHECK-NEXT: sil hidden @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW
+ // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
+ // CHECK-NEXT: debug
+ // CHECK-NEXT: debug_value_addr %1 : $*DidSetWillSetTests
+
+ takeInt(a)
+
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] %1
+ // CHECK-NEXT: [[AADDR:%.*]] = struct_element_addr [[READ]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: [[A:%.*]] = load [trivial] [[AADDR]] : $*Int
+ // CHECK-NEXT: end_access [[READ]]
+ // CHECK-NEXT: // function_ref properties.takeInt(Swift.Int) -> ()
+ // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @$S10properties7takeInt{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply [[TAKEINTFN]]([[A]]) : $@convention(thin) (Int) -> ()
+
+ a = zero // reassign, but don't infinite loop.
+
+ // CHECK-NEXT: // function_ref properties.zero.unsafeMutableAddressor : Swift.Int
+ // CHECK-NEXT: [[ZEROFN:%.*]] = function_ref @$S10properties4zero{{[_0-9a-zA-Z]*}}vau
+ // CHECK-NEXT: [[ZERORAW:%.*]] = apply [[ZEROFN]]() : $@convention(thin) () -> Builtin.RawPointer
+ // CHECK-NEXT: [[ZEROADDR:%.*]] = pointer_to_address [[ZERORAW]] : $Builtin.RawPointer to [strict] $*Int
+ // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[ZEROADDR]] : $*Int
+ // CHECK-NEXT: [[ZERO:%.*]] = load [trivial] [[READ]]
+ // CHECK-NEXT: end_access [[READ]] : $*Int
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
+ // CHECK-NEXT: [[AADDR:%.*]] = struct_element_addr [[WRITE]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: assign [[ZERO]] to [[AADDR]]
+ }
+ }
+
+ init(x : Int) {
+ // Accesses to didset/willset variables are direct in init methods and dtors.
+ a = x
+ a = x
+ }
+
+ // These are the synthesized getter and setter for the willset/didset variable.
+
+ // CHECK-LABEL: // {{.*}}.DidSetWillSetTests.a.getter
+ // CHECK-NEXT: sil hidden [transparent] @$S10properties010DidSetWillC5TestsV1aSivg
+ // CHECK: bb0(%0 : $DidSetWillSetTests):
+ // CHECK-NEXT: debug_value %0
+ // CHECK-NEXT: %2 = struct_extract %0 : $DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: return %2 : $Int{{.*}} // id: %3
+
+ // CHECK-LABEL: // {{.*}}.DidSetWillSetTests.a.setter
+ // CHECK-NEXT: sil hidden @$S10properties010DidSetWillC5TestsV1aSivs
+ // CHECK: bb0(%0 : $Int, %1 : $*DidSetWillSetTests):
+ // CHECK-NEXT: debug_value %0
+ // CHECK-NEXT: debug_value_addr %1
+
+ // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] %1
+ // CHECK-NEXT: [[AADDR:%.*]] = struct_element_addr [[READ]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: [[OLDVAL:%.*]] = load [trivial] [[AADDR]] : $*Int
+ // CHECK-NEXT: end_access [[READ]]
+ // CHECK-NEXT: debug_value [[OLDVAL]] : $Int, let, name "tmp"
+
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
+ // CHECK-NEXT: // function_ref {{.*}}.DidSetWillSetTests.a.willset : Swift.Int
+ // CHECK-NEXT: [[WILLSETFN:%.*]] = function_ref @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
+ // CHECK-NEXT: apply [[WILLSETFN]](%0, [[WRITE]]) : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
+ // CHECK-NEXT: end_access [[WRITE]]
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
+ // CHECK-NEXT: [[AADDR:%.*]] = struct_element_addr [[WRITE]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: assign %0 to [[AADDR]] : $*Int
+ // CHECK-NEXT: end_access [[WRITE]]
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
+ // CHECK-NEXT: // function_ref {{.*}}.DidSetWillSetTests.a.didset : Swift.Int
+ // CHECK-NEXT: [[DIDSETFN:%.*]] = function_ref @$S10properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
+ // CHECK-NEXT: apply [[DIDSETFN]]([[OLDVAL]], [[WRITE]]) : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
+
+ // CHECK-LABEL: sil hidden @$S10properties010DidSetWillC5TestsV{{[_0-9a-zA-Z]*}}fC
+ // CHECK: bb0(%0 : $Int, %1 : $@thin DidSetWillSetTests.Type):
+ // CHECK: [[SELF:%.*]] = mark_uninitialized [rootself]
+ // CHECK: [[PB_SELF:%.*]] = project_box [[SELF]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_SELF]]
+ // CHECK: [[P1:%.*]] = struct_element_addr [[WRITE]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: assign %0 to [[P1]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_SELF]]
+ // CHECK: [[P2:%.*]] = struct_element_addr [[WRITE]] : $*DidSetWillSetTests, #DidSetWillSetTests.a
+ // CHECK-NEXT: assign %0 to [[P2]]
+}
+
+
+// Test global observing properties.
+
+var global_observing_property : Int = zero {
+ didSet {
+ takeInt(global_observing_property)
+ }
+}
+
+func force_global_observing_property_setter() {
+ let x = global_observing_property
+ global_observing_property = x
+}
+
+// The property is initialized with "zero".
+// CHECK-LABEL: sil private @globalinit_{{.*}}_func1 : $@convention(c) () -> () {
+// CHECK: bb0:
+// CHECK-NEXT: alloc_global @$S10properties25global_observing_propertySiv
+// CHECK-NEXT: %1 = global_addr @$S10properties25global_observing_propertySivp : $*Int
+// CHECK: properties.zero.unsafeMutableAddressor
+// CHECK: return
+
+// The didSet implementation needs to call takeInt.
+
+// CHECK-LABEL: sil hidden @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
+// CHECK: function_ref properties.takeInt
+// CHECK-NEXT: function_ref @$S10properties7takeInt{{[_0-9a-zA-Z]*}}F
+
+// The setter needs to call didSet implementation.
+
+// CHECK-LABEL: sil hidden @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vs
+// CHECK: function_ref properties.global_observing_property.unsafeMutableAddressor
+// CHECK-NEXT: function_ref @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vau
+// CHECK: function_ref properties.global_observing_property.didset
+// CHECK-NEXT: function_ref @$S10properties25global_observing_property{{[_0-9a-zA-Z]*}}vW
+
+
+// Test local observing properties.
+
+func local_observing_property(_ arg: Int) {
+ var localproperty: Int = arg {
+ didSet {
+ takeInt(localproperty)
+ }
+ }
+
+ takeInt(localproperty)
+ localproperty = arg
+}
+
+// This is the local_observing_property function itself. First alloc and
+// initialize the property to the argument value.
+
+// CHECK-LABEL: sil hidden @{{.*}}local_observing_property
+// CHECK: bb0([[ARG:%[0-9]+]] : $Int)
+// CHECK: [[BOX:%[0-9]+]] = alloc_box ${ var Int }
+// CHECK: [[PB:%.*]] = project_box [[BOX]]
+// CHECK: store [[ARG]] to [trivial] [[PB]]
+
+func local_generic_observing_property<T>(_ arg: Int, _: T) {
+ var localproperty1: Int = arg {
+ didSet {
+ takeInt(localproperty1)
+ }
+ }
+
+ takeInt(localproperty1)
+ localproperty1 = arg
+
+ var localproperty2: Int = arg {
+ didSet {
+ _ = T.self
+ takeInt(localproperty2)
+ }
+ }
+
+ takeInt(localproperty2)
+ localproperty2 = arg
+}
+
+
+// <rdar://problem/16006333> observing properties don't work in @objc classes
+@objc
+class ObservingPropertyInObjCClass {
+ var bounds: Int {
+ willSet {}
+ didSet {}
+ }
+
+ init(b: Int) { bounds = b }
+}
+
+
+
+// Superclass init methods should not get direct access to be class properties.
+// rdar://16151899
+
+class rdar16151899Base {
+ var x: Int = zero {
+ willSet {
+ use(x)
+ }
+ }
+}
+
+class rdar16151899Derived : rdar16151899Base {
+ // CHECK-LABEL: sil hidden @$S10properties19rdar16151899DerivedC{{[_0-9a-zA-Z]*}}fc
+ override init() {
+ super.init()
+ // CHECK: upcast {{.*}} : $rdar16151899Derived to $rdar16151899Base
+ // CHECK: function_ref @$S10properties16rdar16151899BaseCACycfc : $@convention(method) (@owned rdar16151899Base) -> @owned rdar16151899Base
+
+ // This should not be a direct access, it should call the setter in the
+ // base.
+ x = zero
+
+ // CHECK: [[BASEPTR:%[0-9]+]] = upcast {{.*}} : $rdar16151899Derived to $rdar16151899Base
+ // CHECK: load{{.*}}Int
+ // CHECK-NEXT: end_access {{.*}} : $*Int
+ // CHECK-NEXT: [[SETTER:%[0-9]+]] = class_method {{.*}} : $rdar16151899Base, #rdar16151899Base.x!setter.1 : (rdar16151899Base)
+ // CHECK-NEXT: apply [[SETTER]]({{.*}}, [[BASEPTR]])
+ }
+}
+
+
+func propertyWithDidSetTakingOldValue() {
+ var p : Int = zero {
+ didSet(oldValue) {
+ // access to oldValue
+ use(oldValue)
+ // and newValue.
+ use(p)
+ }
+ }
+
+ p = zero
+}
+
+// CHECK: // setter of p #1 : Swift.Int in properties.propertyWithDidSetTakingOldValue()
+// CHECK-NEXT: sil {{.*}} @$S10properties32propertyWithDidSetTakingOldValueyyF1pL_Sivs
+// CHECK: bb0([[ARG1:%.*]] : $Int, [[ARG2:%.*]] : ${ var Int }):
+// CHECK-NEXT: debug_value [[ARG1]] : $Int, let, name "newValue", argno 1
+// CHECK-NEXT: [[ARG2_PB:%.*]] = project_box [[ARG2]]
+// CHECK-NEXT: debug_value_addr [[ARG2_PB]] : $*Int, var, name "p", argno 2
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[ARG2_PB]]
+// CHECK-NEXT: [[ARG2_PB_VAL:%.*]] = load [trivial] [[READ]] : $*Int
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: debug_value [[ARG2_PB_VAL]] : $Int
+// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG2_PB]]
+// CHECK-NEXT: assign [[ARG1]] to [[WRITE]] : $*Int
+// CHECK-NEXT: end_access [[WRITE]]
+// SEMANTIC ARC TODO: Another case where we need to put the mark_function_escape on a new projection after a copy.
+// CHECK-NEXT: mark_function_escape [[ARG2_PB]]
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[FUNC:%.*]] = function_ref @$S10properties32propertyWithDidSetTakingOldValueyyF1pL_SivW : $@convention(thin) (Int, @guaranteed { var Int }) -> ()
+// CHECK-NEXT: %{{.*}} = apply [[FUNC]]([[ARG2_PB_VAL]], [[ARG2]]) : $@convention(thin) (Int, @guaranteed { var Int }) -> ()
+// CHECK-NEXT: %{{.*}} = tuple ()
+// CHECK-NEXT: return %{{.*}} : $()
+// CHECK-NEXT:} // end sil function '$S10properties32propertyWithDidSetTakingOldValue{{[_0-9a-zA-Z]*}}'
+
+
+class BaseProperty {
+ var x : Int { get {} set {} }
+}
+
+class DerivedProperty : BaseProperty {
+ override var x : Int { get {} set {} }
+
+ func super_property_reference() -> Int {
+ return super.x
+ }
+}
+
+// rdar://16381392 - Super property references in non-objc classes should be direct.
+
+// CHECK-LABEL: sil hidden @$S10properties15DerivedPropertyC24super_property_referenceSiyF : $@convention(method) (@guaranteed DerivedProperty) -> Int {
+// CHECK: bb0([[SELF:%.*]] : $DerivedProperty):
+// CHECK: [[SELF_COPY:%[0-9]+]] = copy_value [[SELF]]
+// CHECK: [[BASEPTR:%[0-9]+]] = upcast [[SELF_COPY]] : $DerivedProperty to $BaseProperty
+// CHECK: [[FN:%[0-9]+]] = function_ref @$S10properties12BasePropertyC1xSivg : $@convention(method) (@guaranteed BaseProperty) -> Int
+// CHECK: [[RESULT:%.*]] = apply [[FN]]([[BASEPTR]]) : $@convention(method) (@guaranteed BaseProperty) -> Int
+// CHECK: destroy_value [[BASEPTR]]
+// CHECK: return [[RESULT]] : $Int
+// CHECK: } // end sil function '$S10properties15DerivedPropertyC24super_property_referenceSiyF'
+
+
+// <rdar://problem/16411449> ownership qualifiers don't work with non-mutating struct property
+struct ReferenceStorageTypeRValues {
+ unowned var p1 : Ref
+
+ func testRValueUnowned() -> Ref {
+ return p1
+ }
+// CHECK: sil hidden @{{.*}}testRValueUnowned{{.*}} : $@convention(method) (@guaranteed ReferenceStorageTypeRValues) -> @owned Ref {
+// CHECK: bb0([[ARG:%.*]] : $ReferenceStorageTypeRValues):
+// CHECK-NEXT: debug_value [[ARG]] : $ReferenceStorageTypeRValues
+// CHECK-NEXT: [[UNOWNED_ARG_FIELD:%.*]] = struct_extract [[ARG]] : $ReferenceStorageTypeRValues, #ReferenceStorageTypeRValues.p1
+// CHECK-NEXT: [[COPIED_VALUE:%.*]] = copy_unowned_value [[UNOWNED_ARG_FIELD]]
+// CHECK-NEXT: return [[COPIED_VALUE]] : $Ref
+
+ init() {
+ }
+}
+
+
+// <rdar://problem/16406886> Observing properties don't work with ownership types
+struct ObservingPropertiesWithOwnershipTypes {
+ unowned var alwaysPresent : Ref {
+ didSet {
+ }
+ }
+
+ init(res: Ref) {
+ alwaysPresent = res
+ }
+}
+
+struct ObservingPropertiesWithOwnershipTypesInferred {
+ unowned var alwaysPresent = Ref(i: 0) {
+ didSet {
+ }
+ }
+
+ weak var maybePresent = nil as Ref? {
+ willSet {
+ }
+ }
+}
+
+// <rdar://problem/16554876> property accessor synthesization of weak variables doesn't work
+protocol WeakPropertyProtocol {
+ var maybePresent : Ref? { get set }
+}
+
+struct WeakPropertyStruct : WeakPropertyProtocol {
+ weak var maybePresent : Ref?
+
+ init() {
+ maybePresent = nil
+ }
+}
+
+// <rdar://problem/16629598> direct property accesses to generic struct
+// properties were being mischecked as computed property accesses.
+
+struct SomeGenericStruct<T> {
+ var x: Int
+}
+
+// CHECK-LABEL: sil hidden @$S10properties4getX{{[_0-9a-zA-Z]*}}F
+// CHECK: struct_extract {{%.*}} : $SomeGenericStruct<T>, #SomeGenericStruct.x
+func getX<T>(_ g: SomeGenericStruct<T>) -> Int {
+ return g.x
+}
+
+
+// <rdar://problem/16189360> [DF] Assert on subscript with variadic parameter
+struct VariadicSubscript {
+ subscript(subs: Int...) -> Int {
+ get {
+ return 42
+ }
+ }
+
+ func test() {
+ var s = VariadicSubscript()
+ var x = s[0, 1, 2]
+ }
+}
+
+
+//<rdar://problem/16620121> Initializing constructor tries to initialize computed property overridden with willSet/didSet
+class ObservedBase {
+ var printInfo: Ref!
+}
+class ObservedDerived : ObservedBase {
+ override init() {}
+ override var printInfo: Ref! {
+ didSet { }
+ }
+}
+
+
+
+/// <rdar://problem/16953517> Class properties should be allowed in protocols, even without stored class properties
+protocol ProtoWithClassProp {
+ static var x: Int { get }
+}
+
+class ClassWithClassProp : ProtoWithClassProp {
+ class var x: Int {
+ return 42
+ }
+}
+
+struct StructWithClassProp : ProtoWithClassProp {
+ static var x: Int {
+ return 19
+ }
+}
+
+
+func getX<T : ProtoWithClassProp>(_ a : T) -> Int {
+ return T.x
+}
+
+func testClassPropertiesInProtocol() -> Int {
+ return getX(ClassWithClassProp())+getX(StructWithClassProp())
+}
+
+class GenericClass<T> {
+ var x: T
+ var y: Int
+ final let z: T
+
+ init() { fatalError("scaffold") }
+}
+
+// CHECK-LABEL: sil hidden @$S10properties12genericPropsyyAA12GenericClassCySSGF : $@convention(thin) (@guaranteed GenericClass<String>) -> () {
+func genericProps(_ x: GenericClass<String>) {
+ // CHECK: bb0([[ARG:%.*]] : $GenericClass<String>):
+ // CHECK: class_method [[ARG]] : $GenericClass<String>, #GenericClass.x!getter.1
+ // CHECK: apply {{.*}}<String>({{.*}}, [[ARG]]) : $@convention(method) <τ_0_0> (@guaranteed GenericClass<τ_0_0>) -> @out τ_0_0
+ let _ = x.x
+ // CHECK: class_method [[ARG]] : $GenericClass<String>, #GenericClass.y!getter.1
+ // CHECK: apply {{.*}}<String>([[ARG]]) : $@convention(method) <τ_0_0> (@guaranteed GenericClass<τ_0_0>) -> Int
+ let _ = x.y
+ // CHECK: [[Z:%.*]] = ref_element_addr [[ARG]] : $GenericClass<String>, #GenericClass.z
+ // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[Z]] : $*String
+ // CHECK: [[LOADED_Z:%.*]] = load [copy] [[READ]] : $*String
+ // CHECK: destroy_value [[LOADED_Z]]
+ // CHECK-NOT: destroy_value [[ARG]]
+ let _ = x.z
+}
+
+// CHECK-LABEL: sil hidden @$S10properties28genericPropsInGenericContext{{[_0-9a-zA-Z]*}}F
+func genericPropsInGenericContext<U>(_ x: GenericClass<U>) {
+ // CHECK: bb0([[ARG:%.*]] : $GenericClass<U>):
+ // CHECK: [[Z:%.*]] = ref_element_addr [[ARG]] : $GenericClass<U>, #GenericClass.z
+ // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[Z]] : $*U
+ // CHECK: copy_addr [[READ]] {{.*}} : $*U
+ let _ = x.z
+}
+
+
+// <rdar://problem/18275556> 'let' properties in a class should be implicitly final
+class ClassWithLetProperty {
+ let p = 42
+ dynamic let q = 97
+
+ // We shouldn't have any dynamic dispatch within this method, just load p.
+ func ReturnConstant() -> Int { return p }
+// CHECK-LABEL: sil hidden @$S10properties20ClassWithLetPropertyC14ReturnConstant{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG:%.*]] : $ClassWithLetProperty):
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: [[PTR:%[0-9]+]] = ref_element_addr [[ARG]] : $ClassWithLetProperty, #ClassWithLetProperty.p
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[PTR]] : $*Int
+// CHECK-NEXT: [[VAL:%[0-9]+]] = load [trivial] [[READ]] : $*Int
+// CHECK-NEXT: end_access [[READ]] : $*Int
+// CHECK-NEXT: return [[VAL]] : $Int
+
+
+ // This property is marked dynamic, so go through the getter, always.
+ func ReturnDynamicConstant() -> Int { return q }
+// CHECK-LABEL: sil hidden @$S10properties20ClassWithLetPropertyC21ReturnDynamicConstant{{[_0-9a-zA-Z]*}}F
+// CHECK: objc_method %0 : $ClassWithLetProperty, #ClassWithLetProperty.q!getter.1.foreign
+}
+
+
+// <rdar://problem/19254812> DI bug when referencing let member of a class
+class r19254812Base {}
+class r19254812Derived: r19254812Base{
+ let pi = 3.14159265359
+
+ init(x : ()) {
+ use(pi)
+ }
+
+// Accessing the "pi" property should not copy_value/release self.
+// CHECK-LABEL: sil hidden @$S10properties16r19254812DerivedC{{[_0-9a-zA-Z]*}}fc
+// CHECK: [[MARKED_SELF_BOX:%.*]] = mark_uninitialized [derivedself]
+// CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+
+// Initialization of the pi field: no copy_values/releases.
+// CHECK: [[SELF:%[0-9]+]] = load_borrow [[PB_BOX]] : $*r19254812Derived
+// CHECK-NEXT: [[PIPTR:%[0-9]+]] = ref_element_addr [[SELF]] : $r19254812Derived, #r19254812Derived.pi
+// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[PIPTR]] : $*Double
+// CHECK-NEXT: assign {{.*}} to [[WRITE]] : $*Double
+
+// CHECK-NOT: destroy_value
+// CHECK-NOT: copy_value
+
+// Load of the pi field: no copy_values/releases.
+// CHECK: [[SELF:%[0-9]+]] = load_borrow [[PB_BOX]] : $*r19254812Derived
+// CHECK-NEXT: [[PIPTR:%[0-9]+]] = ref_element_addr [[SELF]] : $r19254812Derived, #r19254812Derived.pi
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [dynamic] [[PIPTR]] : $*Double
+// CHECK-NEXT: {{.*}} = load [trivial] [[READ]] : $*Double
+// CHECK-NEXT: end_access [[READ]] : $*Double
+// CHECK: return
+}
+
+
+class RedundantSelfRetains {
+ final var f : RedundantSelfRetains
+
+ init() {
+ f = RedundantSelfRetains()
+ }
+
+ // <rdar://problem/19275047> Extraneous copy_values/releases of self are bad
+ func testMethod1() {
+ f = RedundantSelfRetains()
+ }
+ // CHECK-LABEL: sil hidden @$S10properties20RedundantSelfRetainsC11testMethod1{{[_0-9a-zA-Z]*}}F
+ // CHECK: bb0(%0 : $RedundantSelfRetains):
+
+ // CHECK-NOT: copy_value
+
+ // CHECK: [[FPTR:%[0-9]+]] = ref_element_addr %0 : $RedundantSelfRetains, #RedundantSelfRetains.f
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[FPTR]] : $*RedundantSelfRetains
+ // CHECK-NEXT: assign {{.*}} to [[WRITE]] : $*RedundantSelfRetains
+
+ // CHECK: return
+}
+
+class RedundantRetains {
+ final var field = 0
+}
+
+func testRedundantRetains() {
+ let a = RedundantRetains()
+ a.field = 4 // no copy_value/release of a necessary here.
+}
+
+// CHECK-LABEL: sil hidden @$S10properties20testRedundantRetainsyyF : $@convention(thin) () -> () {
+// CHECK: [[A:%[0-9]+]] = apply
+// CHECK-NOT: copy_value
+// CHECK: destroy_value [[A]] : $RedundantRetains
+// CHECK-NOT: copy_value
+// CHECK-NOT: destroy_value
+// CHECK: return
+
+struct AddressOnlyNonmutatingSet<T> {
+ var x: T
+ init(x: T) { self.x = x }
+ var prop: Int {
+ get { return 0 }
+ nonmutating set { }
+ }
+}
+
+func addressOnlyNonmutatingProperty<T>(_ x: AddressOnlyNonmutatingSet<T>)
+-> Int {
+ x.prop = 0
+ return x.prop
+}
+// CHECK-LABEL: sil hidden @$S10properties30addressOnlyNonmutatingProperty{{[_0-9a-zA-Z]*}}F
+// CHECK: [[SET:%.*]] = function_ref @$S10properties25AddressOnlyNonmutatingSetV4propSivs
+// CHECK: apply [[SET]]<T>({{%.*}}, [[TMP:%[0-9]*]])
+// CHECK: destroy_addr [[TMP]]
+// CHECK: dealloc_stack [[TMP]]
+// CHECK: [[GET:%.*]] = function_ref @$S10properties25AddressOnlyNonmutatingSetV4propSivg
+// CHECK: apply [[GET]]<T>([[TMP:%[0-9]*]])
+// CHECK: destroy_addr [[TMP]]
+// CHECK: dealloc_stack [[TMP]]
+
+protocol MakeAddressOnly {}
+struct AddressOnlyReadOnlySubscript {
+ var x: MakeAddressOnly?
+
+ subscript(z: Int) -> Int { return z }
+}
+
+// CHECK-LABEL: sil hidden @$S10properties015addressOnlyReadC24SubscriptFromMutableBase
+// CHECK: [[BASE:%.*]] = alloc_box ${ var AddressOnlyReadOnlySubscript }
+// CHECK: copy_addr [[BASE:%.*]] to [initialization] [[COPY:%.*]] :
+// CHECK: [[GETTER:%.*]] = function_ref @$S10properties015AddressOnlyReadC9SubscriptV{{[_0-9a-zA-Z]*}}ig
+// CHECK: apply [[GETTER]]({{%.*}}, [[COPY]])
+func addressOnlyReadOnlySubscriptFromMutableBase(_ x: Int) {
+ var base = AddressOnlyReadOnlySubscript()
+ _ = base[x]
+}
+
+
+
+/// <rdar://problem/20912019> passing unmaterialized r-value as inout argument
+struct MutatingGetterStruct {
+ var write: Int {
+ mutating get { }
+ }
+
+ // CHECK-LABEL: sil hidden @$S10properties20MutatingGetterStructV4test
+ // CHECK: [[X:%.*]] = alloc_box ${ var MutatingGetterStruct }, var, name "x"
+ // CHECK-NEXT: [[PB:%.*]] = project_box [[X]]
+ // CHECK: store {{.*}} to [trivial] [[PB]] : $*MutatingGetterStruct
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: apply {{%.*}}([[WRITE]]) : $@convention(method) (@inout MutatingGetterStruct) -> Int
+ static func test() {
+ var x = MutatingGetterStruct()
+ _ = x.write
+ }
+}
+
+
+protocol ProtocolWithReadWriteSubscript {
+ subscript(i: Int) -> Int { get set }
+}
+
+struct CrashWithUnnamedSubscript : ProtocolWithReadWriteSubscript {
+ subscript(_: Int) -> Int { get { } set { } }
+}
+
+
+/// <rdar://problem/26408353> crash when overriding internal property with
+/// public property
+
+public class BaseClassWithInternalProperty {
+ var x: () = ()
+}
+
+public class DerivedClassWithPublicProperty : BaseClassWithInternalProperty {
+ public override var x: () {
+ didSet {}
+ }
+}
+
+// CHECK-LABEL: sil hidden [transparent] @$S10properties29BaseClassWithInternalPropertyC1xytvg
+
+// CHECK-LABEL: sil [transparent] [serialized] @$S10properties30DerivedClassWithPublicPropertyC1xytvg
+// CHECK: bb0([[SELF:%.*]] : $DerivedClassWithPublicProperty):
+// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]] : $DerivedClassWithPublicProperty
+// CHECK-NEXT: [[SUPER:%.*]] = upcast [[SELF_COPY]] : $DerivedClassWithPublicProperty to $BaseClassWithInternalProperty
+// CHECK-NEXT: [[BORROWED_SUPER:%.*]] = begin_borrow [[SUPER]]
+// CHECK-NEXT: [[DOWNCAST_BORROWED_SUPER:%.*]] = unchecked_ref_cast [[BORROWED_SUPER]] : $BaseClassWithInternalProperty to $DerivedClassWithPublicProperty
+// CHECK-NEXT: [[METHOD:%.*]] = super_method [[DOWNCAST_BORROWED_SUPER]] : $DerivedClassWithPublicProperty, #BaseClassWithInternalProperty.x!getter.1 : (BaseClassWithInternalProperty) -> () -> (), $@convention(method) (@guaranteed BaseClassWithInternalProperty) -> ()
+// CHECK-NEXT: end_borrow [[BORROWED_SUPER]] from [[SUPER]]
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SUPER]]) : $@convention(method) (@guaranteed BaseClassWithInternalProperty) -> ()
+// CHECK-NEXT: destroy_value [[SUPER]] : $BaseClassWithInternalProperty
+// CHECK: } // end sil function '$S10properties30DerivedClassWithPublicPropertyC1xytvg'
+
+// Make sure that we can handle this AST:
+// (load_expr
+// (open_existential_expr
+// (opaque_expr A)
+// ...
+// (load_expr
+// (opaque_expr ))))
+
+class ReferenceType {
+ var p: NonmutatingProtocol
+ init(p: NonmutatingProtocol) { self.p = p }
+}
+
+protocol NonmutatingProtocol {
+ var x: Int { get nonmutating set }
+}
+
+// sil hidden @$S10properties19overlappingLoadExpr1cyAA13ReferenceTypeCz_tF : $@convention(thin) (@inout ReferenceType) -> () {
+// CHECK: [[RESULT:%.*]] = alloc_stack $Int
+// CHECK-NEXT: [[UNINIT:%.*]] = mark_uninitialized [var] [[RESULT]] : $*Int
+// CHECK-NEXT: [[C_INOUT:%.*]] = begin_access [read] [unknown] %0 : $*ReferenceType
+// CHECK-NEXT: [[C:%.*]] = load [copy] [[C_INOUT:%.*]] : $*ReferenceType
+// CHECK-NEXT: end_access [[C_INOUT]] : $*ReferenceType
+// CHECK-NEXT: [[C_FIELD_BOX:%.*]] = alloc_stack $NonmutatingProtocol
+// CHECK-NEXT: [[GETTER:%.*]] = class_method [[C]] : $ReferenceType, #ReferenceType.p!getter.1 : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
+// CHECK-NEXT: apply [[GETTER]]([[C_FIELD_BOX]], [[C]]) : $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
+
+// CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*NonmutatingProtocol to $*@opened("{{.*}}") NonmutatingProtocol
+// CHECK-NEXT: [[C_FIELD_COPY:%.*]] = alloc_stack $@opened("{{.*}}") NonmutatingProtocol
+// CHECK-NEXT: copy_addr [[C_FIELD_PAYLOAD]] to [initialization] [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
+// CHECK-NEXT: [[GETTER:%.*]] = witness_method $@opened("{{.*}}") NonmutatingProtocol, #NonmutatingProtocol.x!getter.1 : <Self where Self : NonmutatingProtocol> (Self) -> () -> Int, [[C_FIELD_PAYLOAD]] : $*@opened("{{.*}}") NonmutatingProtocol : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int
+// CHECK-NEXT: [[RESULT_VALUE:%.*]] = apply [[GETTER]]<@opened("{{.*}}") NonmutatingProtocol>([[C_FIELD_COPY]]) : $@convention(witness_method: NonmutatingProtocol) <τ_0_0 where τ_0_0 : NonmutatingProtocol> (@in_guaranteed τ_0_0) -> Int
+// CHECK-NEXT: assign [[RESULT_VALUE]] to [[UNINIT]] : $*Int
+// CHECK-NEXT: destroy_addr [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
+// CHECK-NEXT: destroy_addr [[C_FIELD_BOX]] : $*NonmutatingProtocol
+// CHECK-NEXT: destroy_value [[C]] : $ReferenceType
+// CHECK-NEXT: dealloc_stack [[C_FIELD_COPY]] : $*@opened("{{.*}}") NonmutatingProtocol
+// CHECK-NEXT: dealloc_stack [[C_FIELD_BOX]] : $*NonmutatingProtocol
+// CHECK-NEXT: dealloc_stack [[RESULT]] : $*Int
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+func overlappingLoadExpr(c: inout ReferenceType) {
+ _ = c.p.x
+}
diff --git a/test/SILGen/plus_zero_property_abstraction.swift b/test/SILGen/plus_zero_property_abstraction.swift
new file mode 100644
index 0000000..ab74768
--- /dev/null
+++ b/test/SILGen/plus_zero_property_abstraction.swift
@@ -0,0 +1,144 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen %s | %FileCheck %s
+
+struct Int {
+ mutating func foo() {}
+}
+
+struct Foo<T, U> {
+ var f: (T) -> U
+
+ var g: T
+}
+
+// CHECK-LABEL: sil hidden @$S20property_abstraction4getF{{[_0-9a-zA-Z]*}}Foo{{.*}}F : $@convention(thin) (@guaranteed Foo<Int, Int>) -> @owned @callee_guaranteed (Int) -> Int {
+// CHECK: bb0([[X_ORIG:%.*]] : @guaranteed $Foo<Int, Int>):
+// CHECK: [[F_ORIG:%.*]] = struct_extract [[X_ORIG]] : $Foo<Int, Int>, #Foo.f
+// CHECK: [[F_ORIG_COPY:%.*]] = copy_value [[F_ORIG]]
+// CHECK: [[REABSTRACT_FN:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[F_SUBST:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT_FN]]([[F_ORIG_COPY]])
+// CHECK: return [[F_SUBST]]
+// CHECK: } // end sil function '$S20property_abstraction4getF{{[_0-9a-zA-Z]*}}F'
+func getF(_ x: Foo<Int, Int>) -> (Int) -> Int {
+ return x.f
+}
+
+// CHECK-LABEL: sil hidden @$S20property_abstraction4setF{{[_0-9a-zA-Z]*}}F
+// CHECK: [[REABSTRACT_FN:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[F_ORIG:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT_FN]]({{%.*}})
+// CHECK: [[F_ADDR:%.*]] = struct_element_addr {{%.*}} : $*Foo<Int, Int>, #Foo.f
+// CHECK: assign [[F_ORIG]] to [[F_ADDR]]
+func setF(_ x: inout Foo<Int, Int>, f: @escaping (Int) -> Int) {
+ x.f = f
+}
+
+func inOutFunc(_ f: inout ((Int) -> Int)) { }
+
+// CHECK-LABEL: sil hidden @$S20property_abstraction6inOutF{{[_0-9a-zA-Z]*}}F :
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Foo<Int, Int>):
+// CHECK: [[XBOX:%.*]] = alloc_box ${ var Foo<Int, Int> }, var, name "x"
+// CHECK: [[XBOX_PB:%.*]] = project_box [[XBOX]] : ${ var Foo<Int, Int> }, 0
+// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+// CHECK: store [[ARG_COPY]] to [init] [[XBOX_PB]]
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[XBOX_PB]] : $*Foo<Int, Int>
+// CHECK: [[F_ADDR:%.*]] = struct_element_addr [[WRITE]] : $*Foo<Int, Int>, #Foo.f
+// CHECK: [[F_SUBST_MAT:%.*]] = alloc_stack
+// CHECK: [[F_ORIG:%.*]] = load [copy] [[F_ADDR]]
+// CHECK: [[REABSTRACT_FN:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[F_SUBST_IN:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT_FN]]([[F_ORIG]])
+// CHECK: store [[F_SUBST_IN]] to [init] [[F_SUBST_MAT]]
+// CHECK: [[INOUTFUNC:%.*]] = function_ref @$S20property_abstraction9inOutFunc{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[INOUTFUNC]]([[F_SUBST_MAT]])
+// CHECK: [[F_SUBST_OUT:%.*]] = load [take] [[F_SUBST_MAT]]
+// CHECK: [[REABSTRACT_FN:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[F_ORIG:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT_FN]]([[F_SUBST_OUT]])
+// CHECK: assign [[F_ORIG]] to [[F_ADDR]]
+// CHECK: destroy_value [[XBOX]]
+// CHECK: } // end sil function '$S20property_abstraction6inOutF{{[_0-9a-zA-Z]*}}F'
+func inOutF(_ x: Foo<Int, Int>) {
+ var x = x
+ inOutFunc(&x.f)
+}
+
+// Don't produce a writeback for generic lvalues when there's no real
+// abstraction difference. <rdar://problem/16530674>
+// CHECK-LABEL: sil hidden @$S20property_abstraction23noAbstractionDifference{{[_0-9a-zA-Z]*}}F
+func noAbstractionDifference(_ x: Foo<Int, Int>) {
+ var x = x
+ // CHECK: [[ADDR:%.*]] = struct_element_addr {{%.*}}, #Foo.g
+ // CHECK: apply {{%.*}}([[ADDR]])
+ x.g.foo()
+}
+
+protocol P {}
+
+struct AddressOnlyLet<T> {
+ let f: (T) -> T
+ let makeAddressOnly: P
+}
+
+// CHECK-LABEL: sil hidden @$S20property_abstraction34getAddressOnlyReabstractedProperty{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@in_guaranteed AddressOnlyLet<Int>) -> @owned @callee_guaranteed (Int) -> Int
+// CHECK: bb0([[ARG:%.*]] : @trivial $*AddressOnlyLet<Int>):
+// CHECK: [[CLOSURE_ADDR:%.*]] = struct_element_addr {{%.*}} : $*AddressOnlyLet<Int>, #AddressOnlyLet.f
+// CHECK: [[CLOSURE_ORIG:%.*]] = load [copy] [[CLOSURE_ADDR]]
+// CHECK: [[REABSTRACT:%.*]] = function_ref
+// CHECK: [[CLOSURE_SUBST:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[CLOSURE_ORIG]])
+// CHECK-NOT: destroy_addr [[ARG]]
+// CHECK: return [[CLOSURE_SUBST]]
+// CHECK: } // end sil function '$S20property_abstraction34getAddressOnlyReabstractedProperty{{[_0-9a-zA-Z]*}}F'
+func getAddressOnlyReabstractedProperty(_ x: AddressOnlyLet<Int>) -> (Int) -> Int {
+ return x.f
+}
+
+enum Bar<T, U> {
+ case F((T) -> U)
+}
+
+func getF(_ x: Bar<Int, Int>) -> (Int) -> Int {
+ switch x {
+ case .F(var f):
+ return f
+ }
+}
+
+func makeF(_ f: @escaping (Int) -> Int) -> Bar<Int, Int> {
+ return Bar.F(f)
+}
+
+struct ArrayLike<T> {
+ subscript(x: ()) -> T { get {} set {} }
+}
+
+typealias Test20341012 = (title: (), action: () -> ())
+
+struct T20341012 {
+ private var options: ArrayLike<Test20341012> { get {} set {} }
+
+ // CHECK-LABEL: sil hidden @$S20property_abstraction9T20341012V1t{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[TMP1:%.*]] = alloc_stack $(title: (), action: @callee_guaranteed (@in_guaranteed ()) -> @out ())
+ // CHECK: apply {{.*}}<(title: (), action: () -> ())>([[TMP1]],
+ mutating func t() {
+ _ = self.options[].title
+ }
+}
+
+class MyClass {}
+
+// When simply assigning to a property, reabstract the r-value and assign
+// to the base instead of materializing and then assigning.
+protocol Factory {
+ associatedtype Product
+ var builder : () -> Product { get set }
+}
+func setBuilder<F: Factory where F.Product == MyClass>(_ factory: inout F) {
+ factory.builder = { return MyClass() }
+}
+// CHECK: sil hidden @$S20property_abstraction10setBuilder{{[_0-9a-zA-Z]*}}F : $@convention(thin) <F where F : Factory, F.Product == MyClass> (@inout F) -> ()
+// CHECK: bb0(%0 : @trivial $*F):
+// CHECK: [[F0:%.*]] = function_ref @$S20property_abstraction10setBuilder{{[_0-9a-zA-Z]*}} : $@convention(thin) () -> @owned MyClass
+// CHECK: [[F1:%.*]] = thin_to_thick_function [[F0]]
+// CHECK: [[REABSTRACTOR:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[F2:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACTOR]]([[F1]])
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*F
+// CHECK: [[SETTER:%.*]] = witness_method $F, #Factory.builder!setter.1
+// CHECK: apply [[SETTER]]<F>([[F2]], [[WRITE]])
diff --git a/test/SILGen/plus_zero_protocol_extensions.swift b/test/SILGen/plus_zero_protocol_extensions.swift
new file mode 100644
index 0000000..ec1dd26
--- /dev/null
+++ b/test/SILGen/plus_zero_protocol_extensions.swift
@@ -0,0 +1,901 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -emit-silgen %s | %FileCheck %s
+
+public protocol P1 {
+ func reqP1a()
+ subscript(i: Int) -> Int { get set }
+}
+
+struct Box {
+ var number: Int
+}
+
+extension P1 {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions2P1PAAE6extP1a{{[_0-9a-zA-Z]*}}F : $@convention(method) <Self where Self : P1> (@in_guaranteed Self) -> () {
+ // CHECK: bb0([[SELF:%[0-9]+]] : $*Self):
+ func extP1a() {
+ // CHECK: [[WITNESS:%[0-9]+]] = witness_method $Self, #P1.reqP1a!1 : {{.*}} : $@convention(witness_method: P1) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
+ // CHECK-NEXT: apply [[WITNESS]]<Self>([[SELF]]) : $@convention(witness_method: P1) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
+ reqP1a()
+ // CHECK: return
+ }
+
+ // CHECK-LABEL: sil @$S19protocol_extensions2P1PAAE6extP1b{{[_0-9a-zA-Z]*}}F : $@convention(method) <Self where Self : P1> (@in_guaranteed Self) -> () {
+ // CHECK: bb0([[SELF:%[0-9]+]] : $*Self):
+ public func extP1b() {
+ // CHECK: [[FN:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE6extP1a{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
+ // CHECK-NEXT: apply [[FN]]<Self>([[SELF]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
+ extP1a()
+ // CHECK: return
+ }
+
+ subscript(i: Int) -> Int {
+ // materializeForSet can do static dispatch to peer accessors (tested later, in the emission of the concrete conformance)
+ get {
+ return 0
+ }
+ set {}
+ }
+
+ func callSubscript() -> Int {
+ // But here we have to do a witness method call:
+
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions2P1PAAE13callSubscript{{[_0-9a-zA-Z]*}}F
+ // CHECK: bb0(%0 : $*Self):
+ // CHECK: witness_method $Self, #P1.subscript!getter.1
+ // CHECK: return
+ return self[0]
+ }
+
+ static var staticReadOnlyProperty: Int {
+ return 0
+ }
+
+ static var staticReadWrite1: Int {
+ get { return 0 }
+ set { }
+ }
+
+ static var staticReadWrite2: Box {
+ get { return Box(number: 0) }
+ set { }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Using protocol extension members with concrete types
+// ----------------------------------------------------------------------------
+class C : P1 {
+ func reqP1a() { }
+}
+
+// (materializeForSet test from above)
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_extensions1CCAA2P1A2aDPyS2icimTW
+// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $Int, %3 : $*τ_0_0):
+// CHECK: function_ref @$S19protocol_extensions2P1PAAEyS2icig
+// CHECK: return
+
+class D : C { }
+
+struct S : P1 {
+ func reqP1a() { }
+}
+
+struct G<T> : P1 {
+ func reqP1a() { }
+}
+
+struct MetaHolder {
+ var d: D.Type = D.self
+ var s: S.Type = S.self
+}
+
+struct GenericMetaHolder<T> {
+ var g: G<T>.Type = G<T>.self
+}
+
+func inout_func(_ n: inout Int) {}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions5testD_2dd1dyAA10MetaHolderV_AA1DCmAHtF : $@convention(thin) (MetaHolder, @thick D.Type, @guaranteed D) -> ()
+// CHECK: bb0([[M:%[0-9]+]] : $MetaHolder, [[DD:%[0-9]+]] : $@thick D.Type, [[D:%[0-9]+]] : $D):
+func testD(_ m: MetaHolder, dd: D.Type, d: D) {
+ // CHECK: [[D2:%[0-9]+]] = alloc_box ${ var D }
+ // CHECK: [[RESULT:%.*]] = project_box [[D2]]
+ // CHECK: [[MATERIALIZED_BORROWED_D:%[0-9]+]] = alloc_stack $D
+ // CHECK: store_borrow [[D]] to [[MATERIALIZED_BORROWED_D]]
+ // CHECK: [[FN:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FN]]<D>([[RESULT]], [[MATERIALIZED_BORROWED_D]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK-NEXT: dealloc_stack [[MATERIALIZED_BORROWED_D]]
+ var d2: D = d.returnsSelf()
+
+ // CHECK: metatype $@thick D.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = D.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick D.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ D.staticReadWrite1 = 1
+
+ // CHECK: metatype $@thick D.Type
+ // CHECK: alloc_stack $Int
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ D.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick D.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ D.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: metatype $@thick D.Type
+ // CHECK: alloc_stack $Box
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ D.staticReadWrite2.number += 5
+
+ // CHECK: metatype $@thick D.Type
+ // CHECK: alloc_stack $Box
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&D.staticReadWrite2.number)
+
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = dd.staticReadOnlyProperty
+
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ dd.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ dd.staticReadWrite1 += 1
+
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ dd.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ dd.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&dd.staticReadWrite2.number)
+
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = m.d.staticReadOnlyProperty
+
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ m.d.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ m.d.staticReadWrite1 += 1
+
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ m.d.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ m.d.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&m.d.staticReadWrite2.number)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions5testS_2ssyAA10MetaHolderV_AA1SVmtF
+func testS(_ m: MetaHolder, ss: S.Type) {
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = S.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ S.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ S.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ S.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ S.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&S.staticReadWrite2.number)
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = ss.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ ss.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ ss.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ ss.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ ss.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&ss.staticReadWrite2.number)
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = m.s.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ m.s.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ m.s.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ m.s.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ m.s.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&m.s.staticReadWrite2.number)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions5testG{{[_0-9a-zA-Z]*}}F
+func testG<T>(_ m: GenericMetaHolder<T>, gg: G<T>.Type) {
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = G<T>.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ G<T>.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ G<T>.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ G<T>.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ G<T>.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&G<T>.staticReadWrite2.number)
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = gg.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ gg.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ gg.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ gg.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ gg.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&gg.staticReadWrite2.number)
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
+ let _ = m.g.staticReadOnlyProperty
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ m.g.staticReadWrite1 = 1
+
+ // CHECK: alloc_stack $Int
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite1SivsZ
+ // CHECK: dealloc_stack
+ m.g.staticReadWrite1 += 1
+
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ m.g.staticReadWrite2 = Box(number: 2)
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ m.g.staticReadWrite2.number += 5
+
+ // CHECK: alloc_stack $Box
+ // CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
+ // CHECK: store
+ // CHECK: function_ref @$S19protocol_extensions10inout_funcyySizF
+ // CHECK: load
+ // CHECK: function_ref @$S19protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
+ // CHECK: dealloc_stack
+ inout_func(&m.g.staticReadWrite2.number)
+
+ // CHECK: return
+}
+
+// ----------------------------------------------------------------------------
+// Using protocol extension members with existentials
+// ----------------------------------------------------------------------------
+extension P1 {
+ func f1() { }
+
+ subscript (i: Int64) -> Bool {
+ get { return true }
+ }
+
+ var prop: Bool {
+ get { return true }
+ }
+
+ func returnsSelf() -> Self { return self }
+
+ var prop2: Bool {
+ get { return true }
+ set { }
+ }
+
+ subscript (b: Bool) -> Bool {
+ get { return b }
+ set { }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions17testExistentials1{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[P:%[0-9]+]] : $*P1, [[B:%[0-9]+]] : $Bool, [[I:%[0-9]+]] : $Int64):
+func testExistentials1(_ p1: P1, b: Bool, i: Int64) {
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]])
+ // CHECK: [[F1:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE2f1{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[F1]]<@opened([[UUID]]) P1>([[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> ()
+ p1.f1()
+
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] :
+ // CHECK: [[GETTER:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAEySbs5Int64Vcig
+ // CHECK: apply [[GETTER]]<@opened([[UUID]]) P1>([[I]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Int64, @in_guaranteed τ_0_0) -> Bool
+ // CHECK: store{{.*}} : $*Bool
+ // CHECK: destroy_addr [[POPENED_COPY]]
+ // CHECK: dealloc_stack [[POPENED_COPY]]
+ var b2 = p1[i]
+
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] :
+ // CHECK: [[GETTER:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE4propSbvg
+ // CHECK: apply [[GETTER]]<@opened([[UUID]]) P1>([[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> Bool
+ // CHECK: store{{.*}} : $*Bool
+ // CHECK: dealloc_stack [[POPENED_COPY]]
+ var b3 = p1.prop
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions17testExistentials2{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[P:%[0-9]+]] : $*P1):
+func testExistentials2(_ p1: P1) {
+ // CHECK: [[P1A:%[0-9]+]] = alloc_box ${ var P1 }
+ // CHECK: [[PB:%.*]] = project_box [[P1A]]
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: [[P1AINIT:%[0-9]+]] = init_existential_addr [[PB]] : $*P1, $@opened([[UUID2:".*"]]) P1
+ // CHECK: [[FN:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FN]]<@opened([[UUID]]) P1>([[P1AINIT]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ var p1a: P1 = p1.returnsSelf()
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions23testExistentialsGetters{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[P:%[0-9]+]] : $*P1):
+func testExistentialsGetters(_ p1: P1) {
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] :
+ // CHECK: [[FN:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE5prop2Sbvg
+ // CHECK: [[B:%[0-9]+]] = apply [[FN]]<@opened([[UUID]]) P1>([[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (@in_guaranteed τ_0_0) -> Bool
+ let b: Bool = p1.prop2
+
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr immutable_access [[P]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: copy_addr [[POPENED]] to [initialization] [[POPENED_COPY:%.*]] :
+ // CHECK: [[GETTER:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAEyS2bcig
+ // CHECK: apply [[GETTER]]<@opened([[UUID]]) P1>([[B]], [[POPENED_COPY]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @in_guaranteed τ_0_0) -> Bool
+ let b2: Bool = p1[b]
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions22testExistentialSetters{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[P:%[0-9]+]] : $*P1, [[B:%[0-9]+]] : $Bool):
+func testExistentialSetters(_ p1: P1, b: Bool) {
+ var p1 = p1
+ // CHECK: [[PBOX:%[0-9]+]] = alloc_box ${ var P1 }
+ // CHECK: [[PBP:%[0-9]+]] = project_box [[PBOX]]
+ // CHECK-NEXT: copy_addr [[P]] to [initialization] [[PBP]] : $*P1
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBP]]
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr mutable_access [[WRITE]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: [[GETTER:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE5prop2Sbvs
+ // CHECK: apply [[GETTER]]<@opened([[UUID]]) P1>([[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> ()
+ // CHECK-NOT: deinit_existential_addr
+ p1.prop2 = b
+
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBP]]
+ // CHECK: [[POPENED:%[0-9]+]] = open_existential_addr mutable_access [[WRITE]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: [[SUBSETTER:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAEyS2bcis
+ // CHECK: apply [[SUBSETTER]]<@opened([[UUID]]) P1>([[B]], [[B]], [[POPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, Bool, @inout τ_0_0) -> ()
+ // CHECK-NOT: deinit_existential_addr [[PB]] : $*P1
+ p1[b] = b
+
+ // CHECK: return
+}
+
+struct HasAP1 {
+ var p1: P1
+
+ var someP1: P1 {
+ get { return p1 }
+ set { p1 = newValue }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions29testLogicalExistentialSetters{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[HASP1:%[0-9]+]] : $*HasAP1, [[B:%[0-9]+]] : $Bool)
+func testLogicalExistentialSetters(_ hasAP1: HasAP1, _ b: Bool) {
+ var hasAP1 = hasAP1
+ // CHECK: [[HASP1_BOX:%[0-9]+]] = alloc_box ${ var HasAP1 }
+ // CHECK: [[PBHASP1:%[0-9]+]] = project_box [[HASP1_BOX]]
+ // CHECK-NEXT: copy_addr [[HASP1]] to [initialization] [[PBHASP1]] : $*HasAP1
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBHASP1]]
+ // CHECK: [[P1_COPY:%[0-9]+]] = alloc_stack $P1
+ // CHECK-NEXT: [[HASP1_COPY:%[0-9]+]] = alloc_stack $HasAP1
+ // CHECK-NEXT: copy_addr [[WRITE]] to [initialization] [[HASP1_COPY]] : $*HasAP1
+ // CHECK: [[SOMEP1_GETTER:%[0-9]+]] = function_ref @$S19protocol_extensions6HasAP1V6someP1AA0F0_pvg : $@convention(method) (@in_guaranteed HasAP1) -> @out P1
+ // CHECK: [[RESULT:%[0-9]+]] = apply [[SOMEP1_GETTER]]([[P1_COPY]], [[HASP1_COPY]]) : $@convention(method) (@in_guaranteed HasAP1) -> @out P1
+ // CHECK: [[P1_OPENED:%[0-9]+]] = open_existential_addr mutable_access [[P1_COPY]] : $*P1 to $*@opened([[UUID:".*"]]) P1
+ // CHECK: [[PROP2_SETTER:%[0-9]+]] = function_ref @$S19protocol_extensions2P1PAAE5prop2Sbvs : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> ()
+ // CHECK: apply [[PROP2_SETTER]]<@opened([[UUID]]) P1>([[B]], [[P1_OPENED]]) : $@convention(method) <τ_0_0 where τ_0_0 : P1> (Bool, @inout τ_0_0) -> ()
+ // CHECK: [[SOMEP1_SETTER:%[0-9]+]] = function_ref @$S19protocol_extensions6HasAP1V6someP1AA0F0_pvs : $@convention(method) (@in P1, @inout HasAP1) -> ()
+ // CHECK: apply [[SOMEP1_SETTER]]([[P1_COPY]], [[WRITE]]) : $@convention(method) (@in P1, @inout HasAP1) -> ()
+ // CHECK-NOT: deinit_existential_addr
+ hasAP1.someP1.prop2 = b
+ // CHECK: return
+}
+
+func plusOneP1() -> P1 {}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions38test_open_existential_semantics_opaque{{[_0-9a-zA-Z]*}}F
+func test_open_existential_semantics_opaque(_ guaranteed: P1,
+ immediate: P1) {
+ var immediate = immediate
+ // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var P1 }
+ // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
+ // CHECK: [[VALUE:%.*]] = open_existential_addr immutable_access %0
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+
+ guaranteed.f1()
+
+ // -- Need a guaranteed copy because it's immutable
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: copy_addr [[READ]] to [initialization] [[IMMEDIATE:%.*]] :
+ // CHECK: [[VALUE:%.*]] = open_existential_addr immutable_access [[IMMEDIATE]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // -- Can consume the value from our own copy
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK: destroy_addr [[IMMEDIATE]]
+ // CHECK: dealloc_stack [[IMMEDIATE]]
+ immediate.f1()
+
+ // CHECK: [[PLUS_ONE:%.*]] = alloc_stack $P1
+ // CHECK: [[VALUE:%.*]] = open_existential_addr immutable_access [[PLUS_ONE]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // -- Can consume the value from our own copy
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK: destroy_addr [[PLUS_ONE]]
+ // CHECK: dealloc_stack [[PLUS_ONE]]
+ plusOneP1().f1()
+}
+
+protocol CP1: class {}
+
+extension CP1 {
+ func f1() { }
+}
+
+func plusOneCP1() -> CP1 {}
+
+// CHECK-LABEL: sil hidden @$S19protocol_extensions37test_open_existential_semantics_class{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0([[ARG0:%.*]] : $CP1, [[ARG1:%.*]] : $CP1):
+func test_open_existential_semantics_class(_ guaranteed: CP1,
+ immediate: CP1) {
+ var immediate = immediate
+ // CHECK: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var CP1 }
+ // CHECK: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]
+
+ // CHECK-NOT: copy_value [[ARG0]]
+ // CHECK: [[VALUE:%.*]] = open_existential_ref [[ARG0]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK-NOT: destroy_value [[VALUE]]
+ // CHECK-NOT: destroy_value [[ARG0]]
+ guaranteed.f1()
+
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
+ // CHECK: [[IMMEDIATE:%.*]] = load [copy] [[READ]]
+ // CHECK: [[VALUE:%.*]] = open_existential_ref [[IMMEDIATE]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK: destroy_value [[VALUE]]
+ // CHECK-NOT: destroy_value [[IMMEDIATE]]
+ immediate.f1()
+
+ // CHECK: [[F:%.*]] = function_ref {{.*}}plusOneCP1
+ // CHECK: [[PLUS_ONE:%.*]] = apply [[F]]()
+ // CHECK: [[VALUE:%.*]] = open_existential_ref [[PLUS_ONE]]
+ // CHECK: [[METHOD:%.*]] = function_ref
+ // CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
+ // CHECK: destroy_value [[VALUE]]
+ // CHECK-NOT: destroy_value [[PLUS_ONE]]
+ plusOneCP1().f1()
+}
+// CHECK: } // end sil function '$S19protocol_extensions37test_open_existential_semantics_class{{[_0-9a-zA-Z]*}}F'
+
+protocol InitRequirement {
+ init(c: C)
+}
+
+extension InitRequirement {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions15InitRequirementPAAE1dxAA1DC_tcfC : $@convention(method) <Self where Self : InitRequirement> (@owned D, @thick Self.Type) -> @out Self
+ // CHECK: bb0([[OUT:%.*]] : $*Self, [[ARG:%.*]] : $D, [[SELF_TYPE:%.*]] : $@thick Self.Type):
+ init(d: D) {
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box
+ // CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
+ // CHECK: [[SELF_BOX:%.*]] = alloc_stack $Self
+ // CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+ // CHECK-NEXT: [[ARG_COPY_CAST:%.*]] = upcast [[ARG_COPY]]
+ // CHECK: [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1 : {{.*}} : $@convention(witness_method: InitRequirement) <τ_0_0 where τ_0_0 : InitRequirement> (@owned C, @thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK-NEXT: apply [[DELEGATEE]]<Self>([[SELF_BOX]], [[ARG_COPY_CAST]], [[SELF_TYPE]])
+ // CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
+ // CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [[SELF_BOX_ADDR]]
+ // CHECK-NEXT: dealloc_stack [[SELF_BOX]]
+ // CHECK-NEXT: copy_addr [[SELF_BOX_ADDR]] to [initialization] [[OUT]]
+ // CHECK-NEXT: destroy_value [[ARG]]
+ // CHECK-NEXT: destroy_value [[UNINIT_SELF]]
+ // CHECK: return
+ self.init(c: d)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions15InitRequirementPAAE2d2xAA1DC_tcfC : $@convention(method)
+ // CHECK: bb0([[OUT:%.*]] : $*Self, [[ARG:%.*]] : $D, [[SELF_TYPE:%.*]] : $@thick Self.Type):
+ init(d2: D) {
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box
+ // CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
+ // CHECK: [[SELF_BOX:%.*]] = alloc_stack $Self
+ // CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+ // CHECK: [[DELEGATEE:%.*]] = function_ref @$S19protocol_extensions15InitRequirementPAAE1dxAA1DC_tcfC
+ // CHECK-NEXT: apply [[DELEGATEE]]<Self>([[SELF_BOX]], [[ARG_COPY]], [[SELF_TYPE]])
+ // CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
+ // CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [[SELF_BOX_ADDR]]
+ // CHECK-NEXT: dealloc_stack [[SELF_BOX]]
+ // CHECK-NEXT: copy_addr [[SELF_BOX_ADDR]] to [initialization] [[OUT]]
+ // CHECK-NEXT: destroy_value [[ARG]]
+ // CHECK-NEXT: destroy_value [[UNINIT_SELF]]
+ // CHECK: return
+ self.init(d: d2)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions15InitRequirementPAAE2c2xAA1CC_tcfC : $@convention(method)
+ // CHECK: bb0([[OUT:%.*]] : $*Self, [[ARG:%.*]] : $C, [[SELF_TYPE:%.*]] : $@thick Self.Type):
+ init(c2: C) {
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box
+ // CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
+ // CHECK: [[SELF_BOX:%.*]] = alloc_stack $Self
+ // CHECK-NEXT: [[SELF_TYPE:%.*]] = metatype $@thick Self.Type
+ // CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+ // CHECK: [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1
+ // CHECK-NEXT: apply [[DELEGATEE]]<Self>([[SELF_BOX]], [[ARG_COPY]], [[SELF_TYPE]])
+ // CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
+ // CHECK-NEXT: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[SELF_BOX_ADDR]]
+ // CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [[ACCESS]]
+ // CHECK-NEXT: end_access [[ACCESS]]
+ // CHECK-NEXT: dealloc_stack [[SELF_BOX]]
+ // CHECK-NEXT: copy_addr [[SELF_BOX_ADDR]] to [initialization] [[OUT]]
+ // CHECK-NEXT: destroy_value [[ARG]]
+ // CHECK-NEXT: destroy_value [[UNINIT_SELF]]
+ // CHECK: return
+ self = Self(c: c2)
+ }
+}
+
+protocol ClassInitRequirement: class {
+ init(c: C)
+}
+
+extension ClassInitRequirement {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions20ClassInitRequirementPAAE{{[_0-9a-zA-Z]*}}fC : $@convention(method) <Self where Self : ClassInitRequirement> (@owned D, @thick Self.Type) -> @owned Self
+ // CHECK: bb0([[ARG:%.*]] : $D, [[SELF_TYPE:%.*]] : $@thick Self.Type):
+ // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+ // CHECK: [[ARG_COPY_CAST:%.*]] = upcast [[ARG_COPY]]
+ // CHECK: [[DELEGATEE:%.*]] = witness_method $Self, #ClassInitRequirement.init!allocator.1 : {{.*}} : $@convention(witness_method: ClassInitRequirement) <τ_0_0 where τ_0_0 : ClassInitRequirement> (@owned C, @thick τ_0_0.Type) -> @owned τ_0_0
+ // CHECK: apply [[DELEGATEE]]<Self>([[ARG_COPY_CAST]], [[SELF_TYPE]])
+ // CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
+
+ // CHECK: } // end sil function '$S19protocol_extensions20ClassInitRequirementPAAE{{[_0-9a-zA-Z]*}}fC'
+ init(d: D) {
+ self.init(c: d)
+ }
+}
+
+@objc class OC {}
+@objc class OD: OC {}
+
+@objc protocol ObjCInitRequirement {
+ init(c: OC, d: OC)
+}
+
+func foo(_ t: ObjCInitRequirement.Type, c: OC) -> ObjCInitRequirement {
+ return t.init(c: OC(), d: OC())
+}
+
+extension ObjCInitRequirement {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions19ObjCInitRequirementPAAE{{[_0-9a-zA-Z]*}}fC : $@convention(method) <Self where Self : ObjCInitRequirement> (@owned OD, @thick Self.Type) -> @owned Self
+ // CHECK: bb0([[ARG:%.*]] : $OD, [[SELF_TYPE:%.*]] : $@thick Self.Type):
+ // CHECK: [[OBJC_SELF_TYPE:%.*]] = thick_to_objc_metatype [[SELF_TYPE]]
+ // CHECK: [[SELF:%.*]] = alloc_ref_dynamic [objc] [[OBJC_SELF_TYPE]] : $@objc_metatype Self.Type, $Self
+ // CHECK: [[BORROWED_ARG_1:%.*]] = begin_borrow [[ARG]]
+ // CHECK: [[BORROWED_ARG_1_UPCAST:%.*]] = upcast [[BORROWED_ARG_1]]
+ // CHECK: [[BORROWED_ARG_2:%.*]] = begin_borrow [[ARG]]
+ // CHECK: [[BORROWED_ARG_2_UPCAST:%.*]] = upcast [[BORROWED_ARG_2]]
+ // CHECK: [[WITNESS:%.*]] = objc_method [[SELF]] : $Self, #ObjCInitRequirement.init!initializer.1.foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjCInitRequirement> (OC, OC, @owned τ_0_0) -> @owned τ_0_0
+ // CHECK: apply [[WITNESS]]<Self>([[BORROWED_ARG_1_UPCAST]], [[BORROWED_ARG_2_UPCAST]], [[SELF]])
+ // CHECK: end_borrow [[BORROWED_ARG_2]] from [[ARG]]
+ // CHECK: end_borrow [[BORROWED_ARG_1]] from [[ARG]]
+ // CHECK: } // end sil function '$S19protocol_extensions19ObjCInitRequirementPAAE{{[_0-9a-zA-Z]*}}fC'
+ init(d: OD) {
+ self.init(c: d, d: d)
+ }
+}
+
+// rdar://problem/21370992 - delegation from an initializer in a
+// protocol extension to an @objc initializer in a class.
+class ObjCInitClass {
+ @objc required init() { }
+}
+
+protocol ProtoDelegatesToObjC { }
+
+extension ProtoDelegatesToObjC where Self : ObjCInitClass {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions20ProtoDelegatesToObjCPA2A0F10CInitClassC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: bb0([[STR:%[0-9]+]] : $String, [[SELF_META:%[0-9]+]] : $@thick Self.Type):
+ init(string: String) {
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box $<τ_0_0 where τ_0_0 : ObjCInitClass, τ_0_0 : ProtoDelegatesToObjC> { var τ_0_0 } <Self>
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK: [[PB_SELF_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+ // CHECK: [[SELF_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[SELF_META]] : $@thick Self.Type to $@objc_metatype Self.Type
+ // CHECK: [[SELF_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[SELF_META_OBJC]] : $@objc_metatype Self.Type, $Self
+ // CHECK: [[SELF_ALLOC_C:%[0-9]+]] = upcast [[SELF_ALLOC]] : $Self to $ObjCInitClass
+ // CHECK: [[OBJC_INIT:%[0-9]+]] = class_method [[SELF_ALLOC_C]] : $ObjCInitClass, #ObjCInitClass.init!initializer.1 : (ObjCInitClass.Type) -> () -> ObjCInitClass, $@convention(method) (@owned ObjCInitClass) -> @owned ObjCInitClass
+ // CHECK: [[SELF_RESULT:%[0-9]+]] = apply [[OBJC_INIT]]([[SELF_ALLOC_C]]) : $@convention(method) (@owned ObjCInitClass) -> @owned ObjCInitClass
+ // CHECK: [[SELF_RESULT_AS_SELF:%[0-9]+]] = unchecked_ref_cast [[SELF_RESULT]] : $ObjCInitClass to $Self
+ // CHECK: assign [[SELF_RESULT_AS_SELF]] to [[PB_SELF_BOX]] : $*Self
+ self.init()
+ }
+}
+
+// Delegating from an initializer in a protocol extension where Self
+// has a superclass to a required initializer of that class.
+class RequiredInitClass {
+ required init() { }
+}
+
+protocol ProtoDelegatesToRequired { }
+
+extension ProtoDelegatesToRequired where Self : RequiredInitClass {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions24ProtoDelegatesToRequiredPA2A0F9InitClassC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: bb0([[STR:%[0-9]+]] : $String, [[SELF_META:%[0-9]+]] : $@thick Self.Type):
+ init(string: String) {
+ // CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box $<τ_0_0 where τ_0_0 : RequiredInitClass, τ_0_0 : ProtoDelegatesToRequired> { var τ_0_0 } <Self>
+ // CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK: [[PB_SELF_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
+ // CHECK: [[SELF_META_AS_CLASS_META:%[0-9]+]] = upcast [[SELF_META]] : $@thick Self.Type to $@thick RequiredInitClass.Type
+ // CHECK: [[INIT:%[0-9]+]] = class_method [[SELF_META_AS_CLASS_META]] : $@thick RequiredInitClass.Type, #RequiredInitClass.init!allocator.1 : (RequiredInitClass.Type) -> () -> RequiredInitClass, $@convention(method) (@thick RequiredInitClass.Type) -> @owned RequiredInitClass
+ // CHECK: [[SELF_RESULT:%[0-9]+]] = apply [[INIT]]([[SELF_META_AS_CLASS_META]]) : $@convention(method) (@thick RequiredInitClass.Type) -> @owned RequiredInitClass
+ // CHECK: [[SELF_RESULT_AS_SELF:%[0-9]+]] = unchecked_ref_cast [[SELF_RESULT]] : $RequiredInitClass to $Self
+ // CHECK: assign [[SELF_RESULT_AS_SELF]] to [[PB_SELF_BOX]] : $*Self
+ self.init()
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Default implementations via protocol extensions
+// ----------------------------------------------------------------------------
+
+protocol P2 {
+ associatedtype A
+ func f1(_ a: A)
+ func f2(_ a: A)
+ var x: A { get }
+}
+
+extension P2 {
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions2P2PAAE2f1{{[_0-9a-zA-Z]*}}F
+ // CHECK: witness_method $Self, #P2.f2!1
+ // CHECK: function_ref @$S19protocol_extensions2P2PAAE2f3{{[_0-9a-zA-Z]*}}F
+ // CHECK: return
+ func f1(_ a: A) {
+ f2(a)
+ f3(a)
+ }
+
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions2P2PAAE2f2{{[_0-9a-zA-Z]*}}F
+ // CHECK: witness_method $Self, #P2.f1!1
+ // CHECK: function_ref @$S19protocol_extensions2P2PAAE2f3{{[_0-9a-zA-Z]*}}F
+ // CHECK: return
+ func f2(_ a: A) {
+ f1(a)
+ f3(a)
+ }
+
+ func f3(_ a: A) {}
+
+ // CHECK-LABEL: sil hidden @$S19protocol_extensions2P2PAAE2f4{{[_0-9a-zA-Z]*}}F
+ // CHECK: witness_method $Self, #P2.f1!1
+ // CHECK: witness_method $Self, #P2.f2!1
+ // CHECK: return
+ func f4() {
+ f1(x)
+ f2(x)
+ }
+}
diff --git a/test/SILGen/plus_zero_protocol_optional.swift b/test/SILGen/plus_zero_protocol_optional.swift
new file mode 100644
index 0000000..25e1dd6
--- /dev/null
+++ b/test/SILGen/plus_zero_protocol_optional.swift
@@ -0,0 +1,68 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module -enable-sil-ownership %s | %FileCheck %s
+
+@objc protocol P1 {
+ @objc optional func method(_ x: Int)
+
+ @objc optional var prop: Int { get }
+
+ @objc optional subscript (i: Int) -> Int { get }
+}
+
+// CHECK-LABEL: sil hidden @$S17protocol_optional0B13MethodGeneric1tyx_tAA2P1RzlF : $@convention(thin) <T where T : P1> (@guaranteed T) -> ()
+func optionalMethodGeneric<T : P1>(t t : T) {
+ var t = t
+ // CHECK: bb0([[T:%[0-9]+]] : @guaranteed $T):
+ // CHECK: [[TBOX:%[0-9]+]] = alloc_box $<τ_0_0 where τ_0_0 : P1> { var τ_0_0 } <T>
+ // CHECK: [[PT:%[0-9]+]] = project_box [[TBOX]]
+ // CHECK: [[T_COPY:%.*]] = copy_value [[T]]
+ // CHECK: store [[T_COPY]] to [init] [[PT]] : $*T
+ // CHECK: [[OPT_BOX:%[0-9]+]] = alloc_box ${ var Optional<@callee_guaranteed (Int) -> ()> }
+ // CHECK: project_box [[OPT_BOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T
+ // CHECK: [[T:%[0-9]+]] = load [copy] [[READ]] : $*T
+ // CHECK: alloc_stack $Optional<@callee_guaranteed (Int) -> ()>
+ // CHECK: dynamic_method_br [[T]] : $T, #P1.method!1.foreign
+ var methodRef = t.method
+}
+// CHECK: } // end sil function '$S17protocol_optional0B13MethodGeneric1tyx_tAA2P1RzlF'
+
+// CHECK-LABEL: sil hidden @$S17protocol_optional0B15PropertyGeneric{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : P1> (@guaranteed T) -> ()
+func optionalPropertyGeneric<T : P1>(t t : T) {
+ var t = t
+ // CHECK: bb0([[T:%[0-9]+]] : @guaranteed $T):
+ // CHECK: [[TBOX:%[0-9]+]] = alloc_box $<τ_0_0 where τ_0_0 : P1> { var τ_0_0 } <T>
+ // CHECK: [[PT:%[0-9]+]] = project_box [[TBOX]]
+ // CHECK: [[T_COPY:%.*]] = copy_value [[T]]
+ // CHECK: store [[T_COPY]] to [init] [[PT]] : $*T
+ // CHECK: [[OPT_BOX:%[0-9]+]] = alloc_box ${ var Optional<Int> }
+ // CHECK: project_box [[OPT_BOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T
+ // CHECK: [[T:%[0-9]+]] = load [copy] [[READ]] : $*T
+ // CHECK: alloc_stack $Optional<Int>
+ // CHECK: dynamic_method_br [[T]] : $T, #P1.prop!getter.1.foreign
+ var propertyRef = t.prop
+}
+// CHECK: } // end sil function '$S17protocol_optional0B15PropertyGeneric{{[_0-9a-zA-Z]*}}F'
+
+// CHECK-LABEL: sil hidden @$S17protocol_optional0B16SubscriptGeneric{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : P1> (@guaranteed T) -> ()
+func optionalSubscriptGeneric<T : P1>(t t : T) {
+ var t = t
+ // CHECK: bb0([[T:%[0-9]+]] : @guaranteed $T):
+ // CHECK: [[TBOX:%[0-9]+]] = alloc_box $<τ_0_0 where τ_0_0 : P1> { var τ_0_0 } <T>
+ // CHECK: [[PT:%[0-9]+]] = project_box [[TBOX]]
+ // CHECK: [[T_COPY:%.*]] = copy_value [[T]]
+ // CHECK: store [[T_COPY]] to [init] [[PT]] : $*T
+ // CHECK: [[OPT_BOX:%[0-9]+]] = alloc_box ${ var Optional<Int> }
+ // CHECK: project_box [[OPT_BOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T
+ // CHECK: [[T:%[0-9]+]] = load [copy] [[READ]] : $*T
+ // CHECK: [[INT64:%[0-9]+]] = metatype $@thin Int.Type
+ // CHECK: [[FIVELIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 5
+ // CHECK: [[INTCONV:%[0-9]+]] = function_ref @$SSi2{{[_0-9a-zA-Z]*}}fC
+ // CHECK: [[FIVE:%[0-9]+]] = apply [[INTCONV]]([[FIVELIT]], [[INT64]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+ // CHECK: alloc_stack $Optional<Int>
+ // CHECK: dynamic_method_br [[T]] : $T, #P1.subscript!getter.1.foreign
+ var subscriptRef = t[5]
+}
+// CHECK: } // end sil function '$S17protocol_optional0B16SubscriptGeneric{{[_0-9a-zA-Z]*}}F'
diff --git a/test/SILGen/plus_zero_protocol_resilience.swift b/test/SILGen/plus_zero_protocol_resilience.swift
new file mode 100644
index 0000000..df24b0f
--- /dev/null
+++ b/test/SILGen/plus_zero_protocol_resilience.swift
@@ -0,0 +1,318 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-sil-ownership -enable-resilience -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../Inputs/resilient_protocol.swift
+// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -enable-resilience %s | %FileCheck %s
+
+import resilient_protocol
+
+prefix operator ~~~ {}
+infix operator <*> {}
+infix operator <**> {}
+infix operator <===> {}
+
+public protocol P {}
+
+
+// Protocol is public -- needs resilient witness table
+public protocol ResilientMethods {
+ associatedtype AssocType : P
+
+ func defaultWitness()
+ func anotherDefaultWitness(_ x: Int) -> Self
+ func defaultWitnessWithAssociatedType(_ a: AssocType)
+ func defaultWitnessMoreAbstractThanRequirement(_ a: AssocType, b: Int)
+ func defaultWitnessMoreAbstractThanGenericRequirement<T>(_ a: AssocType, t: T)
+
+ func noDefaultWitness()
+ func defaultWitnessIsNotPublic()
+
+ static func staticDefaultWitness(_ x: Int) -> Self
+}
+
+extension ResilientMethods {
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientMethodsP14defaultWitnessyyF
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientMethodsPAAE14defaultWitnessyyF
+ public func defaultWitness() {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientMethodsP21anotherDefaultWitnessyxSiF
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientMethodsPAAE21anotherDefaultWitnessyxSiF
+ public func anotherDefaultWitness(_ x: Int) -> Self {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientMethodsP32defaultWitnessWithAssociatedTypeyy05AssocI0QzF
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientMethodsPAAE32defaultWitnessWithAssociatedTypeyy05AssocI0QzF
+ public func defaultWitnessWithAssociatedType(_ a: AssocType) {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientMethodsP41defaultWitnessMoreAbstractThanRequirement_1by9AssocTypeQz_SitF
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientMethodsPAAE41defaultWitnessMoreAbstractThanRequirement_1byqd___qd_0_tr0_lF
+ public func defaultWitnessMoreAbstractThanRequirement<A, T>(_ a: A, b: T) {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientMethodsP48defaultWitnessMoreAbstractThanGenericRequirement_1ty9AssocTypeQz_qd__tlF
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientMethodsPAAE48defaultWitnessMoreAbstractThanGenericRequirement_1tyqd___qd_0_tr0_lF
+ public func defaultWitnessMoreAbstractThanGenericRequirement<A, T>(_ a: A, t: T) {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientMethodsP20staticDefaultWitnessyxSiFZ
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientMethodsPAAE20staticDefaultWitnessyxSiFZ
+ public static func staticDefaultWitness(_ x: Int) -> Self {}
+
+// CHECK-LABEL: sil private @$S19protocol_resilience16ResilientMethodsPAAE25defaultWitnessIsNotPublic{{.*}}F
+ private func defaultWitnessIsNotPublic() {}
+
+}
+
+
+public protocol ResilientConstructors {
+ init(noDefault: ())
+ init(default: ())
+ init?(defaultIsOptional: ())
+ init?(defaultNotOptional: ())
+ init(optionalityMismatch: ())
+}
+
+extension ResilientConstructors {
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience21ResilientConstructorsP7defaultxyt_tcfC
+// CHECK-LABEL: sil @$S19protocol_resilience21ResilientConstructorsPAAE7defaultxyt_tcfC
+ public init(default: ()) {
+ self.init(noDefault: ())
+ }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience21ResilientConstructorsP17defaultIsOptionalxSgyt_tcfC
+// CHECK-LABEL: sil @$S19protocol_resilience21ResilientConstructorsPAAE17defaultIsOptionalxSgyt_tcfC
+ public init?(defaultIsOptional: ()) {
+ self.init(noDefault: ())
+ }
+
+// CHECK-LABEL: sil @$S19protocol_resilience21ResilientConstructorsPAAE20defaultIsNotOptionalxyt_tcfC
+ public init(defaultIsNotOptional: ()) {
+ self.init(noDefault: ())
+ }
+
+// CHECK-LABEL: sil @$S19protocol_resilience21ResilientConstructorsPAAE19optionalityMismatchxSgyt_tcfC
+ public init?(optionalityMismatch: ()) {
+ self.init(noDefault: ())
+ }
+}
+
+
+public protocol ResilientStorage {
+ associatedtype T : ResilientConstructors
+
+ var propertyWithDefault: Int { get }
+ var propertyWithNoDefault: Int { get }
+ var mutablePropertyWithDefault: Int { get set }
+ var mutablePropertyNoDefault: Int { get set }
+ var mutableGenericPropertyWithDefault: T { get set }
+
+ subscript(x: T) -> T { get set }
+
+ var mutatingGetterWithNonMutatingDefault: Int { mutating get set }
+}
+
+extension ResilientStorage {
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP19propertyWithDefaultSivg
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE19propertyWithDefaultSivg
+ public var propertyWithDefault: Int {
+ get { return 0 }
+ }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivg
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE26mutablePropertyWithDefaultSivg
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivs
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE26mutablePropertyWithDefaultSivs
+// CHECK-LABEL: sil private [transparent] @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivmytfU_
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivm
+ public var mutablePropertyWithDefault: Int {
+ get { return 0 }
+ set { }
+ }
+
+ public private(set) var mutablePropertyNoDefault: Int {
+ get { return 0 }
+ set { }
+ }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvg
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE33mutableGenericPropertyWithDefault1TQzvg
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvs
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE33mutableGenericPropertyWithDefault1TQzvs
+// CHECK-LABEL: sil private [transparent] @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvmytfU_
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvm
+ public var mutableGenericPropertyWithDefault: T {
+ get {
+ return T(default: ())
+ }
+ set { }
+ }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStoragePy1TQzAEcig
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAEy1TQzAEcig
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStoragePy1TQzAEcis
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAEy1TQzAEcis
+// CHECK-LABEL: sil private [transparent] @$S19protocol_resilience16ResilientStoragePy1TQzAEcimytfU_
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStoragePy1TQzAEcim
+ public subscript(x: T) -> T {
+ get {
+ return x
+ }
+ set { }
+ }
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivg
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE36mutatingGetterWithNonMutatingDefaultSivg
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivs
+// CHECK-LABEL: sil @$S19protocol_resilience16ResilientStoragePAAE36mutatingGetterWithNonMutatingDefaultSivs
+// CHECK-LABEL: sil private [transparent] @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivmytfU_
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivm
+ public var mutatingGetterWithNonMutatingDefault: Int {
+ get {
+ return 0
+ }
+ set { }
+ }
+}
+
+
+public protocol ResilientOperators {
+ associatedtype AssocType : P
+
+ static prefix func ~~~(s: Self)
+ static func <*><T>(s: Self, t: T)
+ static func <**><T>(t: T, s: Self) -> AssocType
+ static func <===><T : ResilientOperators>(t: T, s: Self) -> T.AssocType
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience18ResilientOperatorsP3tttopyyxFZ
+// CHECK-LABEL: sil @$S19protocol_resilience3tttopyyxlF
+public prefix func ~~~<S>(s: S) {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience18ResilientOperatorsP3lmgoiyyx_qd__tlFZ
+// CHECK-LABEL: sil @$S19protocol_resilience3lmgoiyyq__xtr0_lF
+public func <*><T, S>(s: S, t: T) {}
+
+// Swap the generic parameters to make sure we don't mix up our DeclContexts
+// when mapping interface types in and out
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience18ResilientOperatorsP4lmmgoiy9AssocTypeQzqd___xtlFZ
+// CHECK-LABEL: sil @$S19protocol_resilience4lmmgoiy9AssocTypeQzq__xtAA18ResilientOperatorsRzr0_lF
+public func <**><S : ResilientOperators, T>(t: T, s: S) -> S.AssocType {}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience18ResilientOperatorsP5leeegoiy9AssocTypeQyd__qd___xtAaBRd__lFZ
+// CHECK-LABEL: sil @$S19protocol_resilience5leeegoiy9AssocTypeQzx_q_tAA18ResilientOperatorsRzAaER_r0_lF
+public func <===><T : ResilientOperators, S : ResilientOperators>(t: T, s: S) -> T.AssocType {}
+
+
+public protocol ReabstractSelfBase {
+ // No requirements
+}
+
+public protocol ReabstractSelfRefined : class, ReabstractSelfBase {
+ // A requirement with 'Self' abstracted as a class instance
+ var callback: (Self) -> Self { get set }
+}
+
+func id<T>(_ t: T) -> T {}
+
+extension ReabstractSelfBase {
+ // A witness for the above requirement, but with 'Self' maximally abstracted
+ public var callback: (Self) -> Self {
+ get { return id }
+ nonmutating set { }
+ }
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S19protocol_resilience21ReabstractSelfRefinedP8callbackyxxcvg : $@convention(witness_method: ReabstractSelfRefined) <τ_0_0 where τ_0_0 : ReabstractSelfRefined> (@guaranteed τ_0_0) -> @owned @callee_guaranteed (@guaranteed τ_0_0) -> @owned τ_0_0
+// CHECK: [[SELF_BOX:%.*]] = alloc_stack $τ_0_0
+// CHECK-NEXT: [[SELF_COPY:%.*]] = copy_value %0 : $τ_0_0
+// CHECK-NEXT: store [[SELF_COPY]] to [init] [[SELF_BOX]] : $*τ_0_0
+// CHECK: [[WITNESS:%.*]] = function_ref @$S19protocol_resilience18ReabstractSelfBasePAAE8callbackyxxcvg
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS]]<τ_0_0>([[SELF_BOX]])
+// CHECK: [[THUNK_FN:%.*]] = function_ref @$SxxIegnr_xxIeggo_19protocol_resilience21ReabstractSelfRefinedRzlTR
+// CHECK-NEXT: [[THUNK:%.*]] = partial_apply [callee_guaranteed] [[THUNK_FN]]<τ_0_0>([[RESULT]])
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
+// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
+// CHECK-NEXT: return [[THUNK]]
+
+final class X : ReabstractSelfRefined {}
+
+func inoutFunc(_ x: inout Int) {}
+
+// CHECK-LABEL: sil hidden @$S19protocol_resilience22inoutResilientProtocolyy010resilient_A005OtherdE0_pzF
+func inoutResilientProtocol(_ x: inout OtherResilientProtocol) {
+ // CHECK: function_ref @$S18resilient_protocol22OtherResilientProtocolPAAE19propertyInExtensionSivm
+ inoutFunc(&x.propertyInExtension)
+}
+
+struct OtherConformingType : OtherResilientProtocol {}
+
+// CHECK-LABEL: sil hidden @$S19protocol_resilience22inoutResilientProtocolyyAA19OtherConformingTypeVzF
+func inoutResilientProtocol(_ x: inout OtherConformingType) {
+ // CHECK: function_ref @$S18resilient_protocol22OtherResilientProtocolPAAE19propertyInExtensionSivm
+ inoutFunc(&x.propertyInExtension)
+
+ // CHECK: function_ref @$S18resilient_protocol22OtherResilientProtocolPAAE25staticPropertyInExtensionSivmZ
+ inoutFunc(&OtherConformingType.staticPropertyInExtension)
+}
+
+// CHECK-LABEL: sil_default_witness_table P {
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_default_witness_table ResilientMethods {
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientMethods.defaultWitness!1: {{.*}} : @$S19protocol_resilience16ResilientMethodsP14defaultWitnessyyF
+// CHECK-NEXT: method #ResilientMethods.anotherDefaultWitness!1: {{.*}} : @$S19protocol_resilience16ResilientMethodsP21anotherDefaultWitnessyxSiF
+// CHECK-NEXT: method #ResilientMethods.defaultWitnessWithAssociatedType!1: {{.*}} : @$S19protocol_resilience16ResilientMethodsP32defaultWitnessWithAssociatedTypeyy05AssocI0QzF
+// CHECK-NEXT: method #ResilientMethods.defaultWitnessMoreAbstractThanRequirement!1: {{.*}} : @$S19protocol_resilience16ResilientMethodsP41defaultWitnessMoreAbstractThanRequirement_1by9AssocTypeQz_SitF
+// CHECK-NEXT: method #ResilientMethods.defaultWitnessMoreAbstractThanGenericRequirement!1: {{.*}} : @$S19protocol_resilience16ResilientMethodsP48defaultWitnessMoreAbstractThanGenericRequirement_1ty9AssocTypeQz_qd__tlF
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientMethods.staticDefaultWitness!1: {{.*}} : @$S19protocol_resilience16ResilientMethodsP20staticDefaultWitnessyxSiFZ
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_default_witness_table ResilientConstructors {
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientConstructors.init!allocator.1: {{.*}} : @$S19protocol_resilience21ResilientConstructorsP7defaultxyt_tcfC
+// CHECK-NEXT: method #ResilientConstructors.init!allocator.1: {{.*}} : @$S19protocol_resilience21ResilientConstructorsP17defaultIsOptionalxSgyt_tcfC
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_default_witness_table ResilientStorage {
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientStorage.propertyWithDefault!getter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP19propertyWithDefaultSivg
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientStorage.mutablePropertyWithDefault!getter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivg
+// CHECK-NEXT: method #ResilientStorage.mutablePropertyWithDefault!setter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivs
+// CHECK-NEXT: method #ResilientStorage.mutablePropertyWithDefault!materializeForSet.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP26mutablePropertyWithDefaultSivm
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientStorage.mutableGenericPropertyWithDefault!getter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvg
+// CHECK-NEXT: method #ResilientStorage.mutableGenericPropertyWithDefault!setter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvs
+// CHECK-NEXT: method #ResilientStorage.mutableGenericPropertyWithDefault!materializeForSet.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP33mutableGenericPropertyWithDefault1TQzvm
+// CHECK-NEXT: method #ResilientStorage.subscript!getter.1: {{.*}} : @$S19protocol_resilience16ResilientStoragePy1TQzAEcig
+// CHECK-NEXT: method #ResilientStorage.subscript!setter.1: {{.*}} : @$S19protocol_resilience16ResilientStoragePy1TQzAEcis
+// CHECK-NEXT: method #ResilientStorage.subscript!materializeForSet.1: {{.*}} : @$S19protocol_resilience16ResilientStoragePy1TQzAEcim
+// CHECK-NEXT: method #ResilientStorage.mutatingGetterWithNonMutatingDefault!getter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivg
+// CHECK-NEXT: method #ResilientStorage.mutatingGetterWithNonMutatingDefault!setter.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivs
+// CHECK-NEXT: method #ResilientStorage.mutatingGetterWithNonMutatingDefault!materializeForSet.1: {{.*}} : @$S19protocol_resilience16ResilientStorageP36mutatingGetterWithNonMutatingDefaultSivm
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_default_witness_table ResilientOperators {
+// CHECK-NEXT: no_default
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ResilientOperators."~~~"!1: {{.*}} : @$S19protocol_resilience18ResilientOperatorsP3tttopyyxFZ
+// CHECK-NEXT: method #ResilientOperators."<*>"!1: {{.*}} : @$S19protocol_resilience18ResilientOperatorsP3lmgoiyyx_qd__tlFZ
+// CHECK-NEXT: method #ResilientOperators."<**>"!1: {{.*}} : @$S19protocol_resilience18ResilientOperatorsP4lmmgoiy9AssocTypeQzqd___xtlFZ
+// CHECK-NEXT: method #ResilientOperators."<===>"!1: {{.*}} : @$S19protocol_resilience18ResilientOperatorsP5leeegoiy9AssocTypeQyd__qd___xtAaBRd__lFZ
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_default_witness_table ReabstractSelfRefined {
+// CHECK-NEXT: no_default
+// CHECK-NEXT: method #ReabstractSelfRefined.callback!getter.1: {{.*}} : @$S19protocol_resilience21ReabstractSelfRefinedP8callbackyxxcvg
+// CHECK-NEXT: method #ReabstractSelfRefined.callback!setter.1: {{.*}} : @$S19protocol_resilience21ReabstractSelfRefinedP8callbackyxxcvs
+// CHECK-NEXT: method #ReabstractSelfRefined.callback!materializeForSet.1: {{.*}} : @$S19protocol_resilience21ReabstractSelfRefinedP8callbackyxxcvm
+// CHECK-NEXT: }
diff --git a/test/SILGen/plus_zero_protocols.swift b/test/SILGen/plus_zero_protocols.swift
new file mode 100644
index 0000000..20cb940
--- /dev/null
+++ b/test/SILGen/plus_zero_protocols.swift
@@ -0,0 +1,472 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// Calling Existential Subscripts
+//===----------------------------------------------------------------------===//
+
+protocol SubscriptableGet {
+ subscript(a : Int) -> Int { get }
+}
+
+protocol SubscriptableGetSet {
+ subscript(a : Int) -> Int { get set }
+}
+
+var subscriptableGet : SubscriptableGet
+var subscriptableGetSet : SubscriptableGetSet
+
+func use_subscript_rvalue_get(_ i : Int) -> Int {
+ return subscriptableGet[i]
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}use_subscript_rvalue_get
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: [[GLOB:%[0-9]+]] = global_addr @$S9protocols16subscriptableGetAA013SubscriptableC0_pvp : $*SubscriptableGet
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*SubscriptableGet
+// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGet to $*[[OPENED:@opened(.*) SubscriptableGet]]
+// CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]]
+// CHECK: copy_addr [[PROJ]] to [initialization] [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGet.subscript!getter.1
+// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[ALLOCSTACK]])
+// CHECK-NEXT: destroy_addr [[ALLOCSTACK]]
+// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGet
+// CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: return [[RESULT]]
+
+func use_subscript_lvalue_get(_ i : Int) -> Int {
+ return subscriptableGetSet[i]
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}use_subscript_lvalue_get
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: [[GLOB:%[0-9]+]] = global_addr @$S9protocols19subscriptableGetSetAA013SubscriptablecD0_pvp : $*SubscriptableGetSet
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*SubscriptableGetSet
+// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGetSet to $*[[OPENED:@opened(.*) SubscriptableGetSet]]
+// CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]]
+// CHECK: copy_addr [[PROJ]] to [initialization] [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGetSet.subscript!getter.1
+// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[ALLOCSTACK]])
+// CHECK-NEXT: destroy_addr [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGetSet
+// CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: return [[RESULT]]
+
+func use_subscript_lvalue_set(_ i : Int) {
+ subscriptableGetSet[i] = i
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}use_subscript_lvalue_set
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: [[GLOB:%[0-9]+]] = global_addr @$S9protocols19subscriptableGetSetAA013SubscriptablecD0_pvp : $*SubscriptableGetSet
+// CHECK: [[READ:%.*]] = begin_access [modify] [dynamic] [[GLOB]] : $*SubscriptableGetSet
+// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr mutable_access [[READ]] : $*SubscriptableGetSet to $*[[OPENED:@opened(.*) SubscriptableGetSet]]
+// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGetSet.subscript!setter.1
+// CHECK-NEXT: apply [[METH]]<[[OPENED]]>(%0, %0, [[PROJ]])
+
+
+//===----------------------------------------------------------------------===//
+// Calling Archetype Subscripts
+//===----------------------------------------------------------------------===//
+
+func use_subscript_archetype_rvalue_get<T : SubscriptableGet>(_ generic : T, idx : Int) -> Int {
+ return generic[idx]
+}
+// CHECK-LABEL: sil hidden @{{.*}}use_subscript_archetype_rvalue_get
+// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T
+// CHECK: copy_addr %0 to [initialization] [[STACK]]
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGet.subscript!getter.1
+// CHECK-NEXT: apply [[METH]]<T>(%1, [[STACK]])
+// CHECK-NEXT: destroy_addr [[STACK]] : $*T
+// CHECK-NEXT: dealloc_stack [[STACK]] : $*T
+// CHECK: } // end sil function '${{.*}}use_subscript_archetype_rvalue_get
+
+
+func use_subscript_archetype_lvalue_get<T : SubscriptableGetSet>(_ generic: inout T, idx : Int) -> Int {
+ return generic[idx]
+}
+// CHECK-LABEL: sil hidden @{{.*}}use_subscript_archetype_lvalue_get
+// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] %0 : $*T
+// CHECK: [[GUARANTEEDSTACK:%[0-9]+]] = alloc_stack $T
+// CHECK: copy_addr [[READ]] to [initialization] [[GUARANTEEDSTACK]] : $*T
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGetSet.subscript!getter.1
+// CHECK-NEXT: [[APPLYRESULT:%[0-9]+]] = apply [[METH]]<T>(%1, [[GUARANTEEDSTACK]])
+// CHECK-NEXT: destroy_addr [[GUARANTEEDSTACK]] : $*T
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: dealloc_stack [[GUARANTEEDSTACK]] : $*T
+// CHECK: return [[APPLYRESULT]]
+
+
+func use_subscript_archetype_lvalue_set<T : SubscriptableGetSet>(_ generic: inout T, idx : Int) {
+ generic[idx] = idx
+}
+// CHECK-LABEL: sil hidden @{{.*}}use_subscript_archetype_lvalue_set
+// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGetSet.subscript!setter.1
+// CHECK-NEXT: apply [[METH]]<T>(%1, %1, [[WRITE]])
+
+
+//===----------------------------------------------------------------------===//
+// Calling Existential Properties
+//===----------------------------------------------------------------------===//
+
+protocol PropertyWithGetter {
+ var a : Int { get }
+}
+
+protocol PropertyWithGetterSetter {
+ var b : Int { get set }
+}
+
+
+var propertyGet : PropertyWithGetter
+var propertyGetSet : PropertyWithGetterSetter
+
+func use_property_rvalue_get() -> Int {
+ return propertyGet.a
+}
+// CHECK-LABEL: sil hidden @{{.*}}use_property_rvalue_get
+// CHECK: [[GLOB:%[0-9]+]] = global_addr @$S9protocols11propertyGetAA18PropertyWithGetter_pvp : $*PropertyWithGetter
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*PropertyWithGetter
+// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*PropertyWithGetter to $*[[OPENED:@opened(.*) PropertyWithGetter]]
+// CHECK: [[COPY:%.*]] = alloc_stack $[[OPENED]]
+// CHECK-NEXT: copy_addr [[PROJ]] to [initialization] [[COPY]] : $*[[OPENED]]
+// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetter.a!getter.1
+// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[COPY]])
+// CHECK: end_access [[READ]] : $*PropertyWithGetter
+
+func use_property_lvalue_get() -> Int {
+ return propertyGetSet.b
+}
+// CHECK-LABEL: sil hidden @{{.*}}use_property_lvalue_get
+// CHECK: [[GLOB:%[0-9]+]] = global_addr @$S9protocols14propertyGetSetAA24PropertyWithGetterSetter_pvp : $*PropertyWithGetterSetter
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOB]] : $*PropertyWithGetterSetter
+// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*PropertyWithGetterSetter to $*[[OPENED:@opened(.*) PropertyWithGetterSetter]]
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $[[OPENED]]
+// CHECK: copy_addr [[PROJ]] to [initialization] [[STACK]]
+// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetterSetter.b!getter.1
+// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[STACK]])
+
+func use_property_lvalue_set(_ x : Int) {
+ propertyGetSet.b = x
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}use_property_lvalue_set
+// CHECK: bb0(%0 : @trivial $Int):
+// CHECK: [[GLOB:%[0-9]+]] = global_addr @$S9protocols14propertyGetSetAA24PropertyWithGetterSetter_pvp : $*PropertyWithGetterSetter
+// CHECK: [[READ:%.*]] = begin_access [modify] [dynamic] [[GLOB]] : $*PropertyWithGetterSetter
+// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr mutable_access [[READ]] : $*PropertyWithGetterSetter to $*[[OPENED:@opened(.*) PropertyWithGetterSetter]]
+// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetterSetter.b!setter.1
+// CHECK-NEXT: apply [[METH]]<[[OPENED]]>(%0, [[PROJ]])
+
+//===----------------------------------------------------------------------===//
+// Calling Archetype Properties
+//===----------------------------------------------------------------------===//
+
+func use_property_archetype_rvalue_get<T : PropertyWithGetter>(_ generic : T) -> Int {
+ return generic.a
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}use_property_archetype_rvalue_get
+// CHECK: bb0(%0 : @trivial $*T):
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T
+// CHECK: copy_addr %0 to [initialization] [[STACK]]
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetter.a!getter.1
+// CHECK-NEXT: apply [[METH]]<T>([[STACK]])
+// CHECK-NEXT: destroy_addr [[STACK]]
+// CHECK-NEXT: dealloc_stack [[STACK]]
+// CHECK: } // end sil function '{{.*}}use_property_archetype_rvalue_get
+
+
+func use_property_archetype_lvalue_get<T : PropertyWithGetterSetter>(_ generic : T) -> Int {
+ return generic.b
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}use_property_archetype_lvalue_get
+// CHECK: bb0(%0 : @trivial $*T):
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $T
+// CHECK: copy_addr %0 to [initialization] [[STACK]] : $*T
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetterSetter.b!getter.1
+// CHECK-NEXT: apply [[METH]]<T>([[STACK]])
+// CHECK-NEXT: destroy_addr [[STACK]] : $*T
+// CHECK-NEXT: dealloc_stack [[STACK]] : $*T
+// CHECK: } // end sil function '${{.*}}use_property_archetype_lvalue_get
+
+
+func use_property_archetype_lvalue_set<T : PropertyWithGetterSetter>(_ generic: inout T, v : Int) {
+ generic.b = v
+}
+// CHECK-LABEL: sil hidden @{{.*}}use_property_archetype_lvalue_set
+// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
+// CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetterSetter.b!setter.1
+// CHECK-NEXT: apply [[METH]]<T>(%1, [[WRITE]])
+
+//===----------------------------------------------------------------------===//
+// Calling Initializers
+//===----------------------------------------------------------------------===//
+protocol Initializable {
+ init(int: Int)
+}
+
+// CHECK-LABEL: sil hidden @$S9protocols27use_initializable_archetype{{[_0-9a-zA-Z]*}}F
+func use_initializable_archetype<T: Initializable>(_ t: T, i: Int) {
+ // CHECK: [[T_RESULT:%[0-9]+]] = alloc_stack $T
+ // CHECK: [[T_META:%[0-9]+]] = metatype $@thick T.Type
+ // CHECK: [[T_INIT:%[0-9]+]] = witness_method $T, #Initializable.init!allocator.1 : {{.*}} : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK: [[T_RESULT_ADDR:%[0-9]+]] = apply [[T_INIT]]<T>([[T_RESULT]], %1, [[T_META]]) : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK: destroy_addr [[T_RESULT]] : $*T
+ // CHECK: dealloc_stack [[T_RESULT]] : $*T
+ // CHECK: [[RESULT:%[0-9]+]] = tuple ()
+ // CHECK: return [[RESULT]] : $()
+ T(int: i)
+}
+
+// CHECK: sil hidden @$S9protocols29use_initializable_existential{{[_0-9a-zA-Z]*}}F
+func use_initializable_existential(_ im: Initializable.Type, i: Int) {
+// CHECK: bb0([[IM:%[0-9]+]] : @trivial $@thick Initializable.Type, [[I:%[0-9]+]] : @trivial $Int):
+// CHECK: [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[IM]] : $@thick Initializable.Type to $@thick (@opened([[N:".*"]]) Initializable).Type
+// CHECK: [[TEMP_VALUE:%[0-9]+]] = alloc_stack $Initializable
+// CHECK: [[TEMP_ADDR:%[0-9]+]] = init_existential_addr [[TEMP_VALUE]] : $*Initializable, $@opened([[N]]) Initializable
+// CHECK: [[INIT_WITNESS:%[0-9]+]] = witness_method $@opened([[N]]) Initializable, #Initializable.init!allocator.1 : {{.*}}, [[ARCHETYPE_META]]{{.*}} : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
+// CHECK: [[INIT_RESULT:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]]) Initializable>([[TEMP_ADDR]], [[I]], [[ARCHETYPE_META]]) : $@convention(witness_method: Initializable) <τ_0_0 where τ_0_0 : Initializable> (Int, @thick τ_0_0.Type) -> @out τ_0_0
+// CHECK: destroy_addr [[TEMP_VALUE]] : $*Initializable
+// CHECK: dealloc_stack [[TEMP_VALUE]] : $*Initializable
+ im.init(int: i)
+// CHECK: [[RESULT:%[0-9]+]] = tuple ()
+// CHECK: return [[RESULT]] : $()
+}
+
+//===----------------------------------------------------------------------===//
+// Protocol conformance and witness table generation
+//===----------------------------------------------------------------------===//
+
+class ClassWithGetter : PropertyWithGetter {
+ var a: Int {
+ get {
+ return 42
+ }
+ }
+}
+
+// Make sure we are generating a protocol witness that calls the class method on
+// ClassWithGetter.
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9protocols15ClassWithGetterCAA08PropertycD0A2aDP1aSivgTW : $@convention(witness_method: PropertyWithGetter) (@in_guaranteed ClassWithGetter) -> Int {
+// CHECK: bb0([[C:%.*]] : @trivial $*ClassWithGetter):
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load_borrow %0
+// CHECK-NEXT: [[FUN:%.*]] = class_method [[CCOPY_LOADED]] : $ClassWithGetter, #ClassWithGetter.a!getter.1 : (ClassWithGetter) -> () -> Int, $@convention(method) (@guaranteed ClassWithGetter) -> Int
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: end_borrow [[CCOPY_LOADED]] from %0
+// CHECK-NEXT: return
+
+class ClassWithGetterSetter : PropertyWithGetterSetter, PropertyWithGetter {
+ var a: Int {
+ get {
+ return 1
+ }
+ set {}
+ }
+ var b: Int {
+ get {
+ return 2
+ }
+ set {}
+ }
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9protocols21ClassWithGetterSetterCAA08PropertycdE0A2aDP1bSivgTW : $@convention(witness_method: PropertyWithGetterSetter) (@in_guaranteed ClassWithGetterSetter) -> Int {
+// CHECK: bb0([[C:%.*]] : @trivial $*ClassWithGetterSetter):
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load_borrow %0
+// CHECK-NEXT: [[FUN:%.*]] = class_method [[CCOPY_LOADED]] : $ClassWithGetterSetter, #ClassWithGetterSetter.b!getter.1 : (ClassWithGetterSetter) -> () -> Int, $@convention(method) (@guaranteed ClassWithGetterSetter) -> Int
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: end_borrow [[CCOPY_LOADED]] from %0
+// CHECK-NEXT: return
+
+// Stored variables fulfilling property requirements
+//
+class ClassWithStoredProperty : PropertyWithGetter {
+ var a : Int = 0
+
+ // Make sure that accesses go through the generated accessors for classes.
+ func methodUsingProperty() -> Int {
+ return a
+ }
+ // CHECK-LABEL: sil hidden @$S9protocols23ClassWithStoredPropertyC011methodUsingE0SiyF
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $ClassWithStoredProperty):
+ // CHECK-NEXT: debug_value [[ARG]]
+ // CHECK-NOT: copy_value
+ // CHECK-NEXT: [[FUN:%.*]] = class_method [[ARG]] : $ClassWithStoredProperty, #ClassWithStoredProperty.a!getter.1 : (ClassWithStoredProperty) -> () -> Int, $@convention(method) (@guaranteed ClassWithStoredProperty) -> Int
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[FUN]]([[ARG]])
+ // CHECK-NOT: destroy_value
+ // CHECK-NEXT: return [[RESULT]] : $Int
+}
+
+struct StructWithStoredProperty : PropertyWithGetter {
+ var a : Int
+
+ // Make sure that accesses aren't going through the generated accessors.
+ func methodUsingProperty() -> Int {
+ return a
+ }
+ // CHECK-LABEL: sil hidden @$S9protocols24StructWithStoredPropertyV011methodUsingE0SiyF
+ // CHECK: bb0(%0 : @trivial $StructWithStoredProperty):
+ // CHECK-NEXT: debug_value %0
+ // CHECK-NEXT: %2 = struct_extract %0 : $StructWithStoredProperty, #StructWithStoredProperty.a
+ // CHECK-NEXT: return %2 : $Int
+}
+
+// Make sure that we generate direct function calls for out struct protocol
+// witness since structs don't do virtual calls for methods.
+//
+// *NOTE* Even though at first glance the copy_addr looks like a leak
+// here, StructWithStoredProperty is a trivial struct implying that no
+// leak is occurring. See the test with StructWithStoredClassProperty
+// that makes sure in such a case we don't leak. This is due to the
+// thunking code being too dumb but it is harmless to program
+// correctness.
+//
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9protocols24StructWithStoredPropertyVAA0eC6GetterA2aDP1aSivgTW : $@convention(witness_method: PropertyWithGetter) (@in_guaranteed StructWithStoredProperty) -> Int {
+// CHECK: bb0([[C:%.*]] : @trivial $*StructWithStoredProperty):
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load [trivial] [[C]]
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[FUN:%.*]] = function_ref @$S9protocols24StructWithStoredPropertyV1aSivg : $@convention(method) (StructWithStoredProperty) -> Int
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: return
+
+class C {}
+
+// Make sure that if the getter has a class property, we pass it in
+// in_guaranteed and don't leak.
+struct StructWithStoredClassProperty : PropertyWithGetter {
+ var a : Int
+ var c: C = C()
+
+ // Make sure that accesses aren't going through the generated accessors.
+ func methodUsingProperty() -> Int {
+ return a
+ }
+ // CHECK-LABEL: sil hidden @$S9protocols29StructWithStoredClassPropertyV011methodUsingF0SiyF
+ // CHECK: bb0(%0 : @guaranteed $StructWithStoredClassProperty):
+ // CHECK-NEXT: debug_value %0
+ // CHECK-NEXT: %2 = struct_extract %0 : $StructWithStoredClassProperty, #StructWithStoredClassProperty.a
+ // CHECK-NEXT: return %2 : $Int
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9protocols29StructWithStoredClassPropertyVAA0fC6GetterA2aDP1aSivgTW : $@convention(witness_method: PropertyWithGetter) (@in_guaranteed StructWithStoredClassProperty) -> Int {
+// CHECK: bb0([[C:%.*]] : @trivial $*StructWithStoredClassProperty):
+// CHECK-NEXT: [[CCOPY_LOADED:%.*]] = load_borrow [[C]]
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[FUN:%.*]] = function_ref @$S9protocols29StructWithStoredClassPropertyV1aSivg : $@convention(method) (@guaranteed StructWithStoredClassProperty) -> Int
+// CHECK-NEXT: apply [[FUN]]([[CCOPY_LOADED]])
+// CHECK-NEXT: end_borrow [[CCOPY_LOADED]] from %0
+// CHECK-NEXT: return
+
+// rdar://22676810
+
+protocol ExistentialProperty {
+ var p: PropertyWithGetterSetter { get set }
+}
+
+func testExistentialPropertyRead<T: ExistentialProperty>(_ t: inout T) {
+ let b = t.p.b
+}
+// CHECK-LABEL: sil hidden @$S9protocols27testExistentialPropertyRead{{[_0-9a-zA-Z]*}}F
+// CHECK: [[READ:%.*]] = begin_access [read] [unknown] %0 : $*T
+// CHECK: [[P_TEMP:%.*]] = alloc_stack $PropertyWithGetterSetter
+// CHECK: [[T_TEMP:%.*]] = alloc_stack $T
+// CHECK: copy_addr [[READ]] to [initialization] [[T_TEMP]] : $*T
+// CHECK: [[P_GETTER:%.*]] = witness_method $T, #ExistentialProperty.p!getter.1 :
+// CHECK-NEXT: apply [[P_GETTER]]<T>([[P_TEMP]], [[T_TEMP]])
+// CHECK-NEXT: destroy_addr [[T_TEMP]]
+// CHECK-NEXT: [[OPEN:%.*]] = open_existential_addr immutable_access [[P_TEMP]] : $*PropertyWithGetterSetter to $*[[P_OPENED:@opened(.*) PropertyWithGetterSetter]]
+// CHECK-NEXT: [[T0:%.*]] = alloc_stack $[[P_OPENED]]
+// CHECK-NEXT: copy_addr [[OPEN]] to [initialization] [[T0]]
+// CHECK-NEXT: [[B_GETTER:%.*]] = witness_method $[[P_OPENED]], #PropertyWithGetterSetter.b!getter.1
+// CHECK-NEXT: apply [[B_GETTER]]<[[P_OPENED]]>([[T0]])
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: destroy_addr [[T0]]
+// CHECK-NOT: witness_method
+// CHECK: return
+
+func modify(_ x: inout Int) {}
+
+// Make sure we call the materializeForSet callback with the correct
+// generic signature.
+
+func modifyProperty<T : PropertyWithGetterSetter>(_ x: inout T) {
+ modify(&x.b)
+}
+// CHECK-LABEL: sil hidden @$S9protocols14modifyPropertyyyxzAA0C16WithGetterSetterRzlF
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
+// CHECK: [[WITNESS_FN:%.*]] = witness_method $T, #PropertyWithGetterSetter.b!materializeForSet.1
+// CHECK: [[RESULT:%.*]] = apply [[WITNESS_FN]]<T>
+// CHECK: [[TEMPORARY:%.*]] = tuple_extract [[RESULT]]
+// CHECK: [[CALLBACK:%.*]] = tuple_extract [[RESULT]]
+// CHECK: [[TEMPORARY_ADDR_TMP:%.*]] = pointer_to_address [[TEMPORARY]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK: [[TEMPORARY_ADDR:%.*]] = mark_dependence [[TEMPORARY_ADDR_TMP]] : $*Int on [[WRITE]] : $*T
+// CHECK: [[MODIFY_FN:%.*]] = function_ref @$S9protocols6modifyyySizF
+// CHECK: apply [[MODIFY_FN]]([[TEMPORARY_ADDR]])
+// CHECK: switch_enum [[CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: bb2
+// CHECK: bb1([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
+// CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]]
+// CHECK: [[METATYPE:%.*]] = metatype $@thick T.Type
+// CHECK: [[TEMPORARY:%.*]] = address_to_pointer [[TEMPORARY_ADDR]] : $*Int to $Builtin.RawPointer
+// CHECK: apply [[CALLBACK]]<T>
+
+public struct Val {
+ public var x: Int = 0
+}
+
+public protocol Proto {
+ var val: Val { get nonmutating set}
+}
+
+public func test(_ p: Proto) {
+ p.val.x += 1
+}
+
+// CHECK-LABEL: sil @$S9protocols4testyyAA5Proto_pF : $@convention(thin) (@in_guaranteed Proto) -> ()
+// CHECK: [[OPEN:%.*]] = open_existential_addr immutable_access
+// CHECK: [[MAT:%.*]] = witness_method $@opened("{{.*}}") Proto, #Proto.val!materializeForSet
+// CHECK: [[BUF:%.*]] = apply [[MAT]]
+// CHECK: [[WB:%.*]] = pointer_to_thin_function
+// This use looks like it is mutating but really is not. We use to assert in the SIL verifier.
+// CHECK: apply [[WB]]{{.*}}({{.*}}[[OPEN]]
+// CHECK: return
+
+// CHECK-LABEL: sil_witness_table hidden ClassWithGetter: PropertyWithGetter module protocols {
+// CHECK-NEXT: method #PropertyWithGetter.a!getter.1: {{.*}} : @$S9protocols15ClassWithGetterCAA08PropertycD0A2aDP1aSivgTW
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_witness_table hidden ClassWithGetterSetter: PropertyWithGetterSetter module protocols {
+// CHECK-NEXT: method #PropertyWithGetterSetter.b!getter.1: {{.*}} : @$S9protocols21ClassWithGetterSetterCAA08PropertycdE0A2aDP1bSivgTW
+// CHECK-NEXT: method #PropertyWithGetterSetter.b!setter.1: {{.*}} : @$S9protocols21ClassWithGetterSetterCAA08PropertycdE0A2aDP1bSivsTW
+// CHECK-NEXT: method #PropertyWithGetterSetter.b!materializeForSet.1: {{.*}} : @$S9protocols21ClassWithGetterSetterCAA08PropertycdE0A2aDP1bSivmTW
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_witness_table hidden ClassWithGetterSetter: PropertyWithGetter module protocols {
+// CHECK-NEXT: method #PropertyWithGetter.a!getter.1: {{.*}} : @$S9protocols21ClassWithGetterSetterCAA08PropertycD0A2aDP1aSivgTW
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_witness_table hidden StructWithStoredProperty: PropertyWithGetter module protocols {
+// CHECK-NEXT: method #PropertyWithGetter.a!getter.1: {{.*}} : @$S9protocols24StructWithStoredPropertyVAA0eC6GetterA2aDP1aSivgTW
+// CHECK-NEXT: }
+
+// CHECK-LABEL: sil_witness_table hidden StructWithStoredClassProperty: PropertyWithGetter module protocols {
+// CHECK-NEXT: method #PropertyWithGetter.a!getter.1: {{.*}} : @$S9protocols29StructWithStoredClassPropertyVAA0fC6GetterA2aDP1aSivgTW
+// CHECK-NEXT: }
+
+//
+// rdar://problem/37031037
+//
+
+protocol MethodWithDefaultArgGenerator {}
+extension MethodWithDefaultArgGenerator {
+ mutating func foo(_ x: Int = 0) {}
+}
+func invokeMethodWithDefaultArg(x: inout MethodWithDefaultArgGenerator) {
+ x.foo()
+}
diff --git a/test/SILGen/plus_zero_reabstract-tuple.swift b/test/SILGen/plus_zero_reabstract-tuple.swift
new file mode 100644
index 0000000..8553bba
--- /dev/null
+++ b/test/SILGen/plus_zero_reabstract-tuple.swift
@@ -0,0 +1,63 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -verify %s | %FileCheck %s
+
+// SR-3090:
+
+class Box<T> {
+ public let value: T
+
+ public init(_ value: T) {
+ self.value = value
+ }
+}
+
+// CHECK: sil @$S4main7testBoxyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: // function_ref closure #1 in testBox()
+// CHECK: [[CLOSURE:%.*]] = function_ref @$S4main7testBoxyyFyycfU_ : $@convention(thin) () -> ()
+// CHECK: [[THICK:%.*]] = thin_to_thick_function [[CLOSURE]] : $@convention(thin) () -> () to $@callee_guaranteed () -> ()
+// CHECK: [[TUPLEA:%.*]] = tuple (%{{.*}} : $Int, [[THICK]] : $@callee_guaranteed () -> ())
+// CHECK: ([[ELTA_0:%.*]], [[ELTA_1:%.*]]) = destructure_tuple [[TUPLEA]] : $(Int, @callee_guaranteed () -> ())
+// CHECK: [[THUNK1:%.*]] = function_ref @$SIeg_ytytIegnr_TR : $@convention(thin) (@in_guaranteed (), @guaranteed @callee_guaranteed () -> ()) -> @out ()
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[THUNK1]]([[ELTA_1]]) : $@convention(thin) (@in_guaranteed (), @guaranteed @callee_guaranteed () -> ()) -> @out ()
+// CHECK: [[TUPLEB:%.*]] = tuple ([[ELTA_0]] : $Int, [[PA]] : $@callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: [[BORROWB:%.*]] = begin_borrow [[TUPLEB]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: [[TUPLEB_0:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ()), 0
+// CHECK: [[TUPLEB_1:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ()), 1
+// CHECK: [[COPYB_1:%.*]] = copy_value [[TUPLEB_1]] : $@callee_guaranteed (@in_guaranteed ()) -> @out ()
+// CHECK: // function_ref Box.__allocating_init(_:)
+// CHECK: [[INIT_F:%.*]] = function_ref @$S4main3BoxCyACyxGxcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0>
+// CHECK: [[CALL:%.*]] = apply [[INIT_F]]<(Int, () -> ())>(%{{.*}}, %{{.*}}) : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0>
+// CHECK: end_borrow [[BORROWB]] from %{{.*}} : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ()), $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: destroy_value [[TUPLEB]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: [[BORROW_CALL:%.*]] = begin_borrow [[CALL]] : $Box<(Int, () -> ())>
+// CHECK: [[REF:%.*]] = ref_element_addr [[BORROW_CALL]] : $Box<(Int, () -> ())>, #Box.value
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[REF]] : $*(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: [[TUPLEC:%.*]] = load [copy] [[READ]] : $*(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: [[BORROW_TUPLEC:%.*]] = begin_borrow [[TUPLEC]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: [[TUPLEC_0:%.*]] = tuple_extract [[BORROW_TUPLEC]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ()), 0
+// CHECK: [[TUPLEC_1:%.*]] = tuple_extract [[BORROW_TUPLEC]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ()), 1
+// CHECK: [[COPYC_1:%.*]] = copy_value [[TUPLEC_1]] : $@callee_guaranteed (@in_guaranteed ()) -> @out ()
+// CHECK: [[THUNK2:%.*]] = function_ref @$SytytIegnr_Ieg_TR : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out ()) -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed] [[THUNK2]]([[COPYC_1]]) : $@convention(thin) (@guaranteed @callee_guaranteed (@in_guaranteed ()) -> @out ()) -> ()
+// CHECK: end_access [[READ]] : $*(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: destroy_value [[PA2]] : $@callee_guaranteed () -> ()
+// CHECK: end_borrow [[BORROW_TUPLEC]] from %{{.*}} : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ()), $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: destroy_value [[TUPLEC]] : $(Int, @callee_guaranteed (@in_guaranteed ()) -> @out ())
+// CHECK: end_borrow [[BORROW_CALL]] from %{{.*}} : $Box<(Int, () -> ())>, $Box<(Int, () -> ())>
+// CHECK-LABEL: } // end sil function '$S4main7testBoxyyF'
+public func testBox() {
+ let box = Box((22, { () in }))
+ let foo = box.value.0
+ print(foo)
+}
+
+
+// Another crash -- re-abstracting function type inside optional in tuple
+// in-place
+
+func g<T>() -> (Int, T)? { }
+
+func f<T>(t: T) {
+ let _: (Int, ((T) -> (), T))? = g()
+}
diff --git a/test/SILGen/plus_zero_reabstract.swift b/test/SILGen/plus_zero_reabstract.swift
new file mode 100644
index 0000000..03389c7
--- /dev/null
+++ b/test/SILGen/plus_zero_reabstract.swift
@@ -0,0 +1,82 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func takeFn<T>(_ f : (T) -> T?) {}
+func liftOptional(_ x : Int) -> Int? { return x }
+
+func test0() {
+ takeFn(liftOptional)
+}
+// CHECK: sil hidden @$S10reabstract5test0yyF : $@convention(thin) () -> () {
+// Emit a generalized reference to liftOptional.
+// TODO: just emit a globalized thunk
+// CHECK: reabstract.liftOptional
+// CHECK-NEXT: [[T1:%.*]] = function_ref @$S10reabstract12liftOptional{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: [[T2:%.*]] = thin_to_thick_function [[T1]]
+// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T2]]
+// CHECK-NEXT: reabstraction thunk
+// CHECK-NEXT: [[T3:%.*]] = function_ref [[THUNK:@.*]] :
+// CHECK-NEXT: [[T4:%.*]] = partial_apply [callee_guaranteed] [[T3]]([[CVT]])
+// CHECK-NEXT: [[CVT:%.*]] = convert_escape_to_noescape [[T4]]
+// CHECK: [[T0:%.*]] = function_ref @$S10reabstract6takeFn{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: apply [[T0]]<Int>([[CVT]])
+// CHECK-NEXT: destroy_value [[T2]]
+// CHECK-NEXT: destroy_value [[T4]]
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+// CHECK-NEXT: } // end sil function '$S10reabstract5test0yyF'
+
+// CHECK: sil shared [transparent] [serializable] [reabstraction_thunk] [[THUNK]] : $@convention(thin) (@in_guaranteed Int, @noescape @callee_guaranteed (Int) -> Optional<Int>) -> @out Optional<Int> {
+// CHECK: [[T0:%.*]] = load [trivial] %1 : $*Int
+// CHECK-NEXT: [[T1:%.*]] = apply %2([[T0]])
+// CHECK-NEXT: store [[T1]] to [trivial] %0
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+// CHECK-LABEL: sil hidden @$S10reabstract10testThrowsyyypF
+// CHECK: function_ref @$SytytIegnr_Ieg_TR
+// CHECK: function_ref @$Sytyts5Error_pIegnrzo_sAA_pIegzo_TR
+func testThrows(_ x: Any) {
+ _ = x as? () -> ()
+ _ = x as? () throws -> ()
+}
+
+// Make sure that we preserve inout-ness when lowering types with maximum
+// abstraction level -- <rdar://problem/21329377>
+class C {}
+
+struct Box<T> {
+ let t: T
+}
+
+func notFun(_ c: inout C, i: Int) {}
+
+func testInoutOpaque(_ c: C, i: Int) {
+ var c = c
+ let box = Box(t: notFun)
+ box.t(&c, i)
+}
+
+// CHECK-LABEL: sil hidden @$S10reabstract15testInoutOpaque_1iyAA1CC_SitF
+// CHECK: function_ref @$S10reabstract6notFun_1iyAA1CCz_SitF
+// CHECK: thin_to_thick_function {{%[0-9]+}}
+// CHECK: function_ref @$S10reabstract1CCSiIegly_ACSiytIeglnr_TR
+// CHECK: partial_apply
+// CHECK: store
+// CHECK: load
+// CHECK: function_ref @$S10reabstract1CCSiytIeglnr_ACSiIegly_TR
+// CHECK: partial_apply
+// CHECK: apply
+// CHECK: } // end sil function '$S10reabstract15testInoutOpaque_1iyAA1CC_SitF'
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S10reabstract1CCSiIegly_ACSiytIeglnr_TR : $@convention(thin) (@inout C, @in_guaranteed Int, @guaranteed @callee_guaranteed (@inout C, Int) -> ()) -> @out () {
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$S10reabstract1CCSiytIeglnr_ACSiIegly_TR : $@convention(thin) (@inout C, Int, @guaranteed @callee_guaranteed (@inout C, @in_guaranteed Int) -> @out ()) -> () {
+
+func closureTakingOptional(_ fn: (Int?) -> ()) {}
+closureTakingOptional({ (_: Any) -> () in })
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SypIgn_SiSgIegy_TR : $@convention(thin) (Optional<Int>, @noescape @callee_guaranteed (@in_guaranteed Any) -> ()) -> ()
+// CHECK: [[ANYADDR:%.*]] = alloc_stack $Any
+// CHECK: [[OPTADDR:%.*]] = init_existential_addr [[ANYADDR]] : $*Any, $Optional<Int>
+// CHECK: store %0 to [trivial] [[OPTADDR]] : $*Optional<Int>
+// CHECK: apply %1([[ANYADDR]]) : $@noescape @callee_guaranteed (@in_guaranteed Any) -> ()
diff --git a/test/SILGen/plus_zero_reabstract_lvalue.swift b/test/SILGen/plus_zero_reabstract_lvalue.swift
new file mode 100644
index 0000000..66a9907
--- /dev/null
+++ b/test/SILGen/plus_zero_reabstract_lvalue.swift
@@ -0,0 +1,48 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct MyMetatypeIsThin {}
+
+// CHECK-LABEL: sil hidden @$S17reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T> (@inout T) -> ()
+func consumeGenericInOut<T>(_ x: inout T) {}
+
+// CHECK-LABEL: sil hidden @$S17reabstract_lvalue9transformySdSiF : $@convention(thin) (Int) -> Double
+func transform(_ i: Int) -> Double {
+ return Double(i)
+}
+
+// CHECK-LABEL: sil hidden @$S17reabstract_lvalue0A13FunctionInOutyyF : $@convention(thin) () -> ()
+func reabstractFunctionInOut() {
+ // CHECK: [[BOX:%.*]] = alloc_box ${ var @callee_guaranteed (Int) -> Double }
+ // CHECK: [[PB:%.*]] = project_box [[BOX]]
+ // CHECK: [[ARG:%.*]] = function_ref @$S17reabstract_lvalue9transformySdSiF
+ // CHECK: [[THICK_ARG:%.*]] = thin_to_thick_function [[ARG]]
+ // CHECK: store [[THICK_ARG:%.*]] to [init] [[PB]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*@callee_guaranteed (Int) -> Double
+ // CHECK: [[ABSTRACTED_BOX:%.*]] = alloc_stack $@callee_guaranteed (@in_guaranteed Int) -> @out Double
+ // CHECK: [[THICK_ARG:%.*]] = load [copy] [[WRITE]]
+ // CHECK: [[THUNK1:%.*]] = function_ref @$SSiSdIegyd_SiSdIegnr_TR
+ // CHECK: [[ABSTRACTED_ARG:%.*]] = partial_apply [callee_guaranteed] [[THUNK1]]([[THICK_ARG]])
+ // CHECK: store [[ABSTRACTED_ARG]] to [init] [[ABSTRACTED_BOX]]
+ // CHECK: [[FUNC:%.*]] = function_ref @$S17reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC]]<(Int) -> Double>([[ABSTRACTED_BOX]])
+ // CHECK: [[NEW_ABSTRACTED_ARG:%.*]] = load [take] [[ABSTRACTED_BOX]]
+ // CHECK: [[THUNK2:%.*]] = function_ref @$SSiSdIegnr_SiSdIegyd_TR
+ // CHECK: [[NEW_ARG:%.*]] = partial_apply [callee_guaranteed] [[THUNK2]]([[NEW_ABSTRACTED_ARG]])
+ var minimallyAbstracted = transform
+ consumeGenericInOut(&minimallyAbstracted)
+}
+
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSiSdIegyd_SiSdIegnr_TR : $@convention(thin) (@in_guaranteed Int, @guaranteed @callee_guaranteed (Int) -> Double) -> @out Double
+// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSiSdIegnr_SiSdIegyd_TR : $@convention(thin) (Int, @guaranteed @callee_guaranteed (@in_guaranteed Int) -> @out Double) -> Double
+
+// CHECK-LABEL: sil hidden @$S17reabstract_lvalue0A13MetatypeInOutyyF : $@convention(thin) () -> ()
+func reabstractMetatypeInOut() {
+ var thinMetatype = MyMetatypeIsThin.self
+ // CHECK: [[BOX:%.*]] = alloc_stack $@thick MyMetatypeIsThin.Type
+ // CHECK: [[THICK:%.*]] = metatype $@thick MyMetatypeIsThin.Type
+ // CHECK: store [[THICK]] to [trivial] [[BOX]]
+ // CHECK: [[FUNC:%.*]] = function_ref @$S17reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[FUNC]]<MyMetatypeIsThin.Type>([[BOX]])
+ consumeGenericInOut(&thinMetatype)
+}
diff --git a/test/SILGen/plus_zero_result_abstraction.swift b/test/SILGen/plus_zero_result_abstraction.swift
new file mode 100644
index 0000000..af83741
--- /dev/null
+++ b/test/SILGen/plus_zero_result_abstraction.swift
@@ -0,0 +1,60 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+struct S {}
+struct R {}
+
+protocol ReturnsMetatype {
+ associatedtype Assoc
+ mutating
+ func getAssocMetatype() -> Assoc.Type
+}
+
+struct ConformsToReturnsMetatype : ReturnsMetatype {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S18result_abstraction25ConformsToReturnsMetatypeVAA0eF0A2aDP08getAssocF0{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ReturnsMetatype) (@inout ConformsToReturnsMetatype) -> @thick S.Type
+ // CHECK: function_ref @$S18result_abstraction25ConformsToReturnsMetatypeV08getAssocF0{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout ConformsToReturnsMetatype) -> @thin S.Type
+ mutating
+ func getAssocMetatype() -> S.Type {
+ return S.self
+ }
+}
+
+protocol ReturnsFunction {
+ associatedtype Arg
+ associatedtype Result
+ func getFunc() -> (Arg) -> Result
+}
+
+struct ConformsToReturnsFunction : ReturnsFunction {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S18result_abstraction25ConformsToReturnsFunctionVAA0eF0A2aDP7getFunc{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ReturnsFunction) (@in_guaranteed ConformsToReturnsFunction) -> @owned @callee_guaranteed (@in_guaranteed S) -> @out R
+ // CHECK: function_ref @$S18result_abstraction1SVAA1RVIegyd_AcEIegnr_TR : $@convention(thin) (@in_guaranteed S, @guaranteed @callee_guaranteed (S) -> R) -> @out R
+ func getFunc() -> (S) -> R {
+ return {s in R()}
+ }
+}
+
+protocol ReturnsAssoc {
+ associatedtype Assoc
+ mutating
+ func getAssoc() -> Assoc
+}
+
+struct ConformsToReturnsAssocWithMetatype : ReturnsAssoc {
+ typealias Assoc = S.Type
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S18result_abstraction34ConformsToReturnsAssocWithMetatypeVAA0eF0A2aDP03getF0{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ReturnsAssoc) (@inout ConformsToReturnsAssocWithMetatype) -> @out @thick S.Type
+ // CHECK: function_ref @$S18result_abstraction34ConformsToReturnsAssocWithMetatypeV03getF0{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout ConformsToReturnsAssocWithMetatype) -> @thin S.Type
+ mutating
+ func getAssoc() -> S.Type {
+ return S.self
+ }
+}
+
+struct ConformsToReturnsAssocWithFunction : ReturnsAssoc {
+ typealias Assoc = (S) -> R
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S18result_abstraction34ConformsToReturnsAssocWithFunctionVAA0eF0A2aDP03getF0{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ReturnsAssoc) (@inout ConformsToReturnsAssocWithFunction) -> @out @callee_guaranteed (@in_guaranteed S) -> @out R
+ // CHECK: function_ref @$S18result_abstraction34ConformsToReturnsAssocWithFunctionV03getF0{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout ConformsToReturnsAssocWithFunction) -> @owned @callee_guaranteed (S) -> R
+ mutating
+ func getAssoc() -> (S) -> R {
+ return {s in R()}
+ }
+}
diff --git a/test/SILGen/plus_zero_retaining_globals.swift b/test/SILGen/plus_zero_retaining_globals.swift
new file mode 100644
index 0000000..481a643
--- /dev/null
+++ b/test/SILGen/plus_zero_retaining_globals.swift
@@ -0,0 +1,75 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -import-objc-header %S/Inputs/globals.h -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+
+// This test makes sure loading from globals properly retains/releases loads from globals.
+// NSString was the only real problem, as the compiler treats NSString globals specially.
+// The rest of these are just hedges against future changes.
+
+// From header:
+// globalString: __strong NSString*
+// globalObject: __strong NSObject*
+// globalID: __strong id
+// globalArray: __strong NSArray*
+// globalConstArray: __strong NSArray *const
+
+func main() {
+ Globals.sharedInstance() // Initialize globals (dispatch_once)
+
+ // CHECK: global_addr @globalConstArray : $*Optional<NSArray>
+ // CHECK: global_addr @globalArray : $*Optional<NSArray>
+ // CHECK: global_addr @globalId : $*Optional<AnyObject>
+ // CHECK: global_addr @globalObject : $*Optional<NSObject>
+ // CHECK: global_addr @globalString : $*NSString
+
+
+
+ // CHECK: [[globalString:%.*]] = load [copy] {{%.*}} : $*NSString
+ // CHECK: [[bridgeStringFunc:%.*]] = function_ref @{{.*}} : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
+ // CHECK: [[wrappedString:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[globalString]] : $NSString
+ // CHECK: [[stringMetaType:%.*]] = metatype $@thin String.Type
+ // CHECK: [[bridgedString:%.*]] = apply [[bridgeStringFunc]]([[wrappedString]], [[stringMetaType]]) : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
+ let string = globalString // Problematic case, wasn't being retained
+
+ // CHECK: [[load_1:%.*]] = load [copy] {{%.*}} : $*Optional<NSObject>
+ let object = globalObject
+
+ // CHECK: [[load_2:%.*]] = load [copy] {{%.*}} : $*Optional<AnyObject>
+ let id = globalId
+
+ // CHECK: [[load_3:%.*]] = load [copy] {{%.*}} : $*Optional<NSArray>
+ let arr = globalArray
+
+ // CHECK: [[load_4:%.*]] = load [copy] {{%.*}} : $*Optional<NSArray>
+ let constArr = globalConstArray
+
+ // Make sure there's no more copies
+ // CHECK-NOT: load [copy]
+
+ print(string as Any)
+ print(object as Any)
+ print(id as Any)
+ print(arr as Any)
+ print(constArr as Any)
+
+ // CHECK: [[PRINT_FUN:%.*]] = function_ref @$Ss5print_9separator10terminatoryypd_S2StF : $@convention(thin) (@guaranteed Array<Any>, @guaranteed String, @guaranteed String) -> ()
+ // CHECK: apply [[PRINT_FUN]]({{.*}})
+ // CHECK: destroy_value [[load_4]]
+ // CHECK: destroy_value [[load_3]]
+ // CHECK: destroy_value [[load_2]]
+ // CHECK: destroy_value [[load_1]]
+ // CHECK: destroy_value [[bridgedString]]
+
+ // Make sure there's no more destroys
+ // CHECK-NOT: destroy_value
+ // CHECK: } // end sil function '$S17retaining_globals4mainyyF'
+}
+
+
+main()
+main() // Used to crash here, due to use-after-free.
+main()
+main()
+main()
+main()
diff --git a/test/SILGen/plus_zero_rethrows.swift b/test/SILGen/plus_zero_rethrows.swift
new file mode 100644
index 0000000..0b5dfe7
--- /dev/null
+++ b/test/SILGen/plus_zero_rethrows.swift
@@ -0,0 +1,90 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-sil -verify %s | %FileCheck %s
+
+@discardableResult
+func rethrower(_ fn: () throws -> Int) rethrows -> Int {
+ return try fn()
+}
+func thrower() throws -> Int { return 0 }
+func nonthrower() -> Int { return 0 }
+
+// CHECK-LABEL: sil hidden @$S8rethrows5test0yyKF : $@convention(thin) () -> @error Error {
+// CHECK: [[THROWER:%.*]] = function_ref @$S8rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error)
+// CHECK: [[T0:%.*]] = thin_to_thick_function [[THROWER]]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[T0]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @$S8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
+// CHECK: [[NORMAL]]([[RESULT_T0:%.*]] : $Int):
+// FIXME - SR-6979: We should be able to eliminate this strong_release.
+// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: [[T1:%.*]] = tuple ()
+// CHECK-NEXT: return [[T1]]
+// CHECK: [[ERROR]]([[RESULT_T0:%.*]] : $Error):
+// FIXME - SR-6979: We should be able to eliminate this strong_release.
+// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: throw [[RESULT_T0]]
+func test0() throws {
+ try rethrower(thrower)
+}
+
+// CHECK-LABEL: sil hidden @$S8rethrows5test1yyKF : $@convention(thin) () -> @error Error {
+// CHECK: [[CLOSURE:%.*]] = function_ref @$S8rethrows5test1yyKFSiyKXEfU_ : $@convention(thin) () -> (Int, @error Error)
+// CHECK: [[CVT:%.*]] = convert_function [[CLOSURE]]
+// CHECK: [[T0:%.*]] = thin_to_thick_function [[CVT]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @$S8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK: try_apply [[RETHROWER]]([[T0]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
+// CHECK: [[NORMAL]]({{%.*}} : $Int):
+// CHECK-NEXT: [[T1:%.*]] = tuple ()
+// CHECK-NEXT: return [[T1]]
+// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error):
+// CHECK-NEXT: throw [[ERROR]]
+// Closure.
+// CHECK-LABEL: sil private @$S8rethrows5test1yyKFSiyKXEfU_ : $@convention(thin) () -> (Int, @error Error) {
+// CHECK: [[THROWER:%.*]] = function_ref @$S8rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error)
+// CHECK: [[T0:%.*]] = thin_to_thick_function [[THROWER]]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[T0]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @$S8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
+// CHECK: [[NORMAL]]([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: return [[RESULT]]
+// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error):
+// CHECK-NEXT: strong_release [[T0]]
+// CHECK-NEXT: throw [[ERROR]]
+func test1() throws {
+ try rethrower { try rethrower(thrower) }
+}
+
+// CHECK-LABEL: sil hidden @$S8rethrows5test2yyF : $@convention(thin) () -> () {
+// CHECK: [[NONTHROWER:%.*]] = function_ref @$S8rethrows10nonthrowerSiyF : $@convention(thin) () -> Int
+// CHECK: [[T0:%.*]] = thin_to_thick_function [[NONTHROWER]]
+// CHECK: [[T1:%.*]] = convert_function [[T0]] : $@callee_guaranteed () -> Int to $@callee_guaranteed () -> (Int, @error Error)
+// CHECK: [[T2:%.*]] = convert_escape_to_noescape [[T1]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @$S8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK: try_apply [[RETHROWER]]([[T2]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
+// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
+// CHECK-NEXT: strong_release [[T1]]
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]]
+// CHECK: [[ERROR]]([[T0:%.*]] : $Error):
+// CHECK-NEXT: unreachable
+func test2() {
+ rethrower(nonthrower)
+}
+
+// CHECK-LABEL: sil hidden @$S8rethrows5test3yyF : $@convention(thin) () -> () {
+// CHECK: [[CLOSURE:%.*]] = function_ref @$S8rethrows5test3yyFSiyXEfU_ : $@convention(thin) () -> Int
+// CHECK: [[CVT:%.*]] = convert_function [[CLOSURE]] : $@convention(thin) () -> Int to $@convention(thin) @noescape () -> Int
+// CHECK: [[T0:%.*]] = thin_to_thick_function [[CVT]]
+// CHECK: [[T1:%.*]] = convert_function [[T0]] : $@noescape @callee_guaranteed () -> Int to $@noescape @callee_guaranteed () -> (Int, @error Error)
+// CHECK: [[RETHROWER:%.*]] = function_ref @$S8rethrows9rethroweryS2iyKXEKF : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error)
+// CHECK: try_apply [[RETHROWER]]([[T1]]) : $@convention(thin) (@noescape @callee_guaranteed () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
+// CHECK: [[NORMAL]]({{%.*}} : $Int):
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]]
+// CHECK: [[ERROR]]([[ERROR:%.*]] : $Error):
+// CHECK-NEXT: unreachable
+// CHECK-LABEL: // end sil function '$S8rethrows5test3yyF'
+func test3() {
+ rethrower { rethrower(nonthrower) }
+}
diff --git a/test/SILGen/plus_zero_scalar_to_tuple_args.swift b/test/SILGen/plus_zero_scalar_to_tuple_args.swift
new file mode 100644
index 0000000..b6bfb8a
--- /dev/null
+++ b/test/SILGen/plus_zero_scalar_to_tuple_args.swift
@@ -0,0 +1,82 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func inoutWithDefaults(_ x: inout Int, y: Int = 0, z: Int = 0) {}
+func inoutWithCallerSideDefaults(_ x: inout Int, y: Int = #line) {}
+
+func scalarWithDefaults(_ x: Int, y: Int = 0, z: Int = 0) {}
+func scalarWithCallerSideDefaults(_ x: Int, y: Int = #line) {}
+
+func tupleWithDefaults(x x: (Int, Int), y: Int = 0, z: Int = 0) {}
+
+func variadicFirst(_ x: Int...) {}
+func variadicSecond(_ x: Int, _ y: Int...) {}
+
+var x = 0
+// CHECK: [[X_ADDR:%.*]] = global_addr @$S20scalar_to_tuple_args1xSivp : $*Int
+// CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[INOUT_WITH_DEFAULTS:%.*]] = function_ref @$S20scalar_to_tuple_args17inoutWithDefaults_1y1zySiz_S2itF
+// CHECK: apply [[INOUT_WITH_DEFAULTS]]([[WRITE]], [[DEFAULT_Y]], [[DEFAULT_Z]])
+inoutWithDefaults(&x)
+
+// CHECK: [[LINE_VAL:%.*]] = integer_literal
+// CHECK: [[LINE:%.*]] = apply {{.*}}([[LINE_VAL]]
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[INOUT_WITH_CALLER_DEFAULTS:%.*]] = function_ref @$S20scalar_to_tuple_args27inoutWithCallerSideDefaults_1yySiz_SitF
+// CHECK: apply [[INOUT_WITH_CALLER_DEFAULTS]]([[WRITE]], [[LINE]])
+inoutWithCallerSideDefaults(&x)
+
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[X:%.*]] = load [trivial] [[READ]]
+// CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[SCALAR_WITH_DEFAULTS:%.*]] = function_ref @$S20scalar_to_tuple_args0A12WithDefaults_1y1zySi_S2itF
+// CHECK: apply [[SCALAR_WITH_DEFAULTS]]([[X]], [[DEFAULT_Y]], [[DEFAULT_Z]])
+scalarWithDefaults(x)
+
+// CHECK: [[X:%.*]] = load [trivial] [[X_ADDR]]
+// CHECK: [[LINE_VAL:%.*]] = integer_literal
+// CHECK: [[LINE:%.*]] = apply {{.*}}([[LINE_VAL]]
+// CHECK: [[SCALAR_WITH_CALLER_DEFAULTS:%.*]] = function_ref @$S20scalar_to_tuple_args0A22WithCallerSideDefaults_1yySi_SitF
+// CHECK: apply [[SCALAR_WITH_CALLER_DEFAULTS]]([[X]], [[LINE]])
+scalarWithCallerSideDefaults(x)
+
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[X1:%.*]] = load [trivial] [[READ]]
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[X2:%.*]] = load [trivial] [[READ]]
+// CHECK: [[DEFAULT_Y:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[DEFAULT_Z:%.*]] = apply {{.*}} : $@convention(thin) () -> Int
+// CHECK: [[TUPLE_WITH_DEFAULTS:%.*]] = function_ref @$S20scalar_to_tuple_args0C12WithDefaults1x1y1zySi_Sit_S2itF
+// CHECK: apply [[TUPLE_WITH_DEFAULTS]]([[X1]], [[X2]], [[DEFAULT_Y]], [[DEFAULT_Z]])
+tupleWithDefaults(x: (x,x))
+
+// CHECK: [[ALLOC_ARRAY:%.*]] = apply {{.*}} -> (@owned Array<τ_0_0>, Builtin.RawPointer)
+// CHECK: [[BORROWED_ALLOC_ARRAY:%.*]] = begin_borrow [[ALLOC_ARRAY]]
+// CHECK: [[BORROWED_ARRAY:%.*]] = tuple_extract [[BORROWED_ALLOC_ARRAY]] {{.*}}, 0
+// CHECK: [[ARRAY:%.*]] = copy_value [[BORROWED_ARRAY]]
+// CHECK: [[MEMORY:%.*]] = tuple_extract [[BORROWED_ALLOC_ARRAY]] {{.*}}, 1
+// CHECK: end_borrow [[BORROWED_ALLOC_ARRAY]] from [[ALLOC_ARRAY]]
+// CHECK: destroy_value [[ALLOC_ARRAY]]
+// CHECK: [[ADDR:%.*]] = pointer_to_address [[MEMORY]]
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[X:%.*]] = load [trivial] [[READ]]
+// CHECK: store [[X]] to [trivial] [[ADDR]]
+// CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
+// CHECK: [[VARIADIC_FIRST:%.*]] = function_ref @$S20scalar_to_tuple_args13variadicFirstyySid_tF
+// CHECK: apply [[VARIADIC_FIRST]]([[BORROWED_ARRAY]])
+variadicFirst(x)
+
+// CHECK: [[ALLOC_ARRAY:%.*]] = apply {{.*}} -> (@owned Array<τ_0_0>, Builtin.RawPointer)
+// CHECK: [[BORROWED_ALLOC_ARRAY:%.*]] = begin_borrow [[ALLOC_ARRAY]]
+// CHECK: [[BORROWED_ARRAY:%.*]] = tuple_extract [[BORROWED_ALLOC_ARRAY]] {{.*}}, 0
+// CHECK: [[ARRAY:%.*]] = copy_value [[BORROWED_ARRAY]]
+// CHECK: end_borrow [[BORROWED_ALLOC_ARRAY]] from [[ALLOC_ARRAY]]
+// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
+// CHECK: [[X:%.*]] = load [trivial] [[READ]]
+// CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
+// CHECK: [[VARIADIC_SECOND:%.*]] = function_ref @$S20scalar_to_tuple_args14variadicSecondyySi_SidtF
+// CHECK: apply [[VARIADIC_SECOND]]([[X]], [[BORROWED_ARRAY]])
+variadicSecond(x)
diff --git a/test/SILGen/plus_zero_shared.swift b/test/SILGen/plus_zero_shared.swift
new file mode 100644
index 0000000..46ec6da
--- /dev/null
+++ b/test/SILGen/plus_zero_shared.swift
@@ -0,0 +1,184 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
+
+// REQUIRES: owned_parameters
+
+class RefAggregate {}
+struct ValueAggregate { let x = RefAggregate() }
+
+
+// CHECK-LABEL: sil hidden @$S6shared0A10_arguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefG0ChtF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+func shared_arguments(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate):
+ // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @$S6shared15owned_arguments7trivial5value3refySi_AA14ValueAggregateVAA03RefH0CtF
+ // CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+ // CHECK: } // end sil function '$S6shared0A10_arguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefG0ChtF'
+ return owned_arguments(trivial: trivial, value: value, ref: ref)
+}
+
+// CHECK-LABEL: sil hidden @$S6shared15owned_arguments7trivial5value3refySi_AA14ValueAggregateVAA03RefH0CtF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+func owned_arguments(trivial : Int, value : ValueAggregate, ref : RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate):
+ // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+ // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @$S6shared0A10_arguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefG0ChtF
+ // CHECK: {{%.*}} = apply [[SHARED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]])
+ // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
+ // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
+ // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: } // end sil function '$S6shared15owned_arguments7trivial5value3refySi_AA14ValueAggregateVAA03RefH0CtF'
+ return shared_arguments(trivial: trivial, value: value, ref: ref)
+}
+
+// CHECK-LABEL: sil hidden @$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+func shared_argument_capture(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate):
+ // CHECK: [[CLO_1:%[0-9]+]] = function_ref @$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtFyyXEfU_
+ // CHECK: {{%.*}} = apply [[CLO_1]]([[TRIVIAL_VAL]], [[VALUE_VAL]], [[REF_VAL]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ _ = {
+ return shared_arguments(trivial: trivial, value: value, ref: ref)
+ }()
+
+ // CHECK: [[CLO_2:%[0-9]+]] = function_ref @$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtFyyXEfU0_ : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: {{%.*}} = apply [[CLO_2]]([[TRIVIAL_VAL]], [[VALUE_VAL]], [[REF_VAL]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ _ = {
+ return owned_arguments(trivial: trivial, value: value, ref: ref)
+ }()
+
+ // CHECK: } // end sil function '$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtF'
+
+ // ======== FIRST CLOSURE ==========
+
+ // CHECK-LABEL: sil private @$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtFyyXEfU_ : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate):
+ // CHECK: [[SHARED_CALL:%[0-9]+]] = function_ref @$S6shared0A10_arguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefG0ChtF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: {{%.*}} = apply [[SHARED_CALL]]([[TRIVIAL_VAL]], [[VALUE_VAL]], [[REF_VAL]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: } // end sil function '$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtFyyXEfU_'
+
+ // ======== SECOND CLOSURE ==========
+
+ // CHECK-LABEL: sil private @$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtFyyXEfU0_ : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> () {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate):
+ // CHECK: [[COPY_BORROW_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_BORROW_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_CALL:%[0-9]+]] = function_ref @$S6shared15owned_arguments7trivial5value3refySi_AA14ValueAggregateVAA03RefH0CtF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+ // CHECK: {{%.*}} = apply [[OWNED_CALL]]([[TRIVIAL_VAL]], [[COPY_BORROW_VALUE_VAL]], [[COPY_BORROW_REF_VAL]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+ // CHECK: } // end sil function '$S6shared0A17_argument_capture7trivial5value3refySih_AA14ValueAggregateVhAA03RefH0ChtFyyXEfU0_'
+}
+
+// CHECK-LABEL: sil hidden @$S6shared0A20_to_owned_conversionyyySih_AA14ValueAggregateVhAA03RefF0ChtXEF : $@convention(thin) (@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
+func shared_to_owned_conversion(_ f : (__shared Int, __shared ValueAggregate, __shared RefAggregate) -> Void) {
+ // CHECK: bb0([[UNUSED_FUNC:%[0-9]+]] : @trivial $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()):
+ // CHECK: [[OWNED_THUNK:%[0-9]+]] = function_ref @$S6shared0A20_to_owned_conversionyyySih_AA14ValueAggregateVhAA03RefF0ChtXEFySi_AdFtXEfU_ : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_function [[OWNED_THUNK]]
+ // CHECK: [[THICK_OWNED_THUNK:%[0-9]+]] = thin_to_thick_function [[CONVERT]] : $@convention(thin) @noescape (Int, @owned ValueAggregate, @owned RefAggregate) -> () to $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+ // CHECK: [[GUARANTEED_TO_OWNED_THUNK:%[0-9]+]] = function_ref @$SSi6shared14ValueAggregateVAA03RefC0CIgyxx_SiAcEIegygg_TR : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+ // CHECK: [[APPLIED_THUNK:%[0-9]+]] = partial_apply [callee_guaranteed] [[GUARANTEED_TO_OWNED_THUNK]]([[THICK_OWNED_THUNK]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[APPLIED_THUNK]]
+ // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @$S6shared0A20_to_owned_conversionyyySih_AA14ValueAggregateVhAA03RefF0ChtXEF : $@convention(thin) (@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
+ // CHECK: {{%.*}} = apply [[RECUR_FN]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
+ // CHECK-NOT: destroy_value [[UNUSED_FUNC]]
+ // CHECK: } // end sil function '$S6shared0A20_to_owned_conversionyyySih_AA14ValueAggregateVhAA03RefF0ChtXEF'
+
+ // ======== REABSTRACTION THUNK =========
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSi6shared14ValueAggregateVAA03RefC0CIgyxx_SiAcEIegygg_TR : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate, [[FUNC:%[0-9]+]] : @trivial $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()):
+ // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: {{%.*}} = apply [[FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]]) : $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
+ // CHECK: } // end sil function '$SSi6shared14ValueAggregateVAA03RefC0CIgyxx_SiAcEIegygg_TR'
+
+ return shared_to_owned_conversion { (trivial : Int, val : ValueAggregate, ref : RefAggregate) in }
+}
+
+// CHECK-LABEL: sil hidden @$S6shared09owned_to_A11_conversionyyySi_AA14ValueAggregateVAA03RefF0CtXEF : $@convention(thin) (@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+func owned_to_shared_conversion(_ f : (Int, ValueAggregate, RefAggregate) -> Void) {
+ // CHECK: bb0([[UNUSED_FUNC:%[0-9]+]] : @trivial $@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()):
+ // CHECK: [[SHARED_THUNK:%[0-9]+]] = function_ref @$S6shared09owned_to_A11_conversionyyySi_AA14ValueAggregateVAA03RefF0CtXEFySih_ADhAFhtXEfU_ : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_function [[SHARED_THUNK]]
+ // CHECK: [[THICK_SHARED_THUNK:%[0-9]+]] = thin_to_thick_function [[CONVERT]] : $@convention(thin) @noescape (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> () to $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: [[OWNED_TO_GUARANTEED_THUNK:%[0-9]+]] = function_ref @$SSi6shared14ValueAggregateVAA03RefC0CIgygg_SiAcEIegyxx_TR : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
+ // CHECK: [[APPLIED_THUNK:%[0-9]+]] = partial_apply [callee_guaranteed] [[OWNED_TO_GUARANTEED_THUNK]]([[THICK_SHARED_THUNK]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
+ // CHECK: [[CONVERT:%.*]] = convert_escape_to_noescape [[APPLIED_THUNK]]
+ // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @$S6shared09owned_to_A11_conversionyyySi_AA14ValueAggregateVAA03RefF0CtXEF : $@convention(thin) (@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+ // CHECK: {{%.*}} = apply [[RECUR_FN]]([[CONVERT]]) : $@convention(thin) (@noescape @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+ // CHECK-NOT: destroy_value [[UNUSED_FUNC]]
+ // CHECK: } // end sil function '$S6shared09owned_to_A11_conversionyyySi_AA14ValueAggregateVAA03RefF0CtXEF'
+
+ // ======== REABSTRACTION THUNK =========
+
+ // CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @$SSi6shared14ValueAggregateVAA03RefC0CIgygg_SiAcEIegyxx_TR : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate, [[FUNC:%[0-9]+]] : @trivial $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()):
+ // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+ // CHECK: {{%.*}} = apply [[FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]]) : $@noescape @callee_guaranteed (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
+ // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
+ // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
+ // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: } // end sil function '$SSi6shared14ValueAggregateVAA03RefC0CIgygg_SiAcEIegyxx_TR'
+
+ return owned_to_shared_conversion { (trivial : __shared Int, val : __shared ValueAggregate, ref : __shared RefAggregate) in }
+}
+
+// CHECK-LABEL: sil hidden @$S6shared0A17_closure_loweringyyySi_AA14ValueAggregateVAA03RefE0CtchF : $@convention(thin) (@guaranteed @callee_guaranteed (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
+func shared_closure_lowering(_ f : __shared (Int, ValueAggregate, RefAggregate) -> Void) {}
+
+struct Foo {
+ var x: ValueAggregate
+
+ // CHECK-LABEL: sil hidden @$S6shared3FooV21methodSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtF : $@convention(method) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @guaranteed Foo) -> () {
+ func methodSharedArguments(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate, [[SELF:%[0-9]+]] : @guaranteed $Foo):
+ // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV20methodOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtF
+ // CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]], [[SELF]]) : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed Foo) -> ()
+ // CHECK: } // end sil function '$S6shared3FooV21methodSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtF'
+ return methodOwnedArguments(trivial: trivial, value: value, ref: ref)
+ }
+
+ // CHECK-LABEL: sil hidden @$S6shared3FooV20methodOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtF : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @guaranteed Foo) -> () {
+ func methodOwnedArguments(trivial : Int, value : ValueAggregate, ref : RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate, [[SELF:%[0-9]+]] : @guaranteed $Foo):
+ // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+ // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV21methodSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtF
+ // CHECK: {{%.*}} = apply [[SHARED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]], [[SELF]])
+ // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
+ // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
+ // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: } // end sil function '$S6shared3FooV20methodOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtF'
+ return methodSharedArguments(trivial: trivial, value: value, ref: ref)
+ }
+
+ // CHECK-LABEL: sil hidden @$S6shared3FooV21staticSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtFZ : $@convention(method) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @thin Foo.Type) -> () {
+ static func staticSharedArguments(trivial : __shared Int, value : __shared ValueAggregate, ref : __shared RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @guaranteed $ValueAggregate, [[REF_VAL:%[0-9]+]] : @guaranteed $RefAggregate, [[SELF_METATYPE:%[0-9]+]] : @trivial $@thin Foo.Type):
+ // CHECK: [[COPY_VALUE_VAL:%[0-9]+]] = copy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[COPY_REF_VAL:%[0-9]+]] = copy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV20staticOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtFZ
+ // CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]], [[SELF_METATYPE]]) : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @thin Foo.Type) -> ()
+ // CHECK: } // end sil function '$S6shared3FooV21staticSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtFZ'
+ return staticOwnedArguments(trivial: trivial, value: value, ref: ref)
+ }
+ // CHECK-LABEL: sil hidden @$S6shared3FooV20staticOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtFZ : $@convention(method) (Int, @owned ValueAggregate, @owned RefAggregate, @thin Foo.Type) -> () {
+ static func staticOwnedArguments(trivial : Int, value : ValueAggregate, ref : RefAggregate) {
+ // CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate, [[SELF_METATYPE:%[0-9]+]] : @trivial $@thin Foo.Type):
+ // CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
+ // CHECK: [[SHARED_FUNC:%[0-9]+]] = function_ref @$S6shared3FooV21staticSharedArguments7trivial5value3refySih_AA14ValueAggregateVhAA03RefJ0ChtFZ
+ // CHECK: {{%.*}} = apply [[SHARED_FUNC]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]], [[SELF_METATYPE]])
+ // CHECK: end_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
+ // CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
+ // CHECK: destroy_value [[REF_VAL]] : $RefAggregate
+ // CHECK: destroy_value [[VALUE_VAL]] : $ValueAggregate
+ // CHECK: } // end sil function '$S6shared3FooV20staticOwnedArguments7trivial5value3refySi_AA14ValueAggregateVAA03RefJ0CtFZ'
+ return staticSharedArguments(trivial: trivial, value: value, ref: ref)
+ }
+}
diff --git a/test/SILGen/plus_zero_sil_locations.swift b/test/SILGen/plus_zero_sil_locations.swift
new file mode 100644
index 0000000..19f9b55
--- /dev/null
+++ b/test/SILGen/plus_zero_sil_locations.swift
@@ -0,0 +1,400 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -Xllvm -sil-print-debuginfo -emit-verbose-sil -enable-sil-ownership %s | %FileCheck %s
+
+// FIXME: Not sure if this an ideal source info for the branch -
+// it points to if, not the last instruction in the block.
+func ifexpr() -> Int {
+ var x : Int = 0
+ if true {
+ x+=1
+ }
+ return x
+ // CHECK-LABEL: sil hidden @$S13sil_locations6ifexprSiyF
+ // CHECK: apply {{.*}}, loc "{{.*}}":[[@LINE-5]]:6
+ // CHECK: cond_br {{%.*}}, [[TRUE_BB:bb[0-9]+]], [[FALSE_BB:bb[0-9]+]], loc "{{.*}}":[[@LINE-6]]:6
+ // CHECK: br [[FALSE_BB]], loc "{{.*}}":[[@LINE-5]]:3
+ // CHECK: return {{.*}}, loc "{{.*}}":[[@LINE-5]]:3, {{.*}}:return
+}
+
+func ifelseexpr() -> Int {
+ var x : Int = 0
+ if true {
+ x+=1
+ } else {
+ x-=1
+ }
+ return x
+ // CHECK-LABEL: sil hidden @$S13sil_locations10ifelseexprSiyF
+ // CHECK: cond_br {{%.*}}, [[TRUE_BB:bb[0-9]+]], [[FALSE_BB:bb[0-9]+]], loc "{{.*}}":[[@LINE-7]]:6
+ // CHECK: [[TRUE_BB]]:
+ // CHECK: br bb{{[0-9]+}}, loc "{{.*}}":[[@LINE-7]]:3
+ // CHECK: [[FALSE_BB]]:
+ // CHECK: br bb{{[0-9]+}}, loc "{{.*}}":[[@LINE-7]]:3
+ // CHECK: return {{.*}}, loc "{{.*}}":[[@LINE-7]]:3, {{.*}}:return
+}
+
+// The source locations are handled differently here - since
+// the return is unified, we keep the location of the return(not the if)
+// in the branch.
+func ifexpr_return() -> Int {
+ if true {
+ return 5
+ }
+ return 6
+ // CHECK-LABEL: sil hidden @$S13sil_locations13ifexpr_returnSiyF
+ // CHECK: apply {{.*}}, loc "{{.*}}":[[@LINE-5]]:6
+ // CHECK: cond_br {{%.*}}, [[TRUE_BB:bb[0-9]+]], [[FALSE_BB:bb[0-9]+]], loc "{{.*}}":[[@LINE-6]]:6
+ // CHECK: [[TRUE_BB]]:
+ // CHECK: br bb{{[0-9]+}}({{%.*}}), loc "{{.*}}":[[@LINE-7]]:5, {{.*}}:return
+ // CHECK: [[FALSE_BB]]:
+ // CHECK: br bb{{[0-9]+}}({{%.*}}), loc "{{.*}}":[[@LINE-7]]:3, {{.*}}:return
+ // CHECK: return {{.*}}, loc "{{.*}}":[[@LINE+1]]:1, {{.*}}:cleanup
+}
+
+func ifexpr_rval() -> Int {
+ var x = true ? 5 : 6
+ return x
+ // CHECK-LABEL: sil hidden @$S13sil_locations11ifexpr_rvalSiyF
+ // CHECK: apply {{.*}}, loc "{{.*}}":[[@LINE-3]]:11
+ // CHECK: cond_br {{%.*}}, [[TRUE_BB:bb[0-9]+]], [[FALSE_BB:bb[0-9]+]], loc "{{.*}}":[[@LINE-4]]:11
+ // CHECK: [[TRUE_BB]]:
+ // CHECK: br bb{{[0-9]+}}({{%.*}}), loc "{{.*}}":[[@LINE-6]]:18
+ // CHECK: [[FALSE_BB]]:
+ // CHECK: br bb{{[0-9]+}}({{%.*}}), loc "{{.*}}":[[@LINE-8]]:22
+}
+
+// --- Test function calls.
+func simpleDirectCallTest(_ i: Int) -> Int {
+ return simpleDirectCallTest(i)
+ // CHECK-LABEL: sil hidden @$S13sil_locations20simpleDirectCallTestyS2iF
+ // CHECK: function_ref @$S13sil_locations20simpleDirectCallTestyS2iF : {{.*}}, loc "{{.*}}":[[@LINE-2]]:10
+ // CHECK: {{%.*}} apply {{%.*}} line:[[@LINE-3]]:10
+}
+
+func templateTest<T>(_ value: T) -> T {
+ return value
+}
+func useTemplateTest() -> Int {
+ return templateTest(5);
+ // CHECK-LABEL: sil hidden @$S13sil_locations15useTemplateTestSiyF
+ // CHECK: function_ref @$SSi2{{[_0-9a-zA-Z]*}}fC :{{.*}}, loc "{{.*}}":77
+}
+
+func foo(_ x: Int) -> Int {
+ func bar(_ y: Int) -> Int {
+ return x + y
+ }
+ return bar(1)
+ // CHECK-LABEL: sil hidden @$S13sil_locations3foo{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[CLOSURE:%[0-9]+]] = function_ref {{.*}}, loc "{{.*}}":[[@LINE-2]]:10
+ // CHECK: apply [[CLOSURE:%[0-9]+]]
+}
+
+class LocationClass {
+ func mem() {}
+}
+func testMethodCall() {
+ var l: LocationClass
+ l.mem();
+ // CHECK-LABEL: sil hidden @$S13sil_locations14testMethodCallyyF
+
+ // CHECK: class_method {{.[0-9]+}} : $LocationClass, #LocationClass.mem!1 {{.*}}, loc "{{.*}}":[[@LINE-3]]:5
+}
+
+func multipleReturnsImplicitAndExplicit() {
+ var x = 5+3
+ if x > 10 {
+ return
+ }
+ x += 1
+ // CHECK-LABEL: sil hidden @$S13sil_locations34multipleReturnsImplicitAndExplicityyF
+ // CHECK: cond_br
+ // CHECK: br bb{{[0-9]+}}, loc "{{.*}}":[[@LINE-5]]:5, {{.*}}:return
+ // CHECK: br bb{{[0-9]+}}, loc "{{.*}}":[[@LINE+2]]:1, {{.*}}:imp_return
+ // CHECK: return {{.*}}, loc "{{.*}}":[[@LINE+1]]:1, {{.*}}:cleanup
+}
+
+func simplifiedImplicitReturn() -> () {
+ var y = 0
+ // CHECK-LABEL: sil hidden @$S13sil_locations24simplifiedImplicitReturnyyF
+ // CHECK: return {{.*}}, loc "{{.*}}":[[@LINE+1]]:1, {{.*}}:imp_return
+}
+
+func switchfoo() -> Int { return 0 }
+func switchbar() -> Int { return 0 }
+
+// CHECK-LABEL: sil hidden @$S13sil_locations10testSwitchyyF
+func testSwitch() {
+ var x:Int
+ x = 0
+ switch (switchfoo(), switchbar()) {
+ // CHECK: store {{.*}}, loc "{{.*}}":[[@LINE+1]]
+ case (1,2):
+ // CHECK: integer_literal $Builtin.Int2048, 2, loc "{{.*}}":[[@LINE-1]]:11
+ // FIXME: Location info is missing.
+ // CHECK: cond_br
+ //
+ var z: Int = 200
+ // CHECK: [[VAR_Z:%[0-9]+]] = alloc_box ${ var Int }, var, name "z"{{.*}}line:[[@LINE-1]]:9
+ // CHECK: integer_literal $Builtin.Int2048, 200, loc "{{.*}}":[[@LINE-2]]:18
+ x = z
+ // CHECK: destroy_value [[VAR_Z]]{{.*}}, loc "{{.*}}":[[@LINE-1]]:9, {{.*}}:cleanup
+ case (3, let y):
+ x += 1
+ default:
+ ()
+ }
+}
+
+func testIf() {
+ if true {
+ var y:Int
+ } else {
+ var x:Int
+ }
+ // CHECK-LABEL: sil hidden @$S13sil_locations6testIfyyF
+ //
+ // FIXME: Missing location info here.
+ // CHECK: function_ref
+ // CHECK: apply
+ //
+ //
+ //
+ // CHECK: br {{.*}}, loc "{{.*}}":[[@LINE-13]]:6
+}
+
+func testFor() {
+ for i in 0..<10 {
+ var y: Int = 300
+ y+=1
+ if true {
+ break
+ }
+ y-=1
+ continue
+ }
+
+ // CHECK-LABEL: sil hidden @$S13sil_locations7testForyyF
+ // CHECK: [[VAR_Y_IN_FOR:%[0-9]+]] = alloc_box ${ var Int }, var, name "y", loc "{{.*}}":[[@LINE-10]]:9
+ // CHECK: integer_literal $Builtin.Int2048, 300, loc "{{.*}}":[[@LINE-11]]:18
+ // CHECK: destroy_value [[VAR_Y_IN_FOR]] : ${ var Int }
+ // CHECK: br bb{{.*}}, loc "{{.*}}":[[@LINE-10]]:7
+ // CHECK: destroy_value [[VAR_Y_IN_FOR]] : ${ var Int }
+ // CHECK: br bb{{.*}}, loc "{{.*}}":[[@LINE-9]]:5
+
+
+}
+
+func testTuples() {
+ var t = (2,3)
+ var tt = (2, (4,5))
+ var d = "foo"
+ // CHECK-LABEL: sil hidden @$S13sil_locations10testTuplesyyF
+ // CHECK: tuple_element_addr {{.*}}, loc "{{.*}}":[[@LINE-4]]:11
+ // CHECK: integer_literal $Builtin.Int2048, 2, loc "{{.*}}":[[@LINE-5]]:12
+ // CHECK: integer_literal $Builtin.Int2048, 3, loc "{{.*}}":[[@LINE-6]]:14
+ // CHECK: tuple_element_addr {{.*}}, loc "{{.*}}":[[@LINE-6]]:12
+ // CHECK: tuple_element_addr {{.*}}, loc "{{.*}}":[[@LINE-7]]:16
+}
+
+// Test tuple imploding/exploding.
+protocol Ordinable {
+ func ord() -> Int
+}
+
+func b<T : Ordinable>(_ seq: T) -> (Int) -> Int {
+ return {i in i + seq.ord() }
+}
+
+func captures_tuple<T, U>(x: (T, U)) -> () -> (T, U) {
+ return {x}
+ // CHECK-LABEL: sil hidden @$S13sil_locations14captures_tuple{{[_0-9a-zA-Z]*}}F
+ // CHECK: tuple_element_addr {{.*}}, loc "{{.*}}":[[@LINE-3]]:27
+ // CHECK: copy_addr {{.*}}, loc "{{.*}}":[[@LINE-4]]:27
+ // CHECK: function_ref {{.*}}, loc "{{.*}}":[[@LINE-4]]:10
+
+ // CHECK-LABEL: sil private @$S13sil_locations14captures_tuple{{.*}}fU_
+ // CHECK: copy_addr {{.*}}, loc "{{.*}}":[[@LINE-7]]:11
+}
+
+func interpolated_string(_ x: Int, y: String) -> String {
+ return "The \(x) Million Dollar \(y)"
+ // CHECK-LABEL: sil hidden @$S13sil_locations19interpolated_string{{[_0-9a-zA-Z]*}}F
+ // CHECK: copy_value{{.*}}, loc "{{.*}}":[[@LINE-2]]:37
+}
+
+
+func int(_ x: Int) {}
+func tuple() -> (Int, Float) { return (1, 1.0) }
+func tuple_element(_ x: (Int, Float)) {
+ int(tuple().0)
+ // CHECK-LABEL: sil hidden @$S13sil_locations13tuple_element{{[_0-9a-zA-Z]*}}F
+
+ // CHECK: apply {{.*}} line:[[@LINE-3]]:7
+ // CHECK: tuple_extract{{.*}}, 0, {{.*}}line:[[@LINE-4]]:7
+ // CHECK: tuple_extract{{.*}}, 1, {{.*}}line:[[@LINE-5]]:7
+ // CHECK: apply {{.*}} line:[[@LINE-6]]:3
+
+}
+
+func containers() -> ([Int], Dictionary<String, Int>) {
+ return ([1, 2, 3], ["Ankeny": 1, "Burnside": 2, "Couch": 3])
+ // CHECK-LABEL: sil hidden @$S13sil_locations10containers{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply {{%.*}}<(String, Int)>({{%.*}}), loc "{{.*}}":[[@LINE-2]]:22
+
+ // CHECK: string_literal utf8 "Ankeny", loc "{{.*}}":[[@LINE-4]]:23
+
+ // CHECK: integer_literal $Builtin.Int2048, 1, loc "{{.*}}":[[@LINE-6]]:33
+ // CHECK: integer_literal $Builtin.Int2048, 2, loc "{{.*}}":[[@LINE-7]]:48
+
+
+
+}
+
+
+func a() {}
+func b() -> Int { return 0 }
+protocol P { func p() }
+struct X : P { func p() {} }
+func test_isa_2(_ p: P) {
+ switch (p, b()) {
+ case (is X, b()):
+ a()
+ case _:
+ a()
+ }
+
+
+
+ // CHECK-LABEL: sil hidden @$S13sil_locations10test_isa_2{{[_0-9a-zA-Z]*}}F
+ // CHECK: alloc_stack $(P, Int), loc "{{.*}}":[[@LINE-10]]:10
+ // CHECK: tuple_element_addr{{.*}} $*(P, Int), 0, loc "{{.*}}":[[@LINE-11]]:10
+ // CHECK: tuple_element_addr{{.*}} $*(P, Int), 1, loc "{{.*}}":[[@LINE-12]]:10
+ // CHECK: load {{.*}}, loc "{{.*}}":[[@LINE-12]]:8
+ //
+ // CHECK: checked_cast_addr_br {{.*}}, loc "{{.*}}":[[@LINE-14]]:9
+ // CHECK: load {{.*}}, loc "{{.*}}":[[@LINE-15]]:9
+
+}
+
+func runcibleWhy() {}
+protocol Runcible {
+ func runce()
+}
+enum SinglePayloadAddressOnly {
+ case x(Runcible)
+ case y
+}
+func printSinglePayloadAddressOnly(_ v:SinglePayloadAddressOnly) {
+ switch v {
+ case .x(let runcible):
+ runcible.runce()
+ case .y:
+ runcibleWhy()
+ }
+
+
+ // CHECK_LABEL: sil hidden @$S13sil_locations29printSinglePayloadAddressOnly{{[_0-9a-zA-Z]*}}F
+ // CHECK: bb0
+ // CHECK: switch_enum_addr {{.*}} [[FALSE_BB:bb[0-9]+]], {{.*}}line:[[@LINE-10]]:3
+ // CHECK: [[FALSE_BB]]:
+
+}
+
+
+func testStringForEachStmt() {
+ var i = 0
+ for index in 1..<20 {
+ i += 1
+ if i == 15 {
+ break
+ }
+ }
+
+ // CHECK-LABEL: sil hidden @$S13sil_locations21testStringForEachStmtyyF
+ // CHECK: br {{.*}} line:[[@LINE-8]]:3
+ // CHECK: switch_enum {{.*}} line:[[@LINE-9]]:3
+ // CHECK: cond_br {{.*}} line:[[@LINE-8]]:8
+ // Break branch:
+ // CHECK: br {{.*}} line:[[@LINE-9]]:7
+ // Looping back branch:
+ // CHECK: br {{.*}} line:[[@LINE-9]]:3
+ // Condition is false branch:
+ // CHECK: br {{.*}} line:[[@LINE-16]]:3
+
+
+
+
+}
+
+
+func testForStmt() {
+
+ var m = 0
+ for i in 0..<10 {
+ m += 1
+ if m == 15 {
+ break
+ } else {
+ continue
+ }
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+
+func testRepeatWhile() {
+ var m = 0
+ repeat {
+ m += 1
+ } while (m < 200)
+
+
+ // CHECK-LABEL: sil hidden @$S13sil_locations15testRepeatWhileyyF
+ // CHECK: br {{.*}} line:[[@LINE-6]]:3
+ // CHECK: cond_br {{.*}} line:[[@LINE-5]]:11
+ // Loop back branch:
+ // CHECK: br {{.*}} line:[[@LINE-7]]:11
+}
+
+
+
+func testWhile() {
+ var m = 0
+ while m < 100 {
+ m += 1
+ if m > 5 {
+ break
+ }
+ m += 1
+ }
+
+ // CHECK-LABEL: sil hidden @$S13sil_locations9testWhileyyF
+ // CHECK: br {{.*}} line:[[@LINE-9]]:3
+ // While loop conditional branch:
+ // CHECK: cond_br {{.*}} line:[[@LINE-11]]:9
+ // If stmt condition branch:
+ // CHECK: cond_br {{.*}} line:[[@LINE-11]]:8
+ // Break branch:
+ // CHECK: br {{.*}} line:[[@LINE-12]]:7
+ // Looping back branch:
+ // CHECK: br {{.*}} line:[[@LINE-11]]:3
+
+
+
+}
diff --git a/test/SILGen/plus_zero_source_location.swift b/test/SILGen/plus_zero_source_location.swift
new file mode 100644
index 0000000..b61fef9
--- /dev/null
+++ b/test/SILGen/plus_zero_source_location.swift
@@ -0,0 +1,25 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func printSourceLocation(file: String = #file, line: Int = #line) {}
+
+#sourceLocation(file: "caller.swift", line: 10000)
+_ = printSourceLocation()
+// CHECK: [[CALLER_FILE_VAL:%.*]] = string_literal utf16 "caller.swift",
+// CHECK: [[CALLER_FILE:%.*]] = apply {{.*}}([[CALLER_FILE_VAL]],
+// CHECK: [[BORROWED_CALLER_FILE:%.*]] = begin_borrow [[CALLER_FILE]]
+// CHECK: [[CALLER_LINE_VAL:%.*]] = integer_literal $Builtin.Int{{[0-9]+}}, 10000,
+// CHECK: [[CALLER_LINE:%.*]] = apply {{.*}}([[CALLER_LINE_VAL]],
+// CHECK: [[PRINT_SOURCE_LOCATION:%.*]] = function_ref @$S15source_location19printSourceLocation4file4lineySS_SitF
+// CHECK: apply [[PRINT_SOURCE_LOCATION]]([[BORROWED_CALLER_FILE]], [[CALLER_LINE]])
+
+#sourceLocation(file: "inplace.swift", line: 20000)
+let FILE = #file, LINE = #line
+// CHECK: [[FILE_ADDR:%.*]] = global_addr @$S15source_location4FILESSv
+// CHECK: [[INPLACE_FILE_VAL:%.*]] = string_literal utf16 "inplace.swift",
+// CHECK: [[INPLACE_FILE:%.*]] = apply {{.*}}([[INPLACE_FILE_VAL]],
+// CHECK: store [[INPLACE_FILE]] to [init] [[FILE_ADDR]]
+// CHECK: [[LINE_ADDR:%.*]] = global_addr @$S15source_location4LINESiv
+// CHECK: [[INPLACE_LINE_VAL:%.*]] = integer_literal $Builtin.Int{{[0-9]+}}, 20000,
+// CHECK: [[INPLACE_LINE:%.*]] = apply {{.*}}([[INPLACE_LINE_VAL]],
+// CHECK: store [[INPLACE_LINE]] to [trivial] [[LINE_ADDR]]
diff --git a/test/SILGen/plus_zero_specialize_attr.swift b/test/SILGen/plus_zero_specialize_attr.swift
new file mode 100644
index 0000000..7ee8a18
--- /dev/null
+++ b/test/SILGen/plus_zero_specialize_attr.swift
@@ -0,0 +1,109 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
+
+// CHECK-LABEL: @_specialize(exported: false, kind: full, where T == Int, U == Float)
+// CHECK-NEXT: func specializeThis<T, U>(_ t: T, u: U)
+@_specialize(where T == Int, U == Float)
+func specializeThis<T, U>(_ t: T, u: U) {}
+
+public protocol PP {
+ associatedtype PElt
+}
+public protocol QQ {
+ associatedtype QElt
+}
+
+public struct RR : PP {
+ public typealias PElt = Float
+}
+public struct SS : QQ {
+ public typealias QElt = Int
+}
+
+public struct GG<T : PP> {}
+
+// CHECK-LABEL: public class CC<T> where T : PP {
+// CHECK-NEXT: @_specialize(exported: false, kind: full, where T == RR, U == SS)
+// CHECK-NEXT: @inline(never) public func foo<U>(_ u: U, g: GG<T>) -> (U, GG<T>) where U : QQ
+public class CC<T : PP> {
+ @inline(never)
+ @_specialize(where T == RR, U == SS)
+ public func foo<U : QQ>(_ u: U, g: GG<T>) -> (U, GG<T>) {
+ return (u, g)
+ }
+}
+
+// CHECK-LABEL: sil hidden [_specialize exported: false, kind: full, where T == Int, U == Float] @$S15specialize_attr0A4This_1uyx_q_tr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @in_guaranteed U) -> () {
+
+// CHECK-LABEL: sil [noinline] [_specialize exported: false, kind: full, where T == RR, U == SS] @$S15specialize_attr2CCC3foo_1gqd___AA2GGVyxGtqd___AHtAA2QQRd__lF : $@convention(method) <T where T : PP><U where U : QQ> (@in_guaranteed U, GG<T>, @guaranteed CC<T>) -> (@out U, GG<T>) {
+
+// -----------------------------------------------------------------------------
+// Test user-specialized subscript accessors.
+
+public protocol TestSubscriptable {
+ associatedtype Element
+ subscript(i: Int) -> Element { get set }
+}
+
+public class ASubscriptable<Element> : TestSubscriptable {
+ var storage: UnsafeMutablePointer<Element>
+
+ init(capacity: Int) {
+ storage = UnsafeMutablePointer<Element>.allocate(capacity: capacity)
+ }
+
+ public subscript(i: Int) -> Element {
+ @_specialize(where Element == Int)
+ get {
+ return storage[i]
+ }
+ @_specialize(where Element == Int)
+ set(rhs) {
+ storage[i] = rhs
+ }
+ }
+}
+
+// ASubscriptable.subscript.getter with _specialize
+// CHECK-LABEL: sil [_specialize exported: false, kind: full, where Element == Int] @$S15specialize_attr14ASubscriptableCyxSicig : $@convention(method) <Element> (Int, @guaranteed ASubscriptable<Element>) -> @out Element {
+
+// ASubscriptable.subscript.setter with _specialize
+// CHECK-LABEL: sil [_specialize exported: false, kind: full, where Element == Int] @$S15specialize_attr14ASubscriptableCyxSicis : $@convention(method) <Element> (@in Element, Int, @guaranteed ASubscriptable<Element>) -> () {
+
+// ASubscriptable.subscript.materializeForSet with no attribute
+// CHECK-LABEL: sil [transparent] [serialized] @$S15specialize_attr14ASubscriptableCyxSicim : $@convention(method) <Element> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, Int, @guaranteed ASubscriptable<Element>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+
+public class Addressable<Element> : TestSubscriptable {
+ var storage: UnsafeMutablePointer<Element>
+
+ init(capacity: Int) {
+ storage = UnsafeMutablePointer<Element>.allocate(capacity: capacity)
+ }
+
+ public subscript(i: Int) -> Element {
+ @_specialize(where Element == Int)
+ unsafeAddress {
+ return UnsafePointer<Element>(storage + i)
+ }
+ @_specialize(where Element == Int)
+ unsafeMutableAddress {
+ return UnsafeMutablePointer<Element>(storage + i)
+ }
+ }
+}
+
+// Addressable.subscript.getter with no attribute
+// CHECK-LABEL: sil [transparent] [serialized] @$S15specialize_attr11AddressableCyxSicig : $@convention(method) <Element> (Int, @guaranteed Addressable<Element>) -> @out Element {
+
+// Addressable.subscript.unsafeAddressor with _specialize
+// CHECK-LABEL: sil [_specialize exported: false, kind: full, where Element == Int] @$S15specialize_attr11AddressableCyxSicilu : $@convention(method) <Element> (Int, @guaranteed Addressable<Element>) -> UnsafePointer<Element> {
+
+// Addressable.subscript.setter with no attribute
+// CHECK-LABEL: sil [transparent] [serialized] @$S15specialize_attr11AddressableCyxSicis : $@convention(method) <Element> (@in Element, Int, @guaranteed Addressable<Element>) -> () {
+
+// Addressable.subscript.unsafeMutableAddressor with _specialize
+// CHECK-LABEL: sil [_specialize exported: false, kind: full, where Element == Int] @$S15specialize_attr11AddressableCyxSiciau : $@convention(method) <Element> (Int, @guaranteed Addressable<Element>) -> UnsafeMutablePointer<Element> {
+
+// Addressable.subscript.materializeForSet with no attribute
+// CHECK-LABEL: sil [transparent] [serialized] @$S15specialize_attr11AddressableCyxSicim : $@convention(method) <Element> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, Int, @guaranteed Addressable<Element>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+
diff --git a/test/SILGen/plus_zero_statements.swift b/test/SILGen/plus_zero_statements.swift
new file mode 100644
index 0000000..d3fe1bd
--- /dev/null
+++ b/test/SILGen/plus_zero_statements.swift
@@ -0,0 +1,697 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-silgen -enable-sil-ownership -verify %s | %FileCheck %s
+
+class MyClass {
+ func foo() { }
+}
+
+func markUsed<T>(_ t: T) {}
+
+func marker_1() {}
+func marker_2() {}
+func marker_3() {}
+
+class BaseClass {}
+class DerivedClass : BaseClass {}
+
+var global_cond: Bool = false
+
+func bar(_ x: Int) {}
+func foo(_ x: Int, _ y: Bool) {}
+
+func abort() -> Never { abort() }
+
+
+
+func assignment(_ x: Int, y: Int) {
+ var x = x
+ var y = y
+ x = 42
+ y = 57
+ _ = x
+ _ = y
+ (x, y) = (1,2)
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}assignment
+// CHECK: integer_literal $Builtin.Int2048, 42
+// CHECK: assign
+// CHECK: integer_literal $Builtin.Int2048, 57
+// CHECK: assign
+
+func if_test(_ x: Int, y: Bool) {
+ if (y) {
+ bar(x);
+ }
+ bar(x);
+}
+
+// CHECK-LABEL: sil hidden @$S10statements7if_test{{[_0-9a-zA-Z]*}}F
+
+func if_else(_ x: Int, y: Bool) {
+ if (y) {
+ bar(x);
+ } else {
+ foo(x, y);
+ }
+ bar(x);
+}
+
+// CHECK-LABEL: sil hidden @$S10statements7if_else{{[_0-9a-zA-Z]*}}F
+
+func nested_if(_ x: Int, y: Bool, z: Bool) {
+ if (y) {
+ if (z) {
+ bar(x);
+ }
+ } else {
+ if (z) {
+ foo(x, y);
+ }
+ }
+ bar(x);
+}
+
+// CHECK-LABEL: sil hidden @$S10statements9nested_if{{[_0-9a-zA-Z]*}}F
+
+func nested_if_merge_noret(_ x: Int, y: Bool, z: Bool) {
+ if (y) {
+ if (z) {
+ bar(x);
+ }
+ } else {
+ if (z) {
+ foo(x, y);
+ }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10statements21nested_if_merge_noret{{[_0-9a-zA-Z]*}}F
+
+func nested_if_merge_ret(_ x: Int, y: Bool, z: Bool) -> Int {
+ if (y) {
+ if (z) {
+ bar(x);
+ }
+ return 1
+ } else {
+ if (z) {
+ foo(x, y);
+ }
+ }
+ return 2
+}
+
+// CHECK-LABEL: sil hidden @$S10statements19nested_if_merge_ret{{[_0-9a-zA-Z]*}}F
+
+func else_break(_ x: Int, y: Bool, z: Bool) {
+ while z {
+ if y {
+ } else {
+ break
+ }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10statements10else_break{{[_0-9a-zA-Z]*}}F
+
+func loop_with_break(_ x: Int, _ y: Bool, _ z: Bool) -> Int {
+ while (x > 2) {
+ if (y) {
+ bar(x);
+ break
+ }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10statements15loop_with_break{{[_0-9a-zA-Z]*}}F
+
+func loop_with_continue(_ x: Int, y: Bool, z: Bool) -> Int {
+ while (x > 2) {
+ if (y) {
+ bar(x);
+ continue
+ }
+ _ = loop_with_break(x, y, z);
+ }
+ bar(x);
+}
+
+// CHECK-LABEL: sil hidden @$S10statements18loop_with_continue{{[_0-9a-zA-Z]*}}F
+
+func do_loop_with_continue(_ x: Int, y: Bool, z: Bool) -> Int {
+ repeat {
+ if (x < 42) {
+ bar(x);
+ continue
+ }
+ _ = loop_with_break(x, y, z);
+ }
+ while (x > 2);
+ bar(x);
+}
+
+// CHECK-LABEL: sil hidden @$S10statements21do_loop_with_continue{{[_0-9a-zA-Z]*}}F
+
+
+// CHECK-LABEL: sil hidden @{{.*}}for_loops1
+func for_loops1(_ x: Int, c: Bool) {
+ for i in 1..<100 {
+ markUsed(i)
+ }
+
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}for_loops2
+func for_loops2() {
+ // rdar://problem/19316670
+ // CHECK: alloc_stack $Optional<MyClass>
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown]
+ // CHECK: [[NEXT:%[0-9]+]] = function_ref @$Ss16IndexingIteratorV4next{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply [[NEXT]]<[MyClass]>
+ // CHECK: class_method [[OBJ:%[0-9]+]] : $MyClass, #MyClass.foo!1
+ let objects = [MyClass(), MyClass() ]
+ for obj in objects {
+ obj.foo()
+ }
+
+ return
+}
+
+func void_return() {
+ let b:Bool
+ if b {
+ return
+ }
+}
+// CHECK-LABEL: sil hidden @$S10statements11void_return{{[_0-9a-zA-Z]*}}F
+// CHECK: cond_br {{%[0-9]+}}, [[BB1:bb[0-9]+]], [[BB2:bb[0-9]+]]
+// CHECK: [[BB1]]:
+// CHECK: br [[EPILOG:bb[0-9]+]]
+// CHECK: [[BB2]]:
+// CHECK: br [[EPILOG]]
+// CHECK: [[EPILOG]]:
+// CHECK: [[R:%[0-9]+]] = tuple ()
+// CHECK: return [[R]]
+
+func foo() {}
+
+// <rdar://problem/13549626>
+// CHECK-LABEL: sil hidden @$S10statements14return_from_if{{[_0-9a-zA-Z]*}}F
+func return_from_if(_ a: Bool) -> Int {
+ // CHECK: bb0(%0 : @trivial $Bool):
+ // CHECK: cond_br {{.*}}, [[THEN:bb[0-9]+]], [[ELSE:bb[0-9]+]]
+ if a {
+ // CHECK: [[THEN]]:
+ // CHECK: br [[EPILOG:bb[0-9]+]]({{%.*}})
+ return 1
+ } else {
+ // CHECK: [[ELSE]]:
+ // CHECK: br [[EPILOG]]({{%.*}})
+ return 0
+ }
+ // CHECK-NOT: function_ref @foo
+ // CHECK: [[EPILOG]]([[RET:%.*]] : @trivial $Int):
+ // CHECK: return [[RET]]
+ foo() // expected-warning {{will never be executed}}
+}
+
+class C {}
+
+func use(_ c: C) {}
+
+func for_each_loop(_ x: [C]) {
+ for i in x {
+ use(i)
+ }
+ _ = 0
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}test_break
+func test_break(_ i : Int) {
+ switch i {
+ case (let x) where x != 17:
+ if x == 42 { break }
+ markUsed(x)
+ default:
+ break
+ }
+}
+
+
+// <rdar://problem/19150249> Allow labeled "break" from an "if" statement
+
+// CHECK-LABEL: sil hidden @$S10statements13test_if_breakyyAA1CCSgF : $@convention(thin) (@guaranteed Optional<C>) -> () {
+func test_if_break(_ c : C?) {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<C>):
+label1:
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $Optional<C>, case #Optional.some!enumelt.1: [[TRUE:bb[0-9]+]], case #Optional.none!enumelt: [[FALSE:bb[0-9]+]]
+ if let x = c {
+// CHECK: [[TRUE]]({{.*}} : @owned $C):
+
+ // CHECK: apply
+ foo()
+
+ // CHECK: destroy_value
+ // CHECK: br [[FALSE:bb[0-9]+]]
+ break label1
+ use(x) // expected-warning {{will never be executed}}
+ }
+
+ // CHECK: [[FALSE]]:
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S10statements18test_if_else_breakyyAA1CCSgF : $@convention(thin) (@guaranteed Optional<C>) -> () {
+func test_if_else_break(_ c : C?) {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<C>):
+label2:
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[ARG_COPY]] : $Optional<C>, case #Optional.some!enumelt.1: [[TRUE:bb[0-9]+]], case #Optional.none!enumelt: [[FALSE:bb[0-9]+]]
+
+ // CHECK: [[FALSE]]:
+ // CHECK: br [[AFTER_FALSE:bb[0-9]+]]
+ if let x = c {
+ // CHECK: [[TRUE]]({{.*}} : @owned $C):
+ use(x)
+ // CHECK: br [[CONT:bb[0-9]+]]
+ // CHECK: [[CONT]]:
+ // CHECK: br [[EPILOG:bb[0-9]+]]
+ } else {
+ // CHECK: [[AFTER_FALSE]]:
+ // CHECK: apply
+ // CHECK: br [[EPILOG]]
+ foo()
+ break label2
+ foo() // expected-warning {{will never be executed}}
+ }
+ // CHECK: [[EPILOG]]:
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S10statements23test_if_else_then_breakyySb_AA1CCSgtF
+func test_if_else_then_break(_ a : Bool, _ c : C?) {
+label3:
+ // CHECK: bb0({{.*}}, [[ARG2:%.*]] : @guaranteed $Optional<C>):
+ // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]]
+ // CHECK: switch_enum [[ARG2_COPY]] : $Optional<C>, case #Optional.some!enumelt.1: [[TRUE:bb[0-9]+]], case #Optional.none!enumelt: [[FALSE:bb[0-9]+]]
+
+ // CHECK: [[FALSE]]:
+ // CHECK: br [[COND2:bb[0-9]+]]
+ if let x = c {
+ // CHECK: [[TRUE]]({{.*}} : @owned $C):
+ use(x)
+ // CHECK: br [[TRUE_TRAMPOLINE:bb[0-9]+]]
+ //
+ // CHECK: [[TRUE_TRAMPOLINE]]:
+ // CHECK: br [[EPILOG_BB:bb[0-9]+]]
+ } else if a {
+ // CHECK: [[COND2]]:
+ // CHECK: cond_br {{.*}}, [[TRUE2:bb[0-9]+]], [[FALSE2:bb[0-9]+]]
+ //
+ // CHECK: [[TRUE2]]:
+ // CHECK: apply
+ // CHECK: br [[EPILOG_BB]]
+ foo()
+ break label3
+ foo() // expected-warning {{will never be executed}}
+ }
+ // CHECK: [[FALSE2]]:
+ // CHECK: br [[EPILOG_BB]]
+
+ // CHECK: [[EPILOG_BB]]:
+ // CHECK: return
+
+
+}
+
+
+// CHECK-LABEL: sil hidden @$S10statements13test_if_breakyySbF
+func test_if_break(_ a : Bool) {
+ // CHECK: br [[LOOP:bb[0-9]+]]
+ // CHECK: [[LOOP]]:
+ // CHECK: function_ref @$SSb21_getBuiltinLogicValue{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply
+ // CHECK-NEXT: cond_br {{.*}}, [[LOOPTRUE:bb[0-9]+]], [[OUT:bb[0-9]+]]
+ while a {
+ if a {
+ foo()
+ break // breaks out of while, not if.
+ }
+ foo()
+ }
+
+ // CHECK: [[LOOPTRUE]]:
+ // CHECK: function_ref @$SSb21_getBuiltinLogicValue{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply
+ // CHECK-NEXT: cond_br {{.*}}, [[IFTRUE:bb[0-9]+]], [[IFFALSE:bb[0-9]+]]
+
+ // [[IFTRUE]]:
+ // CHECK: function_ref statements.foo
+ // CHECK: br [[OUT]]
+
+ // CHECK: [[IFFALSE]]:
+ // CHECK: function_ref statements.foo
+ // CHECK: br [[LOOP]]
+
+ // CHECK: [[OUT]]:
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S10statements7test_doyyF
+func test_do() {
+ // CHECK: integer_literal $Builtin.Int2048, 0
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(0)
+ // CHECK-NOT: br bb
+ do {
+ // CHECK: [[CTOR:%.*]] = function_ref @$S10statements7MyClassC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: [[OBJ:%.*]] = apply [[CTOR]](
+ let obj = MyClass()
+ _ = obj
+
+ // CHECK: integer_literal $Builtin.Int2048, 1
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(1)
+
+ // CHECK-NOT: br bb
+ // CHECK: destroy_value [[OBJ]]
+ // CHECK-NOT: br bb
+ }
+
+ // CHECK: integer_literal $Builtin.Int2048, 2
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(2)
+}
+
+// CHECK-LABEL: sil hidden @$S10statements15test_do_labeledyyF
+func test_do_labeled() {
+ // CHECK: integer_literal $Builtin.Int2048, 0
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(0)
+ // CHECK: br bb1
+ // CHECK: bb1:
+ lbl: do {
+ // CHECK: [[CTOR:%.*]] = function_ref @$S10statements7MyClassC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: [[OBJ:%.*]] = apply [[CTOR]](
+ let obj = MyClass()
+ _ = obj
+
+ // CHECK: integer_literal $Builtin.Int2048, 1
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(1)
+
+ // CHECK: [[GLOBAL:%.*]] = function_ref @$S10statements11global_condSbvau
+ // CHECK: cond_br {{%.*}}, bb2, bb3
+ if (global_cond) {
+ // CHECK: bb2:
+ // CHECK: destroy_value [[OBJ]]
+ // CHECK: br bb1
+ continue lbl
+ }
+
+ // CHECK: bb3:
+ // CHECK: integer_literal $Builtin.Int2048, 2
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(2)
+
+ // CHECK: [[GLOBAL:%.*]] = function_ref @$S10statements11global_condSbvau
+ // CHECK: cond_br {{%.*}}, bb4, bb5
+ if (global_cond) {
+ // CHECK: bb4:
+ // CHECK: destroy_value [[OBJ]]
+ // CHECK: br bb6
+ break lbl
+ }
+
+ // CHECK: bb5:
+ // CHECK: integer_literal $Builtin.Int2048, 3
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(3)
+
+ // CHECK: destroy_value [[OBJ]]
+ // CHECK: br bb6
+ }
+
+ // CHECK: integer_literal $Builtin.Int2048, 4
+ // CHECK: [[BAR:%.*]] = function_ref @$S10statements3baryySiF
+ // CHECK: apply [[BAR]](
+ bar(4)
+}
+
+
+func callee1() {}
+func callee2() {}
+func callee3() {}
+
+// CHECK-LABEL: sil hidden @$S10statements11defer_test1yyF
+func defer_test1() {
+ defer { callee1() }
+ defer { callee2() }
+ callee3()
+
+ // CHECK: [[C3:%.*]] = function_ref @$S10statements7callee3yyF
+ // CHECK: apply [[C3]]
+ // CHECK: [[C2:%.*]] = function_ref @$S10statements11defer_test1yyF6
+ // CHECK: apply [[C2]]
+ // CHECK: [[C1:%.*]] = function_ref @$S10statements11defer_test1yyF6
+ // CHECK: apply [[C1]]
+}
+// CHECK: sil private @$S10statements11defer_test1yyF6
+// CHECK: function_ref @{{.*}}callee1yyF
+
+// CHECK: sil private @$S10statements11defer_test1yyF6
+// CHECK: function_ref @{{.*}}callee2yyF
+
+// CHECK-LABEL: sil hidden @$S10statements11defer_test2yySbF
+func defer_test2(_ cond : Bool) {
+ // CHECK: [[C3:%.*]] = function_ref @{{.*}}callee3yyF
+ // CHECK: apply [[C3]]
+ // CHECK: br [[LOOP:bb[0-9]+]]
+ callee3()
+
+// CHECK: [[LOOP]]:
+// test the condition.
+// CHECK: [[CONDTRUE:%.*]] = apply {{.*}}(%0)
+// CHECK: cond_br [[CONDTRUE]], [[BODY:bb[0-9]+]], [[EXIT:bb[0-9]+]]
+ while cond {
+// CHECK: [[BODY]]:
+ // CHECK: [[C2:%.*]] = function_ref @{{.*}}callee2yyF
+ // CHECK: apply [[C2]]
+
+ // CHECK: [[C1:%.*]] = function_ref @$S10statements11defer_test2yySbF6
+ // CHECK: apply [[C1]]
+ // CHECK: br [[EXIT]]
+ defer { callee1() }
+ callee2()
+ break
+ }
+
+// CHECK: [[EXIT]]:
+// CHECK: [[C3:%.*]] = function_ref @{{.*}}callee3yyF
+// CHECK: apply [[C3]]
+
+ callee3()
+}
+
+func generic_callee_1<T>(_: T) {}
+func generic_callee_2<T>(_: T) {}
+func generic_callee_3<T>(_: T) {}
+
+// CHECK-LABEL: sil hidden @$S10statements16defer_in_generic{{[_0-9a-zA-Z]*}}F
+func defer_in_generic<T>(_ x: T) {
+ // CHECK: [[C3:%.*]] = function_ref @$S10statements16generic_callee_3{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply [[C3]]<T>
+ // CHECK: [[C2:%.*]] = function_ref @$S10statements16defer_in_genericyyxlF6
+ // CHECK: apply [[C2]]<T>
+ // CHECK: [[C1:%.*]] = function_ref @$S10statements16defer_in_genericyyxlF6
+ // CHECK: apply [[C1]]<T>
+ defer { generic_callee_1(x) }
+ defer { generic_callee_2(x) }
+ generic_callee_3(x)
+}
+
+// CHECK-LABEL: sil hidden @$S10statements017defer_in_closure_C8_genericyyxlF : $@convention(thin) <T> (@in_guaranteed T) -> ()
+func defer_in_closure_in_generic<T>(_ x: T) {
+ // CHECK-LABEL: sil private @$S10statements017defer_in_closure_C8_genericyyxlFyycfU_ : $@convention(thin) <T> () -> ()
+ _ = {
+ // CHECK-LABEL: sil private @$S10statements017defer_in_closure_C8_genericyyxlFyycfU_6$deferL_yylF : $@convention(thin) <T> () -> ()
+ defer { generic_callee_1(T.self) }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10statements13defer_mutableyySiF
+func defer_mutable(_ x: Int) {
+ var x = x
+ // CHECK: [[BOX:%.*]] = alloc_box ${ var Int }
+ // CHECK-NEXT: project_box [[BOX]]
+ // CHECK-NOT: [[BOX]]
+ // CHECK: function_ref @$S10statements13defer_mutableyySiF6$deferL_yyF : $@convention(thin) (@inout_aliasable Int) -> ()
+ // CHECK-NOT: [[BOX]]
+ // CHECK: destroy_value [[BOX]]
+ defer { _ = x }
+}
+
+protocol StaticFooProtocol { static func foo() }
+
+func testDeferOpenExistential(_ b: Bool, type: StaticFooProtocol.Type) {
+ defer { type.foo() }
+ if b { return }
+ return
+}
+
+
+
+
+// CHECK-LABEL: sil hidden @$S10statements22testRequireExprPatternyySiF
+
+func testRequireExprPattern(_ a : Int) {
+ marker_1()
+ // CHECK: [[M1:%[0-9]+]] = function_ref @$S10statements8marker_1yyF : $@convention(thin) () -> ()
+ // CHECK-NEXT: apply [[M1]]() : $@convention(thin) () -> ()
+
+ // CHECK: function_ref Swift.~= infix<A where A: Swift.Equatable>(A, A) -> Swift.Bool
+ // CHECK: cond_br {{.*}}, bb1, bb2
+ guard case 4 = a else { marker_2(); return }
+
+ // Fall through case comes first.
+
+ // CHECK: bb1:
+ // CHECK: [[M3:%[0-9]+]] = function_ref @$S10statements8marker_3yyF : $@convention(thin) () -> ()
+ // CHECK-NEXT: apply [[M3]]() : $@convention(thin) () -> ()
+ // CHECK-NEXT: br bb3
+ marker_3()
+
+ // CHECK: bb2:
+ // CHECK: [[M2:%[0-9]+]] = function_ref @$S10statements8marker_2yyF : $@convention(thin) () -> ()
+ // CHECK-NEXT: apply [[M2]]() : $@convention(thin) () -> ()
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb3:
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+}
+
+
+// CHECK-LABEL: sil hidden @$S10statements20testRequireOptional1yS2iSgF
+// CHECK: bb0([[ARG:%.*]] : @trivial $Optional<Int>):
+// CHECK-NEXT: debug_value [[ARG]] : $Optional<Int>, let, name "a"
+// CHECK-NEXT: switch_enum [[ARG]] : $Optional<Int>, case #Optional.some!enumelt.1: [[SOME:bb[0-9]+]], case #Optional.none!enumelt: [[NONE:bb[0-9]+]]
+func testRequireOptional1(_ a : Int?) -> Int {
+
+ // CHECK: [[NONE]]:
+ // CHECK: br [[ABORT:bb[0-9]+]]
+
+ // CHECK: [[SOME]]([[PAYLOAD:%.*]] : @trivial $Int):
+ // CHECK-NEXT: debug_value [[PAYLOAD]] : $Int, let, name "t"
+ // CHECK-NEXT: br [[EPILOG:bb[0-9]+]]
+ //
+ // CHECK: [[EPILOG]]:
+ // CHECK-NEXT: return [[PAYLOAD]] : $Int
+ guard let t = a else { abort() }
+
+ // CHECK: [[ABORT]]:
+ // CHECK-NEXT: // function_ref statements.abort() -> Swift.Never
+ // CHECK-NEXT: [[FUNC_REF:%.*]] = function_ref @$S10statements5aborts5NeverOyF
+ // CHECK-NEXT: apply [[FUNC_REF]]() : $@convention(thin) () -> Never
+ // CHECK-NEXT: unreachable
+ return t
+}
+
+// CHECK-LABEL: sil hidden @$S10statements20testRequireOptional2yS2SSgF
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $Optional<String>):
+// CHECK-NEXT: debug_value [[ARG]] : $Optional<String>, let, name "a"
+// CHECK-NEXT: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $Optional<String>
+// CHECK-NEXT: switch_enum [[ARG_COPY]] : $Optional<String>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+func testRequireOptional2(_ a : String?) -> String {
+ guard let t = a else { abort() }
+
+ // CHECK: [[NONE_BB]]:
+ // CHECK-NEXT: br [[ABORT_BB:bb[0-9]+]]
+
+ // CHECK: [[SOME_BB]]([[STR:%.*]] : @owned $String):
+ // CHECK-NEXT: debug_value [[STR]] : $String, let, name "t"
+ // CHECK-NEXT: br [[CONT_BB:bb[0-9]+]]
+ // CHECK: [[CONT_BB]]:
+ // CHECK-NEXT: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+ // CHECK-NEXT: [[RETURN:%.*]] = copy_value [[BORROWED_STR]]
+ // CHECK-NEXT: end_borrow [[BORROWED_STR]] from [[STR]]
+ // CHECK-NEXT: destroy_value [[STR]] : $String
+ // CHECK-NEXT: return [[RETURN]] : $String
+
+ // CHECK: [[ABORT_BB]]:
+ // CHECK-NEXT: // function_ref statements.abort() -> Swift.Never
+ // CHECK-NEXT: [[ABORT_FUNC:%.*]] = function_ref @$S10statements5aborts5NeverOyF
+ // CHECK-NEXT: [[NEVER:%.*]] = apply [[ABORT_FUNC]]()
+ // CHECK-NEXT: unreachable
+ return t
+}
+
+
+// CHECK-LABEL: sil hidden @$S10statements19testCleanupEmission{{[_0-9a-zA-Z]*}}F
+// <rdar://problem/20563234> let-else problem: cleanups for bound patterns shouldn't be run in the else block
+protocol MyProtocol {}
+func testCleanupEmission<T>(_ x: T) {
+ // SILGen shouldn't crash/verify abort on this example.
+ guard let x2 = x as? MyProtocol else { return }
+ _ = x2
+}
+
+
+// CHECK-LABEL: sil hidden @$S10statements15test_is_patternyyAA9BaseClassCF
+func test_is_pattern(_ y : BaseClass) {
+ // checked_cast_br %0 : $BaseClass to $DerivedClass
+ guard case is DerivedClass = y else { marker_1(); return }
+
+ marker_2()
+}
+
+// CHECK-LABEL: sil hidden @$S10statements15test_as_patternyAA12DerivedClassCAA04BaseF0CF
+func test_as_pattern(_ y : BaseClass) -> DerivedClass {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $BaseClass):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: checked_cast_br [[ARG_COPY]] : $BaseClass to $DerivedClass
+ guard case let result as DerivedClass = y else { }
+ // CHECK: bb{{.*}}({{.*}} : @owned $DerivedClass):
+
+
+ // CHECK: bb{{.*}}([[PTR:%[0-9]+]] : @owned $DerivedClass):
+ // CHECK-NEXT: debug_value [[PTR]] : $DerivedClass, let, name "result"
+ // CHECK-NEXT: br [[CONT_BB:bb[0-9]+]]
+ // CHECK: [[CONT_BB]]:
+ // CHECK-NEXT: [[BORROWED_PTR:%.*]] = begin_borrow [[PTR]]
+ // CHECK-NEXT: [[RESULT:%.*]] = copy_value [[BORROWED_PTR]]
+ // CHECK-NEXT: end_borrow [[BORROWED_PTR]] from [[PTR]]
+ // CHECK-NEXT: destroy_value [[PTR]] : $DerivedClass
+ // CHECK-NEXT: return [[RESULT]] : $DerivedClass
+ return result
+}
+// CHECK-LABEL: sil hidden @$S10statements22let_else_tuple_bindingyS2i_SitSgF
+func let_else_tuple_binding(_ a : (Int, Int)?) -> Int {
+
+ // CHECK: bb0([[ARG:%.*]] : @trivial $Optional<(Int, Int)>):
+ // CHECK-NEXT: debug_value [[ARG]] : $Optional<(Int, Int)>, let, name "a"
+ // CHECK-NEXT: switch_enum [[ARG]] : $Optional<(Int, Int)>, case #Optional.some!enumelt.1: [[SOME_BB:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BB:bb[0-9]+]]
+
+ guard let (x, y) = a else { }
+ _ = y
+ return x
+
+ // CHECK: [[SOME_BB]]([[PAYLOAD:%.*]] : @trivial $(Int, Int)):
+ // CHECK-NEXT: [[PAYLOAD_1:%.*]] = tuple_extract [[PAYLOAD]] : $(Int, Int), 0
+ // CHECK-NEXT: debug_value [[PAYLOAD_1]] : $Int, let, name "x"
+ // CHECK-NEXT: [[PAYLOAD_2:%.*]] = tuple_extract [[PAYLOAD]] : $(Int, Int), 1
+ // CHECK-NEXT: debug_value [[PAYLOAD_2]] : $Int, let, name "y"
+ // CHECK-NEXT: br [[CONT_BB:bb[0-9]+]]
+ // CHECK: [[CONT_BB]]:
+ // CHECK-NEXT: return [[PAYLOAD_1]] : $Int
+}
+
diff --git a/test/SILGen/plus_zero_struct_resilience.swift b/test/SILGen/plus_zero_struct_resilience.swift
new file mode 100644
index 0000000..b11d502
--- /dev/null
+++ b/test/SILGen/plus_zero_struct_resilience.swift
@@ -0,0 +1,284 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -enable-sil-ownership -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -I %t -enable-sil-ownership -emit-silgen -enable-resilience %s | %FileCheck %s
+
+import resilient_struct
+
+// Resilient structs are always address-only
+
+// CHECK-LABEL: sil hidden @$S17struct_resilience26functionWithResilientTypes_1f010resilient_A04SizeVAF_A2FXEtF : $@convention(thin) (@in_guaranteed Size, @noescape @callee_guaranteed (@in_guaranteed Size) -> @out Size) -> @out Size
+// CHECK: bb0(%0 : @trivial $*Size, %1 : @trivial $*Size, %2 : @trivial $@noescape @callee_guaranteed (@in_guaranteed Size) -> @out Size):
+func functionWithResilientTypes(_ s: Size, f: (Size) -> Size) -> Size {
+
+ // Stored properties of resilient structs from outside our resilience
+ // domain are accessed through accessors
+
+// CHECK: copy_addr %1 to [initialization] [[OTHER_SIZE_BOX:%[0-9]*]] : $*Size
+ var s2 = s
+
+// CHECK: copy_addr %1 to [initialization] [[SIZE_BOX:%.*]] : $*Size
+// CHECK: [[GETTER:%.*]] = function_ref @$S16resilient_struct4SizeV1wSivg : $@convention(method) (@in_guaranteed Size) -> Int
+// CHECK: [[RESULT:%.*]] = apply [[GETTER]]([[SIZE_BOX]])
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[OTHER_SIZE_BOX]] : $*Size
+// CHECK: [[SETTER:%.*]] = function_ref @$S16resilient_struct4SizeV1wSivs : $@convention(method) (Int, @inout Size) -> ()
+// CHECK: apply [[SETTER]]([[RESULT]], [[WRITE]])
+ s2.w = s.w
+
+// CHECK: copy_addr %1 to [initialization] [[SIZE_BOX:%.*]] : $*Size
+// CHECK: [[FN:%.*]] = function_ref @$S16resilient_struct4SizeV1hSivg : $@convention(method) (@in_guaranteed Size) -> Int
+// CHECK: [[RESULT:%.*]] = apply [[FN]]([[SIZE_BOX]])
+ _ = s.h
+
+// CHECK: apply %2(%0, %1)
+// CHECK-NOT: destroy_value %2
+// CHECK: return
+ return f(s)
+}
+
+// Use materializeForSet for inout access of properties in resilient structs
+// from a different resilience domain
+
+public func inoutFunc(_ x: inout Int) {}
+
+// CHECK-LABEL: sil hidden @$S17struct_resilience18resilientInOutTestyy0c1_A04SizeVzF : $@convention(thin) (@inout Size) -> ()
+
+func resilientInOutTest(_ s: inout Size) {
+
+// CHECK: function_ref @$S16resilient_struct4SizeV1wSivm
+// CHECK: function_ref @$S17struct_resilience9inoutFuncyySizF
+
+ inoutFunc(&s.w)
+
+// CHECK: return
+}
+
+// Fixed-layout structs may be trivial or loadable
+
+// CHECK-LABEL: sil hidden @$S17struct_resilience28functionWithFixedLayoutTypes_1f010resilient_A05PointVAF_A2FXEtF : $@convention(thin) (Point, @noescape @callee_guaranteed (Point) -> Point) -> Point
+// CHECK: bb0(%0 : @trivial $Point, %1 : @trivial $@noescape @callee_guaranteed (Point) -> Point):
+func functionWithFixedLayoutTypes(_ p: Point, f: (Point) -> Point) -> Point {
+
+ // Stored properties of fixed layout structs are accessed directly
+ var p2 = p
+
+// CHECK: [[RESULT:%.*]] = struct_extract %0 : $Point, #Point.x
+// CHECK: [[DEST:%.*]] = struct_element_addr [[POINT_BOX:%[0-9]*]] : $*Point, #Point.x
+// CHECK: assign [[RESULT]] to [[DEST]] : $*Int
+ p2.x = p.x
+
+// CHECK: [[RESULT:%.*]] = struct_extract %0 : $Point, #Point.y
+ _ = p.y
+
+// CHECK: [[NEW_POINT:%.*]] = apply %1(%0)
+// CHECK: return [[NEW_POINT]]
+ return f(p)
+}
+
+// Fixed-layout struct with resilient stored properties is still address-only
+
+// CHECK-LABEL: sil hidden @$S17struct_resilience39functionWithFixedLayoutOfResilientTypes_1f010resilient_A09RectangleVAF_A2FXEtF : $@convention(thin) (@in_guaranteed Rectangle, @noescape @callee_guaranteed (@in_guaranteed Rectangle) -> @out Rectangle) -> @out Rectangle
+// CHECK: bb0(%0 : @trivial $*Rectangle, %1 : @trivial $*Rectangle, %2 : @trivial $@noescape @callee_guaranteed (@in_guaranteed Rectangle) -> @out Rectangle):
+func functionWithFixedLayoutOfResilientTypes(_ r: Rectangle, f: (Rectangle) -> Rectangle) -> Rectangle {
+ return f(r)
+}
+
+// Make sure we generate getters and setters for stored properties of
+// resilient structs
+
+public struct MySize {
+
+ // Static computed property
+
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV10expirationSivgZ : $@convention(method) (@thin MySize.Type) -> Int
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV10expirationSivsZ : $@convention(method) (Int, @thin MySize.Type) -> ()
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV10expirationSivmZ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @thin MySize.Type) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public static var expiration: Int {
+ get { return copyright + 70 }
+ set { copyright = newValue - 70 }
+ }
+
+ // Instance computed property
+
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1dSivg : $@convention(method) (@in_guaranteed MySize) -> Int
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1dSivs : $@convention(method) (Int, @inout MySize) -> ()
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1dSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout MySize) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public var d: Int {
+ get { return 0 }
+ set { }
+ }
+
+ // Instance stored property
+
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1wSivg : $@convention(method) (@in_guaranteed MySize) -> Int
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1wSivs : $@convention(method) (Int, @inout MySize) -> ()
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1wSivm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout MySize) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public var w: Int
+
+ // Read-only instance stored property
+
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV1hSivg : $@convention(method) (@in_guaranteed MySize) -> Int
+ public let h: Int
+
+ // Static stored property
+
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV9copyrightSivgZ : $@convention(method) (@thin MySize.Type) -> Int
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV9copyrightSivsZ : $@convention(method) (Int, @thin MySize.Type) -> ()
+// CHECK-LABEL: sil @$S17struct_resilience6MySizeV9copyrightSivmZ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @thin MySize.Type) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ public static var copyright: Int = 0
+}
+
+// CHECK-LABEL: sil @$S17struct_resilience28functionWithMyResilientTypes_1fAA0E4SizeVAE_A2EXEtF : $@convention(thin) (@in_guaranteed MySize, @noescape @callee_guaranteed (@in_guaranteed MySize) -> @out MySize) -> @out MySize
+public func functionWithMyResilientTypes(_ s: MySize, f: (MySize) -> MySize) -> MySize {
+
+ // Stored properties of resilient structs from inside our resilience
+ // domain are accessed directly
+
+// CHECK: copy_addr %1 to [initialization] [[SIZE_BOX:%[0-9]*]] : $*MySize
+ var s2 = s
+
+// CHECK: [[SRC_ADDR:%.*]] = struct_element_addr %1 : $*MySize, #MySize.w
+// CHECK: [[SRC:%.*]] = load [trivial] [[SRC_ADDR]] : $*Int
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[SIZE_BOX]] : $*MySize
+// CHECK: [[DEST_ADDR:%.*]] = struct_element_addr [[WRITE]] : $*MySize, #MySize.w
+// CHECK: assign [[SRC]] to [[DEST_ADDR]] : $*Int
+ s2.w = s.w
+
+// CHECK: [[RESULT_ADDR:%.*]] = struct_element_addr %1 : $*MySize, #MySize.h
+// CHECK: [[RESULT:%.*]] = load [trivial] [[RESULT_ADDR]] : $*Int
+ _ = s.h
+
+// CHECK: apply %2(%0, %1)
+// CHECK-NOT: destroy_value %2
+// CHECK: return
+ return f(s)
+}
+
+// CHECK-LABEL: sil [transparent] [serialized] @$S17struct_resilience25publicTransparentFunctionySiAA6MySizeVF : $@convention(thin) (@in_guaranteed MySize) -> Int
+@_transparent public func publicTransparentFunction(_ s: MySize) -> Int {
+
+ // Since the body of a public transparent function might be inlined into
+ // other resilience domains, we have to use accessors
+
+// CHECK: [[SELF:%.*]] = alloc_stack $MySize
+// CHECK-NEXT: copy_addr %0 to [initialization] [[SELF]]
+
+// CHECK: [[GETTER:%.*]] = function_ref @$S17struct_resilience6MySizeV1wSivg
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]]([[SELF]])
+// CHECK-NEXT: destroy_addr [[SELF]]
+// CHECK-NEXT: dealloc_stack [[SELF]]
+// CHECK-NEXT: return [[RESULT]]
+ return s.w
+}
+
+// CHECK-LABEL: sil [transparent] [serialized] @$S17struct_resilience30publicTransparentLocalFunctionySiycAA6MySizeVF : $@convention(thin) (@in_guaranteed MySize) -> @owned @callee_guaranteed () -> Int
+@_transparent public func publicTransparentLocalFunction(_ s: MySize) -> () -> Int {
+
+// CHECK-LABEL: sil shared [serialized] @$S17struct_resilience30publicTransparentLocalFunctionySiycAA6MySizeVFSiycfU_ : $@convention(thin) (@guaranteed { var MySize }) -> Int
+// CHECK: function_ref @$S17struct_resilience6MySizeV1wSivg : $@convention(method) (@in_guaranteed MySize) -> Int
+// CHECK: return {{.*}} : $Int
+
+ return { s.w }
+
+}
+
+// CHECK-LABEL: sil hidden [transparent] @$S17struct_resilience27internalTransparentFunctionySiAA6MySizeVF : $@convention(thin) (@in_guaranteed MySize) -> Int
+// CHECK: bb0([[ARG:%.*]] : @trivial $*MySize):
+@_transparent func internalTransparentFunction(_ s: MySize) -> Int {
+
+ // The body of an internal transparent function will not be inlined into
+ // other resilience domains, so we can access storage directly
+
+// CHECK: [[W_ADDR:%.*]] = struct_element_addr [[ARG]] : $*MySize, #MySize.w
+// CHECK-NEXT: [[RESULT:%.*]] = load [trivial] [[W_ADDR]] : $*Int
+// CHECK-NEXT: return [[RESULT]]
+ return s.w
+}
+
+// CHECK-LABEL: sil [serialized] [always_inline] @$S17struct_resilience26publicInlineAlwaysFunctionySiAA6MySizeVF : $@convention(thin) (@in_guaranteed MySize) -> Int
+@inline(__always) public func publicInlineAlwaysFunction(_ s: MySize) -> Int {
+
+ // Since the body of a public transparent function might be inlined into
+ // other resilience domains, we have to use accessors
+
+// CHECK: [[SELF:%.*]] = alloc_stack $MySize
+// CHECK-NEXT: copy_addr %0 to [initialization] [[SELF]]
+
+// CHECK: [[GETTER:%.*]] = function_ref @$S17struct_resilience6MySizeV1wSivg
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[GETTER]]([[SELF]])
+// CHECK-NEXT: destroy_addr [[SELF]]
+// CHECK-NEXT: dealloc_stack [[SELF]]
+// CHECK-NEXT: return [[RESULT]]
+ return s.w
+
+}
+
+// Make sure that @_versioned entities can be resilient
+
+@_versioned struct VersionedResilientStruct {
+ @_versioned let x: Int
+ @_versioned let y: Int
+
+ @_versioned init(x: Int, y: Int) {
+ self.x = x
+ self.y = y
+ }
+
+ // Non-inlineable initializer, assigns to self -- treated as a root initializer
+
+ // CHECK-LABEL: sil @$S17struct_resilience24VersionedResilientStructV5otherA2C_tcfC : $@convention(method) (@in VersionedResilientStruct, @thin VersionedResilientStruct.Type) -> @out VersionedResilientStruct
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var VersionedResilientStruct }
+ // CHECK-NEXT: [[SELF_UNINIT:%.*]] = mark_uninitialized [rootself] [[SELF_BOX]]
+ // CHECK: return
+ @_versioned init(other: VersionedResilientStruct) {
+ self = other
+ }
+
+ // Inlineable initializer, assigns to self -- treated as a delegating initializer
+
+ // CHECK-LABEL: sil [serialized] @$S17struct_resilience24VersionedResilientStructV6other2A2C_tcfC : $@convention(method) (@in VersionedResilientStruct, @thin VersionedResilientStruct.Type) -> @out VersionedResilientStruct
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var VersionedResilientStruct }
+ // CHECK-NEXT: [[SELF_UNINIT:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
+ // CHECK: return
+ @_versioned @_inlineable init(other2: VersionedResilientStruct) {
+ self = other2
+ }
+}
+
+// CHECK-LABEL: sil [transparent] [serialized] @$S17struct_resilience27useVersionedResilientStructyAA0deF0VADF : $@convention(thin) (@in_guaranteed VersionedResilientStruct) -> @out VersionedResilientStruct
+@_versioned
+@_transparent func useVersionedResilientStruct(_ s: VersionedResilientStruct)
+ -> VersionedResilientStruct {
+ // CHECK: function_ref @$S17struct_resilience24VersionedResilientStructV1ySivg
+ // CHECK: function_ref @$S17struct_resilience24VersionedResilientStructV1xSivg
+ // CHECK: function_ref @$S17struct_resilience24VersionedResilientStructV1x1yACSi_SitcfC
+
+ return VersionedResilientStruct(x: s.y, y: s.x)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil [serialized] @$S17struct_resilience19inlineableInoutTestyyAA6MySizeVzF : $@convention(thin) (@inout MySize) -> ()
+@_inlineable public func inlineableInoutTest(_ s: inout MySize) {
+ // Inlineable functions can be inlined in other resiliene domains.
+ //
+ // Make sure we use materializeForSet for an inout access of a resilient struct
+ // property inside an inlinable function.
+
+ // CHECK: function_ref @$S17struct_resilience6MySizeV1wSivm
+ inoutFunc(&s.w)
+
+ // CHECK: return
+}
+
+// Initializers for resilient structs
+extension Size {
+
+ // CHECK-LABEL: sil hidden @$S16resilient_struct4SizeV0B11_resilienceE5otherA2C_tcfC : $@convention(method) (@in Size, @thin Size.Type) -> @out Size
+ // CHECK: [[SELF_BOX:%.*]] = alloc_box ${ var Size }
+ // CHECK-NEXT: [[SELF_UNINIT:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]] : ${ var Size }
+ // CHECK: return
+ init(other: Size) {
+ self = other
+ }
+}
diff --git a/test/SILGen/plus_zero_subclass_existentials.swift b/test/SILGen/plus_zero_subclass_existentials.swift
new file mode 100644
index 0000000..0189ede
--- /dev/null
+++ b/test/SILGen/plus_zero_subclass_existentials.swift
@@ -0,0 +1,469 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -parse-as-library -primary-file %s -verify | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -parse-as-library -primary-file %s
+
+// Note: we pass -verify above to ensure there are no spurious
+// compiler warnings relating to casts.
+
+protocol Q {}
+
+class Base<T> : Q {
+ required init(classInit: ()) {}
+ func classSelfReturn() -> Self {
+ return self
+ }
+ static func classSelfReturn() -> Self {
+ return self.init(classInit: ())
+ }
+}
+
+protocol P {
+ init(protocolInit: ())
+ func protocolSelfReturn() -> Self
+ static func protocolSelfReturn() -> Self
+}
+
+class Derived : Base<Int>, P {
+ required init(protocolInit: ()) {
+ super.init(classInit: ())
+ }
+
+ required init(classInit: ()) {
+ super.init(classInit: ())
+ }
+
+ func protocolSelfReturn() -> Self {
+ return self
+ }
+ static func protocolSelfReturn() -> Self {
+ return self.init(classInit: ())
+ }
+}
+
+protocol R {}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials11conversions8baseAndP7derived0fE1R0dE5PType0F4Type0fE5RTypeyAA1P_AA4BaseCySiGXc_AA7DerivedCAA1R_ANXcAaI_ALXcXpANmAaO_ANXcXptF : $@convention(thin) (@guaranteed Base<Int> & P, @guaranteed Derived, @guaranteed Derived & R, @thick (Base<Int> & P).Type, @thick Derived.Type, @thick (Derived & R).Type) -> () {
+// CHECK: bb0([[ARG0:%.*]] : $Base<Int> & P,
+
+func conversions(
+ baseAndP: Base<Int> & P,
+ derived: Derived,
+ derivedAndR: Derived & R,
+
+ baseAndPType: (Base<Int> & P).Type,
+ derivedType: Derived.Type,
+ derivedAndRType: (Derived & R).Type) {
+
+ // Values
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base<Int> & P
+ // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]]
+ // CHECK: [[BASE:%.*]] = upcast [[REF]] : $@opened("{{.*}}") Base<Int> & P to $Base<Int>
+ // CHECK: destroy_value [[BASE]] : $Base<Int>
+ let _: Base<Int> = baseAndP
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base<Int> & P
+ // CHECK: [[RESULT:%.*]] = alloc_stack $P
+ // CHECK: [[RESULT_PAYLOAD:%.*]] = init_existential_addr [[RESULT]] : $*P, $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]]
+ // CHECK: store [[REF]] to [init] [[RESULT_PAYLOAD]]
+ // CHECK: destroy_addr [[RESULT]] : $*P
+ // CHECK: dealloc_stack [[RESULT]] : $*P
+ let _: P = baseAndP
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base<Int> & P
+ // CHECK: [[RESULT:%.*]] = alloc_stack $Q
+ // CHECK: [[RESULT_PAYLOAD:%.*]] = init_existential_addr [[RESULT]] : $*Q, $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]]
+ // CHECK: store [[REF]] to [init] [[RESULT_PAYLOAD]]
+ // CHECK: destroy_addr [[RESULT]] : $*Q
+ // CHECK: dealloc_stack [[RESULT]] : $*Q
+ let _: Q = baseAndP
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG2:%.*]] : $Derived & R
+ // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]]
+ // CHECK: [[RESULT:%.*]] = init_existential_ref [[REF]] : $@opened("{{.*}}") Derived & R : $@opened("{{.*}}") Derived & R, $Base<Int> & P
+ // CHECK: destroy_value [[RESULT]]
+ let _: Base<Int> & P = derivedAndR
+
+ // Metatypes
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
+ // CHECK: [[RESULT:%.*]] = upcast [[PAYLOAD]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type to $@thick Base<Int>.Type
+ let _: Base<Int>.Type = baseAndPType
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
+ // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type, $@thick P.Type
+ let _: P.Type = baseAndPType
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %3 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
+ // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type, $@thick Q.Type
+ let _: Q.Type = baseAndPType
+
+ // CHECK: [[RESULT:%.*]] = init_existential_metatype %4 : $@thick Derived.Type, $@thick (Base<Int> & P).Type
+ let _: (Base<Int> & P).Type = derivedType
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_metatype %5 : $@thick (Derived & R).Type to $@thick (@opened("{{.*}}") (Derived & R)).Type
+ // CHECK: [[RESULT:%.*]] = init_existential_metatype [[PAYLOAD]] : $@thick (@opened("{{.*}}") (Derived & R)).Type, $@thick (Base<Int> & P).Type
+ let _: (Base<Int> & P).Type = derivedAndRType
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials11methodCalls8baseAndP0eF5PTypeyAA1P_AA4BaseCySiGXc_AaE_AHXcXptF : $@convention(thin) (@guaranteed Base<Int> & P, @thick (Base<Int> & P).Type) -> () {
+
+func methodCalls(
+ baseAndP: Base<Int> & P,
+ baseAndPType: (Base<Int> & P).Type) {
+ // CHECK: bb0([[ARG0:%.*]] : $Base<Int> & P,
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base<Int> & P to $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[REF:%.*]] = copy_value [[PAYLOAD]] : $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[CLASS_REF:%.*]] = upcast [[REF]] : $@opened("{{.*}}") Base<Int> & P to $Base<Int>
+ // CHECK: [[METHOD:%.*]] = class_method [[CLASS_REF]] : $Base<Int>, #Base.classSelfReturn!1 : <T> (Base<T>) -> () -> @dynamic_self Base<T>, $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0>
+ // CHECK: [[RESULT_CLASS_REF:%.*]] = apply [[METHOD]]<Int>([[CLASS_REF]]) : $@convention(method) <τ_0_0> (@guaranteed Base<τ_0_0>) -> @owned Base<τ_0_0>
+ // CHECK: destroy_value [[CLASS_REF]] : $Base<Int>
+ // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_CLASS_REF]] : $Base<Int> to $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}") Base<Int> & P : $@opened("{{.*}}") Base<Int> & P, $Base<Int> & P
+ // CHECK: destroy_value [[RESULT]] : $Base<Int> & P
+ let _: Base<Int> & P = baseAndP.classSelfReturn()
+
+ // CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[ARG0]] : $Base<Int> & P to $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[RESULT_BOX:%.*]] = alloc_stack $@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[SELF_BOX:%.*]] = alloc_stack $@opened("{{.*}}") Base<Int> & P
+ // CHECK: store_borrow [[PAYLOAD]] to [[SELF_BOX]] : $*@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") Base<Int> & P, #P.protocolSelfReturn!1 : <Self where Self : P> (Self) -> () -> @dynamic_self Self, [[PAYLOAD]] : $@opened("{{.*}}") Base<Int> & P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: apply [[METHOD]]<@opened("{{.*}}") Base<Int> & P>([[RESULT_BOX]], [[SELF_BOX]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ // CHECK: dealloc_stack [[SELF_BOX]] : $*@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT_BOX]] : $*@opened("{{.*}}") Base<Int> & P
+ // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}") Base<Int> & P : $@opened("{{.*}}") Base<Int> & P, $Base<Int> & P
+ // CHECK: destroy_value [[RESULT]] : $Base<Int> & P
+ // CHECK: dealloc_stack [[RESULT_BOX]] : $*@opened("{{.*}}") Base<Int> & P
+ let _: Base<Int> & P = baseAndP.protocolSelfReturn()
+
+ // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
+ // CHECK: [[METATYPE_REF:%.*]] = upcast [[METATYPE]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type to $@thick Base<Int>.Type
+ // CHECK: [[METHOD:%.*]] = function_ref @$S21subclass_existentials4BaseC15classSelfReturnACyxGXDyFZ : $@convention(method) <τ_0_0> (@thick Base<τ_0_0>.Type) -> @owned Base<τ_0_0>
+ // CHECK: [[RESULT_REF2:%.*]] = apply [[METHOD]]<Int>([[METATYPE_REF]])
+ // CHECK: [[RESULT_REF:%.*]] = unchecked_ref_cast [[RESULT_REF2]] : $Base<Int> to $@opened("{{.*}}") (Base<Int> & P)
+ // CHECK: [[RESULT:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}") (Base<Int> & P) : $@opened("{{.*}}") (Base<Int> & P), $Base<Int> & P
+ // CHECK: destroy_value [[RESULT]]
+ let _: Base<Int> & P = baseAndPType.classSelfReturn()
+
+ // CHECK: [[METATYPE:%.*]] = open_existential_metatype %1 : $@thick (Base<Int> & P).Type to $@thick (@opened("{{.*}}") (Base<Int> & P)).Type
+ // CHECK: [[RESULT:%.*]] = alloc_stack $@opened("{{.*}}") (Base<Int> & P)
+ // CHECK: [[METHOD:%.*]] = witness_method $@opened("{{.*}}") (Base<Int> & P), #P.protocolSelfReturn!1 : <Self where Self : P> (Self.Type) -> () -> @dynamic_self Self, [[METATYPE]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK: apply [[METHOD]]<@opened("{{.*}}") (Base<Int> & P)>([[RESULT]], [[METATYPE]]) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK: [[RESULT_REF:%.*]] = load [take] [[RESULT]] : $*@opened("{{.*}}") (Base<Int> & P)
+ // CHECK: [[RESULT_VALUE:%.*]] = init_existential_ref [[RESULT_REF]] : $@opened("{{.*}}") (Base<Int> & P) : $@opened("{{.*}}") (Base<Int> & P), $Base<Int> & P
+ // CHECK: destroy_value [[RESULT_VALUE]]
+ // CHECK: dealloc_stack [[RESULT]]
+ let _: Base<Int> & P = baseAndPType.protocolSelfReturn()
+
+ // Partial applications
+ let _: () -> (Base<Int> & P) = baseAndP.classSelfReturn
+ let _: () -> (Base<Int> & P) = baseAndP.protocolSelfReturn
+
+ let _: () -> (Base<Int> & P) = baseAndPType.classSelfReturn
+ let _: () -> (Base<Int> & P) = baseAndPType.protocolSelfReturn
+
+ let _: () -> (Base<Int> & P) = baseAndPType.init(classInit:)
+ let _: () -> (Base<Int> & P) = baseAndPType.init(protocolInit:)
+
+ // CHECK: return
+ // CHECK-NEXT: }
+}
+
+protocol PropertyP {
+ var p: PropertyP & PropertyC { get set }
+
+ subscript(key: Int) -> Int { get set }
+}
+
+class PropertyC {
+ var c: PropertyP & PropertyC {
+ get {
+ return self as! PropertyP & PropertyC
+ }
+ set { }
+ }
+
+ subscript(key: (Int, Int)) -> Int {
+ get {
+ return 0
+ } set { }
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials16propertyAccessesyyAA9PropertyP_AA0E1CCXcF : $@convention(thin) (@guaranteed PropertyC & PropertyP) -> () {
+func propertyAccesses(_ x: PropertyP & PropertyC) {
+ var xx = x
+ xx.p.p = x
+ xx.c.c = x
+
+ propertyAccesses(xx.p)
+ propertyAccesses(xx.c)
+
+ _ = xx[1]
+ xx[1] = 1
+ xx[1] += 1
+
+ _ = xx[(1, 2)]
+ xx[(1, 2)] = 1
+ xx[(1, 2)] += 1
+}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials19functionConversions15returnsBaseAndP0efG5PType0E7Derived0eI4Type0eiG1R0eiG5RTypeyAA1P_AA0F0CySiGXcyc_AaI_ALXcXpycAA0I0CycANmycAA1R_ANXcycAaO_ANXcXpyctF : $@convention(thin) (@guaranteed @callee_guaranteed () -> @owned Base<Int> & P, @guaranteed @callee_guaranteed () -> @thick (Base<Int> & P).Type, @guaranteed @callee_guaranteed () -> @owned Derived, @guaranteed @callee_guaranteed () -> @thick Derived.Type, @guaranteed @callee_guaranteed () -> @owned Derived & R, @guaranteed @callee_guaranteed () -> @thick (Derived & R).Type) -> () {
+func functionConversions(
+ returnsBaseAndP: @escaping () -> (Base<Int> & P),
+ returnsBaseAndPType: @escaping () -> (Base<Int> & P).Type,
+ returnsDerived: @escaping () -> Derived,
+ returnsDerivedType: @escaping () -> Derived.Type,
+ returnsDerivedAndR: @escaping () -> Derived & R,
+ returnsDerivedAndRType: @escaping () -> (Derived & R).Type) {
+
+ let _: () -> Base<Int> = returnsBaseAndP
+ let _: () -> Base<Int>.Type = returnsBaseAndPType
+
+ let _: () -> P = returnsBaseAndP
+ let _: () -> P.Type = returnsBaseAndPType
+
+ let _: () -> (Base<Int> & P) = returnsDerived
+ let _: () -> (Base<Int> & P).Type = returnsDerivedType
+
+ let _: () -> Base<Int> = returnsDerivedAndR
+ let _: () -> Base<Int>.Type = returnsDerivedAndRType
+
+ let _: () -> (Base<Int> & P) = returnsDerivedAndR
+ let _: () -> (Base<Int> & P).Type = returnsDerivedAndRType
+
+ let _: () -> P = returnsDerivedAndR
+ let _: () -> P.Type = returnsDerivedAndRType
+
+ // CHECK: return %
+ // CHECK-NEXT: }
+}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials9downcasts8baseAndP7derived0dE5PType0F4TypeyAA1P_AA4BaseCySiGXc_AA7DerivedCAaG_AJXcXpALmtF : $@convention(thin) (@guaranteed Base<Int> & P, @guaranteed Derived, @thick (Base<Int> & P).Type, @thick Derived.Type) -> () {
+func downcasts(
+ baseAndP: Base<Int> & P,
+ derived: Derived,
+ baseAndPType: (Base<Int> & P).Type,
+ derivedType: Derived.Type) {
+ // CHECK: bb0([[ARG0:%.*]] : $Base<Int> & P, [[ARG1:%.*]] : $Derived, [[ARG2:%.*]] : $@thick (Base<Int> & P).Type, [[ARG3:%.*]] : $@thick Derived.Type):
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base<Int> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<Int> & P to $Derived
+ let _ = baseAndP as? Derived
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<Int> & P to $Derived
+ let _ = baseAndP as! Derived
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base<Int> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<Int> & P to $Derived & R
+ let _ = baseAndP as? (Derived & R)
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<Int> & P to $Derived & R
+ let _ = baseAndP as! (Derived & R)
+
+ // CHECK: checked_cast_br %3 : $@thick Derived.Type to $@thick (Derived & R).Type
+ let _ = derivedType as? (Derived & R).Type
+
+ // CHECK: unconditional_checked_cast %3 : $@thick Derived.Type to $@thick (Derived & R).Type
+ let _ = derivedType as! (Derived & R).Type
+
+ // CHECK: checked_cast_br %2 : $@thick (Base<Int> & P).Type to $@thick Derived.Type
+ let _ = baseAndPType as? Derived.Type
+
+ // CHECK: unconditional_checked_cast %2 : $@thick (Base<Int> & P).Type to $@thick Derived.Type
+ let _ = baseAndPType as! Derived.Type
+
+ // CHECK: checked_cast_br %2 : $@thick (Base<Int> & P).Type to $@thick (Derived & R).Type
+ let _ = baseAndPType as? (Derived & R).Type
+
+ // CHECK: unconditional_checked_cast %2 : $@thick (Base<Int> & P).Type to $@thick (Derived & R).Type
+ let _ = baseAndPType as! (Derived & R).Type
+
+ // CHECK: return
+ // CHECK-NEXT: }
+}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials16archetypeUpcasts9baseTAndP0E7IntAndP7derivedyq__q0_q1_tAA4BaseCyxGRb_AA1PR_AGySiGRb0_AaIR0_AA7DerivedCRb1_r2_lF : $@convention(thin) <T, BaseTAndP, BaseIntAndP, DerivedT where BaseTAndP : Base<T>, BaseTAndP : P, BaseIntAndP : Base<Int>, BaseIntAndP : P, DerivedT : Derived> (@guaranteed BaseTAndP, @guaranteed BaseIntAndP, @guaranteed DerivedT) -> () {
+func archetypeUpcasts<T,
+ BaseTAndP : Base<T> & P,
+ BaseIntAndP : Base<Int> & P,
+ DerivedT : Derived>(
+ baseTAndP: BaseTAndP,
+ baseIntAndP : BaseIntAndP,
+ derived : DerivedT) {
+ // CHECK: bb0([[ARG0:%.*]] : $BaseTAndP, [[ARG1:%.*]] : $BaseIntAndP, [[ARG2:%.*]] : $DerivedT)
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG0]] : $BaseTAndP
+ // CHECK-NEXT: init_existential_ref [[COPIED]] : $BaseTAndP : $BaseTAndP, $Base<T> & P
+ let _: Base<T> & P = baseTAndP
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG1]] : $BaseIntAndP
+ // CHECK-NEXT: init_existential_ref [[COPIED]] : $BaseIntAndP : $BaseIntAndP, $Base<Int> & P
+ let _: Base<Int> & P = baseIntAndP
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG2]] : $DerivedT
+ // CHECK-NEXT: init_existential_ref [[COPIED]] : $DerivedT : $DerivedT, $Base<Int> & P
+ let _: Base<Int> & P = derived
+
+ // CHECK: return
+ // CHECK-NEXT: }
+}
+
+// CHECK-LABEL: sil hidden @$S21subclass_existentials18archetypeDowncasts1s1t2pt5baseT0F3Int0f6TAndP_C00fg5AndP_C008derived_C00ji2R_C00fH10P_concrete0fgi2P_K0yx_q_q0_q1_q2_q3_q4_q5_AA1R_AA7DerivedCXcAA1P_AA4BaseCyq_GXcAaQ_ASySiGXctAaQR0_ATRb1_AURb2_ATRb3_AaQR3_AURb4_AaQR4_APRb5_r6_lF : $@convention(thin) <S, T, PT, BaseT, BaseInt, BaseTAndP, BaseIntAndP, DerivedT where PT : P, BaseT : Base<T>, BaseInt : Base<Int>, BaseTAndP : Base<T>, BaseTAndP : P, BaseIntAndP : Base<Int>, BaseIntAndP : P, DerivedT : Derived> (@in_guaranteed S, @in_guaranteed T, @in_guaranteed PT, @guaranteed BaseT, @guaranteed BaseInt, @guaranteed BaseTAndP, @guaranteed BaseIntAndP, @guaranteed DerivedT, @guaranteed Derived & R, @guaranteed Base<T> & P, @guaranteed Base<Int> & P) -> () {
+func archetypeDowncasts<S,
+ T,
+ PT : P,
+ BaseT : Base<T>,
+ BaseInt : Base<Int>,
+ BaseTAndP : Base<T> & P,
+ BaseIntAndP : Base<Int> & P,
+ DerivedT : Derived>(
+ s: S,
+ t: T,
+ pt: PT,
+ baseT : BaseT,
+ baseInt : BaseInt,
+
+ baseTAndP_archetype: BaseTAndP,
+ baseIntAndP_archetype : BaseIntAndP,
+ derived_archetype : DerivedT,
+ derivedAndR_archetype : Derived & R,
+
+ baseTAndP_concrete: Base<T> & P,
+ baseIntAndP_concrete: Base<Int> & P) {
+
+ // CHECK: ([[ARG0:%.*]] : $*S, [[ARG1:%.*]] : $*T, [[ARG2:%.*]] : $*PT, [[ARG3:%.*]] : $BaseT, [[ARG4:%.*]] : $BaseInt, [[ARG5:%.*]] : $BaseTAndP, [[ARG6:%.*]] : $BaseIntAndP, [[ARG7:%.*]] : $DerivedT, [[ARG8:%.*]] : $Derived & R, [[ARG9:%.*]] : $Base<T> & P, [[ARG10:%.*]] : $Base<Int> & P)
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $S
+ // CHECK-NEXT: copy_addr %0 to [initialization] [[COPY]] : $*S
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base<T> & P
+ // CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to Base<T> & P in [[RESULT]] : $*Base<T> & P
+ let _ = s as? (Base<T> & P)
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $S
+ // CHECK-NEXT: copy_addr [[ARG0]] to [initialization] [[COPY]] : $*S
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base<T> & P
+ // CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to Base<T> & P in [[RESULT]] : $*Base<T> & P
+ let _ = s as! (Base<T> & P)
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $S
+ // CHECK-NEXT: copy_addr [[ARG0]] to [initialization] [[COPY]] : $*S
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base<Int> & P
+ // CHECK-NEXT: checked_cast_addr_br take_always S in [[COPY]] : $*S to Base<Int> & P in [[RESULT]] : $*Base<Int> & P
+ let _ = s as? (Base<Int> & P)
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $S
+ // CHECK-NEXT: copy_addr [[ARG0]] to [initialization] [[COPY]] : $*S
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast_addr S in [[COPY]] : $*S to Base<Int> & P in [[RESULT]] : $*Base<Int> & P
+ let _ = s as! (Base<Int> & P)
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG5]] : $BaseTAndP
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $BaseTAndP to $Derived & R
+ let _ = baseTAndP_archetype as? (Derived & R)
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG5]] : $BaseTAndP
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseTAndP to $Derived & R
+ let _ = baseTAndP_archetype as! (Derived & R)
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $Base<T> & P
+ // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base<T> & P
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Optional<S>
+ // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[RESULT]] : $*Optional<S>, #Optional.some
+ // CHECK-NEXT: checked_cast_addr_br take_always Base<T> & P in [[COPY]] : $*Base<T> & P to S in [[PAYLOAD]] : $*S
+ let _ = baseTAndP_concrete as? S
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $Base<T> & P
+ // CHECK-NEXT: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base<T> & P
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $S
+ // CHECK-NEXT: unconditional_checked_cast_addr Base<T> & P in [[COPY]] : $*Base<T> & P to S in [[RESULT]] : $*S
+ let _ = baseTAndP_concrete as! S
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<T> & P to $BaseT
+ let _ = baseTAndP_concrete as? BaseT
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<T> & P to $BaseT
+ let _ = baseTAndP_concrete as! BaseT
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<T> & P to $BaseInt
+ let _ = baseTAndP_concrete as? BaseInt
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<T> & P to $BaseInt
+ let _ = baseTAndP_concrete as! BaseInt
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<T> & P to $BaseTAndP
+ let _ = baseTAndP_concrete as? BaseTAndP
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG9]] : $Base<T> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<T> & P to $BaseTAndP
+ let _ = baseTAndP_concrete as! BaseTAndP
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG6]] : $BaseIntAndP
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $BaseIntAndP to $Derived & R
+ let _ = baseIntAndP_archetype as? (Derived & R)
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG6]] : $BaseIntAndP
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $BaseIntAndP to $Derived & R
+ let _ = baseIntAndP_archetype as! (Derived & R)
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: [[COPY:%.*]] = alloc_stack $Base<Int> & P
+ // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base<Int> & P
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $Optional<S>
+ // CHECK-NEXT: [[PAYLOAD:%.*]] = init_enum_data_addr [[RESULT]] : $*Optional<S>, #Optional.some
+ // CHECK-NEXT: checked_cast_addr_br take_always Base<Int> & P in [[COPY]] : $*Base<Int> & P to S in [[PAYLOAD]] : $*S
+ let _ = baseIntAndP_concrete as? S
+
+ // CHECK: [[COPY:%.*]] = alloc_stack $Base<Int> & P
+ // CHECK-NEXT: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: store [[COPIED]] to [init] [[COPY]] : $*Base<Int> & P
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $S
+ // CHECK-NEXT: unconditional_checked_cast_addr Base<Int> & P in [[COPY]] : $*Base<Int> & P to S in [[RESULT]] : $*S
+ let _ = baseIntAndP_concrete as! S
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<Int> & P to $DerivedT
+ let _ = baseIntAndP_concrete as? DerivedT
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<Int> & P to $DerivedT
+ let _ = baseIntAndP_concrete as! DerivedT
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<Int> & P to $BaseT
+ let _ = baseIntAndP_concrete as? BaseT
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<Int> & P to $BaseT
+ let _ = baseIntAndP_concrete as! BaseT
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<Int> & P to $BaseInt
+ let _ = baseIntAndP_concrete as? BaseInt
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<Int> & P to $BaseInt
+ let _ = baseIntAndP_concrete as! BaseInt
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: checked_cast_br [[COPIED]] : $Base<Int> & P to $BaseTAndP
+ let _ = baseIntAndP_concrete as? BaseTAndP
+
+ // CHECK: [[COPIED:%.*]] = copy_value [[ARG10]] : $Base<Int> & P
+ // CHECK-NEXT: unconditional_checked_cast [[COPIED]] : $Base<Int> & P to $BaseTAndP
+ let _ = baseIntAndP_concrete as! BaseTAndP
+
+ // CHECK: return
+ // CHECK-NEXT: }
+}
diff --git a/test/SILGen/plus_zero_super.swift b/test/SILGen/plus_zero_super.swift
new file mode 100644
index 0000000..5184967
--- /dev/null
+++ b/test/SILGen/plus_zero_super.swift
@@ -0,0 +1,202 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -I %t -emit-module -emit-module-path=%t/resilient_struct.swiftmodule -module-name resilient_struct %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend -I %t -emit-module -emit-module-path=%t/resilient_class.swiftmodule -module-name resilient_class %S/../Inputs/resilient_class.swift
+// RUN: %target-swift-frontend -emit-silgen -parse-as-library -I %t %s | %FileCheck %s
+
+import resilient_class
+
+public class Parent {
+ public final var finalProperty: String {
+ return "Parent.finalProperty"
+ }
+
+ public var property: String {
+ return "Parent.property"
+ }
+
+ public final class var finalClassProperty: String {
+ return "Parent.finalProperty"
+ }
+
+ public class var classProperty: String {
+ return "Parent.property"
+ }
+
+ public func methodOnlyInParent() {}
+ public final func finalMethodOnlyInParent() {}
+ public func method() {}
+
+ public final class func finalClassMethodOnlyInParent() {}
+ public class func classMethod() {}
+}
+
+public class Child : Parent {
+ // CHECK-LABEL: sil @$S5super5ChildC8propertySSvg : $@convention(method) (@guaranteed Child) -> @owned String {
+ // CHECK: bb0([[SELF:%.*]] : $Child):
+ // CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $Child to $Parent
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @$S5super6ParentC8propertySSvg : $@convention(method) (@guaranteed Parent) -> @owned String
+ // CHECK: [[RESULT:%.*]] = apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]])
+ // CHECK: destroy_value [[CASTED_SELF_COPY]]
+ // CHECK: return [[RESULT]]
+ public override var property: String {
+ return super.property
+ }
+
+ // CHECK-LABEL: sil @$S5super5ChildC13otherPropertySSvg : $@convention(method) (@guaranteed Child) -> @owned String {
+ // CHECK: bb0([[SELF:%.*]] : $Child):
+ // CHECK: [[COPIED_SELF:%.*]] = copy_value [[SELF]]
+ // CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[COPIED_SELF]] : $Child to $Parent
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @$S5super6ParentC13finalPropertySSvg
+ // CHECK: [[RESULT:%.*]] = apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]])
+ // CHECK: destroy_value [[CASTED_SELF_COPY]]
+ // CHECK: return [[RESULT]]
+ public var otherProperty: String {
+ return super.finalProperty
+ }
+}
+
+public class Grandchild : Child {
+ // CHECK-LABEL: sil @$S5super10GrandchildC06onlyInB0yyF
+ public func onlyInGrandchild() {
+ // CHECK: function_ref @$S5super6ParentC012methodOnlyInB0yyF : $@convention(method) (@guaranteed Parent) -> ()
+ super.methodOnlyInParent()
+ // CHECK: function_ref @$S5super6ParentC017finalMethodOnlyInB0yyF
+ super.finalMethodOnlyInParent()
+ }
+
+ // CHECK-LABEL: sil @$S5super10GrandchildC6methodyyF
+ public override func method() {
+ // CHECK: function_ref @$S5super6ParentC6methodyyF : $@convention(method) (@guaranteed Parent) -> ()
+ super.method()
+ }
+}
+
+public class GreatGrandchild : Grandchild {
+ // CHECK-LABEL: sil @$S5super15GreatGrandchildC6methodyyF
+ public override func method() {
+ // CHECK: function_ref @$S5super10GrandchildC6methodyyF : $@convention(method) (@guaranteed Grandchild) -> ()
+ super.method()
+ }
+}
+
+public class ChildToResilientParent : ResilientOutsideParent {
+ // CHECK-LABEL: sil @$S5super22ChildToResilientParentC6methodyyF : $@convention(method) (@guaranteed ChildToResilientParent) -> ()
+ public override func method() {
+ // CHECK: bb0([[SELF:%.*]] : $ChildToResilientParent):
+ // CHECK: [[COPY_SELF:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_SELF:%.*]] = upcast [[COPY_SELF]]
+ // CHECK: [[BORROW_UPCAST_SELF:%.*]] = begin_borrow [[UPCAST_SELF]]
+ // CHECK: [[CAST_BORROW_BACK_TO_BASE:%.*]] = unchecked_ref_cast [[BORROW_UPCAST_SELF]]
+ // CHECK: [[FUNC:%.*]] = super_method [[CAST_BORROW_BACK_TO_BASE]] : $ChildToResilientParent, #ResilientOutsideParent.method!1 : (ResilientOutsideParent) -> () -> (), $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
+ // CHECK: end_borrow [[BORROW_UPCAST_SELF]] from [[UPCAST_SELF]]
+ // CHECK: apply [[FUNC]]([[UPCAST_SELF]])
+ super.method()
+ }
+ // CHECK: } // end sil function '$S5super22ChildToResilientParentC6methodyyF'
+
+ // CHECK-LABEL: sil @$S5super22ChildToResilientParentC11classMethodyyFZ : $@convention(method) (@thick ChildToResilientParent.Type) -> ()
+ public override class func classMethod() {
+ // CHECK: bb0([[METASELF:%.*]] : $@thick ChildToResilientParent.Type):
+ // CHECK: [[UPCAST_METASELF:%.*]] = upcast [[METASELF]]
+ // CHECK: [[FUNC:%.*]] = super_method [[SELF]] : $@thick ChildToResilientParent.Type, #ResilientOutsideParent.classMethod!1 : (ResilientOutsideParent.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
+ // CHECK: apply [[FUNC]]([[UPCAST_METASELF]])
+ super.classMethod()
+ }
+ // CHECK: } // end sil function '$S5super22ChildToResilientParentC11classMethodyyFZ'
+
+ // CHECK-LABEL: sil @$S5super22ChildToResilientParentC11returnsSelfACXDyFZ : $@convention(method) (@thick ChildToResilientParent.Type) -> @owned ChildToResilientParent
+ public class func returnsSelf() -> Self {
+ // CHECK: bb0([[METASELF:%.*]] : $@thick ChildToResilientParent.Type):
+ // CHECK: [[CAST_METASELF:%.*]] = unchecked_trivial_bit_cast [[METASELF]] : $@thick ChildToResilientParent.Type to $@thick @dynamic_self ChildToResilientParent.Type
+ // CHECK: [[UPCAST_CAST_METASELF:%.*]] = upcast [[CAST_METASELF]] : $@thick @dynamic_self ChildToResilientParent.Type to $@thick ResilientOutsideParent.Type
+ // CHECK: [[FUNC:%.*]] = super_method [[METASELF]] : $@thick ChildToResilientParent.Type, #ResilientOutsideParent.classMethod!1 : (ResilientOutsideParent.Type) -> () -> ()
+ // CHECK: apply [[FUNC]]([[UPCAST_CAST_METASELF]])
+ // CHECK: unreachable
+ super.classMethod()
+ }
+ // CHECK: } // end sil function '$S5super22ChildToResilientParentC11returnsSelfACXDyFZ'
+}
+
+public class ChildToFixedParent : OutsideParent {
+ // CHECK-LABEL: sil @$S5super18ChildToFixedParentC6methodyyF : $@convention(method) (@guaranteed ChildToFixedParent) -> ()
+ public override func method() {
+ // CHECK: bb0([[SELF:%.*]] : $ChildToFixedParent):
+ // CHECK: [[COPY_SELF:%.*]] = copy_value [[SELF]]
+ // CHECK: [[UPCAST_COPY_SELF:%.*]] = upcast [[COPY_SELF]]
+ // CHECK: [[BORROWED_UPCAST_COPY_SELF:%.*]] = begin_borrow [[UPCAST_COPY_SELF]]
+ // CHECK: [[DOWNCAST_BORROWED_UPCAST_COPY_SELF:%.*]] = unchecked_ref_cast [[BORROWED_UPCAST_COPY_SELF]] : $OutsideParent to $ChildToFixedParent
+ // CHECK: [[FUNC:%.*]] = super_method [[DOWNCAST_BORROWED_UPCAST_COPY_SELF]] : $ChildToFixedParent, #OutsideParent.method!1 : (OutsideParent) -> () -> (), $@convention(method) (@guaranteed OutsideParent) -> ()
+ // CHECK: end_borrow [[BORROWED_UPCAST_COPY_SELF]] from [[UPCAST_COPY_SELF]]
+ // CHECK: apply [[FUNC]]([[UPCAST_COPY_SELF]])
+ super.method()
+ }
+ // CHECK: } // end sil function '$S5super18ChildToFixedParentC6methodyyF'
+
+ // CHECK-LABEL: sil @$S5super18ChildToFixedParentC11classMethodyyFZ : $@convention(method) (@thick ChildToFixedParent.Type) -> ()
+ public override class func classMethod() {
+ // CHECK: bb0([[SELF:%.*]] : $@thick ChildToFixedParent.Type):
+ // CHECK: [[UPCAST_SELF:%.*]] = upcast [[SELF]]
+ // CHECK: [[FUNC:%.*]] = super_method [[SELF]] : $@thick ChildToFixedParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> ()
+ // CHECK: apply [[FUNC]]([[UPCAST_SELF]])
+ super.classMethod()
+ }
+ // CHECK: } // end sil function '$S5super18ChildToFixedParentC11classMethodyyFZ'
+
+ // CHECK-LABEL: sil @$S5super18ChildToFixedParentC11returnsSelfACXDyFZ : $@convention(method) (@thick ChildToFixedParent.Type) -> @owned ChildToFixedParent
+ public class func returnsSelf() -> Self {
+ // CHECK: bb0([[SELF:%.*]] : $@thick ChildToFixedParent.Type):
+ // CHECK: [[FIRST_CAST:%.*]] = unchecked_trivial_bit_cast [[SELF]]
+ // CHECK: [[SECOND_CAST:%.*]] = upcast [[FIRST_CAST]]
+ // CHECK: [[FUNC:%.*]] = super_method [[SELF]] : $@thick ChildToFixedParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> ()
+ // CHECK: apply [[FUNC]]([[SECOND_CAST]])
+ // CHECK: unreachable
+ super.classMethod()
+ }
+ // CHECK: } // end sil function '$S5super18ChildToFixedParentC11returnsSelfACXDyFZ'
+}
+
+public extension ResilientOutsideChild {
+ public func callSuperMethod() {
+ super.method()
+ }
+
+ public class func callSuperClassMethod() {
+ super.classMethod()
+ }
+}
+
+public class GenericBase<T> {
+ public func method() {}
+}
+
+public class GenericDerived<T> : GenericBase<T> {
+ public override func method() {
+ // CHECK-LABEL: sil private @$S5super14GenericDerivedC6methodyyFyyXEfU_ : $@convention(thin) <T> (@guaranteed GenericDerived<T>) -> ()
+ // CHECK: upcast {{.*}} : $GenericDerived<T> to $GenericBase<T>
+ // CHECK: return
+ {
+ super.method()
+ }()
+ // CHECK: } // end sil function '$S5super14GenericDerivedC6methodyyFyyXEfU_'
+
+ // CHECK-LABEL: sil private @$S5super14GenericDerivedC6methodyyF13localFunctionL_yylF : $@convention(thin) <T> (@guaranteed GenericDerived<T>) -> ()
+ // CHECK: upcast {{.*}} : $GenericDerived<T> to $GenericBase<T>
+ // CHECK: return
+ // CHECK: } // end sil function '$S5super14GenericDerivedC6methodyyF13localFunctionL_yylF'
+ func localFunction() {
+ super.method()
+ }
+ localFunction()
+
+ // CHECK-LABEL: sil private @$S5super14GenericDerivedC6methodyyF15genericFunctionL_yyqd__r__lF : $@convention(thin) <T><U> (@in_guaranteed U, @guaranteed GenericDerived<T>) -> ()
+ // CHECK: upcast {{.*}} : $GenericDerived<T> to $GenericBase<T>
+ // CHECK: return
+ func genericFunction<U>(_: U) {
+ super.method()
+ }
+ // CHECK: } // end sil function '$S5super14GenericDerivedC6methodyyF15genericFunctionL_yyqd__r__lF'
+ genericFunction(0)
+ }
+}
diff --git a/test/SILGen/plus_zero_switch.swift b/test/SILGen/plus_zero_switch.swift
new file mode 100644
index 0000000..e81e078
--- /dev/null
+++ b/test/SILGen/plus_zero_switch.swift
@@ -0,0 +1,1125 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+func markUsed<T>(_ t: T) {}
+
+// TODO: Implement tuple equality in the library.
+// BLOCKED: <rdar://problem/13822406>
+func ~= (x: (Int, Int), y: (Int, Int)) -> Bool {
+ return x.0 == y.0 && x.1 == y.1
+}
+
+// Some fake predicates for pattern guards.
+func runced() -> Bool { return true }
+func funged() -> Bool { return true }
+func ansed() -> Bool { return true }
+
+func foo() -> Int { return 0 }
+func bar() -> Int { return 0 }
+func foobar() -> (Int, Int) { return (0, 0) }
+
+func a() {}
+func b() {}
+func c() {}
+func d() {}
+func e() {}
+func f() {}
+func g() {}
+
+// CHECK-LABEL: sil hidden @$S6switch5test1yyF
+func test1() {
+ switch foo() {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ case _:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1byyF
+ b()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test2yyF
+func test2() {
+ switch foo() {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ case _:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+ case _: // The second case is unreachable.
+ b()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ c()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test3yyF
+func test3() {
+ switch foo() {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch6runcedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
+
+ case _ where runced():
+ // CHECK: [[CASE1]]:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NO_CASE2]]:
+ // CHECK: br [[CASE2:bb[0-9]+]]
+ case _:
+ // CHECK: [[CASE2]]:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ c()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test4yyF
+func test4() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ case _:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1byyF
+ b()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test5yyF
+func test5() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: function_ref @$S6switch6runcedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NOT_CASE1:bb[0-9]+]]
+ case _ where runced():
+ // CHECK: [[CASE1]]:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NOT_CASE1]]:
+ // CHECK: function_ref @$S6switch6fungedSbyF
+ // CHECK: cond_br {{%.*}}, [[YES_CASE2:bb[0-9]+]], [[NOT_CASE2:bb[0-9]+]]
+ // CHECK: [[YES_CASE2]]:
+ case (_, _) where funged():
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[NOT_CASE2]]:
+ // CHECK: br [[CASE3:bb[0-9]+]]
+ case _:
+ // CHECK: [[CASE3]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1dyyF
+ d()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test6yyF
+func test6() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ case (_, _):
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+ case (_, _): // The second case is unreachable.
+ b()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ c()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test7yyF
+func test7() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: function_ref @$S6switch6runcedSbyF
+ // CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], [[NOT_CASE1:bb[0-9]+]]
+ // CHECK: [[YES_CASE1]]:
+ case (_, _) where runced():
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NOT_CASE1]]:
+ // CHECK: br [[CASE2:bb[0-9]+]]
+ case (_, _):
+ // CHECK: [[CASE2]]:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+ }
+ c()
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1cyyF
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test8yyF
+func test8() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: function_ref @$S6switch6foobarSi_SityF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NOT_CASE1:bb[0-9]+]]
+ case foobar():
+ // CHECK: [[CASE1]]:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NOT_CASE1]]:
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NOT_CASE2:bb[0-9]+]]
+ case (foo(), _):
+ // CHECK: [[CASE2]]:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+ // CHECK: [[NOT_CASE2]]:
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE3_GUARD:bb[0-9]+]], [[NOT_CASE3:bb[0-9]+]]
+ // CHECK: [[CASE3_GUARD]]:
+ // CHECK: function_ref @$S6switch6runcedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NOT_CASE3_GUARD:bb[0-9]+]]
+ case (_, bar()) where runced():
+ // CHECK: [[CASE3]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+ // CHECK: [[NOT_CASE3_GUARD]]:
+ // CHECK: [[NOT_CASE3]]:
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE4_GUARD_1:bb[0-9]+]], [[NOT_CASE4_1:bb[0-9]+]]
+ // CHECK: [[CASE4_GUARD_1]]:
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE4_GUARD_2:bb[0-9]+]], [[NOT_CASE4_2:bb[0-9]+]]
+ // CHECK: [[CASE4_GUARD_2]]:
+ // CHECK: function_ref @$S6switch6fungedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE4:bb[0-9]+]], [[NOT_CASE4_3:bb[0-9]+]]
+ case (foo(), bar()) where funged():
+ // CHECK: [[CASE4]]:
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ // CHECK: [[NOT_CASE4_3]]:
+ // CHECK: [[NOT_CASE4_2]]:
+ // CHECK: [[NOT_CASE4_1]]:
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE5_GUARD_1:bb[0-9]+]], [[NOT_CASE5:bb[0-9]+]]
+ // CHECK: [[CASE5_GUARD_1]]:
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: cond_br {{%.*}}, [[YES_CASE5:bb[0-9]+]], [[NOT_CASE5:bb[0-9]+]]
+ // CHECK: [[YES_CASE5]]:
+ case (foo(), bar()):
+ // CHECK: function_ref @$S6switch1eyyF
+ // CHECK: br [[CONT]]
+ e()
+ // CHECK: [[NOT_CASE5]]:
+ // CHECK: br [[CASE6:bb[0-9]+]]
+ case _:
+ // CHECK: [[CASE6]]:
+ // CHECK: function_ref @$S6switch1fyyF
+ // CHECK: br [[CONT]]
+ f()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1gyyF
+ g()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch5test9yyF
+func test9() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], [[NOT_CASE1:bb[0-9]+]]
+ // CHECK: [[YES_CASE1]]:
+ case (foo(), _):
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NOT_CASE1]]:
+ // CHECK: function_ref @$S6switch6foobarSi_SityF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NOT_CASE2:bb[0-9]+]]
+ case foobar():
+ // CHECK: [[CASE2]]:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[NOT_CASE2]]:
+ // CHECK: br [[CASE3:bb[0-9]+]]
+ case _:
+ // CHECK: [[CASE3]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1dyyF
+ d()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch6test10yyF
+func test10() {
+ switch (foo(), bar()) {
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], [[NOT_CASE1:bb[0-9]+]]
+ // CHECK: [[YES_CASE1]]:
+ case (foo()...bar(), _):
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NOT_CASE1]]:
+ // CHECK: br [[CASE2:bb[0-9]+]]
+ case _:
+ // CHECK: [[CASE2]]:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ c()
+}
+
+protocol P { func p() }
+
+struct X : P { func p() {} }
+struct Y : P { func p() {} }
+struct Z : P { func p() {} }
+
+// CHECK-LABEL: sil hidden @$S6switch10test_isa_11pyAA1P_p_tF
+func test_isa_1(p: P) {
+ // CHECK: [[PTMPBUF:%[0-9]+]] = alloc_stack $P
+ // CHECK-NEXT: copy_addr %0 to [initialization] [[PTMPBUF]] : $*P
+ switch p {
+ // CHECK: [[TMPBUF:%[0-9]+]] = alloc_stack $X
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P:%.*]] : $*P to X in [[TMPBUF]] : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]]
+
+ case is X:
+ // CHECK: [[IS_X]]:
+ // CHECK-NEXT: load [trivial] [[TMPBUF]]
+ // CHECK-NEXT: dealloc_stack [[TMPBUF]]
+ // CHECK-NEXT: destroy_addr [[PTMPBUF]]
+ // CHECK-NEXT: dealloc_stack [[PTMPBUF]]
+ a()
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+
+ // CHECK: [[IS_NOT_X]]:
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]]
+
+// CHECK: [[IS_Y]]:
+ case is Y:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[Y_CONT:bb[0-9]+]]
+ b()
+
+ // CHECK: [[IS_NOT_Y]]:
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Z in {{%.*}} : $*Z, [[IS_Z:bb[0-9]+]], [[IS_NOT_Z:bb[0-9]+]]
+
+ // CHECK: [[IS_Z]]:
+ case is Z:
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[Z_CONT:bb[0-9]+]]
+ c()
+
+ // CHECK: [[IS_NOT_Z]]:
+ case _:
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1eyyF
+ e()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch10test_isa_21pyAA1P_p_tF
+func test_isa_2(p: P) {
+ switch (p, foo()) {
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P:%.*]] : $*P to X in {{%.*}} : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]]
+
+ // CHECK: [[IS_X]]:
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NOT_CASE1:bb[0-9]+]]
+ case (is X, foo()):
+ // CHECK: [[CASE1]]:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[IS_NOT_X]]:
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]]
+
+ // CHECK: [[IS_Y]]:
+ // CHECK: function_ref @$S6switch3fooSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NOT_CASE2:bb[0-9]+]]
+ case (is Y, foo()):
+ // CHECK: [[CASE2]]:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[NOT_CASE2]]:
+ // CHECK: [[IS_NOT_Y]]:
+
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P:%.*]] : $*P to X in {{%.*}} : $*X, [[CASE3:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]]
+
+ case (is X, _):
+ // CHECK: [[CASE3]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // -- case (is Y, foo()):
+ // CHECK: [[IS_NOT_X]]:
+ // CHECK: checked_cast_addr_br copy_on_success P in [[P]] : $*P to Y in {{%.*}} : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]]
+ // CHECK: [[IS_Y]]:
+ // CHECK: function_ref @$S6switch3barSiyF
+ // CHECK: cond_br {{%.*}}, [[CASE4:bb[0-9]+]], [[NOT_CASE4:bb[0-9]+]]
+ case (is Y, bar()):
+ // CHECK: [[CASE4]]:
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+
+ // CHECK: [[NOT_CASE4]]:
+ // CHECK: br [[CASE5:bb[0-9]+]]
+ // CHECK: [[IS_NOT_Y]]:
+ // CHECK: br [[CASE5]]
+ case _:
+ // CHECK: [[CASE5]]:
+ // CHECK: function_ref @$S6switch1eyyF
+ // CHECK: br [[CONT]]
+ e()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1fyyF
+ f()
+}
+
+class B {}
+class C : B {}
+class D1 : C {}
+class D2 : D1 {}
+class E : C {}
+
+// CHECK-LABEL: sil hidden @$S6switch16test_isa_class_11xyAA1BC_tF : $@convention(thin) (@guaranteed B) -> () {
+func test_isa_class_1(x: B) {
+ // CHECK: bb0([[X:%.*]] : $B):
+ // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
+ switch x {
+
+ // CHECK: [[IS_D1]]([[CAST_D1:%.*]]):
+ // CHECK: [[CAST_D1_COPY:%.*]] = copy_value [[CAST_D1]]
+ // CHECK: function_ref @$S6switch6runcedSbyF : $@convention(thin) () -> Bool
+ // CHECK: cond_br {{%.*}}, [[YES_CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+
+ // CHECK: [[YES_CASE1]]:
+ case is D1 where runced():
+ // CHECK: destroy_value [[CAST_D1_COPY]]
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: destroy_value [[CAST_D1_COPY]]
+ // CHECK: br [[NEXT_CASE:bb5]]
+
+ // CHECK: [[IS_NOT_D1]]:
+ // CHECK: br [[NEXT_CASE]]
+
+ // CHECK: [[NEXT_CASE]]
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $D2, [[IS_D2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
+ case is D2:
+ // CHECK: [[IS_D2]]([[CAST_D2:%.*]]):
+ // CHECK: [[CAST_D2_COPY:%.*]] = copy_value [[CAST_D2]]
+ // CHECK: destroy_value [[CAST_D2_COPY]]
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[IS_NOT_D2]]:
+ // CHECK: br [[NEXT_CASE:bb8]]
+
+ // CHECK: [[NEXT_CASE]]:
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
+ case is E where funged():
+ // CHECK: [[IS_E]]([[CAST_E:%.*]]):
+ // CHECK: [[CAST_E_COPY:%.*]] = copy_value [[CAST_E]]
+ // CHECK: function_ref @$S6switch6fungedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
+
+ // CHECK: [[CASE3]]:
+ // CHECK: destroy_value [[CAST_E_COPY]]
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[NO_CASE3]]:
+ // CHECK: destroy_value [[CAST_E_COPY]]
+ // CHECK: br [[NEXT_CASE:bb13]]
+
+ // CHECK: [[IS_NOT_E]]:
+ // CHECK: br [[NEXT_CASE]]
+
+ // CHECK: [[NEXT_CASE]]
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $C, [[IS_C:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
+
+ case is C:
+ // CHECK: [[IS_C]]([[CAST_C:%.*]]):
+ // CHECK: [[CAST_C_COPY:%.*]] = copy_value [[CAST_C]]
+ // CHECK: destroy_value [[CAST_C_COPY]]
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+
+ // CHECK: [[IS_NOT_C]]:
+ // CHECK: br [[NEXT_CASE:bb16]]
+
+ // CHECK: [[NEXT_CASE]]:
+ default:
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: function_ref @$S6switch1eyyF
+ // CHECK: br [[CONT]]
+ e()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: [[F_FUNC:%.*]] = function_ref @$S6switch1fyyF : $@convention(thin) () -> ()
+ // CHECK: apply [[F_FUNC]]()
+ f()
+}
+// CHECK: } // end sil function '$S6switch16test_isa_class_11xyAA1BC_tF'
+
+// CHECK-LABEL: sil hidden @$S6switch16test_isa_class_21xyXlAA1BC_tF : $@convention(thin)
+func test_isa_class_2(x: B) -> AnyObject {
+ // CHECK: bb0([[X:%.*]] : $B):
+ // CHECK: [[X_COPY:%.*]] = copy_value [[X]]
+ switch x {
+
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $D1, [[IS_D1:bb[0-9]+]], [[IS_NOT_D1:bb[0-9]+]]
+ case let y as D1 where runced():
+ // CHECK: [[IS_D1]]([[CAST_D1:%.*]] : $D1):
+ // CHECK: [[CAST_D1_COPY:%.*]] = copy_value [[CAST_D1]]
+ // CHECK: function_ref @$S6switch6runcedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+
+ // CHECK: [[CASE1]]:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: [[BORROWED_CAST_D1_COPY:%.*]] = begin_borrow [[CAST_D1_COPY]]
+ // CHECK: [[CAST_D1_COPY_COPY:%.*]] = copy_value [[BORROWED_CAST_D1_COPY]]
+ // CHECK: [[RET:%.*]] = init_existential_ref [[CAST_D1_COPY_COPY]]
+ // CHECK: end_borrow [[BORROWED_CAST_D1_COPY]] from [[CAST_D1_COPY]]
+ // CHECK: destroy_value [[CAST_D1_COPY]]
+ // CHECK: destroy_value [[X_COPY]] : $B
+ // CHECK: br [[CONT:bb[0-9]+]]([[RET]] : $AnyObject)
+ a()
+ return y
+
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: destroy_value [[CAST_D1_COPY]]
+ // CHECK: br [[NEXT_CASE:bb5]]
+
+ // CHECK: [[IS_NOT_D1]]:
+ // CHECK: br [[NEXT_CASE]]
+
+ // CHECK: [[NEXT_CASE]]:
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $D2, [[CASE2:bb[0-9]+]], [[IS_NOT_D2:bb[0-9]+]]
+ case let y as D2:
+ // CHECK: [[CASE2]]([[CAST_D2:%.*]]):
+ // CHECK: [[CAST_D2_COPY:%.*]] = copy_value [[CAST_D2]]
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: [[BORROWED_CAST_D2_COPY:%.*]] = begin_borrow [[CAST_D2_COPY]]
+ // CHECK: [[CAST_D2_COPY_COPY:%.*]] = copy_value [[BORROWED_CAST_D2_COPY]]
+ // CHECK: [[RET:%.*]] = init_existential_ref [[CAST_D2_COPY_COPY]]
+ // CHECK: end_borrow [[BORROWED_CAST_D2_COPY]] from [[CAST_D2_COPY]]
+ // CHECK: destroy_value [[CAST_D2_COPY]]
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: br [[CONT]]([[RET]] : $AnyObject)
+ b()
+ return y
+
+ // CHECK: [[IS_NOT_D2]]:
+ // CHECK: br [[NEXT_CASE:bb8]]
+
+ // CHECK: [[NEXT_CASE]]:
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $E, [[IS_E:bb[0-9]+]], [[IS_NOT_E:bb[0-9]+]]
+ case let y as E where funged():
+ // CHECK: [[IS_E]]([[CAST_E:%.*]]):
+ // CHECK: [[CAST_E_COPY:%.*]] = copy_value [[CAST_E]]
+ // CHECK: function_ref @$S6switch6fungedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
+
+ // CHECK: [[CASE3]]:
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: [[BORROWED_CAST_E_COPY:%.*]] = begin_borrow [[CAST_E_COPY]]
+ // CHECK: [[CAST_E_COPY_COPY:%.*]] = copy_value [[BORROWED_CAST_E_COPY]]
+ // CHECK: [[RET:%.*]] = init_existential_ref [[CAST_E_COPY_COPY]]
+ // CHECK: end_borrow [[BORROWED_CAST_E_COPY]] from [[CAST_E_COPY]]
+ // CHECK: destroy_value [[CAST_E_COPY]]
+ // CHECK: destroy_value [[X_COPY]] : $B
+ // CHECK: br [[CONT]]([[RET]] : $AnyObject)
+ c()
+ return y
+
+ // CHECK: [[NO_CASE3]]:
+ // CHECK destroy_value [[CAST_E_COPY]]
+ // CHECK: br [[NEXT_CASE:bb13]]
+
+ // CHECK: [[IS_NOT_E]]:
+ // CHECK: br [[NEXT_CASE]]
+
+ // CHECK: [[NEXT_CASE]]
+ // CHECK: checked_cast_br [[X_COPY]] : $B to $C, [[CASE4:bb[0-9]+]], [[IS_NOT_C:bb[0-9]+]]
+ case let y as C:
+ // CHECK: [[CASE4]]([[CAST_C:%.*]]):
+ // CHECK: [[CAST_C_COPY:%.*]] = copy_value [[CAST_C]]
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: [[BORROWED_CAST_C_COPY:%.*]] = begin_borrow [[CAST_C_COPY]]
+ // CHECK: [[CAST_C_COPY_COPY:%.*]] = copy_value [[BORROWED_CAST_C_COPY]]
+ // CHECK: [[RET:%.*]] = init_existential_ref [[CAST_C_COPY_COPY]]
+ // CHECK: end_borrow [[BORROWED_CAST_C_COPY]] from [[CAST_C_COPY]]
+ // CHECK: destroy_value [[CAST_C_COPY]]
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: br [[CONT]]([[RET]] : $AnyObject)
+ d()
+ return y
+
+ // CHECK: [[IS_NOT_C]]:
+ // CHECK: br [[NEXT_CASE:bb16]]
+
+ // CHECK: [[NEXT_CASE]]:
+ default:
+ // CHECK: destroy_value [[X_COPY]]
+ // CHECK: function_ref @$S6switch1eyyF
+ // CHECK: [[X_COPY_2:%.*]] = copy_value [[X]]
+ // CHECK: [[RET:%.*]] = init_existential_ref [[X_COPY_2]]
+ // CHECK: br [[CONT]]([[RET]] : $AnyObject)
+ e()
+ return x
+ }
+
+ // CHECK: [[CONT]]([[T0:%.*]] : $AnyObject):
+ // CHECK: return [[T0]]
+}
+// CHECK: } // end sil function '$S6switch16test_isa_class_21xyXlAA1BC_tF'
+
+enum MaybePair {
+ case Neither
+ case Left(Int)
+ case Right(String)
+ case Both(Int, String)
+}
+
+// CHECK-LABEL: sil hidden @$S6switch12test_union_11uyAA9MaybePairO_tF
+func test_union_1(u: MaybePair) {
+ switch u {
+ // CHECK: switch_enum [[SUBJECT:%.*]] : $MaybePair,
+ // CHECK: case #MaybePair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
+ // CHECK: case #MaybePair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Both!enumelt.1: [[IS_BOTH:bb[0-9]+]]
+
+ // CHECK: [[IS_NEITHER]]:
+ // CHECK-NOT: destroy_value
+ case .Neither:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[IS_LEFT]]({{%.*}}):
+ // CHECK-NOT: destroy_value
+ case (.Left):
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[IS_RIGHT]]([[STR:%.*]] : $String):
+ case var .Right:
+ // CHECK: destroy_value [[STR]] : $String
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[IS_BOTH]]([[TUP:%.*]] : $(Int, String)):
+ case .Both:
+ // CHECK: tuple_extract [[TUP]] : $(Int, String), 0
+ // CHECK: [[TUP_STR:%.*]] = tuple_extract [[TUP]] : $(Int, String), 1
+ // CHECK: destroy_value [[TUP_STR]] : $String
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ }
+
+ // CHECK: [[CONT]]:
+ // CHECK-NOT: switch_enum [[SUBJECT]]
+ // CHECK: function_ref @$S6switch1eyyF
+ e()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch12test_union_31uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
+func test_union_3(u: MaybePair) {
+ // CHECK: bb0([[ARG:%.*]] : $MaybePair):
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: switch_enum [[SUBJECT]] : $MaybePair,
+ // CHECK: case #MaybePair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
+ // CHECK: case #MaybePair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
+ // CHECK: default [[DEFAULT:bb[0-9]+]]
+ switch u {
+ // CHECK: [[IS_NEITHER]]:
+ case .Neither:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[IS_LEFT]]({{%.*}}):
+ case .Left:
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[IS_RIGHT]]([[STR:%.*]] : $String):
+ case .Right:
+ // CHECK: destroy_value [[STR]] : $String
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[DEFAULT]]:
+ // -- Ensure the fully-opaque value is destroyed in the default case.
+ // CHECK: destroy_value [[ARG_COPY]] :
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+
+ default:
+ d()
+ }
+
+ // CHECK: [[CONT]]:
+ // CHECK-NOT: switch_enum [[ARG]]
+ // CHECK: function_ref @$S6switch1eyyF
+ e()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch12test_union_41uyAA9MaybePairO_tF
+func test_union_4(u: MaybePair) {
+ switch u {
+ // CHECK: switch_enum {{%.*}} : $MaybePair,
+ // CHECK: case #MaybePair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
+ // CHECK: case #MaybePair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Both!enumelt.1: [[IS_BOTH:bb[0-9]+]]
+
+ // CHECK: [[IS_NEITHER]]:
+ case .Neither(_):
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[IS_LEFT]]({{%.*}}):
+ case .Left(_):
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[IS_RIGHT]]({{%.*}}):
+ case .Right(_):
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[IS_BOTH]]({{%.*}}):
+ case .Both(_):
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ }
+
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1eyyF
+ e()
+}
+
+// CHECK-LABEL: sil hidden @$S6switch12test_union_51uyAA9MaybePairO_tF
+func test_union_5(u: MaybePair) {
+ switch u {
+ // CHECK: switch_enum {{%.*}} : $MaybePair,
+ // CHECK: case #MaybePair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
+ // CHECK: case #MaybePair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
+ // CHECK: case #MaybePair.Both!enumelt.1: [[IS_BOTH:bb[0-9]+]]
+
+ // CHECK: [[IS_NEITHER]]:
+ case .Neither():
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[IS_LEFT]]({{%.*}}):
+ case .Left(_):
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[IS_RIGHT]]({{%.*}}):
+ case .Right(_):
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[IS_BOTH]]({{%.*}}):
+ case .Both(_, _):
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ }
+
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1eyyF
+ e()
+}
+
+enum MaybeAddressOnlyPair {
+ case Neither
+ case Left(P)
+ case Right(String)
+ case Both(P, String)
+}
+
+// CHECK-LABEL: sil hidden @$S6switch22test_union_addr_only_11uyAA20MaybeAddressOnlyPairO_tF
+func test_union_addr_only_1(u: MaybeAddressOnlyPair) {
+ switch u {
+ // CHECK: switch_enum_addr [[ENUM_ADDR:%.*]] : $*MaybeAddressOnlyPair,
+ // CHECK: case #MaybeAddressOnlyPair.Neither!enumelt: [[IS_NEITHER:bb[0-9]+]],
+ // CHECK: case #MaybeAddressOnlyPair.Left!enumelt.1: [[IS_LEFT:bb[0-9]+]],
+ // CHECK: case #MaybeAddressOnlyPair.Right!enumelt.1: [[IS_RIGHT:bb[0-9]+]],
+ // CHECK: case #MaybeAddressOnlyPair.Both!enumelt.1: [[IS_BOTH:bb[0-9]+]]
+
+ // CHECK: [[IS_NEITHER]]:
+ case .Neither:
+ // CHECK: function_ref @$S6switch1ayyF
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+
+ // CHECK: [[IS_LEFT]]:
+ // CHECK: [[P:%.*]] = unchecked_take_enum_data_addr [[ENUM_ADDR]] : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Left!enumelt.1
+ case .Left(_):
+ // CHECK: destroy_addr [[P]]
+ // CHECK: function_ref @$S6switch1byyF
+ // CHECK: br [[CONT]]
+ b()
+
+ // CHECK: [[IS_RIGHT]]:
+ // CHECK: [[STR_ADDR:%.*]] = unchecked_take_enum_data_addr [[ENUM_ADDR]] : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Right!enumelt.1
+ // CHECK: [[STR:%.*]] = load [take] [[STR_ADDR]]
+ case .Right(_):
+ // CHECK: destroy_value [[STR]] : $String
+ // CHECK: function_ref @$S6switch1cyyF
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[IS_BOTH]]:
+ // CHECK: [[P_STR_TUPLE:%.*]] = unchecked_take_enum_data_addr [[ENUM_ADDR]] : $*MaybeAddressOnlyPair, #MaybeAddressOnlyPair.Both!enumelt.1
+ case .Both(_):
+ // CHECK: destroy_addr [[P_STR_TUPLE]]
+ // CHECK: function_ref @$S6switch1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S6switch1eyyF
+ e()
+}
+
+enum Generic<T, U> {
+ case Foo(T)
+ case Bar(U)
+}
+
+// Check that switching over a generic instance generates verified SIL.
+func test_union_generic_instance(u: Generic<Int, String>) {
+ switch u {
+ case .Foo(var x):
+ a()
+ case .Bar(var y):
+ b()
+ }
+ c()
+}
+
+enum Foo { case A, B }
+
+// CHECK-LABEL: sil hidden @$S6switch05test_A11_two_unions1x1yyAA3FooO_AFtF
+func test_switch_two_unions(x: Foo, y: Foo) {
+ // CHECK: [[T0:%.*]] = tuple (%0 : $Foo, %1 : $Foo)
+ // CHECK: [[X:%.*]] = tuple_extract [[T0]] : $(Foo, Foo), 0
+ // CHECK: [[Y:%.*]] = tuple_extract [[T0]] : $(Foo, Foo), 1
+
+ // CHECK: switch_enum [[Y]] : $Foo, case #Foo.A!enumelt: [[IS_CASE1:bb[0-9]+]], default [[IS_NOT_CASE1:bb[0-9]+]]
+
+ switch (x, y) {
+ // CHECK: [[IS_CASE1]]:
+ case (_, Foo.A):
+ // CHECK: function_ref @$S6switch1ayyF
+ a()
+
+ // CHECK: [[IS_NOT_CASE1]]:
+ // CHECK: switch_enum [[X]] : $Foo, case #Foo.B!enumelt: [[IS_CASE2:bb[0-9]+]], default [[IS_NOT_CASE2:bb[0-9]+]]
+ // CHECK: [[IS_CASE2]]:
+ case (Foo.B, _):
+ // CHECK: function_ref @$S6switch1byyF
+ b()
+
+ // CHECK: [[IS_NOT_CASE2]]:
+ // CHECK: switch_enum [[Y]] : $Foo, case #Foo.B!enumelt: [[IS_CASE3:bb[0-9]+]], default [[UNREACHABLE:bb[0-9]+]]
+ // CHECK: [[IS_CASE3]]:
+ case (_, Foo.B):
+ // CHECK: function_ref @$S6switch1cyyF
+ c()
+
+ // CHECK: [[UNREACHABLE]]:
+ // CHECK: unreachable
+ }
+}
+
+
+// <rdar://problem/14826416>
+func rdar14826416<T, U>(t: T, u: U) {
+ switch t {
+ case is Int: markUsed("Int")
+ case is U: markUsed("U")
+ case _: markUsed("other")
+ }
+}
+// CHECK-LABEL: sil hidden @$S6switch12rdar14826416{{[_0-9a-zA-Z]*}}F
+// CHECK: checked_cast_addr_br copy_on_success T in {{%.*}} : $*T to Int in {{%.*}} : $*Int, [[IS_INT:bb[0-9]+]], [[ISNT_INT:bb[0-9]+]]
+// CHECK: [[ISNT_INT]]:
+// CHECK: checked_cast_addr_br copy_on_success T in {{%.*}} : $*T to U in {{%.*}} : $*U, [[ISNT_INT_IS_U:bb[0-9]+]], [[ISNT_INT_ISNT_U:bb[0-9]+]]
+
+// <rdar://problem/14835992>
+class Rdar14835992 {}
+class SubRdar14835992 : Rdar14835992 {}
+
+// CHECK-LABEL: sil hidden @$S6switch12rdar14835992{{[_0-9a-zA-Z]*}}F
+func rdar14835992<T, U>(t: Rdar14835992, tt: T, uu: U) {
+ switch t {
+ case is SubRdar14835992: markUsed("Sub")
+ case is T: markUsed("T")
+ case is U: markUsed("U")
+ case _: markUsed("other")
+ }
+}
+
+
+
+
+// <rdar://problem/17272985>
+enum ABC { case A, B, C }
+
+// CHECK-LABEL: sil hidden @$S6switch18testTupleWildcardsyyAA3ABCO_ADtF
+// CHECK: [[X:%.*]] = tuple_extract {{%.*}} : $(ABC, ABC), 0
+// CHECK: [[Y:%.*]] = tuple_extract {{%.*}} : $(ABC, ABC), 1
+// CHECK: switch_enum [[X]] : $ABC, case #ABC.A!enumelt: [[X_A:bb[0-9]+]], default [[X_NOT_A:bb[0-9]+]]
+// CHECK: [[X_A]]:
+// CHECK: function_ref @$S6switch1ayyF
+// CHECK: [[X_NOT_A]]:
+// CHECK: switch_enum [[Y]] : $ABC, case #ABC.A!enumelt: [[Y_A:bb[0-9]+]], case #ABC.B!enumelt: [[Y_B:bb[0-9]+]], case #ABC.C!enumelt: [[Y_C:bb[0-9]+]]
+// CHECK-NOT: default
+// CHECK: [[Y_A]]:
+// CHECK: function_ref @$S6switch1byyF
+// CHECK: [[Y_B]]:
+// CHECK: function_ref @$S6switch1cyyF
+// CHECK: [[Y_C]]:
+// CHECK: switch_enum [[X]] : $ABC, case #ABC.C!enumelt: [[X_C:bb[0-9]+]], default [[X_NOT_C:bb[0-9]+]]
+// CHECK: [[X_C]]:
+// CHECK: function_ref @$S6switch1dyyF
+// CHECK: [[X_NOT_C]]:
+// CHECK: function_ref @$S6switch1eyyF
+func testTupleWildcards(_ x: ABC, _ y: ABC) {
+ switch (x, y) {
+ case (.A, _):
+ a()
+ case (_, .A):
+ b()
+ case (_, .B):
+ c()
+ case (.C, .C):
+ d()
+ default:
+ e()
+ }
+}
+
+enum LabeledScalarPayload {
+ case Payload(name: Int)
+}
+
+// CHECK-LABEL: sil hidden @$S6switch24testLabeledScalarPayloadyypAA0cdE0OF
+func testLabeledScalarPayload(_ lsp: LabeledScalarPayload) -> Any {
+ // CHECK: switch_enum {{%.*}}, case #LabeledScalarPayload.Payload!enumelt.1: bb1
+ switch lsp {
+ // CHECK: bb1([[TUPLE:%.*]] : $(name: Int)):
+ // CHECK: [[X:%.*]] = tuple_extract [[TUPLE]]
+ // CHECK: [[ANY_X_ADDR:%.*]] = init_existential_addr {{%.*}}, $Int
+ // CHECK: store [[X]] to [trivial] [[ANY_X_ADDR]]
+ case let .Payload(x):
+ return x
+ }
+}
+
+// There should be no unreachable generated.
+// CHECK-LABEL: sil hidden @$S6switch19testOptionalPatternyySiSgF
+func testOptionalPattern(_ value : Int?) {
+ // CHECK: switch_enum %0 : $Optional<Int>, case #Optional.some!enumelt.1: bb1, case #Optional.none!enumelt: [[NILBB:bb[0-9]+]]
+ switch value {
+ case 1?: a()
+ case 2?: b()
+ case nil: d()
+ default: e()
+ }
+}
+
+
+// x? and .none should both be considered "similar" and thus handled in the same
+// switch on the enum kind. There should be no unreachable generated.
+// CHECK-LABEL: sil hidden @$S6switch19testOptionalEnumMixyS2iSgF
+func testOptionalEnumMix(_ a : Int?) -> Int {
+ // CHECK: debug_value %0 : $Optional<Int>, let, name "a"
+ // CHECK-NEXT: switch_enum %0 : $Optional<Int>, case #Optional.some!enumelt.1: [[SOMEBB:bb[0-9]+]], case #Optional.none!enumelt: [[NILBB:bb[0-9]+]]
+ switch a {
+ case let x?:
+ return 0
+
+ // CHECK: [[SOMEBB]](%3 : $Int):
+ // CHECK-NEXT: debug_value %3 : $Int, let, name "x"
+ // CHECK: integer_literal $Builtin.Int2048, 0
+
+ case .none:
+ return 42
+
+ // CHECK: [[NILBB]]:
+ // CHECK: integer_literal $Builtin.Int2048, 42
+ }
+}
+
+// x? and nil should both be considered "similar" and thus handled in the same
+// switch on the enum kind. There should be no unreachable generated.
+// CHECK-LABEL: sil hidden @$S6switch26testOptionalEnumMixWithNilyS2iSgF
+func testOptionalEnumMixWithNil(_ a : Int?) -> Int {
+ // CHECK: debug_value %0 : $Optional<Int>, let, name "a"
+ // CHECK-NEXT: switch_enum %0 : $Optional<Int>, case #Optional.some!enumelt.1: [[SOMEBB:bb[0-9]+]], case #Optional.none!enumelt: [[NILBB:bb[0-9]+]]
+ switch a {
+ case let x?:
+ return 0
+
+ // CHECK: [[SOMEBB]](%3 : $Int):
+ // CHECK-NEXT: debug_value %3 : $Int, let, name "x"
+ // CHECK: integer_literal $Builtin.Int2048, 0
+
+ case nil:
+ return 42
+
+ // CHECK: [[NILBB]]:
+ // CHECK: integer_literal $Builtin.Int2048, 42
+ }
+}
+
+// SR-3518
+// CHECK-LABEL: sil hidden @$S6switch43testMultiPatternsWithOuterScopeSameNamedVar4base6filterySiSg_AEtF
+func testMultiPatternsWithOuterScopeSameNamedVar(base: Int?, filter: Int?) {
+ switch(base, filter) {
+
+ case (.some(let base), .some(let filter)):
+ // CHECK: bb2(%10 : $Int):
+ // CHECK-NEXT: debug_value %8 : $Int, let, name "base"
+ // CHECK-NEXT: debug_value %10 : $Int, let, name "filter"
+ print("both: \(base), \(filter)")
+ case (.some(let base), .none), (.none, .some(let base)):
+ // CHECK: bb3:
+ // CHECK-NEXT: debug_value %8 : $Int, let, name "base"
+ // CHECK-NEXT: br bb6(%8 : $Int)
+
+ // CHECK: bb5([[OTHER_BASE:%.*]] : $Int)
+ // CHECK-NEXT: debug_value [[OTHER_BASE]] : $Int, let, name "base"
+ // CHECK-NEXT: br bb6([[OTHER_BASE]] : $Int)
+
+ // CHECK: bb6([[ARG:%.*]] : $Int):
+ print("single: \(base)")
+ default:
+ print("default")
+ }
+}
+
+// All cases are unreachable, either structurally (tuples involving Never) or
+// nominally (empty enums). We fold all of these to 'unreachable'.
+enum MyNever {}
+func ~= (_ : MyNever, _ : MyNever) -> Bool { return true }
+func myFatalError() -> MyNever { fatalError("asdf") }
+
+func testUninhabitedSwitchScrutinee() {
+ func test1(x : MyNever) {
+ // CHECK: bb0(%0 : $MyNever):
+ // CHECK-NEXT: debug_value %0 : $MyNever, let, name "x"
+ // CHECK-NEXT: unreachable
+ switch x {
+ case myFatalError(): break
+ case myFatalError(): break
+ case myFatalError(): break
+ }
+ }
+ func test2(x : Never) {
+ // CHECK: bb0(%0 : $Never):
+ // CHECK-NEXT: debug_value %0 : $Never, let, name "x"
+ // CHECK-NEXT: unreachable
+ switch (x, x) {}
+ }
+ func test3(x : Never) {
+ // CHECK: unreachable
+ // CHECK-NEXT: } // end sil function '$S6switch30testUninhabitedSwitchScrutineeyyF5test3L_1xys5NeverO_tF'
+ switch (x, 5, x) {}
+ }
+ func test4(x : Never) {
+ // CHECK: unreachable
+ // CHECK-NEXT: } // end sil function '$S6switch30testUninhabitedSwitchScrutineeyyF5test4L_1xys5NeverO_tF'
+ switch ((8, 6, 7), (5, 3, (0, x))) {}
+ }
+ func test5() {
+ // CHECK: %0 = function_ref @$S6switch12myFatalErrorAA7MyNeverOyF : $@convention(thin) () -> MyNever
+ // CHECK-NEXT: %1 = apply %0() : $@convention(thin) () -> MyNever
+ // CHECK-NEXT: unreachable
+ switch myFatalError() {}
+ }
+}
diff --git a/test/SILGen/plus_zero_switch_abstraction.swift b/test/SILGen/plus_zero_switch_abstraction.swift
new file mode 100644
index 0000000..86ebbc9
--- /dev/null
+++ b/test/SILGen/plus_zero_switch_abstraction.swift
@@ -0,0 +1,46 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -parse-stdlib %s | %FileCheck %s
+
+struct A {}
+
+enum Optionable<T> {
+ case Summn(T)
+ case Nuttn
+}
+
+// CHECK-LABEL: sil hidden @$S18switch_abstraction18enum_reabstraction1x1ayAA10OptionableOyAA1AVAHcG_AHtF : $@convention(thin) (@guaranteed Optionable<(A) -> A>, A) -> ()
+// CHECK: switch_enum {{%.*}} : $Optionable<(A) -> A>, case #Optionable.Summn!enumelt.1: [[DEST:bb[0-9]+]]
+// CHECK: [[DEST]]([[ORIG:%.*]] : @owned $@callee_guaranteed (@in_guaranteed A) -> @out A):
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[SUBST:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]([[ORIG]])
+func enum_reabstraction(x x: Optionable<(A) -> A>, a: A) {
+ switch x {
+ case .Summn(var f):
+ f(a)
+ case .Nuttn:
+ ()
+ }
+}
+
+enum Wacky<A, B> {
+ case Foo(A)
+ case Bar((B) -> A)
+}
+
+// CHECK-LABEL: sil hidden @$S18switch_abstraction45enum_addr_only_to_loadable_with_reabstraction{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T> (@in_guaranteed Wacky<T, A>, A) -> @out T {
+// CHECK: switch_enum_addr [[ENUM:%.*]] : $*Wacky<T, A>, {{.*}} case #Wacky.Bar!enumelt.1: [[DEST:bb[0-9]+]]
+// CHECK: [[DEST]]:
+// CHECK: [[ORIG_ADDR:%.*]] = unchecked_take_enum_data_addr [[ENUM]] : $*Wacky<T, A>, #Wacky.Bar
+// CHECK: [[ORIG:%.*]] = load [take] [[ORIG_ADDR]]
+// CHECK: [[REABSTRACT:%.*]] = function_ref @$S{{.*}}TR :
+// CHECK: [[SUBST:%.*]] = partial_apply [callee_guaranteed] [[REABSTRACT]]<T>([[ORIG]])
+func enum_addr_only_to_loadable_with_reabstraction<T>(x x: Wacky<T, A>, a: A)
+ -> T
+{
+ switch x {
+ case .Foo(var b):
+ return b
+ case .Bar(var f):
+ return f(a)
+ }
+}
diff --git a/test/SILGen/plus_zero_switch_isa.swift b/test/SILGen/plus_zero_switch_isa.swift
new file mode 100644
index 0000000..7ad4e70
--- /dev/null
+++ b/test/SILGen/plus_zero_switch_isa.swift
@@ -0,0 +1,74 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+func markUsed<T>(_ t: T) {}
+
+// rdar://17772217
+func testSwitchOnExistential(_ value: Any) {
+ switch value {
+ case true as Bool: markUsed("true")
+ case false as Bool: markUsed("false")
+ default: markUsed("default")
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_isa23testSwitchOnExistentialyyypF :
+// CHECK: [[ANY:%.*]] = alloc_stack $Any
+// CHECK: copy_addr %0 to [initialization] [[ANY]]
+// CHECK: [[BOOL:%.*]] = alloc_stack $Bool
+// CHECK: checked_cast_addr_br copy_on_success Any in [[ANY]] : $*Any to Bool in [[BOOL]] : $*Bool, [[IS_BOOL:bb[0-9]+]], [[IS_NOT_BOOL:bb[0-9]+]]
+// CHECK: [[IS_BOOL]]:
+// CHECK: [[T0:%.*]] = load [trivial] [[BOOL]]
+
+enum Foo {
+ case A
+}
+enum Bar<T> {
+ case B(T)
+}
+func testSwitchEnumOnExistential(_ value: Any) {
+ switch value {
+ case Foo.A:
+ ()
+ case Bar<Int>.B(let i):
+ ()
+ case Bar<Foo>.B(let f):
+ ()
+ default:
+ ()
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_isa27testSwitchEnumOnExistentialyyypF : $@convention(thin) (@in_guaranteed Any) -> ()
+// CHECK: checked_cast_addr_br copy_on_success Any in {{%.*}} : $*Any to Foo
+// CHECK: checked_cast_addr_br copy_on_success Any in {{%.*}} : $*Any to Bar<Int>
+// CHECK: checked_cast_addr_br copy_on_success Any in {{%.*}} : $*Any to Bar<Foo>
+
+class B {}
+class D: B {}
+
+func guardFn(_ l: D, _ r: D) -> Bool { return true }
+
+// rdar://problem/21087371
+// CHECK-LABEL: sil hidden @$S10switch_isa32testSwitchTwoIsPatternsWithGuard_1ryAA1BC_AEtF
+// CHECK: checked_cast_br {{%.*}} : $B to $D, [[R_CAST_YES:bb[0-9]+]], [[R_CAST_NO:bb[0-9]+]]
+// CHECK: [[R_CAST_YES]]({{.*}}):
+// CHECK: checked_cast_br {{%.*}} : $B to $D, [[L_CAST_YES:bb[0-9]+]], [[L_CAST_NO:bb[0-9]+]]
+// CHECK: [[L_CAST_YES]]({{.*}}):
+// CHECK: function_ref @$S10switch_isa7guardFnySbAA1DC_ADtF
+// CHECK: cond_br {{%.*}}, [[GUARD_YES:bb[0-9]+]], [[GUARD_NO:bb[0-9]+]]
+// CHECK: [[GUARD_NO]]:
+// CHECK-NEXT: destroy_value [[R2:%.*]] : $D
+// CHECK-NEXT: destroy_value [[L2:%.*]] : $D
+// CHECK-NEXT: br [[CONT:bb[0-9]+]]
+// CHECK: [[L_CAST_NO]]:
+// CHECK-NEXT: destroy_value [[R2:%.*]] : $D
+// CHECK-NEXT: br [[CONT]]
+func testSwitchTwoIsPatternsWithGuard(_ l: B, r: B) {
+ switch (l, r) {
+ case (let l2 as D, let r2 as D) where guardFn(l2, r2):
+ break
+ default:
+ break
+ }
+}
diff --git a/test/SILGen/plus_zero_switch_multiple_entry_address_only.swift b/test/SILGen/plus_zero_switch_multiple_entry_address_only.swift
new file mode 100644
index 0000000..1e70918
--- /dev/null
+++ b/test/SILGen/plus_zero_switch_multiple_entry_address_only.swift
@@ -0,0 +1,190 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
+
+enum E {
+case a(Any)
+case b(Any)
+case c(Any)
+}
+
+// CHECK-LABEL: sil hidden @$S34switch_multiple_entry_address_only8takesAnyyyypF : $@convention(thin) (@in_guaranteed Any) -> ()
+func takesAny(_ x: Any) {}
+
+// CHECK-LABEL: sil hidden @$S34switch_multiple_entry_address_only0B9LabelsLet1eyAA1EO_tF : $@convention(thin) (@in_guaranteed E) -> ()
+func multipleLabelsLet(e: E) {
+ // CHECK: bb0
+ // CHECK: [[X_PHI:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: [[E_COPY:%.*]] = alloc_stack $E
+ // CHECK-NEXT: copy_addr %0 to [initialization] [[E_COPY]]
+ // CHECK-NEXT: switch_enum_addr [[E_COPY]] : $*E, case #E.a!enumelt.1: bb1, case #E.b!enumelt.1: bb2, default bb4
+
+ // CHECK: bb1:
+ // CHECK-NEXT: [[E_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[E_COPY]] : $*E, #E.a!enumelt.1
+ // CHECK-NEXT: [[ANY_BOX:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [take] [[E_PAYLOAD]] to [initialization] [[ANY_BOX]]
+ // CHECK-NEXT: copy_addr [[ANY_BOX]] to [initialization] [[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb2:
+ // CHECK-NEXT: [[E_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[E_COPY]] : $*E, #E.b!enumelt.1
+ // CHECK-NEXT: [[ANY_BOX:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [take] [[E_PAYLOAD]] to [initialization] [[ANY_BOX]]
+ // CHECK-NEXT: copy_addr [[ANY_BOX]] to [initialization] [[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb3:
+ // CHECK: [[FN:%.*]] = function_ref @$S34switch_multiple_entry_address_only8takesAnyyyypF
+ // CHECK-NEXT: apply [[FN]]([[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[X_PHI]]
+ // CHECK-NEXT: br bb6
+
+ // CHECK: bb4:
+ // CHECK-NEXT: br bb5
+
+ // CHECK: bb5:
+ // CHECK-NEXT: destroy_addr [[E_COPY]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb6
+
+ // CHECK: bb6:
+ // CHECK-NEXT: dealloc_stack [[X_PHI]]
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+
+ switch e {
+ case .a(let x), .b(let x):
+ takesAny(x)
+ default:
+ break
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S34switch_multiple_entry_address_only0B9LabelsVar1eyAA1EO_tF : $@convention(thin) (@in_guaranteed E) -> ()
+func multipleLabelsVar(e: E) {
+ // CHECK: bb0
+ // CHECK: [[X_PHI:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: [[E_COPY:%.*]] = alloc_stack $E
+ // CHECK-NEXT: copy_addr %0 to [initialization] [[E_COPY]]
+ // CHECK-NEXT: switch_enum_addr [[E_COPY]] : $*E, case #E.a!enumelt.1: bb1, case #E.b!enumelt.1: bb2, default bb4
+
+ // CHECK: bb1:
+ // CHECK-NEXT: [[E_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[E_COPY]] : $*E, #E.a!enumelt.1
+ // CHECK-NEXT: [[ANY_BOX:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [take] [[E_PAYLOAD]] to [initialization] [[ANY_BOX]]
+ // CHECK-NEXT: copy_addr [[ANY_BOX]] to [initialization] [[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb2:
+ // CHECK-NEXT: [[E_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[E_COPY]] : $*E, #E.b!enumelt.1
+ // CHECK-NEXT: [[ANY_BOX:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [take] [[E_PAYLOAD]] to [initialization] [[ANY_BOX]]
+ // CHECK-NEXT: copy_addr [[ANY_BOX]] to [initialization] [[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb3:
+ // CHECK-NEXT: [[ANY_BOX:%.*]] = alloc_box ${ var Any }, var, name "x"
+ // CHECK-NEXT: [[BOX_PAYLOAD:%.*]] = project_box [[ANY_BOX]] : ${ var Any }, 0
+ // CHECK-NEXT: copy_addr [take] [[X_PHI]] to [initialization] [[BOX_PAYLOAD]]
+ // CHECK-NEXT: [[ACCESS:%.*]] = begin_access [read] [unknown] [[BOX_PAYLOAD]]
+ // CHECK-NEXT: [[ANY_STACK:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [[ACCESS]] to [initialization] [[ANY_STACK]]
+ // CHECK-NEXT: end_access [[ACCESS]]
+ // CHECK: [[FN:%.*]] = function_ref @$S34switch_multiple_entry_address_only8takesAnyyyypF
+ // CHECK-NEXT: apply [[FN]]([[ANY_STACK]]
+ // CHECK-NEXT: destroy_addr [[ANY_STACK]]
+ // CHECK-NEXT: dealloc_stack [[ANY_STACK]]
+ // CHECK-NEXT: destroy_value [[ANY_BOX]]
+ // CHECK-NEXT: br bb6
+
+ // CHECK: bb4:
+ // CHECK-NEXT: br bb5
+
+ // CHECK: bb5:
+ // CHECK-NEXT: destroy_addr [[E_COPY]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb6
+
+ // CHECK: bb6:
+ // CHECK-NEXT: dealloc_stack [[X_PHI]]
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+
+ switch e {
+ case .a(var x), .b(var x):
+ takesAny(x)
+ default:
+ break
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S34switch_multiple_entry_address_only20fallthroughWithValue1eyAA1EO_tF : $@convention(thin) (@in_guaranteed E) -> ()
+func fallthroughWithValue(e: E) {
+ // CHECK: bb0
+ // CHECK: [[X_PHI:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: [[E_COPY:%.*]] = alloc_stack $E
+ // CHECK-NEXT: copy_addr %0 to [initialization] [[E_COPY]]
+ // CHECK-NEXT: switch_enum_addr [[E_COPY]] : $*E, case #E.a!enumelt.1: bb1, case #E.b!enumelt.1: bb2, default bb4
+
+ // CHECK: bb1:
+ // CHECK-NEXT: [[E_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[E_COPY]] : $*E, #E.a!enumelt.1
+ // CHECK-NEXT: [[ORIGINAL_ANY_BOX:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [take] [[E_PAYLOAD]] to [initialization] [[ORIGINAL_ANY_BOX]]
+ // CHECK: [[FN1:%.*]] = function_ref @$S34switch_multiple_entry_address_only8takesAnyyyypF
+ // CHECK-NEXT: apply [[FN1]]([[ORIGINAL_ANY_BOX]]
+ // CHECK-NEXT: copy_addr [[ORIGINAL_ANY_BOX]] to [initialization] [[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[ORIGINAL_ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[ORIGINAL_ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb2:
+ // CHECK-NEXT: [[E_PAYLOAD:%.*]] = unchecked_take_enum_data_addr [[E_COPY]] : $*E, #E.b!enumelt.1
+ // CHECK-NEXT: [[ANY_BOX:%.*]] = alloc_stack $Any
+ // CHECK-NEXT: copy_addr [take] [[E_PAYLOAD]] to [initialization] [[ANY_BOX]]
+ // CHECK-NEXT: copy_addr [[ANY_BOX]] to [initialization] [[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[ANY_BOX]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb3
+
+ // CHECK: bb3:
+ // CHECK: [[FN2:%.*]] = function_ref @$S34switch_multiple_entry_address_only8takesAnyyyypF
+ // CHECK-NEXT: apply [[FN2]]([[X_PHI]]
+ // CHECK-NEXT: destroy_addr [[X_PHI]]
+ // CHECK-NEXT: br bb6
+
+ // CHECK: bb4:
+ // CHECK-NEXT: br bb5
+
+ // CHECK: bb5:
+ // CHECK-NEXT: destroy_addr [[E_COPY]]
+ // CHECK-NEXT: dealloc_stack [[E_COPY]]
+ // CHECK-NEXT: br bb6
+
+ // CHECK: bb6:
+ // CHECK-NEXT: dealloc_stack [[X_PHI]]
+ // CHECK-NEXT: tuple ()
+ // CHECK-NEXT: return
+
+ switch e {
+ case .a(let x):
+ takesAny(x)
+ fallthrough
+ case .b(let x):
+ takesAny(x)
+ default:
+ break
+ }
+}
diff --git a/test/SILGen/plus_zero_switch_var.swift b/test/SILGen/plus_zero_switch_var.swift
new file mode 100644
index 0000000..becf093
--- /dev/null
+++ b/test/SILGen/plus_zero_switch_var.swift
@@ -0,0 +1,750 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
+
+// TODO: Implement tuple equality in the library.
+// BLOCKED: <rdar://problem/13822406>
+func ~= (x: (Int, Int), y: (Int, Int)) -> Bool {
+ return x.0 == y.0 && x.1 == y.1
+}
+
+// Some fake predicates for pattern guards.
+func runced() -> Bool { return true }
+func funged() -> Bool { return true }
+func ansed() -> Bool { return true }
+
+func runced(x x: Int) -> Bool { return true }
+func funged(x x: Int) -> Bool { return true }
+func ansed(x x: Int) -> Bool { return true }
+
+func foo() -> Int { return 0 }
+func bar() -> Int { return 0 }
+func foobar() -> (Int, Int) { return (0, 0) }
+
+func foos() -> String { return "" }
+func bars() -> String { return "" }
+
+func a() {}
+func b() {}
+func c() {}
+func d() {}
+func e() {}
+func f() {}
+func g() {}
+
+func a(x x: Int) {}
+func b(x x: Int) {}
+func c(x x: Int) {}
+func d(x x: Int) {}
+
+func a(x x: String) {}
+func b(x x: String) {}
+
+func aa(x x: (Int, Int)) {}
+func bb(x x: (Int, Int)) {}
+func cc(x x: (Int, Int)) {}
+
+// CHECK-LABEL: sil hidden @$S10switch_var05test_B2_1yyF
+func test_var_1() {
+ // CHECK: function_ref @$S10switch_var3fooSiyF
+ switch foo() {
+ // CHECK: [[XADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[X:%.*]] = project_box [[XADDR]]
+ // CHECK-NOT: br bb
+ case var x:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: destroy_value [[XADDR]]
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a(x: x)
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S10switch_var1byyF
+ b()
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_var05test_B2_2yyF
+func test_var_2() {
+ // CHECK: function_ref @$S10switch_var3fooSiyF
+ switch foo() {
+ // CHECK: [[XADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[X:%.*]] = project_box [[XADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var6runced1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+ // -- TODO: Clean up these empty waypoint bbs.
+ case var x where runced(x: x):
+ // CHECK: [[CASE1]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: destroy_value [[XADDR]]
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a(x: x)
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: [[YADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[Y:%.*]] = project_box [[YADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var6funged1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
+ case var y where funged(x: y):
+ // CHECK: [[CASE2]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1b1xySi_tF
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: br [[CONT]]
+ b(x: y)
+ // CHECK: [[NO_CASE2]]:
+ // CHECK: br [[CASE3:bb[0-9]+]]
+ case var z:
+ // CHECK: [[CASE3]]:
+ // CHECK: [[ZADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[Z:%.*]] = project_box [[ZADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1c1xySi_tF
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK: br [[CONT]]
+ c(x: z)
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S10switch_var1dyyF
+ d()
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_var05test_B2_3yyF
+func test_var_3() {
+ // CHECK: function_ref @$S10switch_var3fooSiyF
+ // CHECK: function_ref @$S10switch_var3barSiyF
+ switch (foo(), bar()) {
+ // CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[X:%.*]] = project_box [[XADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
+ // CHECK: tuple_element_addr [[READ]] : {{.*}}, 0
+ // CHECK: function_ref @$S10switch_var6runced1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+ case var x where runced(x: x.0):
+ // CHECK: [[CASE1]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var2aa1xySi_Sit_tF
+ // CHECK: destroy_value [[XADDR]]
+ // CHECK: br [[CONT:bb[0-9]+]]
+ aa(x: x)
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: br [[NO_CASE1_TARGET:bb[0-9]+]]
+
+ // CHECK: [[NO_CASE1_TARGET]]:
+ // CHECK: [[YADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[Y:%.*]] = project_box [[YADDR]]
+ // CHECK: [[ZADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[Z:%.*]] = project_box [[ZADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var6funged1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
+ case (var y, var z) where funged(x: y):
+ // CHECK: [[CASE2]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1b1xySi_tF
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: br [[CONT]]
+ a(x: y)
+ b(x: z)
+ // CHECK: [[NO_CASE2]]:
+ // CHECK: [[WADDR:%.*]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[W:%.*]] = project_box [[WADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]]
+ // CHECK: tuple_element_addr [[READ]] : {{.*}}, 0
+ // CHECK: function_ref @$S10switch_var5ansed1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
+ case var w where ansed(x: w.0):
+ // CHECK: [[CASE3]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var2bb1xySi_Sit_tF
+ // CHECK: br [[CONT]]
+ bb(x: w)
+ // CHECK: [[NO_CASE3]]:
+ // CHECK: destroy_value [[WADDR]]
+ // CHECK: br [[CASE4:bb[0-9]+]]
+ case var v:
+ // CHECK: [[CASE4]]:
+ // CHECK: [[VADDR:%.*]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[V:%.*]] = project_box [[VADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[V]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var2cc1xySi_Sit_tF
+ // CHECK: destroy_value [[VADDR]]
+ // CHECK: br [[CONT]]
+ cc(x: v)
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: function_ref @$S10switch_var1dyyF
+ d()
+}
+
+protocol P { func p() }
+
+struct X : P { func p() {} }
+struct Y : P { func p() {} }
+struct Z : P { func p() {} }
+
+// CHECK-LABEL: sil hidden @$S10switch_var05test_B2_41pyAA1P_p_tF
+func test_var_4(p p: P) {
+ // CHECK: function_ref @$S10switch_var3fooSiyF
+ switch (p, foo()) {
+ // CHECK: [[PAIR:%.*]] = alloc_stack $(P, Int)
+ // CHECK: store
+ // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 0
+ // CHECK: [[T0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 1
+ // CHECK: [[PAIR_1:%.*]] = load [trivial] [[T0]] : $*Int
+ // CHECK: [[TMP:%.*]] = alloc_stack $X
+ // CHECK: checked_cast_addr_br copy_on_success P in [[PAIR_0]] : $*P to X in [[TMP]] : $*X, [[IS_X:bb[0-9]+]], [[IS_NOT_X:bb[0-9]+]]
+
+ // CHECK: [[IS_X]]:
+ // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*X
+ // CHECK: [[XADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[X:%.*]] = project_box [[XADDR]]
+ // CHECK: store [[PAIR_1]] to [trivial] [[X]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var6runced1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+ case (is X, var x) where runced(x: x):
+ // CHECK: [[CASE1]]:
+ // CHECK: function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: destroy_value [[XADDR]]
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: destroy_addr [[PAIR_0]] : $*P
+ // CHECK: dealloc_stack [[PAIR]]
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a(x: x)
+
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: destroy_value [[XADDR]]
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: br [[NEXT:bb[0-9]+]]
+ // CHECK: [[IS_NOT_X]]:
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: br [[NEXT]]
+
+ // CHECK: [[NEXT]]:
+ // CHECK: [[TMP:%.*]] = alloc_stack $Y
+ // CHECK: checked_cast_addr_br copy_on_success P in [[PAIR_0]] : $*P to Y in [[TMP]] : $*Y, [[IS_Y:bb[0-9]+]], [[IS_NOT_Y:bb[0-9]+]]
+
+ // CHECK: [[IS_Y]]:
+ // CHECK: [[T0:%.*]] = load [trivial] [[TMP]] : $*Y
+ // CHECK: [[YADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[Y:%.*]] = project_box [[YADDR]]
+ // CHECK: store [[PAIR_1]] to [trivial] [[Y]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var6funged1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
+
+ case (is Y, var y) where funged(x: y):
+ // CHECK: [[CASE2]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1b1xySi_tF
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: destroy_addr [[PAIR_0]] : $*P
+ // CHECK: dealloc_stack [[PAIR]]
+ // CHECK: br [[CONT]]
+ b(x: y)
+
+ // CHECK: [[NO_CASE2]]:
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: br [[NEXT:bb[0-9]+]]
+ // CHECK: [[IS_NOT_Y]]:
+ // CHECK: dealloc_stack [[TMP]]
+ // CHECK: br [[NEXT]]
+
+ // CHECK: [[NEXT]]:
+ // CHECK: [[ZADDR:%.*]] = alloc_box ${ var (P, Int) }
+ // CHECK: [[Z:%.*]] = project_box [[ZADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
+ // CHECK: tuple_element_addr [[READ]] : {{.*}}, 1
+ // CHECK: function_ref @$S10switch_var5ansed1xSbSi_tF
+ // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[DFLT_NO_CASE3:bb[0-9]+]]
+ case var z where ansed(x: z.1):
+ // CHECK: [[CASE3]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
+ // CHECK: tuple_element_addr [[READ]] : {{.*}}, 1
+ // CHECK: function_ref @$S10switch_var1c1xySi_tF
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK-NEXT: dealloc_stack [[PAIR]]
+ // CHECK: br [[CONT]]
+ c(x: z.1)
+
+ // CHECK: [[DFLT_NO_CASE3]]:
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK: br [[CASE4:bb[0-9]+]]
+ case (_, var w):
+ // CHECK: [[CASE4]]:
+ // CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 0
+ // CHECK: [[WADDR:%.*]] = alloc_box ${ var Int }
+ // CHECK: [[W:%.*]] = project_box [[WADDR]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]]
+ // CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @$S10switch_var1d1xySi_tF
+ // CHECK: destroy_value [[WADDR]]
+ // CHECK: destroy_addr [[PAIR_0]] : $*P
+ // CHECK: dealloc_stack [[PAIR]]
+ // CHECK: br [[CONT]]
+ d(x: w)
+ }
+ e()
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_var05test_B2_5yyF : $@convention(thin) () -> () {
+func test_var_5() {
+ // CHECK: function_ref @$S10switch_var3fooSiyF
+ // CHECK: function_ref @$S10switch_var3barSiyF
+ switch (foo(), bar()) {
+ // CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[X:%.*]] = project_box [[XADDR]]
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+ case var x where runced(x: x.0):
+ // CHECK: [[CASE1]]:
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a()
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[Y:%[0-9]+]] = project_box [[YADDR]]
+ // CHECK: [[ZADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[Z:%[0-9]+]] = project_box [[ZADDR]]
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
+ case (var y, var z) where funged(x: y):
+ // CHECK: [[CASE2]]:
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: br [[CONT]]
+ b()
+ // CHECK: [[NO_CASE2]]:
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
+ case (_, _) where runced():
+ // CHECK: [[CASE3]]:
+ // CHECK: br [[CONT]]
+ c()
+ // CHECK: [[NO_CASE3]]:
+ // CHECK: br [[CASE4:bb[0-9]+]]
+ case _:
+ // CHECK: [[CASE4]]:
+ // CHECK: br [[CONT]]
+ d()
+ }
+ // CHECK: [[CONT]]:
+ e()
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_var05test_B7_returnyyF : $@convention(thin) () -> () {
+func test_var_return() {
+ switch (foo(), bar()) {
+ case var x where runced():
+ // CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[X:%[0-9]+]] = project_box [[XADDR]]
+ // CHECK: function_ref @$S10switch_var1ayyF
+ // CHECK: destroy_value [[XADDR]]
+ // CHECK: br [[EPILOG:bb[0-9]+]]
+ a()
+ return
+ // CHECK: [[YADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[Y:%[0-9]+]] = project_box [[YADDR]]
+ // CHECK: [[ZADDR:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[Z:%[0-9]+]] = project_box [[ZADDR]]
+ case (var y, var z) where funged():
+ // CHECK: function_ref @$S10switch_var1byyF
+ // CHECK: destroy_value [[ZADDR]]
+ // CHECK: destroy_value [[YADDR]]
+ // CHECK: br [[EPILOG]]
+ b()
+ return
+ case var w where ansed():
+ // CHECK: [[WADDR:%[0-9]+]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[W:%[0-9]+]] = project_box [[WADDR]]
+ // CHECK: function_ref @$S10switch_var1cyyF
+ // CHECK-NOT: destroy_value [[ZADDR]]
+ // CHECK-NOT: destroy_value [[YADDR]]
+ // CHECK: destroy_value [[WADDR]]
+ // CHECK: br [[EPILOG]]
+ c()
+ return
+ case var v:
+ // CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var (Int, Int) }
+ // CHECK: [[V:%[0-9]+]] = project_box [[VADDR]]
+ // CHECK: function_ref @$S10switch_var1dyyF
+ // CHECK-NOT: destroy_value [[ZADDR]]
+ // CHECK-NOT: destroy_value [[YADDR]]
+ // CHECK: destroy_value [[VADDR]]
+ // CHECK: br [[EPILOG]]
+ d()
+ return
+ }
+}
+
+// When all of the bindings in a column are immutable, don't emit a mutable
+// box. <rdar://problem/15873365>
+// CHECK-LABEL: sil hidden @$S10switch_var8test_letyyF : $@convention(thin) () -> () {
+func test_let() {
+ // CHECK: [[FOOS:%.*]] = function_ref @$S10switch_var4foosSSyF
+ // CHECK: [[VAL:%.*]] = apply [[FOOS]]()
+ // CHECK: [[VAL_COPY:%.*]] = copy_value [[VAL]]
+ // CHECK: function_ref @$S10switch_var6runcedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
+ switch foos() {
+ case let x where runced():
+ // CHECK: [[CASE1]]:
+ // CHECK: [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
+ // CHECK: [[A:%.*]] = function_ref @$S10switch_var1a1xySS_tF
+ // CHECK: apply [[A]]([[BORROWED_VAL_COPY]])
+ // CHECK: destroy_value [[VAL_COPY]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a(x: x)
+ // CHECK: [[NO_CASE1]]:
+ // CHECK: destroy_value [[VAL_COPY]]
+ // CHECK: br [[TRY_CASE2:bb[0-9]+]]
+ // CHECK: [[TRY_CASE2]]:
+ // CHECK: [[VAL_COPY_2:%.*]] = copy_value [[VAL]]
+ // CHECK: function_ref @$S10switch_var6fungedSbyF
+ // CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
+ case let y where funged():
+ // CHECK: [[CASE2]]:
+ // CHECK: [[BORROWED_VAL_COPY_2:%.*]] = begin_borrow [[VAL_COPY_2]]
+ // CHECK: [[B:%.*]] = function_ref @$S10switch_var1b1xySS_tF
+ // CHECK: apply [[B]]([[BORROWED_VAL_COPY_2]])
+ // CHECK: destroy_value [[VAL_COPY_2]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: br [[CONT]]
+ b(x: y)
+ // CHECK: [[NO_CASE2]]:
+ // CHECK: destroy_value [[VAL_COPY_2]]
+ // CHECK: br [[NEXT_CASE:bb6]]
+
+ // CHECK: [[NEXT_CASE]]:
+ // CHECK: [[VAL_COPY_3:%.*]] = copy_value [[VAL]]
+ // CHECK: function_ref @$S10switch_var4barsSSyF
+ // CHECK: [[BORROWED_VAL_COPY_3:%.*]] = begin_borrow [[VAL_COPY_3]]
+ // CHECK: store_borrow [[BORROWED_VAL_COPY_3]] to [[IN_ARG:%.*]] :
+ // CHECK: apply {{%.*}}<String>({{.*}}, [[IN_ARG]])
+ // CHECK: cond_br {{%.*}}, [[YES_CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
+ // ExprPatterns implicitly contain a 'let' binding.
+ case bars():
+ // CHECK: [[YES_CASE3]]:
+ // CHECK: destroy_value [[VAL_COPY_3]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: function_ref @$S10switch_var1cyyF
+ // CHECK: br [[CONT]]
+ c()
+ // CHECK: [[NO_CASE3]]:
+ // CHECK: destroy_value [[VAL_COPY_3]]
+ // CHECK: br [[NEXT_CASE:bb9+]]
+
+ // CHECK: [[NEXT_CASE]]:
+ case _:
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: function_ref @$S10switch_var1dyyF
+ // CHECK: br [[CONT]]
+ d()
+ }
+ // CHECK: [[CONT]]:
+ // CHECK: return
+}
+// CHECK: } // end sil function '$S10switch_var8test_letyyF'
+
+// If one of the bindings is a "var", allocate a box for the column.
+// CHECK-LABEL: sil hidden @$S10switch_var015test_mixed_let_B0yyF : $@convention(thin) () -> () {
+func test_mixed_let_var() {
+ // CHECK: bb0:
+ // CHECK: [[FOOS:%.*]] = function_ref @$S10switch_var4foosSSyF
+ // CHECK: [[VAL:%.*]] = apply [[FOOS]]()
+ switch foos() {
+
+ // First pattern.
+ // CHECK: [[BOX:%.*]] = alloc_box ${ var String }, var, name "x"
+ // CHECK: [[PBOX:%.*]] = project_box [[BOX]]
+ // CHECK: [[VAL_COPY:%.*]] = copy_value [[VAL]]
+ // CHECK: store [[VAL_COPY]] to [init] [[PBOX]]
+ // CHECK: cond_br {{.*}}, [[CASE1:bb[0-9]+]], [[NOCASE1:bb[0-9]+]]
+ case var x where runced():
+ // CHECK: [[CASE1]]:
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOX]]
+ // CHECK: [[X:%.*]] = load [copy] [[READ]]
+ // CHECK: [[A:%.*]] = function_ref @$S10switch_var1a1xySS_tF
+ // CHECK: apply [[A]]([[X]])
+ // CHECK: destroy_value [[BOX]]
+ // CHECK: br [[CONT:bb[0-9]+]]
+ a(x: x)
+
+ // CHECK: [[NOCASE1]]:
+ // CHECK: destroy_value [[BOX]]
+ // CHECK: br [[NEXT_PATTERN:bb[0-9]+]]
+
+ // CHECK: [[NEXT_PATTERN]]:
+ // CHECK: [[VAL_COPY:%.*]] = copy_value [[VAL]]
+ // CHECK: cond_br {{.*}}, [[CASE2:bb[0-9]+]], [[NOCASE2:bb[0-9]+]]
+ case let y where funged():
+
+ // CHECK: [[CASE2]]:
+ // CHECK: [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
+ // CHECK: [[B:%.*]] = function_ref @$S10switch_var1b1xySS_tF
+ // CHECK: apply [[B]]([[BORROWED_VAL_COPY]])
+ // CHECK: end_borrow [[BORROWED_VAL_COPY]] from [[VAL_COPY]]
+ // CHECK: destroy_value [[VAL_COPY]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: br [[CONT]]
+ b(x: y)
+
+ // CHECK: [[NOCASE2]]:
+ // CHECK: destroy_value [[VAL_COPY]]
+ // CHECK: br [[NEXT_CASE:bb[0-9]+]]
+
+ // CHECK: [[NEXT_CASE]]
+ // CHECK: [[VAL_COPY:%.*]] = copy_value [[VAL]]
+ // CHECK: [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
+ // CHECK: store_borrow [[BORROWED_VAL_COPY]] to [[TMP_VAL_COPY_ADDR:%.*]] :
+ // CHECK: apply {{.*}}<String>({{.*}}, [[TMP_VAL_COPY_ADDR]])
+ // CHECK: cond_br {{.*}}, [[CASE3:bb[0-9]+]], [[NOCASE3:bb[0-9]+]]
+ case bars():
+ // CHECK: [[CASE3]]:
+ // CHECK: destroy_value [[VAL_COPY]]
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: [[FUNC:%.*]] = function_ref @$S10switch_var1cyyF : $@convention(thin) () -> ()
+ // CHECK: apply [[FUNC]]()
+ // CHECK: br [[CONT]]
+ c()
+
+ // CHECK: [[NOCASE3]]:
+ // CHECK: destroy_value [[VAL_COPY]]
+ // CHECK: br [[NEXT_CASE:bb[0-9]+]]
+
+ // CHECK: [[NEXT_CASE]]:
+ // CHECK: destroy_value [[VAL]]
+ // CHECK: [[D_FUNC:%.*]] = function_ref @$S10switch_var1dyyF : $@convention(thin) () -> ()
+ // CHECK: apply [[D_FUNC]]()
+ // CHECK: br [[CONT]]
+ case _:
+ d()
+ }
+
+ // CHECK: [[CONT]]:
+ // CHECK: return
+}
+// CHECK: } // end sil function '$S10switch_var015test_mixed_let_B0yyF'
+
+// CHECK-LABEL: sil hidden @$S10switch_var23test_multiple_patterns1yyF : $@convention(thin) () -> () {
+func test_multiple_patterns1() {
+ // CHECK: function_ref @$S10switch_var6foobarSi_SityF
+ switch foobar() {
+ // CHECK-NOT: br bb
+ case (0, let x), (let x, 0):
+ // CHECK: cond_br {{%.*}}, [[FIRST_MATCH_CASE:bb[0-9]+]], [[FIRST_FAIL:bb[0-9]+]]
+ // CHECK: [[FIRST_MATCH_CASE]]:
+ // CHECK: debug_value [[FIRST_X:%.*]] :
+ // CHECK: br [[CASE_BODY:bb[0-9]+]]([[FIRST_X]] : $Int)
+ // CHECK: [[FIRST_FAIL]]:
+ // CHECK: cond_br {{%.*}}, [[SECOND_MATCH_CASE:bb[0-9]+]], [[SECOND_FAIL:bb[0-9]+]]
+ // CHECK: [[SECOND_MATCH_CASE]]:
+ // CHECK: debug_value [[SECOND_X:%.*]] :
+ // CHECK: br [[CASE_BODY]]([[SECOND_X]] : $Int)
+ // CHECK: [[CASE_BODY]]([[BODY_VAR:%.*]] : $Int):
+ // CHECK: [[A:%.*]] = function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: apply [[A]]([[BODY_VAR]])
+ a(x: x)
+ default:
+ // CHECK: [[SECOND_FAIL]]:
+ // CHECK: function_ref @$S10switch_var1byyF
+ b()
+ }
+}
+
+// FIXME(integers): the following checks should be updated for the new integer
+// protocols. <rdar://problem/29939484>
+// XCHECK-LABEL: sil hidden @$S10switch_var23test_multiple_patterns2yyF : $@convention(thin) () -> () {
+func test_multiple_patterns2() {
+ let t1 = 2
+ let t2 = 4
+ // XCHECK: debug_value [[T1:%.*]] :
+ // XCHECK: debug_value [[T2:%.*]] :
+ switch (0,0) {
+ // XCHECK-NOT: br bb
+ case (_, let x) where x > t1, (let x, _) where x > t2:
+ // XCHECK: [[FIRST_X:%.*]] = tuple_extract {{%.*}} : $(Int, Int), 1
+ // XCHECK: debug_value [[FIRST_X]] :
+ // XCHECK: apply {{%.*}}([[FIRST_X]], [[T1]])
+ // XCHECK: cond_br {{%.*}}, [[FIRST_MATCH_CASE:bb[0-9]+]], [[FIRST_FAIL:bb[0-9]+]]
+ // XCHECK: [[FIRST_MATCH_CASE]]:
+ // XCHECK: br [[CASE_BODY:bb[0-9]+]]([[FIRST_X]] : $Int)
+ // XCHECK: [[FIRST_FAIL]]:
+ // XCHECK: debug_value [[SECOND_X:%.*]] :
+ // XCHECK: apply {{%.*}}([[SECOND_X]], [[T2]])
+ // XCHECK: cond_br {{%.*}}, [[SECOND_MATCH_CASE:bb[0-9]+]], [[SECOND_FAIL:bb[0-9]+]]
+ // XCHECK: [[SECOND_MATCH_CASE]]:
+ // XCHECK: br [[CASE_BODY]]([[SECOND_X]] : $Int)
+ // XCHECK: [[CASE_BODY]]([[BODY_VAR:%.*]] : $Int):
+ // XCHECK: [[A:%.*]] = function_ref @$S10switch_var1aySi1x_tF
+ // XCHECK: apply [[A]]([[BODY_VAR]])
+ a(x: x)
+ default:
+ // XCHECK: [[SECOND_FAIL]]:
+ // XCHECK: function_ref @$S10switch_var1byyF
+ b()
+ }
+}
+
+enum Foo {
+ case A(Int, Double)
+ case B(Double, Int)
+ case C(Int, Int, Double)
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_var23test_multiple_patterns3yyF : $@convention(thin) () -> () {
+func test_multiple_patterns3() {
+ let f = Foo.C(0, 1, 2.0)
+ switch f {
+ // CHECK: switch_enum {{%.*}} : $Foo, case #Foo.A!enumelt.1: [[A:bb[0-9]+]], case #Foo.B!enumelt.1: [[B:bb[0-9]+]], case #Foo.C!enumelt.1: [[C:bb[0-9]+]]
+ case .A(let x, let n), .B(let n, let x), .C(_, let x, let n):
+ // CHECK: [[A]]({{%.*}} : $(Int, Double)):
+ // CHECK: [[A_X:%.*]] = tuple_extract
+ // CHECK: [[A_N:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY:bb[0-9]+]]([[A_X]] : $Int, [[A_N]] : $Double)
+
+ // CHECK: [[B]]({{%.*}} : $(Double, Int)):
+ // CHECK: [[B_N:%.*]] = tuple_extract
+ // CHECK: [[B_X:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY]]([[B_X]] : $Int, [[B_N]] : $Double)
+
+ // CHECK: [[C]]({{%.*}} : $(Int, Int, Double)):
+ // CHECK: [[C__:%.*]] = tuple_extract
+ // CHECK: [[C_X:%.*]] = tuple_extract
+ // CHECK: [[C_N:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY]]([[C_X]] : $Int, [[C_N]] : $Double)
+
+ // CHECK: [[CASE_BODY]]([[BODY_X:%.*]] : $Int, [[BODY_N:%.*]] : $Double):
+ // CHECK: [[FUNC_A:%.*]] = function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: apply [[FUNC_A]]([[BODY_X]])
+ a(x: x)
+ }
+}
+
+enum Bar {
+ case Y(Foo, Int)
+ case Z(Int, Foo)
+}
+
+// CHECK-LABEL: sil hidden @$S10switch_var23test_multiple_patterns4yyF : $@convention(thin) () -> () {
+func test_multiple_patterns4() {
+ let b = Bar.Y(.C(0, 1, 2.0), 3)
+ switch b {
+ // CHECK: switch_enum {{%.*}} : $Bar, case #Bar.Y!enumelt.1: [[Y:bb[0-9]+]], case #Bar.Z!enumelt.1: [[Z:bb[0-9]+]]
+ case .Y(.A(let x, _), _), .Y(.B(_, let x), _), .Y(.C, let x), .Z(let x, _):
+ // CHECK: [[Y]]({{%.*}} : $(Foo, Int)):
+ // CHECK: [[Y_F:%.*]] = tuple_extract
+ // CHECK: [[Y_X:%.*]] = tuple_extract
+ // CHECK: switch_enum [[Y_F]] : $Foo, case #Foo.A!enumelt.1: [[A:bb[0-9]+]], case #Foo.B!enumelt.1: [[B:bb[0-9]+]], case #Foo.C!enumelt.1: [[C:bb[0-9]+]]
+
+ // CHECK: [[A]]({{%.*}} : $(Int, Double)):
+ // CHECK: [[A_X:%.*]] = tuple_extract
+ // CHECK: [[A_N:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY:bb[0-9]+]]([[A_X]] : $Int)
+
+ // CHECK: [[B]]({{%.*}} : $(Double, Int)):
+ // CHECK: [[B_N:%.*]] = tuple_extract
+ // CHECK: [[B_X:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY]]([[B_X]] : $Int)
+
+ // CHECK: [[C]]({{%.*}} : $(Int, Int, Double)):
+ // CHECK: br [[CASE_BODY]]([[Y_X]] : $Int)
+
+ // CHECK: [[Z]]({{%.*}} : $(Int, Foo)):
+ // CHECK: [[Z_X:%.*]] = tuple_extract
+ // CHECK: [[Z_F:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY]]([[Z_X]] : $Int)
+
+ // CHECK: [[CASE_BODY]]([[BODY_X:%.*]] : $Int):
+ // CHECK: [[FUNC_A:%.*]] = function_ref @$S10switch_var1a1xySi_tF
+ // CHECK: apply [[FUNC_A]]([[BODY_X]])
+ a(x: x)
+ }
+}
+
+func aaa(x x: inout Int) {}
+
+// CHECK-LABEL: sil hidden @$S10switch_var23test_multiple_patterns5yyF : $@convention(thin) () -> () {
+func test_multiple_patterns5() {
+ let b = Bar.Y(.C(0, 1, 2.0), 3)
+ switch b {
+ // CHECK: switch_enum {{%.*}} : $Bar, case #Bar.Y!enumelt.1: [[Y:bb[0-9]+]], case #Bar.Z!enumelt.1: [[Z:bb[0-9]+]]
+ case .Y(.A(var x, _), _), .Y(.B(_, var x), _), .Y(.C, var x), .Z(var x, _):
+ // CHECK: [[Y]]({{%.*}} : $(Foo, Int)):
+ // CHECK: [[Y_F:%.*]] = tuple_extract
+ // CHECK: [[Y_X:%.*]] = tuple_extract
+ // CHECK: switch_enum [[Y_F]] : $Foo, case #Foo.A!enumelt.1: [[A:bb[0-9]+]], case #Foo.B!enumelt.1: [[B:bb[0-9]+]], case #Foo.C!enumelt.1: [[C:bb[0-9]+]]
+
+ // CHECK: [[A]]({{%.*}} : $(Int, Double)):
+ // CHECK: [[A_X:%.*]] = tuple_extract
+ // CHECK: [[A_N:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY:bb[0-9]+]]([[A_X]] : $Int)
+
+ // CHECK: [[B]]({{%.*}} : $(Double, Int)):
+ // CHECK: [[B_N:%.*]] = tuple_extract
+ // CHECK: [[B_X:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY]]([[B_X]] : $Int)
+
+ // CHECK: [[C]]({{%.*}} : $(Int, Int, Double)):
+ // CHECK: br [[CASE_BODY]]([[Y_X]] : $Int)
+
+ // CHECK: [[Z]]({{%.*}} : $(Int, Foo)):
+ // CHECK: [[Z_X:%.*]] = tuple_extract
+ // CHECK: [[Z_F:%.*]] = tuple_extract
+ // CHECK: br [[CASE_BODY]]([[Z_X]] : $Int)
+
+ // CHECK: [[CASE_BODY]]([[BODY_X:%.*]] : $Int):
+ // CHECK: store [[BODY_X]] to [trivial] [[BOX_X:%.*]] : $*Int
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[BOX_X]]
+ // CHECK: [[FUNC_AAA:%.*]] = function_ref @$S10switch_var3aaa1xySiz_tF
+ // CHECK: apply [[FUNC_AAA]]([[WRITE]])
+ aaa(x: &x)
+ }
+}
+
+// rdar://problem/29252758 -- local decls must not be reemitted.
+func test_against_reemission(x: Bar) {
+ switch x {
+ case .Y(let a, _), .Z(_, let a):
+ let b = a
+ }
+}
+
+class C {}
+class D: C {}
+func f(_: D) -> Bool { return true }
+
+// CHECK-LABEL: sil hidden @{{.*}}test_multiple_patterns_value_semantics
+func test_multiple_patterns_value_semantics(_ y: C) {
+ switch y {
+ // CHECK: checked_cast_br {{%.*}} : $C to $D, [[AS_D:bb[0-9]+]], [[NOT_AS_D:bb[0-9]+]]
+ // CHECK: [[AS_D]]({{.*}}):
+ // CHECK: cond_br {{%.*}}, [[F_TRUE:bb[0-9]+]], [[F_FALSE:bb[0-9]+]]
+ // CHECK: [[F_TRUE]]:
+ // CHECK: [[BINDING:%.*]] = copy_value [[ORIG:%.*]] :
+ // CHECK: destroy_value [[ORIG]]
+ // CHECK: br {{bb[0-9]+}}([[BINDING]]
+ case let x as D where f(x), let x as D: break
+ default: break
+ }
+}
diff --git a/test/SILGen/plus_zero_testable-multifile-other.swift b/test/SILGen/plus_zero_testable-multifile-other.swift
new file mode 100644
index 0000000..b517849
--- /dev/null
+++ b/test/SILGen/plus_zero_testable-multifile-other.swift
@@ -0,0 +1,45 @@
+// REQUIRES: plus_zero_runtime
+// This test is paired with testable-multifile.swift.
+
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module %S/Inputs/TestableMultifileHelper.swift -enable-testing -o %t
+
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %t %s %S/testable-multifile.swift -module-name main | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %t %S/testable-multifile.swift %s -module-name main | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %t -primary-file %s %S/testable-multifile.swift -module-name main | %FileCheck %s
+
+// Just make sure we don't crash later on.
+// RUN: %target-swift-frontend -emit-ir -enable-sil-ownership -I %t -primary-file %s %S/testable-multifile.swift -module-name main -o /dev/null
+// RUN: %target-swift-frontend -emit-ir -enable-sil-ownership -I %t -O -primary-file %s %S/testable-multifile.swift -module-name main -o /dev/null
+
+func use<F: Fooable>(_ f: F) { f.foo() }
+func test(internalFoo: FooImpl, publicFoo: PublicFooImpl) {
+ use(internalFoo)
+ use(publicFoo)
+
+ internalFoo.foo()
+ publicFoo.foo()
+}
+
+// CHECK-LABEL: sil hidden @$S4main4test11internalFoo06publicD0yAA0D4ImplV_AA06PublicdF0VtF
+// CHECK: [[USE_1:%.+]] = function_ref @$S4main3useyyxAA7FooableRzlF
+// CHECK: = apply [[USE_1]]<FooImpl>({{%.+}}) : $@convention(thin) <τ_0_0 where τ_0_0 : Fooable> (@in_guaranteed τ_0_0) -> ()
+// CHECK: [[USE_2:%.+]] = function_ref @$S4main3useyyxAA7FooableRzlF
+// CHECK: = apply [[USE_2]]<PublicFooImpl>({{%.+}}) : $@convention(thin) <τ_0_0 where τ_0_0 : Fooable> (@in_guaranteed τ_0_0) -> ()
+// CHECK: [[IMPL_1:%.+]] = function_ref @$S23TestableMultifileHelper13HasDefaultFooPAAE3fooyyF
+// CHECK: = apply [[IMPL_1]]<FooImpl>({{%.+}}) : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaultFoo> (@in_guaranteed τ_0_0) -> ()
+// CHECK: [[IMPL_2:%.+]] = function_ref @$S23TestableMultifileHelper13HasDefaultFooPAAE3fooyyF
+// CHECK: = apply [[IMPL_2]]<PublicFooImpl>({{%.+}}) : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaultFoo> (@in_guaranteed τ_0_0) -> ()
+// CHECK: } // end sil function '$S4main4test11internalFoo06publicD0yAA0D4ImplV_AA06PublicdF0VtF'
+
+func test(internalSub: Sub, publicSub: PublicSub) {
+ internalSub.foo()
+ publicSub.foo()
+}
+
+// CHECK-LABEL: sil hidden @$S4main4test11internalSub06publicD0yAA0D0C_AA06PublicD0CtF
+// CHECK: bb0([[ARG0:%.*]] : @guaranteed $Sub, [[ARG1:%.*]] : @guaranteed $PublicSub):
+// CHECK: = class_method [[ARG0]] : $Sub, #Sub.foo!1
+// CHECK: = class_method [[ARG1]] : $PublicSub, #PublicSub.foo!1
+// CHECK: } // end sil function '$S4main4test11internalSub06publicD0yAA0D0C_AA06PublicD0CtF'
+
diff --git a/test/SILGen/plus_zero_tuples.swift b/test/SILGen/plus_zero_tuples.swift
new file mode 100644
index 0000000..c0e0a3d
--- /dev/null
+++ b/test/SILGen/plus_zero_tuples.swift
@@ -0,0 +1,166 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+class C {}
+
+enum Foo {
+ case X(C, Int)
+}
+
+// <rdar://problem/16020428>
+// CHECK-LABEL: sil hidden @$S6tuples8matchFoo1xyAA0C0O_tF
+func matchFoo(x x: Foo) {
+ switch x {
+ case .X(let x):
+ ()
+ }
+}
+
+protocol P { func foo() }
+struct A : P { func foo() {} }
+
+func make_int() -> Int { return 0 }
+func make_p() -> P { return A() }
+func make_xy() -> (x: Int, y: P) { return (make_int(), make_p()) }
+
+// CHECK-LABEL: sil hidden @$S6tuples17testShuffleOpaqueyyF
+func testShuffleOpaque() {
+ // CHECK: [[X:%.*]] = alloc_box ${ var P }
+ // CHECK-NEXT: [[PBX:%.*]] = project_box [[X]]
+ // CHECK: [[Y:%.*]] = alloc_box ${ var Int }
+ // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y]]
+
+ // CHECK: [[T0:%.*]] = function_ref @$S6tuples7make_xySi1x_AA1P_p1ytyF
+ // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[PBX]])
+ // CHECK-NEXT: store [[T1]] to [trivial] [[PBY]]
+ var (x,y) : (y:P, x:Int) = make_xy()
+
+ // CHECK-NEXT: [[PAIR:%.*]] = alloc_box ${ var (y: P, x: Int) }
+ // CHECK-NEXT: [[PBPAIR:%.*]] = project_box [[PAIR]]
+ // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 0
+ // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 1
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[T0:%.*]] = function_ref @$S6tuples7make_xySi1x_AA1P_p1ytyF
+ // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[PAIR_0]])
+ // CHECK-NEXT: store [[T1]] to [trivial] [[PAIR_1]]
+ var pair : (y:P, x:Int) = make_xy()
+
+ // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[T0:%.*]] = function_ref @$S6tuples7make_xySi1x_AA1P_p1ytyF
+ // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[TEMP]])
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: P, x: Int)
+ // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 0
+ // CHECK-NEXT: copy_addr [take] [[TEMP]] to [[PAIR_0]]
+ // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 1
+ // CHECK-NEXT: assign [[T1]] to [[PAIR_1]]
+ // CHECK-NEXT: end_access [[WRITE]] : $*(y: P, x: Int)
+ // CHECK-NEXT: dealloc_stack [[TEMP]]
+ pair = make_xy()
+}
+
+// CHECK-LABEL: testShuffleTuple
+func testShuffleTuple() {
+ // CHECK: [[X:%.*]] = alloc_box ${ var P }
+ // CHECK-NEXT: [[PBX:%.*]] = project_box [[X]]
+ // CHECK: [[Y:%.*]] = alloc_box ${ var Int }
+ // CHECK-NEXT: [[PBY:%.*]] = project_box [[Y]]
+
+ // CHECK: [[T0:%.*]] = function_ref @$S6tuples8make_intSiyF
+ // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]()
+ // CHECK-NEXT: store [[T1]] to [trivial] [[PBY]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[T0:%.*]] = function_ref @$S6tuples6make_pAA1P_pyF
+ // CHECK-NEXT: apply [[T0]]([[PBX]])
+ var (x,y) : (y:P, x:Int) = (x: make_int(), y: make_p())
+
+ // CHECK-NEXT: [[PAIR:%.*]] = alloc_box ${ var (y: P, x: Int) }
+ // CHECK-NEXT: [[PBPAIR:%.*]] = project_box [[PAIR]]
+ // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 0
+ // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[PBPAIR]] : $*(y: P, x: Int), 1
+ // CHECK-NEXT: // function_ref
+ // CHECK: [[T0:%.*]] = function_ref @$S6tuples8make_intSiyF
+ // CHECK-NEXT: [[T1:%.*]] = apply [[T0]]()
+ // CHECK-NEXT: store [[T1]] to [trivial] [[PAIR_1]]
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[T0:%.*]] = function_ref @$S6tuples6make_pAA1P_pyF
+ // CHECK-NEXT: apply [[T0]]([[PAIR_0]])
+ var pair : (y:P, x:Int) = (x: make_int(), y: make_p())
+
+ // This isn't really optimal; we should be evaluating make_p directly
+ // into the temporary.
+ // CHECK-NEXT: // function_ref
+ // CHECK: [[T0:%.*]] = function_ref @$S6tuples8make_intSiyF
+ // CHECK-NEXT: [[INT:%.*]] = apply [[T0]]()
+ // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[T0:%.*]] = function_ref @$S6tuples6make_pAA1P_pyF
+ // CHECK-NEXT: apply [[T0]]([[TEMP]])
+ // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBPAIR]] : $*(y: P, x: Int)
+ // CHECK-NEXT: [[PAIR_0:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 0
+ // CHECK-NEXT: copy_addr [take] [[TEMP]] to [[PAIR_0]]
+ // CHECK-NEXT: [[PAIR_1:%.*]] = tuple_element_addr [[WRITE]] : $*(y: P, x: Int), 1
+ // CHECK-NEXT: assign [[INT]] to [[PAIR_1]]
+ // CHECK-NEXT: end_access [[WRITE]] : $*(y: P, x: Int)
+ // CHECK-NEXT: dealloc_stack [[TEMP]]
+ pair = (x: make_int(), y: make_p())
+}
+
+enum GenericEnum<T> {
+ case one(T)
+
+ static var callback: (T) -> Void { fatalError() }
+}
+
+// CHECK-LABEL: $S6tuples16testTupleUnsplatyyF
+func testTupleUnsplat() {
+ // CHECK: debug_value [[X:%.+]] : $Int, let, name "x"
+ // CHECK: debug_value [[Y:%.+]] : $Int, let, name "y"
+ let x = 1, y = 2
+
+ // CHECK: [[TUPLE:%.+]] = tuple ([[X]] : $Int, [[Y]] : $Int)
+ // CHECK: enum $GenericEnum<(Int, Int)>, #GenericEnum.one!enumelt.1, [[TUPLE]]
+ _ = GenericEnum<(Int, Int)>.one((x, y))
+ // CHECK: [[TUPLE:%.+]] = tuple ([[X]] : $Int, [[Y]] : $Int)
+ // CHECK: enum $GenericEnum<(Int, Int)>, #GenericEnum.one!enumelt.1, [[TUPLE]]
+ _ = GenericEnum<(Int, Int)>.one(x, y)
+
+ // CHECK: [[THUNK:%.+]] = function_ref @$SSi_SitIegn_S2iIegyy_TR
+ // CHECK: [[REABSTRACTED:%.+]] = partial_apply [callee_guaranteed] [[THUNK]]({{%.+}})
+ // CHECK: [[BORROW:%.*]] = begin_borrow [[REABSTRACTED]]
+ // CHECK: apply [[BORROW]]([[X]], [[Y]])
+ _ = GenericEnum<(Int, Int)>.callback((x, y))
+ // CHECK: [[THUNK:%.+]] = function_ref @$SSi_SitIegn_S2iIegyy_TR
+ // CHECK: [[REABSTRACTED:%.+]] = partial_apply [callee_guaranteed] [[THUNK]]({{%.+}})
+ // CHECK: [[BORROW:%.*]] = begin_borrow [[REABSTRACTED]]
+ // CHECK: apply [[BORROW]]([[X]], [[Y]])
+ _ = GenericEnum<(Int, Int)>.callback(x, y)
+} // CHECK: end sil function '$S6tuples16testTupleUnsplatyyF'
+
+// Make sure that we use a load_borrow instead of a load [take] when RValues are
+// formed with isGuaranteed set.
+extension P {
+ // CHECK-LABEL: sil hidden @$S6tuples1PPAAE12immutableUse5tupleyAA1CC5index_x5valuet_tFZ
+ // CHECK: bb0([[TUP0:%.*]] : @guaranteed $C, [[TUP1:%.*]] : @trivial $*Self
+ // Allocate space for the RValue.
+ // CHECK: [[RVALUE:%.*]] = alloc_stack $(index: C, value: Self), let, name "tuple"
+ //
+ // Initialize the RValue. (This is here to help pattern matching).
+ // CHECK: [[ZERO_ADDR:%.*]] = tuple_element_addr [[RVALUE]] : $*(index: C, value: Self), 0
+ // CHECK: [[TUP0_COPY:%.*]] = copy_value [[TUP0]]
+ // CHECK: store [[TUP0_COPY]] to [init] [[ZERO_ADDR]]
+ // CHECK: [[ONE_ADDR:%.*]] = tuple_element_addr [[RVALUE]] : $*(index: C, value: Self), 1
+ // CHECK: copy_addr [[TUP1]] to [initialization] [[ONE_ADDR]]
+ //
+ // What we are actually trying to check. Note that there is no actual use of
+ // LOADED_CLASS. This is b/c of the nature of the RValue we are working with.
+ // CHECK: [[ZERO_ADDR:%.*]] = tuple_element_addr [[RVALUE]] : $*(index: C, value: Self), 0
+ // CHECK: [[LOADED_CLASS:%.*]] = load_borrow [[ZERO_ADDR]]
+ // CHECK: [[ONE_ADDR:%.*]] = tuple_element_addr [[RVALUE]] : $*(index: C, value: Self), 1
+ // CHECK: apply {{.*}}([[ONE_ADDR]]) : $@convention(witness_method: P)
+ // CHECK: end_borrow [[LOADED_CLASS]] from [[ZERO_ADDR]]
+ // CHECK: destroy_addr [[RVALUE]]
+ // CHECK: dealloc_stack [[RVALUE]]
+ public static func immutableUse(tuple: (index: C, value: Self)) -> () {
+ return tuple.value.foo()
+ }
+}
diff --git a/test/SILGen/plus_zero_types.swift b/test/SILGen/plus_zero_types.swift
new file mode 100644
index 0000000..ff5aae4
--- /dev/null
+++ b/test/SILGen/plus_zero_types.swift
@@ -0,0 +1,105 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -parse-as-library -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class C {
+ var member: Int = 0
+
+ // Methods have method calling convention.
+ // CHECK-LABEL: sil hidden @$S5types1CC3foo1xySi_tF : $@convention(method) (Int, @guaranteed C) -> () {
+ func foo(x x: Int) {
+ // CHECK: bb0([[X:%[0-9]+]] : @trivial $Int, [[THIS:%[0-9]+]] : @guaranteed $C):
+ member = x
+
+ // CHECK-NOT: copy_value
+ // CHECK: [[FN:%[0-9]+]] = class_method %1 : $C, #C.member!setter.1
+ // CHECK: apply [[FN]](%0, %1) : $@convention(method) (Int, @guaranteed C) -> ()
+ // CHECK-NOT: destroy_value
+ }
+ // CHECK: } // end sil function '$S5types1CC3foo1xySi_tF'
+}
+
+struct S {
+ var member: Int
+
+ // CHECK-LABEL: sil hidden @{{.*}}1SV3foo{{.*}} : $@convention(method) (Int, @inout S) -> ()
+ mutating
+ func foo(x x: Int) {
+ var x = x
+ // CHECK: bb0([[X:%[0-9]+]] : @trivial $Int, [[THIS:%[0-9]+]] : @trivial $*S):
+ member = x
+ // CHECK: [[XBOX:%[0-9]+]] = alloc_box ${ var Int }
+ // CHECK: [[XADDR:%[0-9]+]] = project_box [[XBOX]]
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[XADDR]] : $*Int
+ // CHECK: [[X:%.*]] = load [trivial] [[READ]] : $*Int
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[THIS]] : $*S
+ // CHECK: [[MEMBER:%[0-9]+]] = struct_element_addr [[WRITE]] : $*S, #S.member
+ // CHECK: assign [[X]] to [[MEMBER]] : $*Int
+ }
+
+ class SC {
+ // CHECK-LABEL: sil hidden @$S5types1SV2SCC3bar{{.*}}
+ func bar() {}
+ }
+}
+
+func f() {
+ class FC {
+ func zim() {}
+ }
+}
+
+func g(b b : Bool) {
+ if (b) {
+ class FC {
+ func zim() {}
+ }
+ } else {
+ class FC {
+ func zim() {}
+ }
+ }
+}
+
+struct ReferencedFromFunctionStruct {
+ let f: (ReferencedFromFunctionStruct) -> () = {x in ()}
+ let g: (ReferencedFromFunctionEnum) -> () = {x in ()}
+}
+
+enum ReferencedFromFunctionEnum {
+ case f((ReferencedFromFunctionEnum) -> ())
+ case g((ReferencedFromFunctionStruct) -> ())
+}
+
+// CHECK-LABEL: sil hidden @$S5types34referencedFromFunctionStructFieldsyyAA010ReferencedcdE0Vc_yAA0gcD4EnumOctADF{{.*}} : $@convention(thin) (@guaranteed ReferencedFromFunctionStruct) -> (@owned @callee_guaranteed (@guaranteed ReferencedFromFunctionStruct) -> (), @owned @callee_guaranteed (@guaranteed ReferencedFromFunctionEnum) -> ()) {
+// CHECK: bb0([[X:%.*]] : @guaranteed $ReferencedFromFunctionStruct):
+// CHECK: [[F:%.*]] = struct_extract [[X]] : $ReferencedFromFunctionStruct, #ReferencedFromFunctionStruct.f
+// CHECK: [[COPIED_F:%.*]] = copy_value [[F]] : $@callee_guaranteed (@guaranteed ReferencedFromFunctionStruct) -> ()
+// CHECK: [[G:%.*]] = struct_extract [[X]] : $ReferencedFromFunctionStruct, #ReferencedFromFunctionStruct.g
+// CHECK: [[COPIED_G:%.*]] = copy_value [[G]] : $@callee_guaranteed (@guaranteed ReferencedFromFunctionEnum) -> ()
+// CHECK: [[RESULT:%.*]] = tuple ([[COPIED_F]] : {{.*}}, [[COPIED_G]] : {{.*}})
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function '$S5types34referencedFromFunctionStructFieldsyyAA010ReferencedcdE0Vc_yAA0gcD4EnumOctADF'
+func referencedFromFunctionStructFields(_ x: ReferencedFromFunctionStruct)
+ -> ((ReferencedFromFunctionStruct) -> (), (ReferencedFromFunctionEnum) -> ()) {
+ return (x.f, x.g)
+}
+
+// CHECK-LABEL: sil hidden @$S5types32referencedFromFunctionEnumFieldsyyAA010ReferencedcdE0OcSg_yAA0gcD6StructVcSgtADF
+// CHECK: bb{{[0-9]+}}([[F:%.*]] : @owned $@callee_guaranteed (@guaranteed ReferencedFromFunctionEnum) -> ()):
+// CHECK: bb{{[0-9]+}}([[G:%.*]] : @owned $@callee_guaranteed (@guaranteed ReferencedFromFunctionStruct) -> ()):
+func referencedFromFunctionEnumFields(_ x: ReferencedFromFunctionEnum)
+ -> (
+ ((ReferencedFromFunctionEnum) -> ())?,
+ ((ReferencedFromFunctionStruct) -> ())?
+ ) {
+ switch x {
+ case .f(let f):
+ return (f, nil)
+ case .g(let g):
+ return (nil, g)
+ }
+}
+
+// CHECK-LABEL: sil private @$S5types1fyyF2FCL_C3zimyyF
+// CHECK-LABEL: sil private @$S5types1g1bySb_tF2FCL_C3zimyyF
+// CHECK-LABEL: sil private @$S5types1g1bySb_tF2FCL0_C3zimyyF
diff --git a/test/SILGen/plus_zero_unmanaged.swift b/test/SILGen/plus_zero_unmanaged.swift
new file mode 100644
index 0000000..0a8d7b2
--- /dev/null
+++ b/test/SILGen/plus_zero_unmanaged.swift
@@ -0,0 +1,57 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-sil %s | %FileCheck %s
+
+class C {}
+
+struct Holder {
+ unowned(unsafe) var value: C
+}
+_ = Holder(value: C())
+// CHECK-LABEL:sil hidden @$S9unmanaged6HolderV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned C, @thin Holder.Type) -> Holder
+// CHECK: bb0([[T0:%.*]] : $C,
+// CHECK-NEXT: [[T1:%.*]] = ref_to_unmanaged [[T0]] : $C to $@sil_unmanaged C
+// CHECK-NEXT: strong_release [[T0]] : $C
+// CHECK-NEXT: [[T2:%.*]] = struct $Holder ([[T1]] : $@sil_unmanaged C)
+// CHECK-NEXT: return [[T2]] : $Holder
+
+func set(holder holder: inout Holder) {
+ holder.value = C()
+}
+// CHECK-LABEL:sil hidden @$S9unmanaged3set6holderyAA6HolderVz_tF : $@convention(thin) (@inout Holder) -> ()
+// CHECK: bb0([[ADDR:%.*]] : $*Holder):
+// CHECK: [[T0:%.*]] = function_ref @$S9unmanaged1CC{{[_0-9a-zA-Z]*}}fC
+// CHECK: [[C:%.*]] = apply [[T0]](
+// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[ADDR]] : $*Holder
+// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[WRITE]] : $*Holder, #Holder.value
+// CHECK-NEXT: [[T1:%.*]] = ref_to_unmanaged [[C]]
+// CHECK-NEXT: store [[T1]] to [[T0]]
+// CHECK-NEXT: strong_release [[C]]
+// CHECK-NEXT: end_access [[WRITE]] : $*Holder
+// CHECK-NEXT: tuple ()
+// CHECK-NEXT: return
+
+func get(holder holder: inout Holder) -> C {
+ return holder.value
+}
+// CHECK-LABEL:sil hidden @$S9unmanaged3get6holderAA1CCAA6HolderVz_tF : $@convention(thin) (@inout Holder) -> @owned C
+// CHECK: bb0([[ADDR:%.*]] : $*Holder):
+// CHECK-NEXT: debug_value_addr %0 : $*Holder, var, name "holder", argno 1
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [static] [[ADDR]] : $*Holder
+// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[READ]] : $*Holder, #Holder.value
+// CHECK-NEXT: [[T1:%.*]] = load [[T0]] : $*@sil_unmanaged C
+// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
+// CHECK-NEXT: strong_retain [[T2]]
+// CHECK-NEXT: end_access [[READ]] : $*Holder
+// CHECK-NEXT: return [[T2]]
+
+func project(fn fn: () -> Holder) -> C {
+ return fn().value
+}
+// CHECK-LABEL: sil hidden @$S9unmanaged7project2fnAA1CCAA6HolderVyXE_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Holder) -> @owned C
+// CHECK: bb0([[FN:%.*]] : $@noescape @callee_guaranteed () -> Holder):
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: [[T0:%.*]] = apply [[FN]]()
+// CHECK-NEXT: [[T1:%.*]] = struct_extract [[T0]] : $Holder, #Holder.value
+// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
+// CHECK-NEXT: strong_retain [[T2]]
+// CHECK-NEXT: return [[T2]]
diff --git a/test/SILGen/plus_zero_unmanaged_ownership.swift b/test/SILGen/plus_zero_unmanaged_ownership.swift
new file mode 100644
index 0000000..8384266
--- /dev/null
+++ b/test/SILGen/plus_zero_unmanaged_ownership.swift
@@ -0,0 +1,69 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -module-name Swift -emit-silgen %s | %FileCheck %s
+
+class C {}
+
+enum Optional<T> {
+case none
+case some(T)
+}
+
+precedencegroup AssignmentPrecedence {
+ assignment: true
+ associativity: right
+}
+
+struct Holder {
+ unowned(unsafe) var value: C
+}
+
+_ = Holder(value: C())
+// CHECK-LABEL:sil hidden @$Ss6HolderV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@owned C, @thin Holder.Type) -> Holder
+// CHECK: bb0([[T0:%.*]] : @owned $C,
+// CHECK-NEXT: [[T1:%.*]] = ref_to_unmanaged [[T0]] : $C to $@sil_unmanaged C
+// CHECK-NEXT: destroy_value [[T0]] : $C
+// CHECK-NEXT: [[T2:%.*]] = struct $Holder ([[T1]] : $@sil_unmanaged C)
+// CHECK-NEXT: return [[T2]] : $Holder
+// CHECK-NEXT: } // end sil function '$Ss6HolderV5valueABs1CC_tcfC'
+func set(holder holder: inout Holder) {
+ holder.value = C()
+}
+
+// CHECK-LABEL: sil hidden @$Ss3set6holderys6HolderVz_tF : $@convention(thin) (@inout Holder) -> () {
+// CHECK: bb0([[ADDR:%.*]] : @trivial $*Holder):
+// CHECK: [[T0:%.*]] = function_ref @$Ss1CC{{[_0-9a-zA-Z]*}}fC
+// CHECK: [[C:%.*]] = apply [[T0]](
+// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ADDR]] : $*Holder
+// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[WRITE]] : $*Holder, #Holder.value
+// CHECK-NEXT: [[T1:%.*]] = ref_to_unmanaged [[C]]
+// CHECK-NEXT: assign [[T1]] to [[T0]]
+// CHECK-NEXT: destroy_value [[C]]
+// CHECK-NEXT: end_access [[WRITE]] : $*Holder
+// CHECK: } // end sil function '$Ss3set6holderys6HolderVz_tF'
+
+func get(holder holder: inout Holder) -> C {
+ return holder.value
+}
+// CHECK-LABEL: sil hidden @$Ss3get6holders1CCs6HolderVz_tF : $@convention(thin) (@inout Holder) -> @owned C {
+// CHECK: bb0([[ADDR:%.*]] : @trivial $*Holder):
+// CHECK-NEXT: debug_value_addr %0 : $*Holder, var, name "holder", argno 1
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[ADDR]] : $*Holder
+// CHECK-NEXT: [[T0:%.*]] = struct_element_addr [[READ]] : $*Holder, #Holder.value
+// CHECK-NEXT: [[T1:%.*]] = load [trivial] [[T0]] : $*@sil_unmanaged C
+// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
+// CHECK-NEXT: [[T2_COPY:%.*]] = copy_value [[T2]]
+// CHECK-NEXT: end_access [[READ]] : $*Holder
+// CHECK-NEXT: return [[T2_COPY]]
+
+func project(fn fn: () -> Holder) -> C {
+ return fn().value
+}
+// CHECK-LABEL: sil hidden @$Ss7project2fns1CCs6HolderVyXE_tF : $@convention(thin) (@noescape @callee_guaranteed () -> Holder) -> @owned C {
+// CHECK: bb0([[FN:%.*]] : @trivial $@noescape @callee_guaranteed () -> Holder):
+// CHECK-NEXT: debug_value
+// CHECK-NEXT: [[T0:%.*]] = apply [[FN]]()
+// CHECK-NEXT: [[T1:%.*]] = struct_extract [[T0]] : $Holder, #Holder.value
+// CHECK-NEXT: [[T2:%.*]] = unmanaged_to_ref [[T1]]
+// CHECK-NEXT: [[COPIED_T2:%.*]] = copy_value [[T2]]
+// CHECK-NOT: destroy_value [[BORROWED_FN_COPY]]
+// CHECK-NEXT: return [[COPIED_T2]]
diff --git a/test/SILGen/plus_zero_unowned.swift b/test/SILGen/plus_zero_unowned.swift
new file mode 100644
index 0000000..ff712fb
--- /dev/null
+++ b/test/SILGen/plus_zero_unowned.swift
@@ -0,0 +1,162 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+func takeClosure(_ fn: () -> Int) {}
+
+class C {
+ func f() -> Int { return 42 }
+}
+
+struct A {
+ unowned var x: C
+}
+_ = A(x: C())
+// CHECK-LABEL: sil hidden @$S7unowned1AV{{[_0-9a-zA-Z]*}}fC
+// CHECK: bb0([[X:%.*]] : @owned $C, %1 : @trivial $@thin A.Type):
+// CHECK: [[X_UNOWNED:%.*]] = ref_to_unowned [[X]] : $C to $@sil_unowned C
+// CHECK: [[X_UNOWNED_COPY:%.*]] = copy_value [[X_UNOWNED]]
+// CHECK: destroy_value [[X]]
+// CHECK: [[A:%.*]] = struct $A ([[X_UNOWNED_COPY]] : $@sil_unowned C)
+// CHECK: return [[A]]
+// CHECK: }
+
+protocol P {}
+struct X: P {}
+
+struct AddressOnly {
+ unowned var x: C
+ var p: P
+}
+_ = AddressOnly(x: C(), p: X())
+// CHECK-LABEL: sil hidden @$S7unowned11AddressOnlyV{{[_0-9a-zA-Z]*}}fC
+// CHECK: bb0([[RET:%.*]] : @trivial $*AddressOnly, [[X:%.*]] : @owned $C, {{.*}}):
+// CHECK: [[X_ADDR:%.*]] = struct_element_addr [[RET]] : $*AddressOnly, #AddressOnly.x
+// CHECK: [[X_UNOWNED:%.*]] = ref_to_unowned [[X]] : $C to $@sil_unowned C
+// CHECK: [[X_UNOWNED_COPY:%.*]] = copy_value [[X_UNOWNED]] : $@sil_unowned C
+// CHECK: store [[X_UNOWNED_COPY]] to [init] [[X_ADDR]]
+// CHECK: destroy_value [[X]]
+// CHECK: }
+
+// CHECK-LABEL: sil hidden @$S7unowned5test01cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+func test0(c c: C) {
+ // CHECK: bb0([[ARG:%.*]] : @guaranteed $C):
+
+ var a: A
+ // CHECK: [[A1:%.*]] = alloc_box ${ var A }, var, name "a"
+ // CHECK: [[MARKED_A1:%.*]] = mark_uninitialized [var] [[A1]]
+ // CHECK: [[PBA:%.*]] = project_box [[MARKED_A1]]
+
+ unowned var x = c
+ // CHECK: [[X:%.*]] = alloc_box ${ var @sil_unowned C }
+ // CHECK: [[PBX:%.*]] = project_box [[X]]
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[T2:%.*]] = ref_to_unowned [[ARG_COPY]] : $C to $@sil_unowned C
+ // CHECK: [[T2_COPY:%.*]] = copy_value [[T2]] : $@sil_unowned C
+ // CHECK: store [[T2_COPY]] to [init] [[PBX]] : $*@sil_unowned C
+ // CHECK: destroy_value [[ARG_COPY]]
+
+ a.x = c
+ // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBA]]
+ // CHECK: [[T1:%.*]] = struct_element_addr [[WRITE]] : $*A, #A.x
+ // CHECK: [[T2:%.*]] = ref_to_unowned [[ARG_COPY]] : $C
+ // CHECK: [[T2_COPY:%.*]] = copy_value [[T2]] : $@sil_unowned C
+ // CHECK: assign [[T2_COPY]] to [[T1]] : $*@sil_unowned C
+ // CHECK: destroy_value [[ARG_COPY]]
+
+ a.x = x
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBX]]
+ // CHECK: [[T2:%.*]] = load_borrow [[READ]] : $*@sil_unowned C
+ // CHECK: [[T3:%.*]] = copy_unowned_value [[T2]] : $@sil_unowned C
+ // CHECK: end_borrow [[T2]] from [[READ]]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBA]]
+ // CHECK: [[XP:%.*]] = struct_element_addr [[WRITE]] : $*A, #A.x
+ // CHECK: [[T4:%.*]] = ref_to_unowned [[T3]] : $C to $@sil_unowned C
+ // CHECK: [[T4_COPY:%.*]] = copy_value [[T4]] : $@sil_unowned C
+ // CHECK: assign [[T4_COPY]] to [[XP]] : $*@sil_unowned C
+ // CHECK: destroy_value [[T3]] : $C
+ // CHECK: destroy_value [[X]]
+ // CHECK: destroy_value [[MARKED_A1]]
+}
+// CHECK: } // end sil function '$S7unowned5test01cyAA1CC_tF'
+
+// CHECK-LABEL: sil hidden @{{.*}}testunowned_local
+func testunowned_local() -> C {
+ // CHECK: [[C:%.*]] = apply
+ let c = C()
+
+ // CHECK: [[UC:%.*]] = alloc_box ${ var @sil_unowned C }, let, name "uc"
+ // CHECK: [[PB_UC:%.*]] = project_box [[UC]]
+ // CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
+ // CHECK: [[C_COPY:%.*]] = copy_value [[BORROWED_C]]
+ // CHECK: [[tmp1:%.*]] = ref_to_unowned [[C_COPY]] : $C to $@sil_unowned C
+ // CHECK: [[tmp1_copy:%.*]] = copy_value [[tmp1]]
+ // CHECK: store [[tmp1_copy]] to [init] [[PB_UC]]
+ // CHECK: destroy_value [[C_COPY]]
+ // CHECK: end_borrow [[BORROWED_C]] from [[C]]
+ unowned let uc = c
+
+ // CHECK: [[tmp2:%.*]] = load_borrow [[PB_UC]]
+ // CHECK: [[tmp3:%.*]] = copy_unowned_value [[tmp2]]
+ // CHECK: end_borrow [[tmp2]] from [[PB_UC]]
+ return uc
+
+ // CHECK: destroy_value [[UC]]
+ // CHECK: destroy_value [[C]]
+ // CHECK: return [[tmp3]]
+}
+
+// <rdar://problem/16877510> capturing an unowned let crashes in silgen
+func test_unowned_let_capture(_ aC : C) {
+ unowned let bC = aC
+ takeClosure { bC.f() }
+}
+
+// CHECK-LABEL: sil private @$S7unowned05test_A12_let_captureyyAA1CCFSiyXEfU_ : $@convention(thin) (@guaranteed @sil_unowned C) -> Int {
+// CHECK: bb0([[ARG:%.*]] : @guaranteed $@sil_unowned C):
+// CHECK-NEXT: debug_value %0 : $@sil_unowned C, let, name "bC", argno 1
+// CHECK-NEXT: [[UNOWNED_ARG:%.*]] = copy_unowned_value [[ARG]] : $@sil_unowned C
+// CHECK-NEXT: [[BORROWED_UNOWNED_ARG:%.*]] = begin_borrow [[UNOWNED_ARG]]
+// CHECK-NEXT: [[FUN:%.*]] = class_method [[BORROWED_UNOWNED_ARG]] : $C, #C.f!1 : (C) -> () -> Int, $@convention(method) (@guaranteed C) -> Int
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FUN]]([[BORROWED_UNOWNED_ARG]]) : $@convention(method) (@guaranteed C) -> Int
+// CHECK-NEXT: end_borrow [[BORROWED_UNOWNED_ARG]]
+// CHECK-NEXT: destroy_value [[UNOWNED_ARG]]
+// CHECK-NEXT: return [[RESULT]] : $Int
+
+
+
+// <rdar://problem/16880044> unowned let properties don't work as struct and class members
+class TestUnownedMember {
+ unowned let member : C
+ init(inval: C) {
+ self.member = inval
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S7unowned17TestUnownedMemberC5invalAcA1CC_tcfc :
+// CHECK: bb0([[ARG1:%.*]] : @owned $C, [[SELF_PARAM:%.*]] : @owned $TestUnownedMember):
+// CHECK: [[SELF:%.*]] = mark_uninitialized [rootself] [[SELF_PARAM]] : $TestUnownedMember
+// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
+// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
+// CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
+// CHECK: [[FIELDPTR:%.*]] = ref_element_addr [[BORROWED_SELF]] : $TestUnownedMember, #TestUnownedMember.member
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[FIELDPTR]] : $*@sil_unowned C
+// CHECK: [[INVAL:%.*]] = ref_to_unowned [[ARG1_COPY]] : $C to $@sil_unowned C
+// CHECK: [[INVAL_COPY:%.*]] = copy_value [[INVAL]] : $@sil_unowned C
+// CHECK: assign [[INVAL_COPY]] to [[WRITE]] : $*@sil_unowned C
+// CHECK: destroy_value [[ARG1_COPY]] : $C
+// CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
+// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
+// CHECK: [[RET_SELF:%.*]] = copy_value [[SELF]]
+// CHECK: destroy_value [[SELF]]
+// CHECK: destroy_value [[ARG1]]
+// CHECK: return [[RET_SELF]] : $TestUnownedMember
+// CHECK: } // end sil function '$S7unowned17TestUnownedMemberC5invalAcA1CC_tcfc'
+
+// Just verify that lowering an unowned reference to a type parameter
+// doesn't explode.
+struct Unowned<T: AnyObject> {
+ unowned var object: T
+}
+func takesUnownedStruct(_ z: Unowned<C>) {}
+// CHECK-LABEL: sil hidden @$S7unowned18takesUnownedStructyyAA0C0VyAA1CCGF : $@convention(thin) (@guaranteed Unowned<C>) -> ()
diff --git a/test/SILGen/plus_zero_vtable_thunks_reabstraction_final.swift b/test/SILGen/plus_zero_vtable_thunks_reabstraction_final.swift
new file mode 100644
index 0000000..4cd5aee
--- /dev/null
+++ b/test/SILGen/plus_zero_vtable_thunks_reabstraction_final.swift
@@ -0,0 +1,49 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol Fooable {
+ func foo(_ x: Int) -> Int?
+}
+
+protocol Barrable {
+ associatedtype Bar
+ func foo(_ x: Bar) -> Bar?
+}
+
+class GenericSuper<T> {
+ func foo(_ x: T) -> T? {
+ return nil
+ }
+}
+
+class NongenericSub: GenericSuper<Int>, Fooable {
+ override func foo(_ x: Int) -> Int? {
+ return 6502
+ }
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S33vtable_thunks_reabstraction_final13NongenericSubCAA7FooableA2aDP3foo{{[_0-9a-zA-Z]*}}FTW
+// CHECK: class_method {{%.*}} : $NongenericSub, #NongenericSub.foo!1 {{.*}}, $@convention(method) (@in_guaranteed Int, @guaranteed NongenericSub) -> @out Optional<Int>
+
+class GenericSub<U: AnyObject>: GenericSuper<U>, Barrable {
+ override func foo(_ x: U) -> U? {
+ return x
+ }
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S33vtable_thunks_reabstraction_final10GenericSubCyxGAA8BarrableA2aEP3fooy3BarQzSgAIFTW
+// CHECK: class_method {{%.*}} : $GenericSub<τ_0_0>, #GenericSub.foo!1 {{.*}}, $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@in_guaranteed τ_0_0, @guaranteed GenericSub<τ_0_0>) -> @out Optional<τ_0_0>
+
+class C {}
+
+// CHECK-LABEL: sil hidden @$S33vtable_thunks_reabstraction_final4testyyF
+func test() {
+ // CHECK: class_method {{%.*}} : $NongenericSub, #NongenericSub.foo!1 {{.*}}, $@convention(method) (@in_guaranteed Int, @guaranteed NongenericSub) -> @out Optional<Int>
+ NongenericSub().foo(0)
+
+ // FIXME: rdar://problem/21167978
+ // let f = NongenericSub().curried(0)
+
+ // CHECK: class_method {{%.*}} : $GenericSub<C>, #GenericSub.foo!1 {{.*}}, $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@in_guaranteed τ_0_0, @guaranteed GenericSub<τ_0_0>) -> @out Optional<τ_0_0>
+ GenericSub<C>().foo(C())
+}
diff --git a/test/SILGen/plus_zero_vtables_objc.swift b/test/SILGen/plus_zero_vtables_objc.swift
new file mode 100644
index 0000000..ef5fbb0
--- /dev/null
+++ b/test/SILGen/plus_zero_vtables_objc.swift
@@ -0,0 +1,95 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -sdk %S/Inputs -emit-silgen -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import gizmo
+
+// Test ObjC base class
+
+class Hoozit : Gizmo {
+ // Overrides Gizmo.frob
+ override func frob() {}
+
+ // Overrides Gizmo.funge
+ override func funge() {}
+
+ // Overrides Gizmo.foo
+ final override func foo() {}
+
+ func anse() {}
+ func incorrige() {}
+}
+
+// CHECK-LABEL: sil hidden @$S12vtables_objc10callHoozityyAA0D0CF : $@convention(thin) (@guaranteed Hoozit) -> ()
+func callHoozit(_ h: Hoozit) {
+ // CHECK: objc_method {{.*}} : $Hoozit, #Hoozit.frob!1.foreign
+ h.frob()
+ // CHECK: function_ref @$S12vtables_objc6HoozitC3fooyyF
+ h.foo()
+ // CHECK: class_method {{.*}} : $Hoozit, #Hoozit.anse!1
+ h.anse()
+ // CHECK: return
+}
+
+class Wotsit : Hoozit {
+ // Overrides Gizmo.funge
+ override func funge() {}
+
+ // Overrides Hoozit.incorrige
+ override func incorrige() {}
+
+ // Overrides Gizmo.frob
+ final override func frob() {}
+}
+
+// CHECK-LABEL: sil hidden @$S12vtables_objc10callWotsityyAA0D0CF : $@convention(thin) (@guaranteed Wotsit) -> ()
+func callWotsit(_ w: Wotsit) {
+ // CHECK: objc_method {{.*}} : $Wotsit, #Wotsit.funge!1.foreign
+ w.funge()
+ // CHECK: class_method {{.*}} : $Wotsit, #Wotsit.incorrige!1
+ w.incorrige()
+ // CHECK: function_ref @$S12vtables_objc6WotsitC4frobyyF
+ w.frob()
+ // CHECK: return
+}
+
+// Entries only exist for native Swift methods
+
+// CHECK: sil_vtable Hoozit {
+// CHECK-NEXT: #Hoozit.anse!1: {{.*}} : @$S12vtables_objc6HoozitC4anse{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : @$S12vtables_objc6HoozitC9incorrige{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit? : @$S12vtables_objc6HoozitCACSgycfc
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit? : @$S12vtables_objc6HoozitC7bellsOnACSgSi_tcfc
+// CHECK-NEXT: #Hoozit.deinit!deallocator: @$S12vtables_objc6HoozitCfD
+// CHECK-NEXT: }
+
+// CHECK: sil_vtable Wotsit {
+// CHECK-NEXT: #Hoozit.anse!1: {{.*}} : @$S12vtables_objc6HoozitC4anse{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.incorrige!1: {{.*}} : @$S12vtables_objc6WotsitC9incorrige{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> () -> Hoozit? : @$S12vtables_objc6WotsitCACSgycfc
+// CHECK-NEXT: #Hoozit.init!initializer.1: (Hoozit.Type) -> (Int) -> Hoozit? : @$S12vtables_objc6WotsitC7bellsOnACSgSi_tcfc
+// CHECK-NEXT: #Wotsit.deinit!deallocator: @$S12vtables_objc6WotsitCfD
+// CHECK-NEXT: }
+
+// <rdar://problem/15282548>
+// CHECK: sil_vtable Base {
+// CHECK: #Base.init!initializer.1: {{.*}} : @$S12vtables_objc4BaseC{{[_0-9a-zA-Z]*}}fc
+// CHECK: }
+// CHECK: sil_vtable Derived {
+// CHECK: #Base.init!initializer.1: {{.*}} : @$S12vtables_objc7DerivedC{{[_0-9a-zA-Z]*}}fc
+// CHECK: }
+@objc class Base {}
+
+extension Base {
+ // note: does not have a vtable slot, because it is from an extension
+ func identify() -> Int {
+ return 0
+ }
+}
+
+class Derived : Base {
+ override func identify() -> Int {
+ return 1
+ }
+}
diff --git a/test/SILGen/plus_zero_weak.swift b/test/SILGen/plus_zero_weak.swift
new file mode 100644
index 0000000..919a55f
--- /dev/null
+++ b/test/SILGen/plus_zero_weak.swift
@@ -0,0 +1,87 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+class C {
+ func f() -> Int { return 42 }
+}
+
+func takeClosure(fn: @escaping () -> Int) {}
+
+struct A {
+ weak var x: C?
+}
+
+// CHECK: sil hidden @$S4weak5test01cyAA1CC_tF : $@convention(thin) (@guaranteed C) -> () {
+func test0(c c: C) {
+ var c = c
+// CHECK: bb0(%0 : @guaranteed $C):
+// CHECK: [[C:%.*]] = alloc_box ${ var C }
+// CHECK-NEXT: [[PBC:%.*]] = project_box [[C]]
+
+ var a: A
+// CHECK: [[A1:%.*]] = alloc_box ${ var A }
+// CHECK: [[MARKED_A1:%.*]] = mark_uninitialized [var] [[A1]]
+// CHECK-NEXT: [[PBA:%.*]] = project_box [[MARKED_A1]]
+
+ weak var x = c
+// CHECK: [[X:%.*]] = alloc_box ${ var @sil_weak Optional<C> }, var, name "x"
+// CHECK-NEXT: [[PBX:%.*]] = project_box [[X]]
+// Implicit conversion
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[PBC]]
+// CHECK-NEXT: [[TMP:%.*]] = load [copy] [[READ]] : $*C
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: [[OPTVAL:%.*]] = enum $Optional<C>, #Optional.some!enumelt.1, [[TMP]] : $C
+// CHECK-NEXT: store_weak [[OPTVAL]] to [initialization] [[PBX]] : $*@sil_weak Optional<C>
+// CHECK-NEXT: destroy_value [[OPTVAL]] : $Optional<C>
+
+ a.x = c
+// Implicit conversion
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[PBC]]
+// CHECK-NEXT: [[TMP:%.*]] = load [copy] [[READ]] : $*C
+// CHECK-NEXT: end_access [[READ]]
+// CHECK-NEXT: [[OPTVAL:%.*]] = enum $Optional<C>, #Optional.some!enumelt.1, [[TMP]] : $C
+
+// Drill to a.x
+// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PBA]]
+// CHECK-NEXT: [[A_X:%.*]] = struct_element_addr [[WRITE]] : $*A, #A.x
+
+// Store to a.x.
+// CHECK-NEXT: store_weak [[OPTVAL]] to [[A_X]] : $*@sil_weak Optional<C>
+// CHECK-NEXT: destroy_value [[OPTVAL]] : $Optional<C>
+}
+
+// <rdar://problem/16871284> silgen crashes on weak capture
+// CHECK: closure #1 () -> Swift.Int in weak.testClosureOverWeak() -> ()
+// CHECK-LABEL: sil private @$S4weak19testClosureOverWeakyyFSiycfU_ : $@convention(thin) (@guaranteed { var @sil_weak Optional<C> }) -> Int {
+// CHECK: bb0(%0 : @guaranteed ${ var @sil_weak Optional<C> }):
+// CHECK-NEXT: %1 = project_box %0
+// CHECK-NEXT: debug_value_addr %1 : $*@sil_weak Optional<C>, var, name "bC", argno 1
+// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] %1
+// CHECK-NEXT: [[STK:%.*]] = alloc_stack $Optional<C>
+// CHECK-NEXT: [[VAL:%.*]] = load_weak [[READ]] : $*@sil_weak Optional<C>
+// CHECK-NEXT: store [[VAL]] to [init] [[STK]] : $*Optional<C>
+func testClosureOverWeak() {
+ weak var bC = C()
+ takeClosure { bC!.f() }
+}
+
+class CC {
+ weak var x: CC?
+
+ // CHECK-LABEL: sil hidden @$S4weak2CCC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (@owned CC) -> @owned CC {
+ // CHECK: bb0([[SELF:%.*]] : @owned $CC):
+ // CHECK: [[UNINIT_SELF:%.*]] = mark_uninitialized [rootself] [[SELF]] : $CC
+ // CHECK: [[FOO:%.*]] = alloc_box ${ var Optional<CC> }, var, name "foo"
+ // CHECK: [[PB:%.*]] = project_box [[FOO]]
+ // CHECK: [[BORROWED_UNINIT_SELF:%.*]] = begin_borrow [[UNINIT_SELF]]
+ // CHECK: [[X:%.*]] = ref_element_addr [[BORROWED_UNINIT_SELF]] : $CC, #CC.x
+ // CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X]] : $*@sil_weak Optional<CC>
+ // CHECK: [[VALUE:%.*]] = load_weak [[READ]] : $*@sil_weak Optional<CC>
+ // CHECK: store [[VALUE]] to [init] [[PB]] : $*Optional<CC>
+ // CHECK: end_borrow [[BORROWED_UNINIT_SELF]] from [[UNINIT_SELF]]
+ // CHECK: destroy_value [[FOO]]
+ // CHECK: } // end sil function '$S4weak2CCC{{[_0-9a-zA-Z]*}}fc'
+ init() {
+ var foo = x
+ }
+}
diff --git a/test/SILGen/plus_zero_weak_multiple_modules.swift b/test/SILGen/plus_zero_weak_multiple_modules.swift
new file mode 100644
index 0000000..2c97546
--- /dev/null
+++ b/test/SILGen/plus_zero_weak_multiple_modules.swift
@@ -0,0 +1,23 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/weak_other.swiftmodule -module-name=weak_other %S/Inputs/weak_other.swift
+// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
+
+import weak_other
+
+// CHECK-LABEL: sil hidden @$S21weak_multiple_modules11doSomething2uiSb0A6_other2UIC_tF : $@convention(thin) (@guaranteed UI) -> Bool
+func doSomething(ui: UI) -> Bool {
+ // CHECK: ref_element_addr
+ // CHECK-objc: load_unowned
+ // CHECK-native: load_borrow
+ // CHECK-native: copy_unowned_value
+ // CHECK-native: end_borrow
+ // CHECK: open_existential_ref
+ // CHECK: witness_method
+ // CHECK: apply
+ // CHECK: open_existential_ref
+ // CHECK: function_ref
+ // CHECK: apply
+ // CHECK: return
+ return ui.environment.router.flags.asBoolean()
+}
diff --git a/test/SILGen/plus_zero_without_actually_escaping.swift b/test/SILGen/plus_zero_without_actually_escaping.swift
new file mode 100644
index 0000000..cce3e9c
--- /dev/null
+++ b/test/SILGen/plus_zero_without_actually_escaping.swift
@@ -0,0 +1,46 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+var escapeHatch: Any = 0
+
+// CHECK-LABEL: sil hidden @$S25without_actually_escaping9letEscape1fyycyyXE_tF
+func letEscape(f: () -> ()) -> () -> () {
+ // CHECK: bb0([[ARG:%.*]] : @trivial $@noescape @callee_guaranteed () -> ()):
+ // TODO: Use a canary wrapper instead of just copying the nonescaping value
+ // CHECK: [[ESCAPABLE_COPY:%.*]] = partial_apply [callee_guaranteed] {{%.*}}([[ARG]])
+ // CHECK: [[MD_ESCAPABLE_COPY:%.*]] = mark_dependence [[ESCAPABLE_COPY]]
+ // CHECK: [[BORROW_MD_ESCAPABLE_COPY:%.*]] = begin_borrow [[MD_ESCAPABLE_COPY]]
+ // CHECK: [[SUB_CLOSURE:%.*]] = function_ref @
+ // CHECK: [[RESULT:%.*]] = apply [[SUB_CLOSURE]]([[BORROW_MD_ESCAPABLE_COPY]])
+ // CHECK: destroy_value [[MD_ESCAPABLE_COPY]]
+ // CHECK: return [[RESULT]]
+ return withoutActuallyEscaping(f) { return $0 }
+}
+
+
+// CHECK-LABEL: sil hidden @$S25without_actually_escaping14letEscapeThrow1fyycyycyKXE_tKF
+// CHECK: bb0([[ARG:%.*]] : @trivial $@noescape @callee_guaranteed () -> (@owned @callee_guaranteed () -> (), @error Error)):
+// CHECK: [[CVT:%.*]] = function_ref @$SIeg_s5Error_pIgozo_Ieg_sAA_pIegozo_TR
+// CHECK: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CVT]]([[ARG]])
+// CHECK: [[MD:%.*]] = mark_dependence [[CLOSURE]] : {{.*}} on [[ARG]]
+// CHECK: [[BORROW:%.*]] = begin_borrow [[MD]]
+// CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
+// CHECK: [[USER:%.*]] = function_ref @$S25without_actually_escaping14letEscapeThrow1fyycyycyKXE_tKFyycyycyKcKXEfU_
+// CHECK: try_apply [[USER]]([[COPY]]) : {{.*}}, normal bb1, error bb2
+//
+// CHECK: bb1([[RES:%.*]] : @owned $@callee_guaranteed () -> ()):
+// CHECK: [[ESCAPED:%.*]] = is_escaping_closure [[BORROW]]
+// CHECK: cond_fail [[ESCAPED]] : $Builtin.Int1
+// CHECK: end_borrow [[BORROW]] from [[MD]]
+// CHECK: destroy_value [[MD]]
+// CHECK: return [[RES]]
+//
+// CHECK: bb2([[ERR:%.*]] : @owned $Error):
+// CHECK: end_borrow [[BORROW]] from [[MD]]
+// CHECK: destroy_value [[MD]]
+// CHECK: throw [[ERR]] : $Error
+// CHECK: }
+
+func letEscapeThrow(f: () throws -> () -> ()) throws -> () -> () {
+ return try withoutActuallyEscaping(f) { return try $0() }
+}
diff --git a/test/SILGen/plus_zero_witness_same_type.swift b/test/SILGen/plus_zero_witness_same_type.swift
new file mode 100644
index 0000000..93335d1
--- /dev/null
+++ b/test/SILGen/plus_zero_witness_same_type.swift
@@ -0,0 +1,35 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-ir %s
+
+protocol Fooable {
+ associatedtype Bar
+
+ func foo<T: Fooable where T.Bar == Self.Bar>(x x: T) -> Self.Bar
+}
+
+struct X {}
+
+// Ensure that the protocol witness for requirements with same-type constraints
+// is set correctly. <rdar://problem/16369105>
+// CHECK-LABEL: sil private [transparent] [thunk] @$S17witness_same_type3FooVAA7FooableA2aDP3foo1x3BarQzqd___tAaDRd__AHQyd__AIRSlFTW : $@convention(witness_method: Fooable) <τ_0_0 where τ_0_0 : Fooable, τ_0_0.Bar == X> (@in_guaranteed τ_0_0, @in_guaranteed Foo) -> @out X
+struct Foo: Fooable {
+ typealias Bar = X
+
+ func foo<T: Fooable where T.Bar == X>(x x: T) -> X { return X() }
+}
+
+// rdar://problem/19049566
+// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] @$S17witness_same_type14LazySequenceOfVyxq_Gs0E0AAsAEP12makeIterator0H0QzyFTW : $@convention(witness_method: Sequence) <τ_0_0, τ_0_1 where τ_0_0 : Sequence, τ_0_1 == τ_0_0.Element> (@in_guaranteed LazySequenceOf<τ_0_0, τ_0_1>) -> @out AnyIterator<τ_0_1>
+public struct LazySequenceOf<SS : Sequence, A where SS.Iterator.Element == A> : Sequence {
+ public func makeIterator() -> AnyIterator<A> {
+ var opt: AnyIterator<A>?
+ return opt!
+ }
+ public subscript(i : Int) -> A {
+ get {
+ var opt: A?
+ return opt!
+ }
+ }
+}
diff --git a/test/SILGen/plus_zero_witness_tables.swift b/test/SILGen/plus_zero_witness_tables.swift
new file mode 100644
index 0000000..e188c03
--- /dev/null
+++ b/test/SILGen/plus_zero_witness_tables.swift
@@ -0,0 +1,551 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module > %t.sil
+// RUN: %FileCheck -check-prefix=TABLE -check-prefix=TABLE-ALL %s < %t.sil
+// RUN: %FileCheck -check-prefix=SYMBOL %s < %t.sil
+
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module -enable-testing > %t.testable.sil
+// RUN: %FileCheck -check-prefix=TABLE-TESTABLE -check-prefix=TABLE-ALL %s < %t.testable.sil
+// RUN: %FileCheck -check-prefix=SYMBOL-TESTABLE %s < %t.testable.sil
+
+import witness_tables_b
+
+struct Arg {}
+
+@objc class ObjCClass {}
+
+infix operator <~>
+
+protocol AssocReqt {
+ func requiredMethod()
+}
+
+protocol ArchetypeReqt {
+ func requiredMethod()
+}
+
+protocol AnyProtocol {
+ associatedtype AssocType
+ associatedtype AssocWithReqt: AssocReqt
+
+ func method(x: Arg, y: Self)
+ func generic<A: ArchetypeReqt>(x: A, y: Self)
+
+ func assocTypesMethod(x: AssocType, y: AssocWithReqt)
+
+ static func staticMethod(x: Self)
+
+ static func <~>(x: Self, y: Self)
+}
+
+protocol ClassProtocol : class {
+ associatedtype AssocType
+ associatedtype AssocWithReqt: AssocReqt
+
+ func method(x: Arg, y: Self)
+ func generic<B: ArchetypeReqt>(x: B, y: Self)
+
+ func assocTypesMethod(x: AssocType, y: AssocWithReqt)
+
+ static func staticMethod(x: Self)
+
+ static func <~>(x: Self, y: Self)
+}
+
+@objc protocol ObjCProtocol {
+ func method(x: ObjCClass)
+ static func staticMethod(y: ObjCClass)
+}
+
+class SomeAssoc {}
+
+struct ConformingAssoc : AssocReqt {
+ func requiredMethod() {}
+}
+// TABLE-LABEL: sil_witness_table hidden ConformingAssoc: AssocReqt module witness_tables {
+// TABLE-TESTABLE-LABEL: sil_witness_table [serialized] ConformingAssoc: AssocReqt module witness_tables {
+// TABLE-ALL-NEXT: method #AssocReqt.requiredMethod!1: {{.*}} : @$S14witness_tables15ConformingAssocVAA0D4ReqtA2aDP14requiredMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-ALL-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables15ConformingAssocVAA0D4ReqtA2aDP14requiredMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AssocReqt) (@in_guaranteed ConformingAssoc) -> ()
+// SYMBOL-TESTABLE: sil shared [transparent] [serialized] [thunk] @$S14witness_tables15ConformingAssocVAA0D4ReqtA2aDP14requiredMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AssocReqt) (@in_guaranteed ConformingAssoc) -> ()
+
+struct ConformingStruct : AnyProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: ConformingStruct) {}
+ func generic<D: ArchetypeReqt>(x: D, y: ConformingStruct) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: ConformingStruct) {}
+}
+func <~>(x: ConformingStruct, y: ConformingStruct) {}
+// TABLE-LABEL: sil_witness_table hidden ConformingStruct: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW {{.*}}: ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed ConformingStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingStruct, @thick ConformingStruct.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct, @thick ConformingStruct.Type) -> ()
+// SYMBOL-TESTABLE: sil shared [transparent] [serialized] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct) -> ()
+// SYMBOL-TESTABLE: sil shared [transparent] [serialized] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct) -> ()
+// SYMBOL-TESTABLE: sil shared [transparent] [serialized] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed ConformingStruct) -> ()
+// SYMBOL-TESTABLE: sil shared [transparent] [serialized] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingStruct, @thick ConformingStruct.Type) -> ()
+// SYMBOL-TESTABLE: sil shared [transparent] [serialized] [thunk] @$S14witness_tables16ConformingStructVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct, @thick ConformingStruct.Type) -> ()
+
+protocol AddressOnly {}
+
+struct ConformingAddressOnlyStruct : AnyProtocol {
+ var p: AddressOnly // force address-only layout with a protocol-type field
+
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: ConformingAddressOnlyStruct) {}
+ func generic<E: ArchetypeReqt>(x: E, y: ConformingAddressOnlyStruct) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: ConformingAddressOnlyStruct) {}
+}
+func <~>(x: ConformingAddressOnlyStruct, y: ConformingAddressOnlyStruct) {}
+// TABLE-LABEL: sil_witness_table hidden ConformingAddressOnlyStruct: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ConformingAddressOnlyStruct, @in_guaranteed ConformingAddressOnlyStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed ConformingAddressOnlyStruct, @in_guaranteed ConformingAddressOnlyStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed ConformingAddressOnlyStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingAddressOnlyStruct, @thick ConformingAddressOnlyStruct.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables27ConformingAddressOnlyStructVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingAddressOnlyStruct, @in_guaranteed ConformingAddressOnlyStruct, @thick ConformingAddressOnlyStruct.Type) -> ()
+
+class ConformingClass : AnyProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: ConformingClass) {}
+ func generic<F: ArchetypeReqt>(x: F, y: ConformingClass) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ class func staticMethod(x: ConformingClass) {}
+}
+func <~>(x: ConformingClass, y: ConformingClass) {}
+// TABLE-LABEL: sil_witness_table hidden ConformingClass: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ConformingClass, @in_guaranteed ConformingClass) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed ConformingClass, @in_guaranteed ConformingClass) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed ConformingClass) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingClass, @thick ConformingClass.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables15ConformingClassCAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformingClass, @in_guaranteed ConformingClass, @thick ConformingClass.Type) -> ()
+
+struct ConformsByExtension {}
+extension ConformsByExtension : AnyProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: ConformsByExtension) {}
+ func generic<G: ArchetypeReqt>(x: G, y: ConformsByExtension) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: ConformsByExtension) {}
+}
+func <~>(x: ConformsByExtension, y: ConformsByExtension) {}
+// TABLE-LABEL: sil_witness_table hidden ConformsByExtension: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ConformsByExtension, @in_guaranteed ConformsByExtension) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed ConformsByExtension, @in_guaranteed ConformsByExtension) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed ConformsByExtension) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformsByExtension, @thick ConformsByExtension.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables19ConformsByExtensionVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformsByExtension, @in_guaranteed ConformsByExtension, @thick ConformsByExtension.Type) -> ()
+
+extension OtherModuleStruct : AnyProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: OtherModuleStruct) {}
+ func generic<H: ArchetypeReqt>(x: H, y: OtherModuleStruct) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: OtherModuleStruct) {}
+}
+func <~>(x: OtherModuleStruct, y: OtherModuleStruct) {}
+// TABLE-LABEL: sil_witness_table hidden OtherModuleStruct: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed OtherModuleStruct, @in_guaranteed OtherModuleStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed OtherModuleStruct, @in_guaranteed OtherModuleStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed OtherModuleStruct) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed OtherModuleStruct, @thick OtherModuleStruct.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S16witness_tables_b17OtherModuleStructV0a1_B011AnyProtocolA2dEP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed OtherModuleStruct, @in_guaranteed OtherModuleStruct, @thick OtherModuleStruct.Type) -> ()
+
+protocol OtherProtocol {}
+
+struct ConformsWithMoreGenericWitnesses : AnyProtocol, OtherProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method<I, J>(x: I, y: J) {}
+ func generic<K, L>(x: K, y: L) {}
+
+ func assocTypesMethod<M, N>(x: M, y: N) {}
+
+ static func staticMethod<O>(x: O) {}
+}
+func <~> <P: OtherProtocol>(x: P, y: P) {}
+// TABLE-LABEL: sil_witness_table hidden ConformsWithMoreGenericWitnesses: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ConformsWithMoreGenericWitnesses, @in_guaranteed ConformsWithMoreGenericWitnesses) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @in_guaranteed ConformsWithMoreGenericWitnesses, @in_guaranteed ConformsWithMoreGenericWitnesses) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @in_guaranteed ConformsWithMoreGenericWitnesses) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformsWithMoreGenericWitnesses, @thick ConformsWithMoreGenericWitnesses.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables32ConformsWithMoreGenericWitnessesVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: AnyProtocol) (@in_guaranteed ConformsWithMoreGenericWitnesses, @in_guaranteed ConformsWithMoreGenericWitnesses, @thick ConformsWithMoreGenericWitnesses.Type) -> ()
+
+class ConformingClassToClassProtocol : ClassProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: ConformingClassToClassProtocol) {}
+ func generic<Q: ArchetypeReqt>(x: Q, y: ConformingClassToClassProtocol) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ class func staticMethod(x: ConformingClassToClassProtocol) {}
+}
+func <~>(x: ConformingClassToClassProtocol,
+ y: ConformingClassToClassProtocol) {}
+// TABLE-LABEL: sil_witness_table hidden ConformingClassToClassProtocol: ClassProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #ClassProtocol.method!1: {{.*}} : @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #ClassProtocol.generic!1: {{.*}} : @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #ClassProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #ClassProtocol.staticMethod!1: {{.*}} : @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #ClassProtocol."<~>"!1: {{.*}} : @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ClassProtocol) (Arg, @guaranteed ConformingClassToClassProtocol, @guaranteed ConformingClassToClassProtocol) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ClassProtocol) <τ_0_0 where τ_0_0 : ArchetypeReqt> (@in_guaranteed τ_0_0, @guaranteed ConformingClassToClassProtocol, @guaranteed ConformingClassToClassProtocol) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ClassProtocol) (@in_guaranteed SomeAssoc, @in_guaranteed ConformingAssoc, @guaranteed ConformingClassToClassProtocol) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: ClassProtocol) (@guaranteed ConformingClassToClassProtocol, @thick ConformingClassToClassProtocol.Type) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables017ConformingClassToD8ProtocolCAA0dF0A2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: ClassProtocol) (@guaranteed ConformingClassToClassProtocol, @guaranteed ConformingClassToClassProtocol, @thick ConformingClassToClassProtocol.Type) -> ()
+
+class ConformingClassToObjCProtocol : ObjCProtocol {
+ @objc func method(x: ObjCClass) {}
+ @objc class func staticMethod(y: ObjCClass) {}
+}
+// TABLE-NOT: sil_witness_table hidden ConformingClassToObjCProtocol
+
+struct ConformingGeneric<R: AssocReqt> : AnyProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = R
+
+ func method(x: Arg, y: ConformingGeneric) {}
+ func generic<Q: ArchetypeReqt>(x: Q, y: ConformingGeneric) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: R) {}
+
+ static func staticMethod(x: ConformingGeneric) {}
+}
+func <~> <R: AssocReqt>(x: ConformingGeneric<R>, y: ConformingGeneric<R>) {}
+// TABLE-LABEL: sil_witness_table hidden <R where R : AssocReqt> ConformingGeneric<R>: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: R
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): dependent
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables17ConformingGenericVyxGAA11AnyProtocolA2aEP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables17ConformingGenericVyxGAA11AnyProtocolA2aEP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables17ConformingGenericVyxGAA11AnyProtocolA2aEP16assocTypesMetho{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables17ConformingGenericVyxGAA11AnyProtocolA2aEP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables17ConformingGenericVyxGAA11AnyProtocolA2aEP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+
+protocol AnotherProtocol {}
+
+struct ConformingGenericWithMoreGenericWitnesses<S: AssocReqt>
+ : AnyProtocol, AnotherProtocol
+{
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = S
+
+ func method<T, U>(x: T, y: U) {}
+ func generic<V, W>(x: V, y: W) {}
+
+ func assocTypesMethod<X, Y>(x: X, y: Y) {}
+
+ static func staticMethod<Z>(x: Z) {}
+}
+func <~> <AA: AnotherProtocol, BB: AnotherProtocol>(x: AA, y: BB) {}
+// TABLE-LABEL: sil_witness_table hidden <S where S : AssocReqt> ConformingGenericWithMoreGenericWitnesses<S>: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: S
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): dependent
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables025ConformingGenericWithMoreD9WitnessesVyxGAA11AnyProtocolA2aEP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables025ConformingGenericWithMoreD9WitnessesVyxGAA11AnyProtocolA2aEP7{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables025ConformingGenericWithMoreD9WitnessesVyxGAA11AnyProtocolA2aEP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables025ConformingGenericWithMoreD9WitnessesVyxGAA11AnyProtocolA2aEP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables025ConformingGenericWithMoreD9WitnessesVyxGAA11AnyProtocolA2aEP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+
+protocol InheritedProtocol1 : AnyProtocol {
+ func inheritedMethod()
+}
+
+protocol InheritedProtocol2 : AnyProtocol {
+ func inheritedMethod()
+}
+
+protocol InheritedClassProtocol : class, AnyProtocol {
+ func inheritedMethod()
+}
+
+struct InheritedConformance : InheritedProtocol1 {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: InheritedConformance) {}
+ func generic<H: ArchetypeReqt>(x: H, y: InheritedConformance) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: InheritedConformance) {}
+
+ func inheritedMethod() {}
+}
+func <~>(x: InheritedConformance, y: InheritedConformance) {}
+// TABLE-LABEL: sil_witness_table hidden InheritedConformance: InheritedProtocol1 module witness_tables {
+// TABLE-NEXT: base_protocol AnyProtocol: InheritedConformance: AnyProtocol module witness_tables
+// TABLE-NEXT: method #InheritedProtocol1.inheritedMethod!1: {{.*}} : @$S14witness_tables20InheritedConformanceVAA0C9Protocol1A2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: }
+// TABLE-LABEL: sil_witness_table hidden InheritedConformance: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables20InheritedConformanceVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables20InheritedConformanceVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables20InheritedConformanceVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables20InheritedConformanceVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables20InheritedConformanceVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+
+struct RedundantInheritedConformance : InheritedProtocol1, AnyProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: RedundantInheritedConformance) {}
+ func generic<H: ArchetypeReqt>(x: H, y: RedundantInheritedConformance) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: RedundantInheritedConformance) {}
+
+ func inheritedMethod() {}
+}
+func <~>(x: RedundantInheritedConformance, y: RedundantInheritedConformance) {}
+// TABLE-LABEL: sil_witness_table hidden RedundantInheritedConformance: InheritedProtocol1 module witness_tables {
+// TABLE-NEXT: base_protocol AnyProtocol: RedundantInheritedConformance: AnyProtocol module witness_tables
+// TABLE-NEXT: method #InheritedProtocol1.inheritedMethod!1: {{.*}} : @$S14witness_tables29RedundantInheritedConformanceVAA0D9Protocol1A2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: }
+// TABLE-LABEL: sil_witness_table hidden RedundantInheritedConformance: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables29RedundantInheritedConformanceVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables29RedundantInheritedConformanceVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables29RedundantInheritedConformanceVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables29RedundantInheritedConformanceVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables29RedundantInheritedConformanceVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+
+struct DiamondInheritedConformance : InheritedProtocol1, InheritedProtocol2 {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: DiamondInheritedConformance) {}
+ func generic<H: ArchetypeReqt>(x: H, y: DiamondInheritedConformance) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ static func staticMethod(x: DiamondInheritedConformance) {}
+
+ func inheritedMethod() {}
+}
+func <~>(x: DiamondInheritedConformance, y: DiamondInheritedConformance) {}
+// TABLE-LABEL: sil_witness_table hidden DiamondInheritedConformance: InheritedProtocol1 module witness_tables {
+// TABLE-NEXT: base_protocol AnyProtocol: DiamondInheritedConformance: AnyProtocol module witness_tables
+// TABLE-NEXT: method #InheritedProtocol1.inheritedMethod!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA0D9Protocol1A2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: }
+// TABLE-LABEL: sil_witness_table hidden DiamondInheritedConformance: InheritedProtocol2 module witness_tables {
+// TABLE-NEXT: base_protocol AnyProtocol: DiamondInheritedConformance: AnyProtocol module witness_tables
+// TABLE-NEXT: method #InheritedProtocol2.inheritedMethod!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA0D9Protocol2A2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: }
+// TABLE-LABEL: sil_witness_table hidden DiamondInheritedConformance: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables27DiamondInheritedConformanceVAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+
+class ClassInheritedConformance : InheritedClassProtocol {
+ typealias AssocType = SomeAssoc
+ typealias AssocWithReqt = ConformingAssoc
+
+ func method(x: Arg, y: ClassInheritedConformance) {}
+ func generic<H: ArchetypeReqt>(x: H, y: ClassInheritedConformance) {}
+
+ func assocTypesMethod(x: SomeAssoc, y: ConformingAssoc) {}
+
+ class func staticMethod(x: ClassInheritedConformance) {}
+
+ func inheritedMethod() {}
+}
+func <~>(x: ClassInheritedConformance, y: ClassInheritedConformance) {}
+// TABLE-LABEL: sil_witness_table hidden ClassInheritedConformance: InheritedClassProtocol module witness_tables {
+// TABLE-NEXT: base_protocol AnyProtocol: ClassInheritedConformance: AnyProtocol module witness_tables
+// TABLE-NEXT: method #InheritedClassProtocol.inheritedMethod!1: {{.*}} : @$S14witness_tables25ClassInheritedConformanceCAA0dC8ProtocolA2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: }
+// TABLE-LABEL: sil_witness_table hidden ClassInheritedConformance: AnyProtocol module witness_tables {
+// TABLE-NEXT: associated_type AssocType: SomeAssoc
+// TABLE-NEXT: associated_type AssocWithReqt: ConformingAssoc
+// TABLE-NEXT: associated_type_protocol (AssocWithReqt: AssocReqt): ConformingAssoc: AssocReqt module witness_tables
+// TABLE-NEXT: method #AnyProtocol.method!1: {{.*}} : @$S14witness_tables25ClassInheritedConformanceCAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.generic!1: {{.*}} : @$S14witness_tables25ClassInheritedConformanceCAA11AnyProtocolA2aDP7generic{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.assocTypesMethod!1: {{.*}} : @$S14witness_tables25ClassInheritedConformanceCAA11AnyProtocolA2aDP16assocTypesMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: method #AnyProtocol.staticMethod!1: {{.*}} : @$S14witness_tables25ClassInheritedConformanceCAA11AnyProtocolA2aDP12staticMethod{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: method #AnyProtocol."<~>"!1: {{.*}} : @$S14witness_tables25ClassInheritedConformanceCAA11AnyProtocolA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW
+// TABLE-NEXT: }
+// -- Witnesses have the 'self' abstraction level of their protocol.
+// AnyProtocol has no class bound, so its witnesses treat Self as opaque.
+// InheritedClassProtocol has a class bound, so its witnesses treat Self as
+// a reference value.
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables25ClassInheritedConformanceCAA0dC8ProtocolA2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: InheritedClassProtocol) (@guaranteed ClassInheritedConformance) -> ()
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables25ClassInheritedConformanceCAA11AnyProtocolA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AnyProtocol) (Arg, @in_guaranteed ClassInheritedConformance, @in_guaranteed ClassInheritedConformance) -> ()
+
+struct GenericAssocType<T> : AssocReqt {
+ func requiredMethod() {}
+}
+
+protocol AssocTypeWithReqt {
+ associatedtype AssocType : AssocReqt
+}
+
+struct ConformsWithDependentAssocType1<CC: AssocReqt> : AssocTypeWithReqt {
+ typealias AssocType = CC
+}
+// TABLE-LABEL: sil_witness_table hidden <CC where CC : AssocReqt> ConformsWithDependentAssocType1<CC>: AssocTypeWithReqt module witness_tables {
+// TABLE-NEXT: associated_type AssocType: CC
+// TABLE-NEXT: associated_type_protocol (AssocType: AssocReqt): dependent
+// TABLE-NEXT: }
+
+struct ConformsWithDependentAssocType2<DD> : AssocTypeWithReqt {
+ typealias AssocType = GenericAssocType<DD>
+}
+// TABLE-LABEL: sil_witness_table hidden <DD> ConformsWithDependentAssocType2<DD>: AssocTypeWithReqt module witness_tables {
+// TABLE-NEXT: associated_type AssocType: GenericAssocType<DD>
+// TABLE-NEXT: associated_type_protocol (AssocType: AssocReqt): <T> GenericAssocType<T>: AssocReqt module witness_tables
+// TABLE-NEXT: }
+
+protocol InheritedFromObjC : ObjCProtocol {
+ func inheritedMethod()
+}
+
+class ConformsInheritedFromObjC : InheritedFromObjC {
+ @objc func method(x: ObjCClass) {}
+ @objc class func staticMethod(y: ObjCClass) {}
+ func inheritedMethod() {}
+}
+// TABLE-LABEL: sil_witness_table hidden ConformsInheritedFromObjC: InheritedFromObjC module witness_tables {
+// TABLE-NEXT: method #InheritedFromObjC.inheritedMethod!1: {{.*}} : @$S14witness_tables25ConformsInheritedFromObjCCAA0deF1CA2aDP15inheritedMethod{{[_0-9a-zA-Z]*}}FTW
+// TABLE-NEXT: }
+
+protocol ObjCAssoc {
+ associatedtype AssocType : ObjCProtocol
+}
+
+struct HasObjCAssoc : ObjCAssoc {
+ typealias AssocType = ConformsInheritedFromObjC
+}
+// TABLE-LABEL: sil_witness_table hidden HasObjCAssoc: ObjCAssoc module witness_tables {
+// TABLE-NEXT: associated_type AssocType: ConformsInheritedFromObjC
+// TABLE-NEXT: }
+
+protocol Initializer {
+ init(arg: Arg)
+}
+
+// TABLE-LABEL: sil_witness_table hidden HasInitializerStruct: Initializer module witness_tables {
+// TABLE-NEXT: method #Initializer.init!allocator.1: {{.*}} : @$S14witness_tables20HasInitializerStructVAA0D0A2aDP{{[_0-9a-zA-Z]*}}fCTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables20HasInitializerStructVAA0D0A2aDP{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: Initializer) (Arg, @thick HasInitializerStruct.Type) -> @out HasInitializerStruct
+struct HasInitializerStruct : Initializer {
+ init(arg: Arg) { }
+}
+
+// TABLE-LABEL: sil_witness_table hidden HasInitializerClass: Initializer module witness_tables {
+// TABLE-NEXT: method #Initializer.init!allocator.1: {{.*}} : @$S14witness_tables19HasInitializerClassCAA0D0A2aDP{{[_0-9a-zA-Z]*}}fCTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables19HasInitializerClassCAA0D0A2aDP{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: Initializer) (Arg, @thick HasInitializerClass.Type) -> @out HasInitializerClass
+class HasInitializerClass : Initializer {
+ required init(arg: Arg) { }
+}
+
+// TABLE-LABEL: sil_witness_table hidden HasInitializerEnum: Initializer module witness_tables {
+// TABLE-NEXT: method #Initializer.init!allocator.1: {{.*}} : @$S14witness_tables18HasInitializerEnumOAA0D0A2aDP{{[_0-9a-zA-Z]*}}fCTW
+// TABLE-NEXT: }
+// SYMBOL: sil private [transparent] [thunk] @$S14witness_tables18HasInitializerEnumOAA0D0A2aDP{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: Initializer) (Arg, @thick HasInitializerEnum.Type) -> @out HasInitializerEnum
+enum HasInitializerEnum : Initializer {
+ case A
+
+ init(arg: Arg) { self = .A }
+}
+
diff --git a/test/SILGen/plus_zero_witnesses.swift b/test/SILGen/plus_zero_witnesses.swift
new file mode 100644
index 0000000..f618418
--- /dev/null
+++ b/test/SILGen/plus_zero_witnesses.swift
@@ -0,0 +1,513 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
+
+infix operator <~> {}
+
+func archetype_method<T: X>(x: T, y: T) -> T {
+ var x = x
+ var y = y
+ return x.selfTypes(x: y)
+}
+// CHECK-LABEL: sil hidden @$S9witnesses16archetype_method{{[_0-9a-zA-Z]*}}F{{.*}} : $@convention(thin) <T where T : X> (@in_guaranteed T, @in_guaranteed T) -> @out T {
+// CHECK: [[METHOD:%.*]] = witness_method $T, #X.selfTypes!1 : {{.*}} : $@convention(witness_method: X) <τ_0_0 where τ_0_0 : X> (@in_guaranteed τ_0_0, @inout τ_0_0) -> @out τ_0_0
+// CHECK: apply [[METHOD]]<T>({{%.*}}, {{%.*}}, {{%.*}}) : $@convention(witness_method: X) <τ_0_0 where τ_0_0 : X> (@in_guaranteed τ_0_0, @inout τ_0_0) -> @out τ_0_0
+// CHECK: }
+
+func archetype_generic_method<T: X>(x: T, y: Loadable) -> Loadable {
+ var x = x
+ return x.generic(x: y)
+}
+// CHECK-LABEL: sil hidden @$S9witnesses24archetype_generic_method{{[_0-9a-zA-Z]*}}F{{.*}} : $@convention(thin) <T where T : X> (@in_guaranteed T, Loadable) -> Loadable {
+// CHECK: [[METHOD:%.*]] = witness_method $T, #X.generic!1 : {{.*}} : $@convention(witness_method: X) <τ_0_0 where τ_0_0 : X><τ_1_0> (@in_guaranteed τ_1_0, @inout τ_0_0) -> @out τ_1_0
+// CHECK: apply [[METHOD]]<T, Loadable>({{%.*}}, {{%.*}}, {{%.*}}) : $@convention(witness_method: X) <τ_0_0 where τ_0_0 : X><τ_1_0> (@in_guaranteed τ_1_0, @inout τ_0_0) -> @out τ_1_0
+// CHECK: }
+
+// CHECK-LABEL: sil hidden @$S9witnesses32archetype_associated_type_method{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : WithAssoc> (@in_guaranteed T, @in_guaranteed T.AssocType) -> @out T
+// CHECK: apply %{{[0-9]+}}<T>
+func archetype_associated_type_method<T: WithAssoc>(x: T, y: T.AssocType) -> T {
+ return x.useAssocType(x: y)
+}
+
+protocol StaticMethod { static func staticMethod() }
+
+// CHECK-LABEL: sil hidden @$S9witnesses23archetype_static_method{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : StaticMethod> (@in_guaranteed T) -> ()
+func archetype_static_method<T: StaticMethod>(x: T) {
+ // CHECK: [[METHOD:%.*]] = witness_method $T, #StaticMethod.staticMethod!1 : {{.*}} : $@convention(witness_method: StaticMethod) <τ_0_0 where τ_0_0 : StaticMethod> (@thick τ_0_0.Type) -> ()
+ // CHECK: apply [[METHOD]]<T>
+ T.staticMethod()
+}
+
+protocol Existentiable {
+ func foo() -> Loadable
+ func generic<T>() -> T
+}
+
+func protocol_method(x: Existentiable) -> Loadable {
+ return x.foo()
+}
+// CHECK-LABEL: sil hidden @$S9witnesses15protocol_method1xAA8LoadableVAA13Existentiable_p_tF : $@convention(thin) (@in_guaranteed Existentiable) -> Loadable {
+// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened(.*) Existentiable]], #Existentiable.foo!1
+// CHECK: apply [[METHOD]]<[[OPENED]]>({{%.*}})
+// CHECK: }
+
+func protocol_generic_method(x: Existentiable) -> Loadable {
+ return x.generic()
+}
+// CHECK-LABEL: sil hidden @$S9witnesses23protocol_generic_method1xAA8LoadableVAA13Existentiable_p_tF : $@convention(thin) (@in_guaranteed Existentiable) -> Loadable {
+// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened(.*) Existentiable]], #Existentiable.generic!1
+// CHECK: apply [[METHOD]]<[[OPENED]], Loadable>({{%.*}}, {{%.*}})
+// CHECK: }
+
+@objc protocol ObjCAble {
+ func foo()
+}
+
+// CHECK-LABEL: sil hidden @$S9witnesses20protocol_objc_method1xyAA8ObjCAble_p_tF : $@convention(thin) (@guaranteed ObjCAble) -> ()
+// CHECK: objc_method {{%.*}} : $@opened({{.*}}) ObjCAble, #ObjCAble.foo!1.foreign
+func protocol_objc_method(x: ObjCAble) {
+ x.foo()
+}
+
+struct Loadable {}
+protocol AddrOnly {}
+protocol Classes : class {}
+
+protocol X {
+ mutating
+ func selfTypes(x: Self) -> Self
+ mutating
+ func loadable(x: Loadable) -> Loadable
+ mutating
+ func addrOnly(x: AddrOnly) -> AddrOnly
+ mutating
+ func generic<A>(x: A) -> A
+ mutating
+ func classes<A2: Classes>(x: A2) -> A2
+ static func <~>(_ x: Self, y: Self) -> Self
+}
+protocol Y {}
+
+protocol WithAssoc {
+ associatedtype AssocType
+ func useAssocType(x: AssocType) -> Self
+}
+
+protocol ClassBounded : class {
+ func selfTypes(x: Self) -> Self
+}
+
+struct ConformingStruct : X {
+ mutating
+ func selfTypes(x: ConformingStruct) -> ConformingStruct { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16ConformingStructVAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in_guaranteed ConformingStruct, @inout ConformingStruct) -> @out ConformingStruct {
+ // CHECK: bb0(%0 : @trivial $*ConformingStruct, %1 : @trivial $*ConformingStruct, %2 : @trivial $*ConformingStruct):
+ // CHECK-NEXT: %3 = load [trivial] %1 : $*ConformingStruct
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %4 = function_ref @$S9witnesses16ConformingStructV9selfTypes{{[_0-9a-zA-Z]*}}F : $@convention(method) (ConformingStruct, @inout ConformingStruct) -> ConformingStruct
+ // CHECK-NEXT: %5 = apply %4(%3, %2) : $@convention(method) (ConformingStruct, @inout ConformingStruct) -> ConformingStruct
+ // CHECK-NEXT: store %5 to [trivial] %0 : $*ConformingStruct
+ // CHECK-NEXT: %7 = tuple ()
+ // CHECK-NEXT: return %7 : $()
+ // CHECK-NEXT: }
+
+ mutating
+ func loadable(x: Loadable) -> Loadable { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16ConformingStructVAA1XA2aDP8loadable{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (Loadable, @inout ConformingStruct) -> Loadable {
+ // CHECK: bb0(%0 : @trivial $Loadable, %1 : @trivial $*ConformingStruct):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %2 = function_ref @$S9witnesses16ConformingStructV8loadable{{[_0-9a-zA-Z]*}}F : $@convention(method) (Loadable, @inout ConformingStruct) -> Loadable
+ // CHECK-NEXT: %3 = apply %2(%0, %1) : $@convention(method) (Loadable, @inout ConformingStruct) -> Loadable
+ // CHECK-NEXT: return %3 : $Loadable
+ // CHECK-NEXT: }
+
+ mutating
+ func addrOnly(x: AddrOnly) -> AddrOnly { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16ConformingStructVAA1XA2aDP8addrOnly{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in_guaranteed AddrOnly, @inout ConformingStruct) -> @out AddrOnly {
+ // CHECK: bb0(%0 : @trivial $*AddrOnly, %1 : @trivial $*AddrOnly, %2 : @trivial $*ConformingStruct):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %3 = function_ref @$S9witnesses16ConformingStructV8addrOnly{{[_0-9a-zA-Z]*}}F : $@convention(method) (@in_guaranteed AddrOnly, @inout ConformingStruct) -> @out AddrOnly
+ // CHECK-NEXT: %4 = apply %3(%0, %1, %2) : $@convention(method) (@in_guaranteed AddrOnly, @inout ConformingStruct) -> @out AddrOnly
+ // CHECK-NEXT: %5 = tuple ()
+ // CHECK-NEXT: return %5 : $()
+ // CHECK-NEXT: }
+
+ mutating
+ func generic<C>(x: C) -> C { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16ConformingStructVAA1XA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformingStruct) -> @out τ_0_0 {
+ // CHECK: bb0(%0 : @trivial $*τ_0_0, %1 : @trivial $*τ_0_0, %2 : @trivial $*ConformingStruct):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %3 = function_ref @$S9witnesses16ConformingStructV7generic{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformingStruct) -> @out τ_0_0
+ // CHECK-NEXT: %4 = apply %3<τ_0_0>(%0, %1, %2) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformingStruct) -> @out τ_0_0
+ // CHECK-NEXT: %5 = tuple ()
+ // CHECK-NEXT: return %5 : $()
+ // CHECK-NEXT: }
+ mutating
+ func classes<C2: Classes>(x: C2) -> C2 { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16ConformingStructVAA1XA2aDP7classes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) <τ_0_0 where τ_0_0 : Classes> (@guaranteed τ_0_0, @inout ConformingStruct) -> @owned τ_0_0 {
+ // CHECK: bb0(%0 : @guaranteed $τ_0_0, %1 : @trivial $*ConformingStruct):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %2 = function_ref @$S9witnesses16ConformingStructV7classes{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0 where τ_0_0 : Classes> (@guaranteed τ_0_0, @inout ConformingStruct) -> @owned τ_0_0
+ // CHECK-NEXT: %3 = apply %2<τ_0_0>(%0, %1) : $@convention(method) <τ_0_0 where τ_0_0 : Classes> (@guaranteed τ_0_0, @inout ConformingStruct) -> @owned τ_0_0
+ // CHECK-NEXT: return %3 : $τ_0_0
+ // CHECK-NEXT: }
+}
+func <~>(_ x: ConformingStruct, y: ConformingStruct) -> ConformingStruct { return x }
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16ConformingStructVAA1XA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: X) (@in_guaranteed ConformingStruct, @in_guaranteed ConformingStruct, @thick ConformingStruct.Type) -> @out ConformingStruct {
+// CHECK: bb0([[ARG1:%.*]] : @trivial $*ConformingStruct, [[ARG2:%.*]] : @trivial $*ConformingStruct, [[ARG3:%.*]] : @trivial $*ConformingStruct, [[ARG4:%.*]] : @trivial $@thick ConformingStruct.Type):
+// CHECK-NEXT: [[LOADED_ARG2:%.*]] = load [trivial] [[ARG2]] : $*ConformingStruct
+// CHECK-NEXT: [[LOADED_ARG3:%.*]] = load [trivial] [[ARG3]] : $*ConformingStruct
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[FUNC:%.*]] = function_ref @$S9witnesses3ltgoiyAA16ConformingStructVAD_ADtF : $@convention(thin) (ConformingStruct, ConformingStruct) -> ConformingStruct
+// CHECK-NEXT: [[FUNC_RESULT:%.*]] = apply [[FUNC]]([[LOADED_ARG2]], [[LOADED_ARG3]]) : $@convention(thin) (ConformingStruct, ConformingStruct) -> ConformingStruct
+// CHECK-NEXT: store [[FUNC_RESULT]] to [trivial] [[ARG1]] : $*ConformingStruct
+// CHECK-NEXT: %9 = tuple ()
+// CHECK-NEXT: return %9 : $()
+// CHECK-NEXT: }
+
+final class ConformingClass : X {
+ func selfTypes(x: ConformingClass) -> ConformingClass { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses15ConformingClassCAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in_guaranteed ConformingClass, @inout ConformingClass) -> @out ConformingClass {
+ // CHECK: bb0([[ARG1:%.*]] : @trivial $*ConformingClass, [[ARG2:%.*]] : @trivial $*ConformingClass, [[ARG3:%.*]] : @trivial $*ConformingClass):
+ // -- load and copy_value 'self' from inout witness 'self' parameter
+ // CHECK: [[ARG2_LOADED:%.*]] = load_borrow [[ARG2]] : $*ConformingClass
+ // CHECK: [[ARG3_LOADED:%.*]] = load_borrow [[ARG3]] : $*ConformingClass
+ // CHECK: [[FUNC:%.*]] = function_ref @$S9witnesses15ConformingClassC9selfTypes{{[_0-9a-zA-Z]*}}F
+ // CHECK: [[FUNC_RESULT:%.*]] = apply [[FUNC]]([[ARG2_LOADED]], [[ARG3_LOADED]]) : $@convention(method) (@guaranteed ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass
+ // CHECK: store [[FUNC_RESULT]] to [init] [[ARG1]] : $*ConformingClass
+ // CHECK: end_borrow [[ARG3_LOADED]] from [[ARG3]]
+ // CHECK: } // end sil function '$S9witnesses15ConformingClassCAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW'
+ func loadable(x: Loadable) -> Loadable { return x }
+ func addrOnly(x: AddrOnly) -> AddrOnly { return x }
+ func generic<D>(x: D) -> D { return x }
+ func classes<D2: Classes>(x: D2) -> D2 { return x }
+}
+func <~>(_ x: ConformingClass, y: ConformingClass) -> ConformingClass { return x }
+
+extension ConformingClass : ClassBounded { }
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses15ConformingClassCAA0C7BoundedA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: ClassBounded) (@guaranteed ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass {
+// CHECK: bb0([[C0:%.*]] : @guaranteed $ConformingClass, [[C1:%.*]] : @guaranteed $ConformingClass):
+// CHECK-NEXT: function_ref
+// CHECK-NEXT: [[FUN:%.*]] = function_ref @$S9witnesses15ConformingClassC9selfTypes{{[_0-9a-zA-Z]*}}F
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FUN]]([[C0]], [[C1]]) : $@convention(method) (@guaranteed ConformingClass, @guaranteed ConformingClass) -> @owned ConformingClass
+// CHECK-NEXT: return [[RESULT]] : $ConformingClass
+// CHECK-NEXT: }
+
+struct ConformingAOStruct : X {
+ var makeMeAO : AddrOnly
+
+ mutating
+ func selfTypes(x: ConformingAOStruct) -> ConformingAOStruct { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses18ConformingAOStructVAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in_guaranteed ConformingAOStruct, @inout ConformingAOStruct) -> @out ConformingAOStruct {
+ // CHECK: bb0(%0 : @trivial $*ConformingAOStruct, %1 : @trivial $*ConformingAOStruct, %2 : @trivial $*ConformingAOStruct):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %3 = function_ref @$S9witnesses18ConformingAOStructV9selfTypes{{[_0-9a-zA-Z]*}}F : $@convention(method) (@in_guaranteed ConformingAOStruct, @inout ConformingAOStruct) -> @out ConformingAOStruct
+ // CHECK-NEXT: %4 = apply %3(%0, %1, %2) : $@convention(method) (@in_guaranteed ConformingAOStruct, @inout ConformingAOStruct) -> @out ConformingAOStruct
+ // CHECK-NEXT: %5 = tuple ()
+ // CHECK-NEXT: return %5 : $()
+ // CHECK-NEXT: }
+ func loadable(x: Loadable) -> Loadable { return x }
+ func addrOnly(x: AddrOnly) -> AddrOnly { return x }
+ func generic<D>(x: D) -> D { return x }
+ func classes<D2: Classes>(x: D2) -> D2 { return x }
+}
+func <~>(_ x: ConformingAOStruct, y: ConformingAOStruct) -> ConformingAOStruct { return x }
+
+struct ConformsWithMoreGeneric : X, Y {
+ mutating
+ func selfTypes<E>(x: E) -> E { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses23ConformsWithMoreGenericVAA1XA2aDP9selfTypes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in_guaranteed ConformsWithMoreGeneric, @inout ConformsWithMoreGeneric) -> @out ConformsWithMoreGeneric {
+ // CHECK: bb0(%0 : @trivial $*ConformsWithMoreGeneric, %1 : @trivial $*ConformsWithMoreGeneric, %2 : @trivial $*ConformsWithMoreGeneric):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: [[WITNESS_FN:%.*]] = function_ref @$S9witnesses23ConformsWithMoreGenericV9selfTypes{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS_FN]]<ConformsWithMoreGeneric>(%0, %1, %2) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+ // CHECK-NEXT: return [[RESULT]] : $()
+ // CHECK-NEXT: }
+ func loadable<F>(x: F) -> F { return x }
+ mutating
+ func addrOnly<G>(x: G) -> G { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses23ConformsWithMoreGenericVAA1XA2aDP8addrOnly{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) (@in_guaranteed AddrOnly, @inout ConformsWithMoreGeneric) -> @out AddrOnly {
+ // CHECK: bb0(%0 : @trivial $*AddrOnly, %1 : @trivial $*AddrOnly, %2 : @trivial $*ConformsWithMoreGeneric):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %3 = function_ref @$S9witnesses23ConformsWithMoreGenericV8addrOnly{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: %4 = apply %3<AddrOnly>(%0, %1, %2) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+ // CHECK-NEXT: return [[RESULT]] : $()
+ // CHECK-NEXT: }
+
+ mutating
+ func generic<H>(x: H) -> H { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses23ConformsWithMoreGenericVAA1XA2aDP7generic{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0 {
+ // CHECK: bb0(%0 : @trivial $*τ_0_0, %1 : @trivial $*τ_0_0, %2 : @trivial $*ConformsWithMoreGeneric):
+ // CHECK-NEXT: // function_ref
+ // CHECK-NEXT: %3 = function_ref @$S9witnesses23ConformsWithMoreGenericV7generic{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: %4 = apply %3<τ_0_0>(%0, %1, %2) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+ // CHECK-NEXT: return [[RESULT]] : $()
+ // CHECK-NEXT: }
+
+ mutating
+ func classes<I>(x: I) -> I { return x }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses23ConformsWithMoreGenericVAA1XA2aDP7classes{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: X) <τ_0_0 where τ_0_0 : Classes> (@guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @owned τ_0_0 {
+ // CHECK: bb0([[ARG0:%.*]] : @guaranteed $τ_0_0, [[ARG1:%.*]] : @trivial $*ConformsWithMoreGeneric):
+ // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $τ_0_0
+ // CHECK-NEXT: [[ARG0_COPY:%.*]] = copy_value [[ARG0]]
+ // CHECK-NEXT: store [[ARG0_COPY]] to [init] [[SELF_BOX]] : $*τ_0_0
+ // CHECK-NEXT: // function_ref witnesses.ConformsWithMoreGeneric.classes
+ // CHECK-NEXT: [[WITNESS_FN:%.*]] = function_ref @$S9witnesses23ConformsWithMoreGenericV7classes{{[_0-9a-zA-Z]*}}F : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: [[RESULT_BOX:%.*]] = alloc_stack $τ_0_0
+ // CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS_FN]]<τ_0_0>([[RESULT_BOX]], [[SELF_BOX]], %1) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout ConformsWithMoreGeneric) -> @out τ_0_0
+ // CHECK-NEXT: [[RESULT:%.*]] = load [take] [[RESULT_BOX]] : $*τ_0_0
+ // CHECK-NEXT: dealloc_stack [[RESULT_BOX]] : $*τ_0_0
+ // CHECK-NEXT: destroy_addr [[SELF_BOX]]
+ // CHECK-NEXT: dealloc_stack [[SELF_BOX]] : $*τ_0_0
+ // CHECK-NEXT: return [[RESULT]] : $τ_0_0
+ // CHECK-NEXT: }
+}
+func <~> <J: Y, K: Y>(_ x: J, y: K) -> K { return y }
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses23ConformsWithMoreGenericVAA1XA2aDP3ltgoi{{[_0-9a-zA-Z]*}}FZTW : $@convention(witness_method: X) (@in_guaranteed ConformsWithMoreGeneric, @in_guaranteed ConformsWithMoreGeneric, @thick ConformsWithMoreGeneric.Type) -> @out ConformsWithMoreGeneric {
+// CHECK: bb0(%0 : @trivial $*ConformsWithMoreGeneric, %1 : @trivial $*ConformsWithMoreGeneric, %2 : @trivial $*ConformsWithMoreGeneric, %3 : @trivial $@thick ConformsWithMoreGeneric.Type):
+// CHECK-NEXT: // function_ref
+// CHECK-NEXT: [[WITNESS_FN:%.*]] = function_ref @$S9witnesses3ltgoi{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Y, τ_0_1 : Y> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> @out τ_0_1
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[WITNESS_FN]]<ConformsWithMoreGeneric, ConformsWithMoreGeneric>(%0, %1, %2) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Y, τ_0_1 : Y> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> @out τ_0_1
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: return [[RESULT]] : $()
+// CHECK-NEXT: }
+
+protocol LabeledRequirement {
+ func method(x: Loadable)
+}
+
+struct UnlabeledWitness : LabeledRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16UnlabeledWitnessVAA18LabeledRequirementA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: LabeledRequirement) (Loadable, @in_guaranteed UnlabeledWitness) -> ()
+ func method(x _: Loadable) {}
+}
+
+protocol LabeledSelfRequirement {
+ func method(x: Self)
+}
+
+struct UnlabeledSelfWitness : LabeledSelfRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses20UnlabeledSelfWitnessVAA07LabeledC11RequirementA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: LabeledSelfRequirement) (@in_guaranteed UnlabeledSelfWitness, @in_guaranteed UnlabeledSelfWitness) -> ()
+ func method(x _: UnlabeledSelfWitness) {}
+}
+
+protocol UnlabeledRequirement {
+ func method(x _: Loadable)
+}
+
+struct LabeledWitness : UnlabeledRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses14LabeledWitnessVAA20UnlabeledRequirementA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: UnlabeledRequirement) (Loadable, @in_guaranteed LabeledWitness) -> ()
+ func method(x: Loadable) {}
+}
+
+protocol UnlabeledSelfRequirement {
+ func method(_: Self)
+}
+
+struct LabeledSelfWitness : UnlabeledSelfRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses18LabeledSelfWitnessVAA09UnlabeledC11RequirementA2aDP6method{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: UnlabeledSelfRequirement) (@in_guaranteed LabeledSelfWitness, @in_guaranteed LabeledSelfWitness) -> ()
+ func method(_ x: LabeledSelfWitness) {}
+}
+
+protocol ReadOnlyRequirement {
+ var prop: String { get }
+ static var prop: String { get }
+}
+
+struct ImmutableModel: ReadOnlyRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses14ImmutableModelVAA19ReadOnlyRequirementA2aDP4propSSvgTW : $@convention(witness_method: ReadOnlyRequirement) (@in_guaranteed ImmutableModel) -> @owned String
+ let prop: String = "a"
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses14ImmutableModelVAA19ReadOnlyRequirementA2aDP4propSSvgZTW : $@convention(witness_method: ReadOnlyRequirement) (@thick ImmutableModel.Type) -> @owned String
+ static let prop: String = "b"
+}
+
+protocol FailableRequirement {
+ init?(foo: Int)
+}
+
+protocol NonFailableRefinement: FailableRequirement {
+ init(foo: Int)
+}
+
+protocol IUOFailableRequirement {
+ init!(foo: Int)
+}
+
+struct NonFailableModel: FailableRequirement, NonFailableRefinement, IUOFailableRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16NonFailableModelVAA0C11Requirement{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: FailableRequirement) (Int, @thick NonFailableModel.Type) -> @out Optional<NonFailableModel>
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16NonFailableModelVAA0bC10Refinement{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: NonFailableRefinement) (Int, @thick NonFailableModel.Type) -> @out NonFailableModel
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16NonFailableModelVAA22IUOFailableRequirement{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: FailableRequirement) (Int, @thick NonFailableModel.Type) -> @out Optional<NonFailableModel>
+ init(foo: Int) {}
+}
+
+struct FailableModel: FailableRequirement, IUOFailableRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses13FailableModelVAA0B11Requirement{{[_0-9a-zA-Z]*}}fCTW
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses13FailableModelVAA22IUOFailableRequirement{{[_0-9a-zA-Z]*}}fCTW
+ // CHECK: bb0([[SELF:%[0-9]+]] : @trivial $*Optional<FailableModel>, [[FOO:%[0-9]+]] : @trivial $Int, [[META:%[0-9]+]] : @trivial $@thick FailableModel.Type):
+ // CHECK: [[FN:%.*]] = function_ref @$S9witnesses13FailableModelV{{[_0-9a-zA-Z]*}}fC
+ // CHECK: [[INNER:%.*]] = apply [[FN]](
+ // CHECK: store [[INNER]] to [trivial] [[SELF]]
+ // CHECK: return
+ init?(foo: Int) {}
+}
+
+struct IUOFailableModel : NonFailableRefinement, IUOFailableRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16IUOFailableModelVAA21NonFailableRefinement{{[_0-9a-zA-Z]*}}fCTW
+ // CHECK: bb0([[SELF:%[0-9]+]] : @trivial $*IUOFailableModel, [[FOO:%[0-9]+]] : @trivial $Int, [[META:%[0-9]+]] : @trivial $@thick IUOFailableModel.Type):
+ // CHECK: [[META:%[0-9]+]] = metatype $@thin IUOFailableModel.Type
+ // CHECK: [[INIT:%[0-9]+]] = function_ref @$S9witnesses16IUOFailableModelV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Int, @thin IUOFailableModel.Type) -> Optional<IUOFailableModel>
+ // CHECK: [[IUO_RESULT:%[0-9]+]] = apply [[INIT]]([[FOO]], [[META]]) : $@convention(method) (Int, @thin IUOFailableModel.Type) -> Optional<IUOFailableModel>
+ // CHECK: bb2([[RESULT:%.*]] : @trivial $IUOFailableModel):
+ // CHECK: store [[RESULT]] to [trivial] [[SELF]] : $*IUOFailableModel
+ // CHECK: return
+ init!(foo: Int) { return nil }
+}
+
+protocol FailableClassRequirement: class {
+ init?(foo: Int)
+}
+
+protocol NonFailableClassRefinement: FailableClassRequirement {
+ init(foo: Int)
+}
+
+protocol IUOFailableClassRequirement: class {
+ init!(foo: Int)
+}
+
+final class NonFailableClassModel: FailableClassRequirement, NonFailableClassRefinement, IUOFailableClassRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses21NonFailableClassModelCAA0cD11Requirement{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: FailableClassRequirement) (Int, @thick NonFailableClassModel.Type) -> @owned Optional<NonFailableClassModel>
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses21NonFailableClassModelCAA0bcD10Refinement{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: NonFailableClassRefinement) (Int, @thick NonFailableClassModel.Type) -> @owned NonFailableClassModel
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses21NonFailableClassModelCAA011IUOFailableD11Requirement{{[_0-9a-zA-Z]*}}fCTW : $@convention(witness_method: FailableClassRequirement) (Int, @thick NonFailableClassModel.Type) -> @owned Optional<NonFailableClassModel>
+ init(foo: Int) {}
+}
+
+final class FailableClassModel: FailableClassRequirement, IUOFailableClassRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses18FailableClassModelCAA0bC11Requirement{{[_0-9a-zA-Z]*}}fCTW
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses18FailableClassModelCAA011IUOFailableC11Requirement{{[_0-9a-zA-Z]*}}fCTW
+ // CHECK: [[FUNC:%.*]] = function_ref @$S9witnesses18FailableClassModelC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: [[INNER:%.*]] = apply [[FUNC]](%0, %1)
+ // CHECK: return [[INNER]] : $Optional<FailableClassModel>
+ init?(foo: Int) {}
+}
+
+final class IUOFailableClassModel: NonFailableClassRefinement, IUOFailableClassRequirement {
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses21IUOFailableClassModelCAA011NonFailableC10Refinement{{[_0-9a-zA-Z]*}}fCTW
+ // CHECK: bb0({{.*}}):
+ // CHECK: [[FUNC:%.*]] = function_ref @$S9witnesses21IUOFailableClassModelC3fooACSgSi_tcfC : $@convention(method) (Int, @thick IUOFailableClassModel.Type) -> @owned Optional<IUOFailableClassModel>
+ // CHECK: [[VALUE:%.*]] = apply [[FUNC]]({{.*}})
+ // CHECK: switch_enum [[VALUE]] : $Optional<IUOFailableClassModel>, case #Optional.some!enumelt.1: [[SOMEBB:bb[0-9]+]], case #Optional.none!enumelt: [[NONEBB:bb[0-9]+]]
+ //
+ // CHECK: [[NONEBB]]:
+ // CHECK: unreachable
+ //
+ // CHECK: [[SOMEBB]]([[RESULT:%.*]] : @owned $IUOFailableClassModel)
+ // CHECK: return [[RESULT]] : $IUOFailableClassModel
+ // CHECK: } // end sil function '$S9witnesses21IUOFailableClassModelCAA011NonFailableC10Refinement{{[_0-9a-zA-Z]*}}fCTW'
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses21IUOFailableClassModelCAA0bC11Requirement{{[_0-9a-zA-Z]*}}fCTW
+ init!(foo: Int) {}
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses21IUOFailableClassModelCAA08FailableC11Requirement{{[_0-9a-zA-Z]*}}fCTW
+ // CHECK: [[FUNC:%.*]] = function_ref @$S9witnesses21IUOFailableClassModelC{{[_0-9a-zA-Z]*}}fC
+ // CHECK: [[INNER:%.*]] = apply [[FUNC]](%0, %1)
+ // CHECK: return [[INNER]] : $Optional<IUOFailableClassModel>
+}
+
+protocol HasAssoc {
+ associatedtype Assoc
+}
+
+protocol GenericParameterNameCollisionProtocol {
+ func foo<T>(_ x: T)
+ associatedtype Assoc2
+ func bar<T>(_ x: (T) -> Assoc2)
+}
+
+struct GenericParameterNameCollision<T: HasAssoc> :
+ GenericParameterNameCollisionProtocol {
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses29GenericParameterNameCollisionVyxGAA0bcdE8ProtocolA2aEP3fooyyqd__lFTW : $@convention(witness_method: GenericParameterNameCollisionProtocol) <τ_0_0 where τ_0_0 : HasAssoc><τ_1_0> (@in_guaranteed τ_1_0, @in_guaranteed GenericParameterNameCollision<τ_0_0>) -> () {
+ // CHECK: bb0(%0 : @trivial $*τ_1_0, %1 : @trivial $*GenericParameterNameCollision<τ_0_0>):
+ // CHECK: apply {{%.*}}<τ_0_0, τ_1_0>
+ func foo<U>(_ x: U) {}
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses29GenericParameterNameCollisionVyxGAA0bcdE8ProtocolA2aEP3baryy6Assoc2Qzqd__XElFTW : $@convention(witness_method: GenericParameterNameCollisionProtocol) <τ_0_0 where τ_0_0 : HasAssoc><τ_1_0> (@noescape @callee_guaranteed (@in_guaranteed τ_1_0) -> @out τ_0_0.Assoc, @in_guaranteed GenericParameterNameCollision<τ_0_0>) -> () {
+ // CHECK: bb0(%0 : @trivial $@noescape @callee_guaranteed (@in_guaranteed τ_1_0) -> @out τ_0_0.Assoc, %1 : @trivial $*GenericParameterNameCollision<τ_0_0>):
+ // CHECK: apply {{%.*}}<τ_0_0, τ_1_0>
+ func bar<V>(_ x: (V) -> T.Assoc) {}
+}
+
+protocol PropertyRequirement {
+ var width: Int { get set }
+ static var height: Int { get set }
+ var depth: Int { get set }
+}
+
+class PropertyRequirementBase {
+ var width: Int = 12
+ static var height: Int = 13
+}
+
+class PropertyRequirementWitnessFromBase : PropertyRequirementBase, PropertyRequirement {
+ var depth: Int = 14
+
+ // Make sure the contravariant return type in materializeForSet works correctly
+
+ // If the witness is in a base class of the conforming class, make sure we have a bit_cast in there:
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses34PropertyRequirementWitnessFromBaseCAA0bC0A2aDP5widthSivmTW : {{.*}} {
+ // CHECK: bb0({{.*}} : @trivial $Builtin.RawPointer, {{.*}} : @trivial $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : @trivial $*PropertyRequirementWitnessFromBase):
+ // CHECK-NEXT: [[ARG2_LOADED:%[0-9][0-9]*]] = load_borrow [[ARG2]]
+ // CHECK-NEXT: [[CAST_ARG2_LOADED:%[0-9][0-9]*]] = upcast [[ARG2_LOADED]] : $PropertyRequirementWitnessFromBase to $PropertyRequirementBase
+ // CHECK-NEXT: [[METH:%.*]] = class_method [[CAST_ARG2_LOADED]] : $PropertyRequirementBase, #PropertyRequirementBase.width!materializeForSet.1
+ // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]({{.*}}, {{.*}}, [[CAST_ARG2_LOADED]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed PropertyRequirementBase) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ // CHECK-NEXT: [[CAR:%.*]] = tuple_extract [[RES]] : $({{.*}}), 0
+ // CHECK-NEXT: [[CADR:%.*]] = tuple_extract [[RES]] : $({{.*}}), 1
+ // CHECK-NEXT: [[TUPLE:%.*]] = tuple ([[CAR]] : {{.*}}, [[CADR]] : {{.*}})
+ // CHECK-NEXT: end_borrow [[ARG2_LOADED]] from [[ARG2]]
+ // CHECK-NEXT: return [[TUPLE]]
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses34PropertyRequirementWitnessFromBaseCAA0bC0A2aDP6heightSivmZTW : {{.*}} {
+ // CHECK: [[OBJ:%.*]] = upcast %2 : $@thick PropertyRequirementWitnessFromBase.Type to $@thick PropertyRequirementBase.Type
+ // CHECK: [[METH:%.*]] = function_ref @$S9witnesses23PropertyRequirementBaseC6heightSivmZ
+ // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]
+ // CHECK-NEXT: [[CAR:%.*]] = tuple_extract [[RES]] : $({{.*}}), 0
+ // CHECK-NEXT: [[CADR:%.*]] = tuple_extract [[RES]] : $({{.*}}), 1
+ // CHECK-NEXT: [[TUPLE:%.*]] = tuple ([[CAR]] : {{.*}}, [[CADR]] : {{.*}})
+ // CHECK-NEXT: return [[TUPLE]]
+
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses34PropertyRequirementWitnessFromBaseCAA0bC0A2aDP5depthSivmTW
+ // CHECK: bb0({{.*}} : @trivial $Builtin.RawPointer, {{.*}} : @trivial $*Builtin.UnsafeValueBuffer, [[ARG2:%.*]] : @trivial $*PropertyRequirementWitnessFromBase):
+ // CHECK: [[ARG2_LOADED:%[0-9][0-9]*]] = load_borrow [[ARG2]]
+ // CHECK: [[METH:%.*]] = class_method [[ARG2_LOADED]] : $PropertyRequirementWitnessFromBase, #PropertyRequirementWitnessFromBase.depth!materializeForSet.1
+ // CHECK-NEXT: [[RES:%.*]] = apply [[METH]]({{.*}}, {{.*}}, [[ARG2_LOADED]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed PropertyRequirementWitnessFromBase) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
+ // CHECK-NEXT: tuple_extract
+ // CHECK-NEXT: tuple_extract
+ // CHECK-NEXT: [[RES:%.*]] = tuple
+ // CHECK-NEXT: end_borrow [[ARG2_LOADED]] from [[ARG2]]
+ // CHECK-NEXT: return [[RES]]
+}
+
+protocol Crashable {
+ func crash()
+}
+
+class CrashableBase {
+ func crash() {}
+}
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S9witnesses16GenericCrashableCyxGAA0C0A2aEP5crashyyFTW : $@convention(witness_method: Crashable) <τ_0_0> (@in_guaranteed GenericCrashable<τ_0_0>) -> ()
+// CHECK: bb0(%0 : @trivial $*GenericCrashable<τ_0_0>):
+// CHECK-NEXT: [[SELF:%.*]] = load_borrow %0 : $*GenericCrashable<τ_0_0>
+// CHECK-NEXT: [[BASE:%.*]] = upcast [[SELF]] : $GenericCrashable<τ_0_0> to $CrashableBase
+// CHECK-NEXT: [[FN:%.*]] = class_method [[BASE]] : $CrashableBase, #CrashableBase.crash!1 : (CrashableBase) -> () -> (), $@convention(method) (@guaranteed CrashableBase) -> ()
+// CHECK-NEXT: apply [[FN]]([[BASE]]) : $@convention(method) (@guaranteed CrashableBase) -> ()
+// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
+// CHECK-NEXT: end_borrow [[SELF]] from %0
+// CHECK-NEXT: return [[RESULT]] : $()
+
+class GenericCrashable<T> : CrashableBase, Crashable {}
diff --git a/test/SILGen/plus_zero_witnesses_class.swift b/test/SILGen/plus_zero_witnesses_class.swift
new file mode 100644
index 0000000..3ec494b
--- /dev/null
+++ b/test/SILGen/plus_zero_witnesses_class.swift
@@ -0,0 +1,104 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen %s | %FileCheck %s
+
+protocol Fooable: class {
+ func foo()
+ static func bar()
+ init()
+}
+
+class Foo: Fooable {
+
+ func foo() { }
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class3FooCAA7FooableA2aDP3foo{{[_0-9a-zA-Z]*}}FTW
+ // CHECK-NOT: function_ref
+ // CHECK: class_method
+
+ class func bar() {}
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class3FooCAA7FooableA2aDP3bar{{[_0-9a-zA-Z]*}}FZTW
+ // CHECK-NOT: function_ref
+ // CHECK: class_method
+
+ required init() {}
+ // CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class3FooCAA7FooableA2aDP{{[_0-9a-zA-Z]*}}fCTW
+ // CHECK-NOT: function_ref
+ // CHECK: class_method
+}
+
+// CHECK-LABEL: sil hidden @$S15witnesses_class3genyyxAA7FooableRzlF
+// CHECK: bb0([[SELF:%.*]] : @guaranteed $T)
+// CHECK-NOT: copy_value [[SELF]]
+// CHECK: [[METHOD:%.*]] = witness_method $T
+// CHECK: apply [[METHOD]]<T>([[SELF]])
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK: return
+func gen<T: Fooable>(_ foo: T) {
+ foo.foo()
+}
+
+// CHECK-LABEL: sil hidden @$S15witnesses_class2exyyAA7Fooable_pF
+// CHECK: bb0([[SELF:%[0-0]+]] : @guaranteed $Fooable):
+// CHECK: [[SELF_PROJ:%.*]] = open_existential_ref [[SELF]]
+// CHECK: [[METHOD:%.*]] = witness_method $[[OPENED:@opened(.*) Fooable]],
+// CHECK-NOT: copy_value [[SELF_PROJ]] : $
+// CHECK: apply [[METHOD]]<[[OPENED]]>([[SELF_PROJ]])
+// CHECK-NOT: destroy_value [[SELF]]
+// CHECK: return
+func ex(_ foo: Fooable) {
+ foo.foo()
+}
+
+// Default implementations in a protocol extension
+protocol HasDefaults {
+ associatedtype T = Self
+
+ func hasDefault()
+
+ func hasDefaultTakesT(_: T)
+
+ func hasDefaultGeneric<U : Fooable>(_: U)
+
+ func hasDefaultGenericTakesT<U : Fooable>(_: T, _: U)
+}
+
+extension HasDefaults {
+ func hasDefault() {}
+
+ func hasDefaultTakesT(_: T) {}
+
+ func hasDefaultGeneric<U : Fooable>(_: U) {}
+
+ func hasDefaultGenericTakesT<U : Fooable>(_: T, _: U) {}
+}
+
+protocol Barable {}
+
+class UsesDefaults<X : Barable> : HasDefaults {}
+
+// Covariant Self:
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP10hasDefaultyyFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable> (@in_guaranteed τ_0_0) -> ()
+// CHECK: [[FN:%.*]] = function_ref @$S15witnesses_class11HasDefaultsPAAE10hasDefaultyyF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults> (@in_guaranteed τ_0_0) -> ()
+// CHECK: apply [[FN]]<τ_0_0>(
+// CHECK: return
+
+// Invariant Self, since type signature contains an associated type:
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP16hasDefaultTakesTyy1TQzFTW : $@convention(witness_method: HasDefaults) <τ_0_0 where τ_0_0 : Barable> (@in_guaranteed UsesDefaults<τ_0_0>, @in_guaranteed UsesDefaults<τ_0_0>) -> ()
+// CHECK: [[FN:%.*]] = function_ref @$S15witnesses_class11HasDefaultsPAAE16hasDefaultTakesTyy1TQzF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults> (@in_guaranteed τ_0_0.T, @in_guaranteed τ_0_0) -> ()
+// CHECK: apply [[FN]]<UsesDefaults<τ_0_0>>(
+// CHECK: return
+
+// Covariant Self:
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP17hasDefaultGenericyyqd__AA7FooableRd__lFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable><τ_2_0 where τ_2_0 : Fooable> (@guaranteed τ_2_0, @in_guaranteed τ_0_0) -> ()
+// CHECK: [[FN:%.*]] = function_ref @$S15witnesses_class11HasDefaultsPAAE17hasDefaultGenericyyqd__AA7FooableRd__lF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults><τ_1_0 where τ_1_0 : Fooable> (@guaranteed τ_1_0, @in_guaranteed τ_0_0) -> ()
+// CHECK: apply [[FN]]<τ_0_0, τ_2_0>(
+// CHECK: return
+
+// Invariant Self, since type signature contains an associated type:
+
+// CHECK-LABEL: sil private [transparent] [thunk] @$S15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP23hasDefaultGenericTakesTyy1TQz_qd__tAA7FooableRd__lFTW : $@convention(witness_method: HasDefaults) <τ_0_0 where τ_0_0 : Barable><τ_1_0 where τ_1_0 : Fooable> (@in_guaranteed UsesDefaults<τ_0_0>, @guaranteed τ_1_0, @in_guaranteed UsesDefaults<τ_0_0>) -> ()
+// CHECK: [[FN:%.*]] = function_ref @$S15witnesses_class11HasDefaultsPAAE23hasDefaultGenericTakesTyy1TQz_qd__tAA7FooableRd__lF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults><τ_1_0 where τ_1_0 : Fooable> (@in_guaranteed τ_0_0.T, @guaranteed τ_1_0, @in_guaranteed τ_0_0) -> ()
+// CHECK: apply [[FN]]<UsesDefaults<τ_0_0>, τ_1_0>(
+// CHECK: return
diff --git a/test/SILGen/pointer_conversion.swift b/test/SILGen/pointer_conversion.swift
index c47f89c..9d540d2 100644
--- a/test/SILGen/pointer_conversion.swift
+++ b/test/SILGen/pointer_conversion.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
// FIXME: rdar://problem/19648117 Needs splitting objc parts out
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index d108a13..841c8b8 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module %s | %FileCheck %s
var zero: Int = 0
@@ -238,7 +239,7 @@
// -- writeback to val.ref.val_prop
// CHECK: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
- // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Ref, @thick Ref.Type) -> ()
+ // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed Ref, @thick Ref.Type) -> ()
// CHECK: [[REF_MAT:%.*]] = alloc_stack $Ref
// CHECK: store [[VAL_REF]] to [init] [[REF_MAT]]
// CHECK: [[T0:%.*]] = metatype $@thick Ref.Type
diff --git a/test/SILGen/property_abstraction.swift b/test/SILGen/property_abstraction.swift
index 6499fc7..beb71e7 100644
--- a/test/SILGen/property_abstraction.swift
+++ b/test/SILGen/property_abstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen %s | %FileCheck %s
struct Int {
diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift
index b125092..f01358e 100644
--- a/test/SILGen/protocol_extensions.swift
+++ b/test/SILGen/protocol_extensions.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -disable-objc-attr-requires-foundation-module -emit-silgen %s | %FileCheck %s
public protocol P1 {
diff --git a/test/SILGen/protocol_optional.swift b/test/SILGen/protocol_optional.swift
index 72e7f7c..550908f 100644
--- a/test/SILGen/protocol_optional.swift
+++ b/test/SILGen/protocol_optional.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-as-library -emit-silgen -disable-objc-attr-requires-foundation-module -enable-sil-ownership %s | %FileCheck %s
@objc protocol P1 {
diff --git a/test/SILGen/protocol_resilience.swift b/test/SILGen/protocol_resilience.swift
index 04cef96..f28b215 100644
--- a/test/SILGen/protocol_resilience.swift
+++ b/test/SILGen/protocol_resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-sil-ownership -enable-resilience -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../Inputs/resilient_protocol.swift
// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -enable-resilience %s | %FileCheck %s
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 11072b7..15ff6b3 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
//===----------------------------------------------------------------------===//
diff --git a/test/SILGen/reabstract-tuple.swift b/test/SILGen/reabstract-tuple.swift
index 13cada1..d3cfb5d 100644
--- a/test/SILGen/reabstract-tuple.swift
+++ b/test/SILGen/reabstract-tuple.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen -verify %s | %FileCheck %s
// SR-3090:
diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift
index 5c51858..8736780 100644
--- a/test/SILGen/reabstract.swift
+++ b/test/SILGen/reabstract.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func takeFn<T>(_ f : (T) -> T?) {}
diff --git a/test/SILGen/reabstract_lvalue.swift b/test/SILGen/reabstract_lvalue.swift
index 63d8a74..8cbd9b8 100644
--- a/test/SILGen/reabstract_lvalue.swift
+++ b/test/SILGen/reabstract_lvalue.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
struct MyMetatypeIsThin {}
diff --git a/test/SILGen/result_abstraction.swift b/test/SILGen/result_abstraction.swift
index a15924d..e2b49e1 100644
--- a/test/SILGen/result_abstraction.swift
+++ b/test/SILGen/result_abstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
struct S {}
diff --git a/test/SILGen/retaining_globals.swift b/test/SILGen/retaining_globals.swift
index 211070e..87756cc 100644
--- a/test/SILGen/retaining_globals.swift
+++ b/test/SILGen/retaining_globals.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -import-objc-header %S/Inputs/globals.h -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/rethrows.swift b/test/SILGen/rethrows.swift
index 908fb03..ad23e4a 100644
--- a/test/SILGen/rethrows.swift
+++ b/test/SILGen/rethrows.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-sil -verify %s | %FileCheck %s
@discardableResult
diff --git a/test/SILGen/scalar_to_tuple_args.swift b/test/SILGen/scalar_to_tuple_args.swift
index 41476ee..8fd38f6 100644
--- a/test/SILGen/scalar_to_tuple_args.swift
+++ b/test/SILGen/scalar_to_tuple_args.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func inoutWithDefaults(_ x: inout Int, y: Int = 0, z: Int = 0) {}
diff --git a/test/SILGen/shared.swift b/test/SILGen/shared.swift
index dd3c974..c0af68e 100644
--- a/test/SILGen/shared.swift
+++ b/test/SILGen/shared.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
class RefAggregate {}
diff --git a/test/SILGen/sil_locations.swift b/test/SILGen/sil_locations.swift
index e43cf3d..7614fb1 100644
--- a/test/SILGen/sil_locations.swift
+++ b/test/SILGen/sil_locations.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -Xllvm -sil-print-debuginfo -emit-verbose-sil -enable-sil-ownership %s | %FileCheck %s
// FIXME: Not sure if this an ideal source info for the branch -
@@ -76,7 +77,7 @@
func useTemplateTest() -> Int {
return templateTest(5);
// CHECK-LABEL: sil hidden @$S13sil_locations15useTemplateTestSiyF
- // CHECK: function_ref @$SSi2{{[_0-9a-zA-Z]*}}fC :{{.*}}, loc "{{.*}}":77
+ // CHECK: function_ref @$SSi2{{[_0-9a-zA-Z]*}}fC :{{.*}}, loc "{{.*}}":78
}
func foo(_ x: Int) -> Int {
diff --git a/test/SILGen/source_location.swift b/test/SILGen/source_location.swift
index 85a7296..67916ef 100644
--- a/test/SILGen/source_location.swift
+++ b/test/SILGen/source_location.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -Xllvm -sil-print-debuginfo -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func printSourceLocation(file: String = #file, line: Int = #line) {}
diff --git a/test/SILGen/specialize_attr.swift b/test/SILGen/specialize_attr.swift
index ac5b27d..0c45041 100644
--- a/test/SILGen/specialize_attr.swift
+++ b/test/SILGen/specialize_attr.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
// CHECK-LABEL: @_specialize(exported: false, kind: full, where T == Int, U == Float)
diff --git a/test/SILGen/statements.swift b/test/SILGen/statements.swift
index 8b86759..212f42e 100644
--- a/test/SILGen/statements.swift
+++ b/test/SILGen/statements.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -parse-as-library -emit-silgen -enable-sil-ownership -verify %s | %FileCheck %s
class MyClass {
diff --git a/test/SILGen/struct_resilience.swift b/test/SILGen/struct_resilience.swift
index 40d578e..5d50e67 100644
--- a/test/SILGen/struct_resilience.swift
+++ b/test/SILGen/struct_resilience.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-resilience -emit-module-path=%t/resilient_struct.swiftmodule -enable-sil-ownership -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -I %t -enable-sil-ownership -emit-silgen -enable-resilience %s | %FileCheck %s
diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift
index efcbdbf..dbd0cba 100644
--- a/test/SILGen/subclass_existentials.swift
+++ b/test/SILGen/subclass_existentials.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -parse-as-library -primary-file %s -verify | %FileCheck %s
// RUN: %target-swift-frontend -emit-ir -parse-as-library -primary-file %s
diff --git a/test/SILGen/super.swift b/test/SILGen/super.swift
index f762ee1..c00184c 100644
--- a/test/SILGen/super.swift
+++ b/test/SILGen/super.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -I %t -emit-module -emit-module-path=%t/resilient_struct.swiftmodule -module-name resilient_struct %S/../Inputs/resilient_struct.swift
// RUN: %target-swift-frontend -I %t -emit-module -emit-module-path=%t/resilient_class.swiftmodule -module-name resilient_class %S/../Inputs/resilient_class.swift
diff --git a/test/SILGen/switch.swift b/test/SILGen/switch.swift
index b64ab66..175a476 100644
--- a/test/SILGen/switch.swift
+++ b/test/SILGen/switch.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
func markUsed<T>(_ t: T) {}
diff --git a/test/SILGen/switch_abstraction.swift b/test/SILGen/switch_abstraction.swift
index c4bdccd..3b8e042 100644
--- a/test/SILGen/switch_abstraction.swift
+++ b/test/SILGen/switch_abstraction.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -parse-stdlib %s | %FileCheck %s
struct A {}
diff --git a/test/SILGen/switch_isa.swift b/test/SILGen/switch_isa.swift
index a7eca4d..4977f99 100644
--- a/test/SILGen/switch_isa.swift
+++ b/test/SILGen/switch_isa.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
func markUsed<T>(_ t: T) {}
diff --git a/test/SILGen/switch_multiple_entry_address_only.swift b/test/SILGen/switch_multiple_entry_address_only.swift
index 735c9ec..2a94457 100644
--- a/test/SILGen/switch_multiple_entry_address_only.swift
+++ b/test/SILGen/switch_multiple_entry_address_only.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
enum E {
diff --git a/test/SILGen/switch_var.swift b/test/SILGen/switch_var.swift
index 4660bf1..cc8b022 100644
--- a/test/SILGen/switch_var.swift
+++ b/test/SILGen/switch_var.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
// TODO: Implement tuple equality in the library.
diff --git a/test/SILGen/testable-multifile-other.swift b/test/SILGen/testable-multifile-other.swift
index 792d3ae..e33d15c 100644
--- a/test/SILGen/testable-multifile-other.swift
+++ b/test/SILGen/testable-multifile-other.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// This test is paired with testable-multifile.swift.
// RUN: %empty-directory(%t)
diff --git a/test/SILGen/tuples.swift b/test/SILGen/tuples.swift
index e9b4714..a05a467 100644
--- a/test/SILGen/tuples.swift
+++ b/test/SILGen/tuples.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class C {}
diff --git a/test/SILGen/types.swift b/test/SILGen/types.swift
index b30c8c2..d996b3e 100644
--- a/test/SILGen/types.swift
+++ b/test/SILGen/types.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -parse-as-library -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class C {
diff --git a/test/SILGen/unmanaged.swift b/test/SILGen/unmanaged.swift
index 9e939f9..c8d98ea 100644
--- a/test/SILGen/unmanaged.swift
+++ b/test/SILGen/unmanaged.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-sil %s | %FileCheck %s
class C {}
diff --git a/test/SILGen/unmanaged_ownership.swift b/test/SILGen/unmanaged_ownership.swift
index ecb0309..21d447b 100644
--- a/test/SILGen/unmanaged_ownership.swift
+++ b/test/SILGen/unmanaged_ownership.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -parse-stdlib -module-name Swift -emit-silgen %s | %FileCheck %s
class C {}
diff --git a/test/SILGen/unowned.swift b/test/SILGen/unowned.swift
index d55585f..7c7e8a8 100644
--- a/test/SILGen/unowned.swift
+++ b/test/SILGen/unowned.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
func takeClosure(_ fn: () -> Int) {}
diff --git a/test/SILGen/vtable_thunks_reabstraction_final.swift b/test/SILGen/vtable_thunks_reabstraction_final.swift
index 0d31336..68e4b6b 100644
--- a/test/SILGen/vtable_thunks_reabstraction_final.swift
+++ b/test/SILGen/vtable_thunks_reabstraction_final.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
protocol Fooable {
diff --git a/test/SILGen/vtables_objc.swift b/test/SILGen/vtables_objc.swift
index c0d32a7..eb45a91 100644
--- a/test/SILGen/vtables_objc.swift
+++ b/test/SILGen/vtables_objc.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -sdk %S/Inputs -emit-silgen -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILGen/weak.swift b/test/SILGen/weak.swift
index f9fe4a7..0e2567c 100644
--- a/test/SILGen/weak.swift
+++ b/test/SILGen/weak.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen -enable-sil-ownership %s | %FileCheck %s
class C {
diff --git a/test/SILGen/weak_multiple_modules.swift b/test/SILGen/weak_multiple_modules.swift
index fe5bd5c..dcfdd34 100644
--- a/test/SILGen/weak_multiple_modules.swift
+++ b/test/SILGen/weak_multiple_modules.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/weak_other.swiftmodule -module-name=weak_other %S/Inputs/weak_other.swift
// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-runtime
diff --git a/test/SILGen/without_actually_escaping.swift b/test/SILGen/without_actually_escaping.swift
index cd91ae1..1719770 100644
--- a/test/SILGen/without_actually_escaping.swift
+++ b/test/SILGen/without_actually_escaping.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
var escapeHatch: Any = 0
diff --git a/test/SILGen/witness_same_type.swift b/test/SILGen/witness_same_type.swift
index 69bf55e..b5659c5 100644
--- a/test/SILGen/witness_same_type.swift
+++ b/test/SILGen/witness_same_type.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
// RUN: %target-swift-frontend -enable-sil-ownership -emit-ir %s
diff --git a/test/SILGen/witness_tables.swift b/test/SILGen/witness_tables.swift
index d5ae931..9e0f98b 100644
--- a/test/SILGen/witness_tables.swift
+++ b/test/SILGen/witness_tables.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -I %S/Inputs -enable-source-import %s -disable-objc-attr-requires-foundation-module > %t.sil
// RUN: %FileCheck -check-prefix=TABLE -check-prefix=TABLE-ALL %s < %t.sil
// RUN: %FileCheck -check-prefix=SYMBOL %s < %t.sil
diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift
index bf8da17..e78392d 100644
--- a/test/SILGen/witnesses.swift
+++ b/test/SILGen/witnesses.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s -disable-objc-attr-requires-foundation-module -enable-sil-ownership | %FileCheck %s
infix operator <~> {}
diff --git a/test/SILGen/witnesses_class.swift b/test/SILGen/witnesses_class.swift
index 461c980..64ca7a1 100644
--- a/test/SILGen/witnesses_class.swift
+++ b/test/SILGen/witnesses_class.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-silgen %s | %FileCheck %s
protocol Fooable: class {
diff --git a/test/SILOptimizer/Inputs/TestMod.sil b/test/SILOptimizer/Inputs/TestMod.sil
index 3e12d13..9ae4a7a 100644
--- a/test/SILOptimizer/Inputs/TestMod.sil
+++ b/test/SILOptimizer/Inputs/TestMod.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// Test module for the specialize_cg_update_crash.sil test.
sil_stage canonical
diff --git a/test/SILOptimizer/Inputs/plus_zero_TestMod.sil b/test/SILOptimizer/Inputs/plus_zero_TestMod.sil
new file mode 100644
index 0000000..62126fb
--- /dev/null
+++ b/test/SILOptimizer/Inputs/plus_zero_TestMod.sil
@@ -0,0 +1,64 @@
+// REQUIRES: plus_zero_runtime
+// Test module for the specialize_cg_update_crash.sil test.
+
+sil_stage canonical
+
+import Builtin
+
+func genlibfunc<X>(x: X) -> X
+
+func genlibfunc2<X>(x: X) -> X
+
+func genlibfunc3<X>(x: X) -> X
+
+class MyClass {
+ init()
+ func mymethod<X>(x: X) -> X
+ deinit
+}
+
+sil @_TFC7TestMod7MyClassD : $@convention(method) (@owned MyClass) -> ()
+sil @_TFC7TestMod7MyClasscfMS0_FT_S0_ : $@convention(method) (@owned MyClass) -> @owned MyClass
+
+sil @_TF7TestMod11genlibfunc3urFq_q_ : $@convention(thin) <X> (@in_guaranteed X) -> @out X {
+bb0(%0 : $*X, %1 : $*X):
+ %4 = tuple ()
+ return %4 : $()
+}
+
+sil @_TF7TestMod11genlibfunc2urFq_q_ : $@convention(thin) <X> (@in_guaranteed X) -> @out X {
+bb0(%0 : $*X, %1 : $*X):
+ %3 = function_ref @_TF7TestMod11genlibfunc3urFq_q_ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ %9 = tuple ()
+ return %9 : $()
+}
+
+sil @_TFC7TestMod7MyClass8mymethodurfS0_Fq_q_ : $@convention(method) <X> (@in_guaranteed X, @guaranteed MyClass) -> @out X {
+bb0(%0 : $*X, %1 : $*X, %2 : $MyClass):
+ %5 = function_ref @_TF7TestMod11genlibfunc3urFq_q_ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ %11 = tuple ()
+ return %11 : $()
+}
+
+// This is the critical function.
+sil @_TF7TestMod10genlibfuncurFq_q_ : $@convention(thin) <X> (@in_guaranteed X) -> @out X {
+bb0(%0 : $*X, %1 : $*X):
+
+ // First reference the method, which lets the method be deserialized, but not processed.
+ %x0 = function_ref @_TFC7TestMod7MyClass8mymethodurfS0_Fq_q_ : $@convention(method) <X> (@in_guaranteed X, @guaranteed MyClass) -> @out X
+
+ // Then reference the metatype which reads the vtable and processes the method.
+ // The bug was that during reading the vtable (and processing the vtable functions),
+ // the callback (to update the CG) was lost.
+ %x4 = metatype $@thick MyClass.Type
+
+ %17 = tuple ()
+ return %17 : $()
+}
+
+sil_vtable MyClass {
+ #MyClass.init!initializer.1: @_TFC7TestMod7MyClasscfMS0_FT_S0_ // TestMod.MyClass.init (TestMod.MyClass.Type)() -> TestMod.MyClass
+ #MyClass.mymethod!1: @_TFC7TestMod7MyClass8mymethodurfS0_Fq_q_ // TestMod.MyClass.mymethod <A> (TestMod.MyClass)(A) -> A
+ #MyClass.deinit!deallocator: @_TFC7TestMod7MyClassD // TestMod.MyClass.__deallocating_deinit
+}
+
diff --git a/test/SILOptimizer/access_enforcement_noescape.swift b/test/SILOptimizer/access_enforcement_noescape.swift
index b9930d6..ef753a5 100644
--- a/test/SILOptimizer/access_enforcement_noescape.swift
+++ b/test/SILOptimizer/access_enforcement_noescape.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -enforce-exclusivity=checked -Onone -emit-sil -swift-version 4 -verify -parse-as-library %s
// RUN: %target-swift-frontend -enable-sil-ownership -enforce-exclusivity=checked -Onone -emit-sil -swift-version 3 -parse-as-library %s | %FileCheck %s
// REQUIRES: asserts
diff --git a/test/SILOptimizer/access_marker_mandatory.swift b/test/SILOptimizer/access_marker_mandatory.swift
index 3f01c45..be19716 100644
--- a/test/SILOptimizer/access_marker_mandatory.swift
+++ b/test/SILOptimizer/access_marker_mandatory.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -parse-as-library -Xllvm -sil-full-demangle -emit-sil -Onone -enforce-exclusivity=checked %s | %FileCheck %s
public struct S {
diff --git a/test/SILOptimizer/access_marker_verify.swift b/test/SILOptimizer/access_marker_verify.swift
index 3ef80fa..3e7cd7f 100644
--- a/test/SILOptimizer/access_marker_verify.swift
+++ b/test/SILOptimizer/access_marker_verify.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-verify-exclusivity -enforce-exclusivity=checked -enable-sil-ownership -emit-silgen -swift-version 4 -parse-as-library %s | %FileCheck %s
// RUN: %target-swift-frontend -enable-verify-exclusivity -enforce-exclusivity=checked -enable-sil-ownership -Onone -emit-sil -swift-version 4 -parse-as-library %s
// RUN: %target-swift-frontend -enable-verify-exclusivity -enforce-exclusivity=checked -enable-sil-ownership -O -emit-sil -swift-version 4 -parse-as-library %s
@@ -754,7 +755,7 @@
// CHECK-NOT: begin_access
// CHECK: store [[PA]] to [init] [[ADR]] : $*@callee_guaranteed () -> @out Int
// CHECK: [[PTR:%.*]] = address_to_pointer [[ADR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
-// CHECK: [[FPTR:%.*]] = thin_function_to_pointer %{{.*}} : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout C, @thick C.Type) -> () to $Builtin.RawPointer
+// CHECK: [[FPTR:%.*]] = thin_function_to_pointer %{{.*}} : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed C, @thick C.Type) -> () to $Builtin.RawPointer
// CHECK: [[ENUM:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[FPTR]] : $Builtin.RawPointer
// CHECK: [[R:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[ENUM]] : $Optional<Builtin.RawPointer>)
// CHECK: return [[R]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
diff --git a/test/SILOptimizer/array_element_propagation.sil b/test/SILOptimizer/array_element_propagation.sil
index 55a6515..438b01a 100644
--- a/test/SILOptimizer/array_element_propagation.sil
+++ b/test/SILOptimizer/array_element_propagation.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -array-element-propagation %s | %FileCheck %s
sil_stage canonical
diff --git a/test/SILOptimizer/bridged_casts_folding.swift b/test/SILOptimizer/bridged_casts_folding.swift
index 9623da3..1716b1f 100644
--- a/test/SILOptimizer/bridged_casts_folding.swift
+++ b/test/SILOptimizer/bridged_casts_folding.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILOptimizer/capture_promotion_generic_context.sil b/test/SILOptimizer/capture_promotion_generic_context.sil
index 845eedf..7287e75 100644
--- a/test/SILOptimizer/capture_promotion_generic_context.sil
+++ b/test/SILOptimizer/capture_promotion_generic_context.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-sil -O -Xllvm -sil-fso-enable-generics=false %s | %FileCheck %s
sil_stage raw
diff --git a/test/SILOptimizer/capture_promotion_generic_context_ownership.sil b/test/SILOptimizer/capture_promotion_generic_context_ownership.sil
index c456d05..e2dc783 100644
--- a/test/SILOptimizer/capture_promotion_generic_context_ownership.sil
+++ b/test/SILOptimizer/capture_promotion_generic_context_ownership.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -emit-sil -O -Xllvm -sil-fso-enable-generics=false %s | %FileCheck %s
sil_stage raw
diff --git a/test/SILOptimizer/cast_folding_no_bridging.sil b/test/SILOptimizer/cast_folding_no_bridging.sil
index 54f6d27..ed7a539 100644
--- a/test/SILOptimizer/cast_folding_no_bridging.sil
+++ b/test/SILOptimizer/cast_folding_no_bridging.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -O -emit-sil %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILOptimizer/cast_folding_objc_generics.swift b/test/SILOptimizer/cast_folding_objc_generics.swift
index 1dd55c6..d6ad317 100644
--- a/test/SILOptimizer/cast_folding_objc_generics.swift
+++ b/test/SILOptimizer/cast_folding_objc_generics.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -O -emit-sil %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILOptimizer/cast_folding_objc_no_foundation.swift b/test/SILOptimizer/cast_folding_objc_no_foundation.swift
index b5304ff..17a88ee 100644
--- a/test/SILOptimizer/cast_folding_objc_no_foundation.swift
+++ b/test/SILOptimizer/cast_folding_objc_no_foundation.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -O -emit-sil %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILOptimizer/dead_code_elimination.sil b/test/SILOptimizer/dead_code_elimination.sil
index fdc3742..535cd1a 100644
--- a/test/SILOptimizer/dead_code_elimination.sil
+++ b/test/SILOptimizer/dead_code_elimination.sil
@@ -1,5 +1,7 @@
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -dce %s | %FileCheck %s
+// REQUIRES: rdar34013900
+
sil_stage canonical
import Builtin
diff --git a/test/SILOptimizer/devirt_covariant_return.swift b/test/SILOptimizer/devirt_covariant_return.swift
index a1f838d..be2da43 100644
--- a/test/SILOptimizer/devirt_covariant_return.swift
+++ b/test/SILOptimizer/devirt_covariant_return.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -O -Xllvm -disable-sil-cm-rr-cm=0 -Xllvm -sil-inline-generics=false -primary-file %s -emit-sil -sil-inline-threshold 1000 -Xllvm -sil-disable-pass=ObjectOutliner -sil-verify-all | %FileCheck %s
// Make sure that we can dig all the way through the class hierarchy and
diff --git a/test/SILOptimizer/devirt_default_case.swift b/test/SILOptimizer/devirt_default_case.swift
index f5a2126..5d86209 100644
--- a/test/SILOptimizer/devirt_default_case.swift
+++ b/test/SILOptimizer/devirt_default_case.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil -enable-testing %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
diff --git a/test/SILOptimizer/devirt_nested_class.swift b/test/SILOptimizer/devirt_nested_class.swift
index e4e1fd9..520ffc6 100644
--- a/test/SILOptimizer/devirt_nested_class.swift
+++ b/test/SILOptimizer/devirt_nested_class.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s
fileprivate class Outer<T> {
diff --git a/test/SILOptimizer/devirt_protocol_method_invocations.swift b/test/SILOptimizer/devirt_protocol_method_invocations.swift
index 92d38bf..d05e1ba 100644
--- a/test/SILOptimizer/devirt_protocol_method_invocations.swift
+++ b/test/SILOptimizer/devirt_protocol_method_invocations.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
protocol PPP {
diff --git a/test/SILOptimizer/devirt_speculative_nested.swift b/test/SILOptimizer/devirt_speculative_nested.swift
index ea35da2..41bbdfa 100644
--- a/test/SILOptimizer/devirt_speculative_nested.swift
+++ b/test/SILOptimizer/devirt_speculative_nested.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend %s -parse-as-library -O -emit-sil | %FileCheck %s
// RUN: %target-swift-frontend %s -parse-as-library -Osize -emit-sil
//
diff --git a/test/SILOptimizer/devirt_value_metatypes.swift b/test/SILOptimizer/devirt_value_metatypes.swift
index 93d6b01..69ce24f 100644
--- a/test/SILOptimizer/devirt_value_metatypes.swift
+++ b/test/SILOptimizer/devirt_value_metatypes.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s
open class A {
diff --git a/test/SILOptimizer/devirt_witness_method_conformance.swift b/test/SILOptimizer/devirt_witness_method_conformance.swift
index 61cb7ae..b8f8c66 100644
--- a/test/SILOptimizer/devirt_witness_method_conformance.swift
+++ b/test/SILOptimizer/devirt_witness_method_conformance.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -emit-ir -primary-file %s | %FileCheck %s
// This is a swift file because the crash doesn't reproduce with SIL.
@inline(never)
diff --git a/test/SILOptimizer/globalopt-iter.sil b/test/SILOptimizer/globalopt-iter.sil
index b69962d..9daabd7 100644
--- a/test/SILOptimizer/globalopt-iter.sil
+++ b/test/SILOptimizer/globalopt-iter.sil
@@ -8,7 +8,8 @@
// CHECK: sil @patatino : $@convention(thin) () -> () {
// CHECK: bb0:
-// CHECK-NEXT: %0 = global_value @patatinoTv_ : $B
+// CHECK-NEXT: integer_literal
+// CHECK-NEXT: global_value @patatinoTv_ : $B
// CHECK-NEXT: strong_retain
// CHECK-NEXT: strong_release
// CHECK-NEXT: tuple ()
@@ -16,9 +17,10 @@
// CHECK-NEXT: }
sil @patatino : $@convention(thin) () -> () {
- %1 = alloc_ref [stack] $B
+ %0 = integer_literal $Builtin.Word, 0
+ %1 = alloc_ref [tail_elems $Int64 * %0 : $Builtin.Word] $B
set_deallocating %1 : $B
- dealloc_ref [stack] %1 : $B
+ dealloc_ref %1 : $B
%45 = tuple ()
return %45 : $()
}
diff --git a/test/SILOptimizer/let_properties_opts.swift b/test/SILOptimizer/let_properties_opts.swift
index 9351c22..d0c96e8 100644
--- a/test/SILOptimizer/let_properties_opts.swift
+++ b/test/SILOptimizer/let_properties_opts.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend %s -O -emit-sil | %FileCheck -check-prefix=CHECK-WMO %s
// RUN: %target-swift-frontend -primary-file %s -O -emit-sil | %FileCheck %s
diff --git a/test/SILOptimizer/mandatory_inlining.swift b/test/SILOptimizer/mandatory_inlining.swift
index a765c18..0f5d34d 100644
--- a/test/SILOptimizer/mandatory_inlining.swift
+++ b/test/SILOptimizer/mandatory_inlining.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -enable-sil-ownership -sil-verify-all -primary-file %s -emit-sil -o - -verify | %FileCheck %s
// These tests are deliberately shallow, because I do not want to depend on the
diff --git a/test/SILOptimizer/objectoutliner.sil b/test/SILOptimizer/objectoutliner.sil
index 7e94f44..c13e622 100644
--- a/test/SILOptimizer/objectoutliner.sil
+++ b/test/SILOptimizer/objectoutliner.sil
@@ -35,9 +35,10 @@
// CHECK: return
sil @outline_global_simple : $@convention(thin) () -> () {
bb0:
+ %0 = integer_literal $Builtin.Word, 0
%1 = integer_literal $Builtin.Int64, 1
%4 = struct $Int64 (%1 : $Builtin.Int64)
- %7 = alloc_ref $Obj
+ %7 = alloc_ref [tail_elems $Int64 * %0 : $Builtin.Word] $Obj
%9 = ref_element_addr %7 : $Obj, #Obj.value
store %4 to %9 : $*Int64
strong_release %7 : $Obj
@@ -83,9 +84,10 @@
// CHECK-NEXT: return
sil @handle_deallocation : $@convention(thin) () -> () {
bb0:
+ %0 = integer_literal $Builtin.Word, 0
%3 = integer_literal $Builtin.Int64, 3
%4 = struct $Int64 (%3 : $Builtin.Int64)
- %5 = alloc_ref $Obj
+ %5 = alloc_ref [tail_elems $Int64 * %0 : $Builtin.Word] $Obj
%6 = ref_element_addr %5 : $Obj, #Obj.value
store %4 to %6 : $*Int64
set_deallocating %5 : $Obj
@@ -94,15 +96,32 @@
return %r : $()
}
+// CHECK-LABEL: sil @dont_outline_without_tail_elems
+// CHECK: alloc_ref
+// CHECK: store
+// CHECK: return
+sil @dont_outline_without_tail_elems : $@convention(thin) () -> () {
+bb0:
+ %1 = integer_literal $Builtin.Int64, 1
+ %4 = struct $Int64 (%1 : $Builtin.Int64)
+ %7 = alloc_ref $Obj
+ %9 = ref_element_addr %7 : $Obj, #Obj.value
+ store %4 to %9 : $*Int64
+ strong_release %7 : $Obj
+ %r = tuple ()
+ return %r : $()
+}
+
// CHECK-LABEL: sil @dont_outline_global_double_store
// CHECK: alloc_ref
// CHECK: store
// CHECK: return
sil @dont_outline_global_double_store : $@convention(thin) () -> () {
bb0:
+ %0 = integer_literal $Builtin.Word, 0
%1 = integer_literal $Builtin.Int64, 1
%4 = struct $Int64 (%1 : $Builtin.Int64)
- %7 = alloc_ref $Obj
+ %7 = alloc_ref [tail_elems $Int64 * %0 : $Builtin.Word] $Obj
%9 = ref_element_addr %7 : $Obj, #Obj.value
store %4 to %9 : $*Int64
store %4 to %9 : $*Int64
@@ -116,9 +135,10 @@
// CHECK: return
sil @dont_outline_global_missing_store : $@convention(thin) () -> () {
bb0:
+ %0 = integer_literal $Builtin.Word, 0
%1 = integer_literal $Builtin.Int64, 1
%4 = struct $Int64 (%1 : $Builtin.Int64)
- %7 = alloc_ref $Obj
+ %7 = alloc_ref [tail_elems $Int64 * %0 : $Builtin.Word] $Obj
%9 = ref_element_addr %7 : $Obj, #Obj.value
strong_release %7 : $Obj
%r = tuple ()
@@ -148,9 +168,10 @@
// CHECK: return
sil @dont_outline_global_unknown_addr_use : $@convention(thin) () -> () {
bb0:
+ %0 = integer_literal $Builtin.Word, 0
%1 = integer_literal $Builtin.Int64, 1
%4 = struct $Int64 (%1 : $Builtin.Int64)
- %7 = alloc_ref $Obj
+ %7 = alloc_ref [tail_elems $Int64 * %0 : $Builtin.Word] $Obj
%9 = ref_element_addr %7 : $Obj, #Obj.value
store %4 to %9 : $*Int64
%10 = address_to_pointer %9 : $*Int64 to $Builtin.RawPointer
@@ -167,8 +188,9 @@
sil @dont_outline_global_escaping_obj : $@convention(thin) (@inout Obj) -> () {
bb0(%0: $*Obj):
%1 = integer_literal $Builtin.Int64, 1
+ %2 = integer_literal $Builtin.Word, 0
%4 = struct $Int64 (%1 : $Builtin.Int64)
- %7 = alloc_ref $Obj
+ %7 = alloc_ref [tail_elems $Int64 * %2 : $Builtin.Word] $Obj
%9 = ref_element_addr %7 : $Obj, #Obj.value
store %4 to %9 : $*Int64
store %7 to %0 : $*Obj
diff --git a/test/SILOptimizer/performance_inliner.sil b/test/SILOptimizer/performance_inliner.sil
index 6984d00..acdedf0 100644
--- a/test/SILOptimizer/performance_inliner.sil
+++ b/test/SILOptimizer/performance_inliner.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -inline -sil-combine | %FileCheck %s
sil_stage canonical
diff --git a/test/SILOptimizer/plus_zero_access_enforcement_noescape.swift b/test/SILOptimizer/plus_zero_access_enforcement_noescape.swift
new file mode 100644
index 0000000..07fb511
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_access_enforcement_noescape.swift
@@ -0,0 +1,593 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -enforce-exclusivity=checked -Onone -emit-sil -swift-version 4 -verify -parse-as-library %s
+// RUN: %target-swift-frontend -enable-sil-ownership -enforce-exclusivity=checked -Onone -emit-sil -swift-version 3 -parse-as-library %s | %FileCheck %s
+// REQUIRES: asserts
+
+// This tests SILGen and AccessEnforcementSelection as a single set of tests.
+// (Some static/dynamic enforcement selection is done in SILGen, and some is
+// deferred. That may change over time but we want the outcome to be the same).
+//
+// These tests attempt to fully cover the possibilities of reads and
+// modifications to captures along with `inout` arguments on both the caller and
+// callee side.
+
+// Helper
+func doOne(_ f: () -> ()) {
+ f()
+}
+
+// Helper
+func doTwo(_: ()->(), _: ()->()) {}
+
+// Helper
+func doOneInout(_: ()->(), _: inout Int) {}
+
+// Error: Cannot capture nonescaping closure.
+// This triggers an early diagnostics, so it's handled in inout_capture_disgnostics.swift.
+// func reentrantCapturedNoescape(fn: (() -> ()) -> ()) {
+// let c = { fn {} }
+// fn(c)
+// }
+
+// Helper
+struct Frob {
+ mutating func outerMut() { doOne { innerMut() } }
+ mutating func innerMut() {}
+}
+
+// Allow nested mutable access via closures.
+func nestedNoEscape(f: inout Frob) {
+ doOne { f.outerMut() }
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape14nestedNoEscape1fyAA4FrobVz_tF : $@convention(thin) (@inout Frob) -> () {
+// CHECK-NOT: begin_access
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14nestedNoEscape1fyAA4FrobVz_tF'
+
+// closure #1 in nestedNoEscape(f:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape14nestedNoEscape1fyAA4FrobVz_tFyyXEfU_ : $@convention(thin) (@inout_aliasable Frob) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Frob
+// CHECK: %{{.*}} = apply %{{.*}}([[ACCESS]]) : $@convention(method) (@inout Frob) -> ()
+// CHECK: end_access [[ACCESS]] : $*Frob
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14nestedNoEscape1fyAA4FrobVz_tFyyXEfU_'
+
+// Allow aliased noescape reads.
+func readRead() {
+ var x = 3
+ // Inside each closure: [read] [static]
+ doTwo({ _ = x }, { _ = x })
+ x = 42
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape8readReadyyF : $@convention(thin) () -> () {
+// CHECK: [[ALLOC:%.*]] = alloc_stack $Int, var, name "x"
+// CHECK-NOT: begin_access
+// CHECK: apply
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape8readReadyyF'
+
+// closure #1 in readRead()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape8readReadyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK-NOT: begin_access [read] [dynamic]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape8readReadyyFyyXEfU_'
+
+// closure #2 in readRead()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape8readReadyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK-NOT: begin_access [read] [dynamic]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape8readReadyyFyyXEfU0_'
+
+// Allow aliased noescape reads of an `inout` arg.
+func inoutReadRead(x: inout Int) {
+ // Inside each closure: [read] [static]
+ doTwo({ _ = x }, { _ = x })
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape09inoutReadE01xySiz_tF : $@convention(thin) (@inout Int) -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape09inoutReadE01xySiz_tF'
+
+// closure #1 in inoutReadRead(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape09inoutReadE01xySiz_tFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK-NOT: begin_access [read] [dynamic]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape09inoutReadE01xySiz_tFyyXEfU_'
+
+// closure #2 in inoutReadRead(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape09inoutReadE01xySiz_tFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK-NOT: begin_access [read] [dynamic]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape09inoutReadE01xySiz_tFyyXEfU0_'
+
+// Allow aliased noescape read + boxed read.
+func readBoxRead() {
+ var x = 3
+ let c = { _ = x }
+ // Inside may-escape closure `c`: [read] [dynamic]
+ // Inside never-escape closure: [read] [dynamic]
+ doTwo(c, { _ = x })
+ x = 42
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape11readBoxReadyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape11readBoxReadyyF'
+
+// closure #1 in readBoxRead()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape11readBoxReadyyFyycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+// CHECK: [[ADDR:%.*]] = project_box %0 : ${ var Int }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[ADDR]] : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape11readBoxReadyyFyycfU_'
+
+// closure #2 in readBoxRead()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape11readBoxReadyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape11readBoxReadyyFyyXEfU0_'
+
+// Error: cannout capture inout.
+//
+// func inoutReadReadBox(x: inout Int) {
+// let c = { _ = x }
+// doTwo({ _ = x }, c)
+// }
+
+// Allow aliased noescape read + write.
+func readWrite() {
+ var x = 3
+ // Inside closure 1: [read] [static]
+ // Inside closure 2: [modify] [static]
+ doTwo({ _ = x }, { x = 42 })
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape9readWriteyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape9readWriteyyF'
+
+// closure #1 in readWrite()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape9readWriteyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK-NOT: [[ACCESS:%.*]] = begin_access [read] [dynamic]
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape9readWriteyyFyyXEfU_'
+
+// closure #2 in readWrite()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape9readWriteyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK-NOT: [[ACCESS:%.*]] = begin_access [modify] [dynamic]
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape9readWriteyyFyyXEfU0_'
+
+// Allow aliased noescape read + write of an `inout` arg.
+func inoutReadWrite(x: inout Int) {
+ // Inside closure 1: [read] [static]
+ // Inside closure 2: [modify] [static]
+ doTwo({ _ = x }, { x = 3 })
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape14inoutReadWrite1xySiz_tF : $@convention(thin) (@inout Int) -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14inoutReadWrite1xySiz_tF'
+
+// closure #1 in inoutReadWrite(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape14inoutReadWrite1xySiz_tFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14inoutReadWrite1xySiz_tFyyXEfU_'
+
+// closure #2 in inoutReadWrite(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape14inoutReadWrite1xySiz_tFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14inoutReadWrite1xySiz_tFyyXEfU0_'
+
+
+func readBoxWrite() {
+ var x = 3
+ let c = { _ = x }
+ // Inside may-escape closure `c`: [read] [dynamic]
+ // Inside never-escape closure: [modify] [dynamic]
+ doTwo(c, { x = 42 })
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape12readBoxWriteyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape12readBoxWriteyyF'
+
+// closure #1 in readBoxWrite()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape12readBoxWriteyyFyycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+// CHECK: [[ADDR:%.*]] = project_box %0 : ${ var Int }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[ADDR]] : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape12readBoxWriteyyFyycfU_'
+
+// closure #2 in readBoxWrite()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape12readBoxWriteyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape12readBoxWriteyyFyyXEfU0_'
+
+// Error: cannout capture inout.
+// func inoutReadBoxWrite(x: inout Int) {
+// let c = { _ = x }
+// doTwo({ x = 42 }, c)
+// }
+
+func readWriteBox() {
+ var x = 3
+ let c = { x = 42 }
+ // Inside may-escape closure `c`: [modify] [dynamic]
+ // Inside never-escape closure: [read] [dynamic]
+ doTwo({ _ = x }, c)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape12readWriteBoxyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT2]], [[CVT1]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape12readWriteBoxyyF'
+
+// closure #1 in readWriteBox()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape12readWriteBoxyyFyycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+// CHECK: [[ADDR:%.*]] = project_box %0 : ${ var Int }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape12readWriteBoxyyFyycfU_'
+
+// closure #2 in readWriteBox()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape12readWriteBoxyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape12readWriteBoxyyFyyXEfU0_'
+
+// Error: cannout capture inout.
+// func inoutReadWriteBox(x: inout Int) {
+// let c = { x = 42 }
+// doTwo({ _ = x }, c)
+// }
+
+// Error: noescape read + write inout.
+func readWriteInout() {
+ var x = 3
+ // Around the call: [modify] [static]
+ // Inside closure: [modify] [static]
+ // expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
+ // expected-note@+1{{conflicting access is here}}
+ doOneInout({ _ = x }, &x)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape14readWriteInoutyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: apply %{{.*}}([[CVT]], [[ACCESS2]])
+// CHECK: end_access [[ACCESS2]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14readWriteInoutyyF'
+
+// closure #1 in readWriteInout()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape14readWriteInoutyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape14readWriteInoutyyFyyXEfU_'
+
+// Error: noescape read + write inout of an inout.
+func inoutReadWriteInout(x: inout Int) {
+ // Around the call: [modify] [static]
+ // Inside closure: [modify] [static]
+ // expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
+ // expected-note@+1{{conflicting access is here}}
+ doOneInout({ _ = x }, &x)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape19inoutReadWriteInout1xySiz_tF : $@convention(thin) (@inout Int) -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: apply %{{.*}}([[CVT]], [[ACCESS2]])
+// CHECK: end_access [[ACCESS2]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape19inoutReadWriteInout1xySiz_tF'
+
+// closure #1 in inoutReadWriteInout(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape19inoutReadWriteInout1xySiz_tFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape19inoutReadWriteInout1xySiz_tFyyXEfU_'
+
+// Traps on boxed read + write inout.
+// Covered by Interpreter/enforce_exclusive_access.swift.
+func readBoxWriteInout() {
+ var x = 3
+ let c = { _ = x }
+ // Around the call: [modify] [dynamic]
+ // Inside closure: [read] [dynamic]
+ doOneInout(c, &x)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape17readBoxWriteInoutyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] %1 : $*Int
+// CHECK: apply %{{.*}}([[CVT]], [[ACCESS]])
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape17readBoxWriteInoutyyF'
+
+// closure #1 in readBoxWriteInout()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape17readBoxWriteInoutyyFyycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+// CHECK: [[ADDR:%.*]] = project_box %0 : ${ var Int }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[ADDR]] : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape17readBoxWriteInoutyyFyycfU_'
+
+// Error: inout cannot be captured.
+// This triggers an early diagnostics, so it's handled in inout_capture_disgnostics.swift.
+// func inoutReadBoxWriteInout(x: inout Int) {
+// let c = { _ = x }
+// doOneInout(c, &x)
+// }
+
+// Allow aliased noescape write + write.
+func writeWrite() {
+ var x = 3
+ // Inside closure 1: [modify] [static]
+ // Inside closure 2: [modify] [static]
+ doTwo({ x = 42 }, { x = 87 })
+ _ = x
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape10writeWriteyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape10writeWriteyyF'
+
+// closure #1 in writeWrite()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape10writeWriteyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape10writeWriteyyFyyXEfU_'
+
+// closure #2 in writeWrite()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape10writeWriteyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape10writeWriteyyFyyXEfU0_'
+
+
+// Allow aliased noescape write + write of an `inout` arg.
+func inoutWriteWrite(x: inout Int) {
+ // Inside closure 1: [modify] [static]
+ // Inside closure 2: [modify] [static]
+ doTwo({ x = 42}, { x = 87 })
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape010inoutWriteE01xySiz_tF : $@convention(thin) (@inout Int) -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT1]], [[CVT2]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape010inoutWriteE01xySiz_tF'
+
+// closure #1 in inoutWriteWrite(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape010inoutWriteE01xySiz_tFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape010inoutWriteE01xySiz_tFyyXEfU_'
+
+// closure #2 in inoutWriteWrite(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape010inoutWriteE01xySiz_tFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape010inoutWriteE01xySiz_tFyyXEfU0_'
+
+// Traps on aliased boxed write + noescape write.
+// Covered by Interpreter/enforce_exclusive_access.swift.
+func writeWriteBox() {
+ var x = 3
+ let c = { x = 87 }
+ // Inside may-escape closure `c`: [modify] [dynamic]
+ // Inside never-escape closure: [modify] [dynamic]
+ doTwo({ x = 42 }, c)
+ _ = x
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape13writeWriteBoxyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[PA2:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT2:%.*]] = convert_escape_to_noescape [[PA2]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[CVT1:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[CVT2]], [[CVT1]])
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape13writeWriteBoxyyF'
+
+// closure #1 in writeWriteBox()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape13writeWriteBoxyyFyycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+// CHECK: [[ADDR:%.*]] = project_box %0 : ${ var Int }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape13writeWriteBoxyyFyycfU_'
+
+// closure #2 in writeWriteBox()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape13writeWriteBoxyyFyyXEfU0_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape13writeWriteBoxyyFyyXEfU0_'
+
+// Error: inout cannot be captured.
+// func inoutWriteWriteBox(x: inout Int) {
+// let c = { x = 87 }
+// doTwo({ x = 42 }, c)
+// }
+
+// Error: on noescape write + write inout.
+func writeWriteInout() {
+ var x = 3
+ // Around the call: [modify] [static]
+ // Inside closure: [modify] [static]
+ // expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
+ // expected-note@+1{{conflicting access is here}}
+ doOneInout({ x = 42 }, &x)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape15writeWriteInoutyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: apply %{{.*}}([[CVT]], [[ACCESS2]])
+// CHECK: end_access [[ACCESS2]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape15writeWriteInoutyyF'
+
+// closure #1 in writeWriteInout()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape15writeWriteInoutyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape15writeWriteInoutyyFyyXEfU_'
+
+// Error: on noescape write + write inout.
+func inoutWriteWriteInout(x: inout Int) {
+ // Around the call: [modify] [static]
+ // Inside closure: [modify] [static]
+ // expected-error@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
+ // expected-note@+1{{conflicting access is here}}
+ doOneInout({ x = 42 }, &x)
+}
+
+// inoutWriteWriteInout(x:)
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape010inoutWriteE5Inout1xySiz_tF : $@convention(thin) (@inout Int) -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[ACCESS2:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: apply %{{.*}}([[CVT]], [[ACCESS2]])
+// CHECK: end_access [[ACCESS2]]
+// CHECK-LABEL: // end sil function '$S27access_enforcement_noescape010inoutWriteE5Inout1xySiz_tF'
+
+// closure #1 in inoutWriteWriteInout(x:)
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape010inoutWriteE5Inout1xySiz_tFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape010inoutWriteE5Inout1xySiz_tFyyXEfU_'
+
+// Traps on boxed write + write inout.
+// Covered by Interpreter/enforce_exclusive_access.swift.
+func writeBoxWriteInout() {
+ var x = 3
+ let c = { x = 42 }
+ // Around the call: [modify] [dynamic]
+ // Inside closure: [modify] [dynamic]
+ doOneInout(c, &x)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape18writeBoxWriteInoutyyF : $@convention(thin) () -> () {
+// CHECK: [[PA1:%.*]] = partial_apply [callee_guaranteed]
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA1]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] %1 : $*Int
+// CHECK: apply %{{.*}}([[CVT]], [[ACCESS]])
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape18writeBoxWriteInoutyyF'
+
+// closure #1 in writeBoxWriteInout()
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape18writeBoxWriteInoutyyFyycfU_ : $@convention(thin) (@guaranteed { var Int }) -> () {
+// CHECK: [[ADDR:%.*]] = project_box %0 : ${ var Int }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADDR]] : $*Int
+// CHECK: end_access [[ACCESS]]
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape18writeBoxWriteInoutyyFyycfU_'
+
+// Error: Cannot capture inout
+// This triggers an early diagnostics, so it's handled in inout_capture_disgnostics.swift.
+// func inoutWriteBoxWriteInout(x: inout Int) {
+// let c = { x = 42 }
+// doOneInout(c, &x)
+// }
+
+// Helper
+func doBlockInout(_: @convention(block) ()->(), _: inout Int) {}
+
+func readBlockWriteInout() {
+ var x = 3
+ // Around the call: [modify] [static]
+ // Inside closure: [read] [static]
+ // expected-warning@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
+ // expected-note@+1{{conflicting access is here}}
+ doBlockInout({ _ = x }, &x)
+}
+
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape19readBlockWriteInoutyyF : $@convention(thin) () -> () {
+// CHECK: [[F1:%.*]] = function_ref @$S27access_enforcement_noescape19readBlockWriteInoutyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> ()
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F1]](%0) : $@convention(thin) (@inout_aliasable Int) -> ()
+// CHECK-NOT: begin_access
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: apply
+// CHECK: end_access [[WRITE]] : $*Int
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape19readBlockWriteInoutyyF'
+
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape19readBlockWriteInoutyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: begin_access [read] [static] %0 : $*Int
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape19readBlockWriteInoutyyFyyXEfU_'
+
+// Test AccessSummaryAnalysis.
+//
+// The captured @inout_aliasable argument to `doOne` is re-partially applied,
+// then stored is a box before passing it to doBlockInout.
+func noEscapeBlock() {
+ var x = 3
+ doOne {
+ // expected-warning@+2{{overlapping accesses to 'x', but modification requires exclusive access; consider copying to a local variable}}
+ // expected-note@+1{{conflicting access is here}}
+ doBlockInout({ _ = x }, &x)
+ }
+}
+// CHECK-LABEL: sil hidden @$S27access_enforcement_noescape13noEscapeBlockyyF : $@convention(thin) () -> () {
+// CHECK: partial_apply [callee_guaranteed]
+// CHECK-NOT: begin_access
+// CHECK: apply
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape13noEscapeBlockyyF'
+
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape13noEscapeBlockyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: [[F1:%.*]] = function_ref @$S27access_enforcement_noescape13noEscapeBlockyyFyyXEfU_yyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> ()
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [[F1]](%0) : $@convention(thin) (@inout_aliasable Int) -> ()
+// CHECK: [[CVT:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> () to $@noescape @callee_guaranteed () -> ()
+// CHECK: [[STORAGE:%.*]] = alloc_stack $@block_storage @noescape @callee_guaranteed () -> ()
+// CHECK: [[ADDR:%.*]] = project_block_storage [[STORAGE]] : $*@block_storage @noescape @callee_guaranteed () -> ()
+// CHECK: store [[CVT]] to [[ADDR]] : $*@noescape @callee_guaranteed () -> ()
+// CHECK: [[F2:%.*]] = function_ref @$SIg_IyB_TR : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_guaranteed () -> ()) -> ()
+// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[STORAGE]] : $*@block_storage @noescape @callee_guaranteed () -> (), invoke [[F2]] : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_guaranteed () -> ()) -> (), type $@convention(block) @noescape () -> ()
+// CHECK: [[ARG:%.*]] = copy_block [[BLOCK]] : $@convention(block) @noescape () -> ()
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] %0 : $*Int
+// CHECK: apply %{{.*}}([[ARG]], [[WRITE]]) : $@convention(thin) (@guaranteed @convention(block) @noescape () -> (), @inout Int) -> ()
+// CHECK: end_access [[WRITE]] : $*Int
+// CHECK: dealloc_stack [[STORAGE]] : $*@block_storage @noescape @callee_guaranteed () -> ()
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape13noEscapeBlockyyFyyXEfU_'
+
+// CHECK-LABEL: sil private @$S27access_enforcement_noescape13noEscapeBlockyyFyyXEfU_yyXEfU_ : $@convention(thin) (@inout_aliasable Int) -> () {
+// CHECK: begin_access [read] [static] %0 : $*Int
+// CHECK-LABEL: } // end sil function '$S27access_enforcement_noescape13noEscapeBlockyyFyyXEfU_yyXEfU_'
diff --git a/test/SILOptimizer/plus_zero_access_marker_mandatory.swift b/test/SILOptimizer/plus_zero_access_marker_mandatory.swift
new file mode 100644
index 0000000..dde3001
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_access_marker_mandatory.swift
@@ -0,0 +1,86 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-as-library -Xllvm -sil-full-demangle -emit-sil -Onone -enforce-exclusivity=checked %s | %FileCheck %s
+
+public struct S {
+ var i: Int
+ var o: AnyObject
+}
+
+// CHECK-LABEL: sil [noinline] @$S23access_marker_mandatory5initSyAA1SVSi_yXltF : $@convention(thin) (Int, @guaranteed AnyObject) -> @owned S {
+// CHECK: bb0(%0 : $Int, %1 : $AnyObject):
+// CHECK: [[STK:%.*]] = alloc_stack $S, var, name "s"
+// CHECK: cond_br %{{.*}}, bb1, bb2
+// CHECK: bb1:
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[STK]] : $*S
+// CHECK: store %{{.*}} to [[WRITE]] : $*S
+// CHECK: end_access [[WRITE]]
+// CHECK: bb2:
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[STK]] : $*S
+// CHECK: store %{{.*}} to [[WRITE]] : $*S
+// CHECK: end_access [[WRITE]]
+// CHECK: bb3:
+// CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*S
+// CHECK: [[RET:%.*]] = load [[READ]] : $*S
+// CHECK: end_access [[READ]]
+// CHECK: destroy_addr [[STK]]
+// CHECK: dealloc_stack [[STK]]
+// CHECK: return [[RET]] : $S
+// CHECK-LABEL: } // end sil function '$S23access_marker_mandatory5initSyAA1SVSi_yXltF'
+@inline(never)
+public func initS(_ x: Int, _ o: AnyObject) -> S {
+ var s: S
+ if x == 0 {
+ s = S(i: 1, o: o)
+ } else {
+ s = S(i: x, o: o)
+ }
+ return s
+}
+
+@inline(never)
+func takeS(_ s: S) {}
+
+// CHECK-LABEL: sil @$S23access_marker_mandatory14modifyAndReadS1oyyXl_tF : $@convention(thin) (@guaranteed AnyObject) -> () {
+// CHECK: bb0(%0 : $AnyObject):
+// CHECK: [[STK:%.*]] = alloc_stack $S, var, name "s"
+// CHECK: [[FINIT:%.*]] = function_ref @$S23access_marker_mandatory5initSyAA1SVSi_yXltF : $@convention(thin) (Int, @guaranteed AnyObject) -> @owned S
+// CHECK: [[INITS:%.*]] = apply [[FINIT]](%{{.*}}, %0) : $@convention(thin) (Int, @guaranteed AnyObject) -> @owned S
+// CHECK: store [[INITS]] to [[STK]] : $*S
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[STK]] : $*S
+// CHECK: [[ADDRI:%.*]] = struct_element_addr [[WRITE]] : $*S, #S.i
+// CHECK: store %{{.*}} to [[ADDRI]] : $*Int
+// CHECK: end_access [[WRITE]]
+// CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*S
+// CHECK: end_access [[READ]]
+// CHECK: [[FTAKE:%.*]] = function_ref @$S23access_marker_mandatory5takeSyyAA1SVF : $@convention(thin) (@guaranteed S) -> ()
+// CHECK: apply [[FTAKE]](%{{.*}}) : $@convention(thin) (@guaranteed S) -> ()
+// CHECK-LABEL: } // end sil function '$S23access_marker_mandatory14modifyAndReadS1oyyXl_tF'
+public func modifyAndReadS(o: AnyObject) {
+ var s = initS(3, o)
+ s.i = 42
+ takeS(s)
+}
+
+// Test capture promotion followed by stack promotion.
+// Access enforcement selection must run after capture promotion
+// so that we never stack promote something with dynamic access.
+// Otherwise, we may try to convert the access to [deinit] which
+// doesn't make sense dynamically.
+//
+// CHECK-LABEL: sil hidden @$S23access_marker_mandatory19captureStackPromoteSiycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> Int {
+// CHECK-LABEL: bb0:
+// CHECK: [[STK:%.*]] = alloc_stack $Int, var, name "x"
+// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[STK]] : $*Int
+// CHECK: store %{{.*}} to [[WRITE]] : $*Int
+// CHECK: end_access [[WRITE]] : $*Int
+// CHECK: [[F:%.*]] = function_ref @$S23access_marker_mandatory19captureStackPromoteSiycyFSiycfU_Tf2i_n : $@convention(thin) (Int) -> Int
+// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]](%{{.*}}) : $@convention(thin) (Int) -> Int
+// CHECK: dealloc_stack [[STK]] : $*Int
+// CHECK: return [[C]] : $@callee_guaranteed () -> Int
+// CHECK-LABEL: } // end sil function '$S23access_marker_mandatory19captureStackPromoteSiycyF'
+func captureStackPromote() -> () -> Int {
+ var x = 1
+ x = 2
+ let f = { x }
+ return f
+}
diff --git a/test/SILOptimizer/plus_zero_access_marker_verify.swift b/test/SILOptimizer/plus_zero_access_marker_verify.swift
new file mode 100644
index 0000000..f24f230
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_access_marker_verify.swift
@@ -0,0 +1,1000 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-verify-exclusivity -enforce-exclusivity=checked -enable-sil-ownership -emit-silgen -swift-version 4 -parse-as-library %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-verify-exclusivity -enforce-exclusivity=checked -enable-sil-ownership -Onone -emit-sil -swift-version 4 -parse-as-library %s
+// RUN: %target-swift-frontend -enable-verify-exclusivity -enforce-exclusivity=checked -enable-sil-ownership -O -emit-sil -swift-version 4 -parse-as-library %s
+// REQUIRES: asserts
+
+// Test the combination of SILGen + DiagnoseStaticExclusivity with verification.
+//
+// This is a collection of tests that cover SILGen cases that require special
+// handling for exclusivity verification. SILGen must generate access markers,
+// possibly unenforced, to satisfy the verification run during the
+// DiagnoseStaticExclusivity pass.
+//
+// These cases are mostly covered by existing SILGen tests, but need to be
+// repeated here to ensure they are run with exclusivity verification enabled.
+import SwiftShims
+
+protocol P {}
+struct StructP : P {}
+
+protocol PBar {
+ func bar()
+}
+
+class BaseClass {
+ init() {}
+}
+class SubClass : BaseClass {
+ override required init() {}
+}
+
+enum E {
+case V(Int)
+}
+
+func takesClosure(_ f: () -> ()) {
+ f()
+}
+
+// --- struct initialization.
+struct StructOfInt {
+ var i: Int
+
+ init() {
+ i = 1
+ }
+
+ mutating func changeMe() {
+ i = 3
+ }
+}
+// The verifier ignores the load of the self box.
+// CHECK-LABEL: sil hidden @$S20access_marker_verify11StructOfIntVACycfC : $@convention(method) (@thin StructOfInt.Type) -> StructOfInt {
+// CHECK: bb0(%0 : @trivial $@thin StructOfInt.Type):
+// CHECK: [[BOX:%.*]] = alloc_box ${ var StructOfInt }, var, name "self"
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]] : ${ var StructOfInt }
+// CHECK: [[PROJ:%.*]] = project_box [[UNINIT]] : ${ var StructOfInt }, 0
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJ]] : $*StructOfInt
+// CHECK: [[ADR:%.*]] = struct_element_addr [[ACCESS]] : $*StructOfInt, #StructOfInt.i
+// CHECK: assign %{{.*}} to [[ADR]] : $*Int
+// CHECK: end_access [[ACCESS]] : $*StructOfInt
+// CHECK-NOT: begin_access
+// CHECK: [[VAL:%.*]] = load [trivial] [[PROJ]] : $*StructOfInt
+// CHECK: destroy_value [[UNINIT]] : ${ var StructOfInt }
+// CHECK: return [[VAL]] : $StructOfInt
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify11StructOfIntVACycfC'
+
+// --- class initialization.
+class SuperHasInt {
+ var i: Int
+
+ init() {
+ i = 3
+ }
+}
+
+class SubHasInt : SuperHasInt {
+ var j: Int
+
+ override init() {
+ j = 4
+ super.init()
+ }
+
+ init(x: Int) {
+ j = x
+ super.init()
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify11SuperHasIntCACycfc : $@convention(method) (@owned SuperHasInt) -> @owned SuperHasInt {
+// CHECK: bb0(%0 : @owned $SuperHasInt):
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [rootself] %0 : $SuperHasInt
+// CHECK: [[BORROW:%.*]] = begin_borrow [[UNINIT]] : $SuperHasInt
+// CHECK: [[ADR:%.*]] = ref_element_addr [[BORROW]] : $SuperHasInt, #SuperHasInt.i
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADR]] : $*Int
+// CHECK: assign %{{.*}} to [[ACCESS]] : $*Int
+// CHECK: end_access [[ACCESS]] : $*Int
+// CHECK: end_borrow [[BORROW]] from [[UNINIT]] : $SuperHasInt, $SuperHasInt
+// CHECK-NOT: begin_access
+// CHECK: [[VAL:%.*]] = copy_value [[UNINIT]] : $SuperHasInt
+// CHECK: destroy_value [[UNINIT]] : $SuperHasInt
+// CHECK: return [[VAL]] : $SuperHasInt
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify11SuperHasIntCACycfc'
+
+// CHECK-LABEL: sil hidden @$S20access_marker_verify9SubHasIntCACycfc : $@convention(method) (@owned SubHasInt) -> @owned SubHasInt {
+// CHECK: bb0(%0 : @owned $SubHasInt):
+// CHECK: [[BOX:%.*]] = alloc_box ${ var SubHasInt }, let, name "self"
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [derivedself] [[BOX]] : ${ var SubHasInt }
+// CHECK: [[PROJ:%.*]] = project_box [[UNINIT]] : ${ var SubHasInt }, 0
+// CHECK-NOT: begin_access
+// CHECK: store %0 to [init] [[PROJ]] : $*SubHasInt
+// CHECK-NOT: begin_access
+// CHECK: [[BORROW:%.*]] = load_borrow [[PROJ]] : $*SubHasInt
+// CHECK: [[ADR:%.*]] = ref_element_addr [[BORROW]] : $SubHasInt, #SubHasInt.j
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADR]] : $*Int
+// CHECK: assign %{{.*}} to [[ACCESS]] : $*Int
+// CHECK: end_access [[ACCESS]] : $*Int
+// CHECK: end_borrow [[BORROW]] from [[PROJ]] : $SubHasInt, $*SubHasInt
+// CHECK-NOT: begin_access
+// CHECK: load [take] [[PROJ]] : $*SubHasInt
+// CHECK: upcast %{{.*}} : $SubHasInt to $SuperHasInt
+// CHECK: function_ref @$S20access_marker_verify11SuperHasIntCACycfc : $@convention(method) (@owned SuperHasInt) -> @owned SuperHasInt
+// CHECK: apply
+// CHECK: unchecked_ref_cast %{{.*}} : $SuperHasInt to $SubHasInt
+// CHECK-NOT: begin_access
+// CHECK: store %{{.*}} to [init] [[PROJ]] : $*SubHasInt
+// CHECK: [[VAL:%.*]] = load [copy] [[PROJ]] : $*SubHasInt
+// CHECK: destroy_value [[UNINIT]] : ${ var SubHasInt }
+// CHECK: return [[VAL]] : $SubHasInt
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify9SubHasIntCACycfc'
+
+// CHECK-LABEL: sil hidden @$S20access_marker_verify9SubHasIntC1xACSi_tcfc : $@convention(method) (Int, @owned SubHasInt) -> @owned SubHasInt {
+// CHECK: bb0(%0 : @trivial $Int, %1 : @owned $SubHasInt):
+// CHECK: [[BOX:%.*]] = alloc_box ${ var SubHasInt }, let, name "self"
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [derivedself] [[BOX]] : ${ var SubHasInt }
+// CHECK: [[PROJ:%.*]] = project_box [[UNINIT]] : ${ var SubHasInt }, 0
+// CHECK-NOT: begin_access
+// CHECK: store %{{.*}} to [init] [[PROJ]] : $*SubHasInt
+// CHECK-NOT: begin_access
+// CHECK: [[BORROW:%.*]] = load_borrow [[PROJ]] : $*SubHasInt
+// CHECK: [[ADR:%.*]] = ref_element_addr [[BORROW]] : $SubHasInt, #SubHasInt.j
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [dynamic] [[ADR]] : $*Int
+// CHECK: assign %0 to [[ACCESS]] : $*Int
+// CHECK: end_access [[ACCESS]] : $*Int
+// CHECK: end_borrow [[BORROW]] from [[PROJ]] : $SubHasInt, $*SubHasInt
+// CHECK-NOT: begin_access
+// CHECK: load [take] [[PROJ]] : $*SubHasInt
+// CHECK: upcast %{{.*}} : $SubHasInt to $SuperHasInt
+// CHECK: function_ref @$S20access_marker_verify11SuperHasIntCACycfc : $@convention(method) (@owned SuperHasInt) -> @owned SuperHasInt
+// CHECK: apply
+// CHECK: unchecked_ref_cast %{{.*}} : $SuperHasInt to $SubHasInt
+// CHECK-NOT: begin_access
+// CHECK: store %{{.*}} to [init] [[PROJ]] : $*SubHasInt
+// CHECK: [[VAL:%.*]] = load [copy] [[PROJ]] : $*SubHasInt
+// CHECK: destroy_value [[UNINIT]] : ${ var SubHasInt }
+// CHECK: return [[VAL]] : $SubHasInt
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify9SubHasIntC1xACSi_tcfc'
+
+// --- access `let` property.
+class LetClass {
+ let x = 3
+}
+
+// FIXME: should be a [unknown] access.
+//
+// CHECK-LABEL: sil hidden @$S20access_marker_verify10testGetLet1cSiAA0F5ClassC_tF : $@convention(thin) (@guaranteed LetClass) -> Int {
+// CHECK: bb0(%0 : @guaranteed $LetClass):
+// CHECK: ref_element_addr
+// CHECK: begin_access [read] [dynamic]
+// CHECK: load [trivial]
+// CHECK: end_access
+// CHECK: return
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify10testGetLet1cSiAA0F5ClassC_tF'
+func testGetLet(c: LetClass) -> Int {
+ return c.x
+}
+
+// --- initialize let property and superclass.
+struct IntWrapper {
+ var x: Int
+}
+
+final class SubWrapper : BaseClass {
+ let val: IntWrapper
+
+ init(_ val: IntWrapper) {
+ self.val = val
+ super.init()
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify10SubWrapperCyAcA03IntE0Vcfc : $@convention(method) (IntWrapper, @owned SubWrapper) -> @owned SubWrapper {
+// CHECK: bb0(%0 : @trivial $IntWrapper, %1 : @owned $SubWrapper):
+// CHECK: alloc_box ${ var SubWrapper }, let, name "self"
+// CHECK: mark_uninitialized [derivedself]
+// CHECK: project_box
+// CHECK-NOT: begin_access
+// CHECK: store %1 to [init]
+// CHECK-NOT: begin_access
+// CHECK: load_borrow
+// CHECK: ref_element_addr
+// CHECK: begin_access [modify] [dynamic]
+// CHECK: assign %0 to
+// CHECK: end_access
+// CHECK: end_borrow
+// CHECK-NOT: begin_access
+// CHECK: load [take]
+// CHECK-NOT: begin_access
+// CHECK: store %{{.*}} to [init]
+// CHECK: [[VAL:%.*]] = load [copy]
+// CHECK: destroy_value %{{.*}} : ${ var SubWrapper }
+// CHECK: return [[VAL]] : $SubWrapper
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify10SubWrapperCyAcA03IntE0Vcfc'
+
+// --- captured local.
+func testCaptureLocal() -> ()->() {
+ var x = 1
+ let f = { x = 3 }
+ _ = x
+ return f
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify16testCaptureLocalyycyF : $@convention(thin) () -> @owned @callee_guaranteed () -> () {
+// CHECK: bb0:
+// CHECK: alloc_box ${ var Int }, var, name "x"
+// CHECK: [[PROJ:%.*]] = project_box
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]] : $*Int
+// CHECK: store %{{.*}} to [trivial] [[ACCESS]]
+// CHECK: end_access
+// CHECK: [[CAPTURE:%.*]] = copy_value %0 : ${ var Int }
+// CHECK: partial_apply [callee_guaranteed] %{{.*}}([[CAPTURE]]) : $@convention(thin) (@guaranteed { var Int }) -> ()
+// CHECK: alloc_stack $Int
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [var]
+// CHECK: begin_access [read] [unknown] [[PROJ]]
+// CHECK: [[VAL:%.*]] = load [trivial]
+// CHECK: end_access
+// CHECK-NOT: begin_access
+// CHECK: assign [[VAL]] to [[UNINIT]] : $*Int
+// CHECK: return {{.*}} : $@callee_guaranteed () -> ()
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify16testCaptureLocalyycyF'
+
+// --- mutating struct.
+func testModifyS(_ arg: StructOfInt) -> StructOfInt {
+ var lhs: StructOfInt
+ lhs = arg
+ lhs.changeMe()
+ return lhs
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify11testModifySyAA11StructOfIntVADF : $@convention(thin) (StructOfInt) -> StructOfInt {
+// CHECK: bb0(%0 : @trivial $StructOfInt):
+// CHECK: alloc_box ${ var StructOfInt }, var, name "lhs"
+// CHECK: mark_uninitialized [var]
+// CHECK: project_box
+// CHECK: begin_access [modify] [unknown]
+// CHECK: assign
+// CHECK: end_access
+// CHECK: begin_access [modify] [unknown]
+// CHECK: function_ref @$S20access_marker_verify11StructOfIntV8changeMeyyF : $@convention(method) (@inout StructOfInt) -> ()
+// CHECK: apply
+// CHECK: end_access
+// CHECK: begin_access [read] [unknown]
+// CHECK: load [trivial]
+// CHECK: end_access
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify11testModifySyAA11StructOfIntVADF'
+
+// --- initialize LValue.
+protocol HasIntGetter {
+ var x: Int { get }
+}
+func testInitLValue(p: HasIntGetter) -> Int {
+ var x = p.x
+ return x
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify14testInitLValue1pSiAA12HasIntGetter_p_tF : $@convention(thin) (@in_guaranteed HasIntGetter) -> Int {
+// CHECK: bb0(%0 : @trivial $*HasIntGetter):
+// CHECK: alloc_box ${ var Int }, var, name "x"
+// CHECK: [[PROJ:%.*]] = project_box
+// CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access %0
+// CHECK: [[X:%.*]] = alloc_stack $@opened
+// CHECK-NOT: begin_access
+// CHECK: copy_addr %{{.*}} to [initialization] [[X]] : $*@opened
+// CHECK: witness_method $@opened
+// CHECK: apply %{{.*}}<@opened("{{.*}}") HasIntGetter>([[X]]) : $@convention(witness_method: HasIntGetter) <τ_0_0 where τ_0_0 : HasIntGetter> (@in_guaranteed τ_0_0) -> Int
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]] : $*Int
+// CHECK: store %{{.*}} to [trivial] [[ACCESS]] : $*Int
+// CHECK: end_access
+// CHECK: destroy_addr
+// CHECK: dealloc_stack
+// CHECK: begin_access [read] [unknown] [[PROJ]]
+// CHECK: load [trivial]
+// CHECK: end_access
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify14testInitLValue1pSiAA12HasIntGetter_p_tF'
+
+// --- initialize let.
+func testCopyS(_ arg: StructOfInt) -> StructOfInt {
+ let lhs: StructOfInt
+ lhs = arg
+ return lhs
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify9testCopySyAA11StructOfIntVADF : $@convention(thin) (StructOfInt) -> StructOfInt {
+// CHECK: bb0(%0 : @trivial $StructOfInt):
+// CHECK: alloc_stack $StructOfInt, let, name "lhs"
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [var]
+// CHECK-NOT: begin_access
+// CHECK: assign %0 to [[UNINIT]] : $*StructOfInt
+// CHECK-NOT: begin_access
+// CHECK: %5 = load [trivial] [[UNINIT]] : $*StructOfInt
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify9testCopySyAA11StructOfIntVADF'
+
+// --- local var init (single buffer).
+func testLocalVarInit(_ arg: StructOfInt) -> Int {
+ var lhs = arg
+ return lhs.i
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify16testLocalVarInitySiAA11StructOfIntVF : $@convention(thin) (StructOfInt) -> Int {
+// CHECK: bb0(%0 : @trivial $StructOfInt):
+// CHECK: alloc_box ${ var StructOfInt }, var, name "lhs"
+// CHECK: [[BOX:%.*]] = project_box
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[BOX]]
+// CHECK: store %0 to [trivial] [[ACCESS]]
+// CHECK: end_access
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify16testLocalVarInitySiAA11StructOfIntVF'
+
+// --- init generic enum
+enum GenericEnum<T> {
+case V(T)
+
+ init?(t: T) {
+ self = .V(t)
+ }
+}
+
+func testInitGenericEnum<T>(t: T) -> GenericEnum<T>? {
+ return GenericEnum(t: t)
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify11GenericEnumO1tACyxGSgx_tcfC : $@convention(method) <T> (@in T, @thin GenericEnum<T>.Type) -> @out Optional<GenericEnum<T>> {
+// CHECK: bb0(%0 : @trivial $*Optional<GenericEnum<T>>, %1 : @trivial $*T, %2 : @trivial $@thin GenericEnum<T>.Type):
+// CHECK: alloc_box $<τ_0_0> { var GenericEnum<τ_0_0> } <T>, var, name "self"
+// CHECK: mark_uninitialized [delegatingself] %3 : $<τ_0_0> { var GenericEnum<τ_0_0> } <T>
+// CHECK: [[PROJ:%.*]] = project_box
+// CHECK: [[STK:%.*]] = alloc_stack $GenericEnum<T>
+// CHECK: [[ADR1:%.*]] = init_enum_data_addr [[STK]]
+// CHECK-NOT: begin_access
+// CHECK: copy_addr %1 to [initialization] [[ADR1]] : $*T
+// CHECK: inject_enum_addr
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[PROJ]]
+// CHECK: copy_addr [take] %{{.*}} to [[ACCESS]] : $*GenericEnum<T>
+// CHECK: end_access [[ACCESS]] : $*GenericEnum<T>
+// CHECK: [[ADR2:%.*]] = init_enum_data_addr %0
+// CHECK-NOT: begin_access
+// CHECK: copy_addr %{{.*}} to [initialization] [[ADR2]] : $*GenericEnum<T>
+// CHECK: inject_enum_addr %0 : $*Optional<GenericEnum<T>>, #Optional.some!enumelt.1
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify11GenericEnumO1tACyxGSgx_tcfC'
+
+// -- initialize indirect enum.
+enum IndirectEnum {
+ indirect case V(Int)
+}
+
+func testIndirectEnum() -> IndirectEnum {
+ return IndirectEnum.V(3)
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify16testIndirectEnumAA0eF0OyF : $@convention(thin) () -> @owned IndirectEnum {
+// CHECK: bb0:
+// CHECK: alloc_box ${ var Int }
+// CHECK: [[PROJ:%.*]] = project_box
+// CHECK: apply
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]]
+// CHECK: store %{{.*}} to [trivial] [[ACCESS]] : $*Int
+// CHECK: end_access
+// CHECK: enum $IndirectEnum, #IndirectEnum.V!enumelt.1
+// CHECK: return
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify16testIndirectEnumAA0eF0OyF'
+
+// -- indirect enum with getter.
+enum IntEnum {
+ indirect case int(Int)
+
+ var getValue: Int {
+ switch self {
+ case .int(let x): return x
+ }
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify7IntEnumO8getValueSivg : $@convention(method) (@guaranteed IntEnum) -> Int {
+// CHECK: bb0(%0 : @guaranteed $IntEnum):
+// CHECK: switch_enum %{{.*}} : $IntEnum, case #IntEnum.int!enumelt.1: bb1
+// CHECK: bb1(%{{.*}} : @owned ${ var Int }):
+// CHECK: [[PROJ:%.*]] = project_box
+// CHECK-NOT: begin_access
+// CHECK: load [trivial] [[PROJ]] : $*Int
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify7IntEnumO8getValueSivg'
+
+// -- indirect enum reference.
+enum RefEnum {
+ indirect case ref(BaseClass)
+
+ var getValue: BaseClass {
+ switch self {
+ case .ref(let c): return c
+ }
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify7RefEnumO8getValueAA9BaseClassCvg : $@convention(method) (@guaranteed RefEnum) -> @owned BaseClass {
+// CHECK: bb0(%0 : @guaranteed $RefEnum):
+// CHECK: switch_enum %{{.*}} : $RefEnum, case #RefEnum.ref!enumelt.1: bb1
+// CHECK: bb1(%{{.*}} : @owned ${ var BaseClass }):
+// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var BaseClass }, 0
+// CHECK-NOT: begin_access
+// CHECK: load_borrow [[PROJ]] : $*BaseClass
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify7RefEnumO8getValueAA9BaseClassCvg'
+
+// --- indirect enum pattern.
+func testEnumPattern(ie: IndirectEnum) -> Bool {
+ guard case .V(let kind) = ie else {
+ return false
+ }
+ _ = kind
+ return true
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify15testEnumPattern2ieSbAA08IndirectE0O_tF : $@convention(thin) (@guaranteed IndirectEnum) -> Bool {
+// CHECK: bb0(%0 : @guaranteed $IndirectEnum):
+// CHECK: switch_enum %{{.*}} : $IndirectEnum, case #IndirectEnum.V!enumelt.1: [[BBV:bb.*]], default bb
+// CHECK: [[BBV]](%{{.*}} : @owned ${ var Int }):
+// CHECK: [[PROJ:%.*]] = project_box
+// CHECK-NOT: begin_access
+// CHECK: load [trivial] [[PROJ]] : $*Int
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify15testEnumPattern2ieSbAA08IndirectE0O_tF'
+
+// --- enum LValue.
+struct StructOfEnum {
+ var e: E
+ var f: E
+}
+func enumLValueHelper(_: inout E, _: inout E) {}
+
+// CHECK-LABEL: sil hidden @$S20access_marker_verify14testEnumLValue1syAA08StructOfE0Vz_tF : $@convention(thin) (@inout StructOfEnum) -> () {
+// CHECK: bb0(%0 : @trivial $*StructOfEnum):
+// CHECK: begin_access [modify] [unknown] %0 : $*StructOfEnum
+// CHECK: struct_element_addr %2 : $*StructOfEnum, #StructOfEnum.e
+// CHECK: begin_access [modify] [unknown] %0 : $*StructOfEnum
+// CHECK: struct_element_addr %4 : $*StructOfEnum, #StructOfEnum.f
+// CHECK: function_ref @$S20access_marker_verify16enumLValueHelperyyAA1EOz_ADztF : $@convention(thin) (@inout E, @inout E) -> ()
+// CHECK: apply %6(%3, %5) : $@convention(thin) (@inout E, @inout E) -> ()
+// CHECK: end_access %4 : $*StructOfEnum
+// CHECK: end_access %2 : $*StructOfEnum
+// CHECK: %10 = tuple ()
+// CHECK: return %10 : $()
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify14testEnumLValue1syAA08StructOfE0Vz_tF'
+func testEnumLValue(s: inout StructOfEnum) {
+ enumLValueHelper(&s.e, &s.f)
+}
+
+// --- Optional access.
+func accessOptionalArray(_ dict : [Int : [Int]] = [:]) {
+ var dict = dict
+ dict[1]?.append(2)
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify0A13OptionalArrayyys10DictionaryVySiSaySiGGF : $@convention(thin) (@guaranteed Dictionary<Int, Array<Int>>) -> () {
+// CHECK: bb0(%0 : @guaranteed $Dictionary<Int, Array<Int>>):
+// CHECK: alloc_box ${ var Dictionary<Int, Array<Int>> }, var, name "dict"
+// CHECK: [[PROJ:%.*]] = project_box
+// ----- initialize the box.
+// CHECK: [[INITACCESS:%.*]] = begin_access [modify] [unsafe] [[PROJ]]
+// CHECK: store %{{.*}} to [init] [[INITACCESS]]
+// CHECK: end_access [[INITACCESS]]
+// ----- begin formal access for Dictionary.subscript.setter
+// CHECK: [[BOXACCESS:%.*]] = begin_access [modify] [unknown] [[PROJ]]
+// CHECK: [[TEMP:%.*]] = alloc_stack $Optional<Array<Int>>
+// CHECK: load_borrow [[BOXACCESS]] : $*Dictionary<Int, Array<Int>>
+// ----- Initialize some trivial temporaries.
+// CHECK: alloc_stack $Int
+// CHECK-NOT: begin_access
+// CHECK: store %{{.*}} to [trivial]
+// ----- Call Dictionary.subscript.getter.
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}<Int, [Int]>
+// ----- access the temporary array result of the getter
+// CHECK: [[TEMPACCESS:%.*]] = begin_access [modify] [unsafe] [[TEMP]]
+// CHECK: select_enum_addr [[TEMPACCESS]] : $*Optional<Array<Int>>, case #Optional.some!enumelt.1
+// CHECK: cond_br %{{.*}}, bb2, bb1
+//
+// CHECK: bb1:
+// CHECK: [[TEMPARRAY:%.*]] = load [copy] [[TEMPACCESS]]
+// CHECK: [[WRITEBACK:%.*]] = alloc_stack $Optional<Array<Int>>
+// CHECK-NOT: begin_access
+// CHECK: store [[TEMPARRAY]] to [init] [[WRITEBACK]]
+// CHECK: alloc_stack $Int
+// CHECK-NOT: begin_access
+// CHECK: store %{{.*}} to [trivial] %29 : $*Int
+// Call Dictionary.subscript.setter
+// CHECK: apply %{{.*}}<Int, [Int]>([[WRITEBACK]], %{{.*}}, [[BOXACCESS]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_0, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
+// CHECK: end_access [[TEMPACCESS]] : $*Optional<Array<Int>>
+// CHECK: end_access [[BOXACCESS]] : $*Dictionary<Int, Array<Int>>
+// CHECK: br
+//
+// CHECK: bb2:
+// CHECK-NOT: begin_access
+// CHECK: [[TEMPARRAYADR:%.*]] = unchecked_take_enum_data_addr [[TEMPACCESS]] : $*Optional<Array<Int>>, #Optional.some!enumelt.1
+// ----- call Array.append
+// CHECK: alloc_stack $Int
+// CHECK: store %{{.*}} to [trivial]
+// CHECK: function_ref @$SSa6appendyyxF : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout Array<τ_0_0>) -> ()
+// CHECK: apply %{{.*}}<Int>(%{{.*}}, [[TEMPARRAYADR]]) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @inout Array<τ_0_0>) -> ()
+// CHECK: [[TEMPARRAYVAL:%.*]] = load [take] [[TEMPACCESS]] : $*Optional<Array<Int>>
+// CHECK: [[ARRAYCOPY:%.*]] = alloc_stack $Optional<Array<Int>>
+// CHECK: store [[TEMPARRAYVAL]] to [init] [[ARRAYCOPY]] : $*Optional<Array<Int>>
+// CHECK: alloc_stack $Int
+// CHECK: store %{{.*}} to [trivial]
+// ----- call Dictionary.subscript.setter
+// CHECK: apply %{{.*}}<Int, [Int]>([[ARRAYCOPY]], %{{.*}}, [[BOXACCESS]]) : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in Optional<τ_0_1>, @in τ_0_0, @inout Dictionary<τ_0_0, τ_0_1>) -> ()
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify0A13OptionalArrayyys10DictionaryVySiSaySiGGF'
+
+// --- Optional map.
+enum OptionalWithMap<Wrapped> {
+ case none
+
+ case some(Wrapped)
+
+ init(_ some: Wrapped) { self = .some(some) }
+
+ func map<U>(
+ _ transform: (Wrapped) throws -> U
+ ) rethrows -> U? {
+ switch self {
+ case .some(let y):
+ return .some(try transform(y))
+ case .none:
+ return .none
+ }
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify15OptionalWithMapO3mapyqd__Sgqd__xKXEKlF : $@convention(method) <Wrapped><U> (@noescape @callee_guaranteed (@in_guaranteed Wrapped) -> (@out U, @error Error), @in_guaranteed OptionalWithMap<Wrapped>) -> (@out Optional<U>, @error Error) {
+// CHECK: bb0(%0 : @trivial $*Optional<U>, %1 : @trivial $@noescape @callee_guaranteed (@in_guaranteed Wrapped) -> (@out U, @error Error), %2 : @trivial $*OptionalWithMap<Wrapped>):
+// CHECK: [[STK:%.]] = alloc_stack $OptionalWithMap<Wrapped>
+// CHECK-NOT: begin_access
+// CHECK: copy_addr %2 to [initialization] [[STK]] : $*OptionalWithMap<Wrapped>
+// CHECK: switch_enum_addr [[STK]] : $*OptionalWithMap<Wrapped>, case #OptionalWithMap.some!enumelt.1: [[BBSOME:bb.*]], case #OptionalWithMap.none!enumelt: bb
+//
+// CHECK: [[BBSOME]]:
+// CHECK-NOT: begin_access
+// CHECK: [[ADR:%.*]] = unchecked_take_enum_data_addr [[STK]]
+// CHECK: alloc_stack $Wrapped, let, name "y"
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [take] [[ADR]] to [initialization]
+// ----- call transform.
+// CHECK: try_apply
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify15OptionalWithMapO3mapyqd__Sgqd__xKXEKlF'
+
+// --- delegating initializer.
+struct DelegatingInit {
+ var i: Int
+ init(i: Int) {
+ self.i = i
+ }
+ init() {
+ self.init(i: 4)
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify14DelegatingInitV1iACSi_tcfC : $@convention(method) (Int, @thin DelegatingInit.Type) -> DelegatingInit {
+// CHECK: bb0(%0 : @trivial $Int, %1 : @trivial $@thin DelegatingInit.Type):
+// CHECK: alloc_box ${ var DelegatingInit }, var, name "self"
+// CHECK: mark_uninitialized [rootself] %2 : ${ var DelegatingInit }
+// CHECK: [[BOX:%.*]] = project_box
+// CHECK: begin_access [modify] [unknown]
+// CHECK: struct_element_addr
+// CHECK: assign
+// CHECK: end_access
+// CHECK-NOT: begin_access
+// CHECK: load [trivial] [[BOX]] : $*DelegatingInit
+// CHECK: destroy_value
+// CHECK: return %10 : $DelegatingInit
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify14DelegatingInitV1iACSi_tcfC'
+
+// --- addressor.
+func testAddressor(p: UnsafePointer<Int>) -> Int {
+ return p.pointee
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify13testAddressor1pSiSPySiG_tF : $@convention(thin) (UnsafePointer<Int>) -> Int {
+// CHECK: bb0(%0 : @trivial $UnsafePointer<Int>):
+// CHECK: apply
+// CHECK: struct_extract
+// CHECK: [[ADR:%.*]] = pointer_to_address
+// CHECK-NOT: begin_access
+// CHECK: load [trivial] [[ADR]] : $*Int
+// CHECK: return
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify13testAddressor1pSiSPySiG_tF'
+
+// --- shims.
+func testShims() -> UInt32 {
+ return _SwiftKeyPathBufferHeader_SizeMask
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify9testShimss6UInt32VyF : $@convention(thin) () -> UInt32 {
+// CHECK: bb0:
+// CHECK: [[GA:%.*]] = global_addr @_SwiftKeyPathBufferHeader_SizeMask : $*UInt32
+// CHECK-NOT: begin_access
+// CHECK: load [trivial] [[GA]] : $*UInt32
+// CHECK: return
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify9testShimss6UInt32VyF'
+
+// --- global variable initialization.
+var globalString1 = "⓪" // start non-empty
+// CHECK-LABEL: sil private @globalinit_33_{{.*}}_func0 : $@convention(c) () -> () {
+// CHECK: alloc_global @$S20access_marker_verify13globalString1SSvp
+// CHECK: [[GA:%.*]] = global_addr @$S20access_marker_verify13globalString1SSvp : $*String
+// CHECK: apply
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[GA]] : $*String
+// CHECK: store %{{.*}} to [init] [[ACCESS]] : $*String
+// CHECK: end_access
+// CHECK-LABEL: } // end sil function 'globalinit_33_180BF7B9126DB0C8C6C26F15ACD01908_func0'
+
+var globalString2 = globalString1
+// CHECK-LABEL: sil private @globalinit_33_180BF7B9126DB0C8C6C26F15ACD01908_func1 : $@convention(c) () -> () {
+// CHECK: alloc_global @$S20access_marker_verify13globalString2SSvp
+// CHECK: [[GA:%.*]] = global_addr @$S20access_marker_verify13globalString2SSvp : $*String
+// CHECK: apply
+// CHECK: [[PTR:%.*]] = pointer_to_address
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[PTR]] : $*String
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [[ACCESS]] to [initialization] [[GA]] : $*String
+// CHECK: end_access [[ACCESS]] : $*String
+// CHECK-NOT: end_access
+// CHECK-LABEL: } // end sil function 'globalinit_33_180BF7B9126DB0C8C6C26F15ACD01908_func1'
+
+
+// --- getter.
+struct GenericStructWithGetter<T> {
+ var t: T
+ var val: Int
+
+ struct Value {
+ internal var val: Int
+
+ internal init(_ val: Int) { self.val = val }
+ }
+ var value : Value {
+ get { return Value(val) }
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify23GenericStructWithGetterV5valueAC5ValueVyx_Gvg : $@convention(method) <T> (@in_guaranteed GenericStructWithGetter<T>) -> GenericStructWithGetter<T>.Value {
+// CHECK: bb0(%0 : @trivial $*GenericStructWithGetter<T>):
+// CHECK: [[ADR:%.*]] = struct_element_addr %0 : $*GenericStructWithGetter<T>, #GenericStructWithGetter.val
+// CHECK-NOT: begin_access
+// CHECK: load [trivial] [[ADR]] : $*Int
+// CHECK: apply
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify23GenericStructWithGetterV5valueAC5ValueVyx_Gvg'
+
+// --- setter.
+struct StructWithSetter {
+ var _val: Int
+
+ internal var val: Int {
+ get {
+ return _val
+ }
+ set {
+ _val = newValue
+ }
+ }
+
+ mutating func inc(incVal: Int) {
+ val += incVal
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify16StructWithSetterV3inc0G3ValySi_tF : $@convention(method) (Int, @inout StructWithSetter) -> () {
+// CHECK: bb0(%0 : @trivial $Int, %1 : @trivial $*StructWithSetter):
+// CHECK: [[FORMALACCESS:%.*]] = begin_access [modify] [unknown] %1
+// CHECK: alloc_stack $Int
+// CHECK: load [trivial] [[FORMALACCESS]] : $*StructWithSetter
+// CHECK: [[GETTER:%.*]] = function_ref @$S20access_marker_verify16StructWithSetterV3valSivg
+// CHECK: apply [[GETTER]]
+// CHECK: begin_access [modify] [unsafe]
+// CHECK: store %{{.*}} to [trivial]
+// CHECK: end_access
+// CHECK: begin_access [modify] [unsafe]
+// CHECK: [[INC:%.*]] = function_ref @$SSi2peoiyySiz_SitFZ
+// CHECK: apply [[INC]]
+// CHECK: load [trivial] %13 : $*Int
+// CHECK: [[SETTER:%.*]] = function_ref @$S20access_marker_verify16StructWithSetterV3valSivs
+// CHECK: apply [[SETTER]]
+// CHECK: end_access
+// CHECK: end_access [[FORMALACCESS]]
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify16StructWithSetterV3inc0G3ValySi_tF'
+
+// --- lazy inout.
+func increment(_ x: inout Int) { x += 1 }
+
+final class LazyFinalClassProperty {
+ lazy var cat: Int = 5
+}
+
+func inoutWriteOfLazyFinalClassProperty(l: inout LazyFinalClassProperty) {
+ increment(&l.cat)
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify34inoutWriteOfLazyFinalClassProperty1lyAA0ghiJ0Cz_tF : $@convention(thin) (@inout LazyFinalClassProperty) -> () {
+// CHECK: bb0(%0 : @trivial $*LazyFinalClassProperty):
+// CHECK: [[FORMALACCESS:%.*]] = begin_access [read] [unknown] %0 : $*LazyFinalClassProperty
+// CHECK: load [copy] [[FORMALACCESS]] : $*LazyFinalClassProperty
+// CHECK: end_access [[FORMALACCESS]] : $*LazyFinalClassProperty
+// CHECK: // function_ref LazyFinalClassProperty.cat.getter
+// CHECK: [[GETTER:%.*]] = function_ref @$S20access_marker_verify22LazyFinalClassPropertyC3catSivg
+// CHECK: apply [[GETTER]]
+// CHECK: begin_access [modify] [unsafe]
+// CHECK: store %{{.*}} to [trivial]
+// CHECK: end_access
+// CHECK: [[TEMPACCESS:%.*]] = begin_access [modify] [unsafe] %5 : $*Int
+// CHECK: [[INC:%.*]] = function_ref @$S20access_marker_verify9incrementyySizF : $@convention(thin) (@inout Int) -> ()
+// CHECK: apply [[INC]]([[TEMPACCESS]]) : $@convention(thin) (@inout Int) -> ()
+// CHECK: load [trivial] [[TEMPACCESS]] : $*Int
+// CHECK: [[SETTER:%.*]] = function_ref @$S20access_marker_verify22LazyFinalClassPropertyC3catSivs
+// CHECK: apply [[SETTER]]
+// CHECK: end_access [[TEMPACCESS]] : $*Int
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify34inoutWriteOfLazyFinalClassProperty1lyAA0ghiJ0Cz_tF'
+
+// --- lazy getter.
+func inoutAccessOfLazyFinalClassProperty(
+ l: inout LazyFinalClassProperty
+) -> Int {
+ return l.cat
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify35inoutAccessOfLazyFinalClassProperty1lSiAA0ghiJ0Cz_tF : $@convention(thin) (@inout LazyFinalClassProperty) -> Int {
+// CHECK: bb0(%0 : @trivial $*LazyFinalClassProperty):
+// CHECK: begin_access [read] [unknown] %0
+// CHECK: load [copy]
+// CHECK: end_access
+// CHECK: [[GETTER:%.*]] = function_ref @$S20access_marker_verify22LazyFinalClassPropertyC3catSivg : $@convention(method) (@guaranteed LazyFinalClassProperty) -> Int
+// CHECK: apply [[GETTER]]
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify35inoutAccessOfLazyFinalClassProperty1lSiAA0ghiJ0Cz_tF'
+
+// --- polymorphic getter
+protocol Abstractable {
+ associatedtype Result
+ var storedFunction: () -> Result { get set }
+}
+
+class C : Abstractable {
+ var storedFunction: () -> Int = { 0 }
+}
+// CHECK-LABEL: sil private [transparent] [thunk] @$S20access_marker_verify1CCAA12AbstractableA2aDP14storedFunction6ResultQzycvmTW : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout C) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>) {
+// CHECK: bb0(%0 : @trivial $Builtin.RawPointer, %1 : @trivial $*Builtin.UnsafeValueBuffer, %2 : @trivial $*C):
+// CHECK: [[ADR:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*@callee_guaranteed () -> @out Int
+// CHECK: [[TEMP:%.*]] = alloc_stack $@callee_guaranteed () -> Int
+// CHECK: [[GETTER:%.*]] = apply
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[TEMP]] : $*@callee_guaranteed () -> Int
+// CHECK: store %{{.*}} to [init] [[ACCESS]] : $*@callee_guaranteed () -> Int
+// CHECK: end_access [[ACCESS]] : $*@callee_guaranteed () -> Int
+// CHECK-NOT: begin_access
+// CHECK: load [copy] [[TEMP]] : $*@callee_guaranteed () -> Int
+// CHECK: [[PA:%.*]] = partial_apply
+// CHECK: destroy_addr [[TEMP]] : $*@callee_guaranteed () -> Int
+// CHECK-NOT: begin_access
+// CHECK: store [[PA]] to [init] [[ADR]] : $*@callee_guaranteed () -> @out Int
+// CHECK: [[PTR:%.*]] = address_to_pointer [[ADR]] : $*@callee_guaranteed () -> @out Int to $Builtin.RawPointer
+// CHECK: [[FPTR:%.*]] = thin_function_to_pointer %{{.*}} : $@convention(witness_method: Abstractable) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout C, @thick C.Type) -> () to $Builtin.RawPointer
+// CHECK: [[ENUM:%.*]] = enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, [[FPTR]] : $Builtin.RawPointer
+// CHECK: [[R:%.*]] = tuple ([[PTR]] : $Builtin.RawPointer, [[ENUM]] : $Optional<Builtin.RawPointer>)
+// CHECK: return [[R]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>)
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify1CCAA12AbstractableA2aDP14storedFunction6ResultQzycvmTW'
+
+// --- writeback address-only.
+var addressOnly: P {
+ get {
+ return StructP()
+ }
+ set {}
+}
+
+func takesInoutP(x: inout P) {}
+
+func testWriteback() {
+ takesInoutP(x: &addressOnly)
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify13testWritebackyyF : $@convention(thin) () -> () {
+// CHECK: bb0:
+// CHECK: %0 = alloc_stack $P
+// CHECK: [[GETTER:%.*]] = apply
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] %0 : $*P
+// Call takesInoutP
+// CHECK: apply %{{.*}}([[ACCESS]]) : $@convention(thin) (@inout P) -> ()
+// Call addressOnly.setter
+// CHECK: apply %{{.*}}([[ACCESS]]) : $@convention(thin) (@in P) -> ()
+// CHECK: end_access [[ACCESS]] : $*P
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify13testWritebackyyF'
+
+// --- writeback temp.
+struct MutableStorage {
+ mutating func push() {}
+}
+
+class Container {
+ var storage: MutableStorage
+
+ init() {
+ storage = MutableStorage()
+ }
+
+ func testWritebackTemp() {
+ self.storage.push()
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify9ContainerC17testWritebackTempyyF : $@convention(method) (@guaranteed Container) -> () {
+// CHECK: bb0(%0 : @guaranteed $Container):
+// call storage.materializeForSet
+// CHECK: [[MATSET:%.*]] = class_method %0 : $Container, #Container.storage!materializeForSet.1
+// CHECK: apply [[MATSET]]
+// call MutableStorage.push()
+// CHECK: apply %{{.*}}(%{{.*}}) : $@convention(method) (@inout MutableStorage) -> ()
+// CHECK: switch_enum %{{.*}} : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[BBSOME:bb.*]], case #Optional.none!enumelt: bb
+// CHECK: [[BBSOME]]([[WB:%.*]] : @trivial $Builtin.RawPointer):
+// CHECK: [[WBF:%.*]] = pointer_to_thin_function [[WB]]
+// CHECK: [[TEMP:%.*]] = alloc_stack $Container
+// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unsafe] [[TEMP]] : $*Container
+// CHECK: store_borrow %0 to [[ACCESS]] : $*Container
+// writeback
+// CHECK: apply [[WBF]]
+// CHECK: end_access [[ACCESS]] : $*Container
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify9ContainerC17testWritebackTempyyF'
+
+// --- return mixed tuple
+protocol HasClassGetter {
+ var c: BaseClass { get }
+}
+func testMixedTuple(p: HasClassGetter) -> (BaseClass, Any) {
+ return (p.c, p.c)
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify14testMixedTuple1pAA9BaseClassC_yptAA03HasH6Getter_p_tF : $@convention(thin) (@in_guaranteed HasClassGetter) -> (@owned BaseClass, @out Any) {
+// CHECK: bb0(%0 : @trivial $*Any, %1 : @trivial $*HasClassGetter):
+// CHECK: [[P1:%.*]] = open_existential_addr immutable_access %1 : $*HasClassGetter to $*@opened
+// CHECK: [[TEMP1:%.*]] = alloc_stack $@opened
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [[P1]] to [initialization] [[TEMP1]] : $*@opened
+// CHECK-NOT: begin_access
+// CHECK: [[OUTC:%.*]] = apply {{.*}} $@convention(witness_method: HasClassGetter) <τ_0_0 where τ_0_0 : HasClassGetter> (@in_guaranteed τ_0_0) -> @owned BaseClass
+// CHECK: [[OUTANY:%.*]] = init_existential_addr %0 : $*Any, $BaseClass
+// CHECK: [[P2:%.*]] = open_existential_addr immutable_access %1 : $*HasClassGetter to $*@opened
+// CHECK: [[TEMP2:%.*]] = alloc_stack $@opened
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [[P2]] to [initialization] [[TEMP2]] : $*@opened
+// CHECK-NOT: begin_access
+// CHECK: apply {{.*}} $@convention(witness_method: HasClassGetter) <τ_0_0 where τ_0_0 : HasClassGetter> (@in_guaranteed τ_0_0) -> @owned BaseClass
+// CHECK: store %{{.*}} to [init] [[OUTANY]] : $*BaseClass
+// CHECK: return [[OUTC]] : $BaseClass
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify14testMixedTuple1pAA9BaseClassC_yptAA03HasH6Getter_p_tF'
+
+// --- existential cast.
+internal protocol CanCast {
+ func unbox<T : Hashable>() -> T?
+}
+
+internal struct CanCastStruct<Base : Hashable> : CanCast {
+ internal var base: Base
+
+ internal func unbox<T : Hashable>() -> T? {
+ return (self as CanCast as? CanCastStruct<T>)?.base
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify13CanCastStructV5unboxqd__Sgys8HashableRd__lF : $@convention(method) <Base where Base : Hashable><T where T : Hashable> (@in_guaranteed CanCastStruct<Base>) -> @out Optional<T> {
+// CHECK: bb0(%0 : @trivial $*Optional<T>, %1 : @trivial $*CanCastStruct<Base>):
+// CHECK: [[OUT_ENUM:%.*3]] = init_enum_data_addr %0 : $*Optional<T>, #Optional.some!enumelt.1
+// CHECK: [[TEMP_SUB:%.*]] = alloc_stack $Optional<CanCastStruct<T>>
+// CHECK: [[TEMP_BASE:%.*]] = alloc_stack $CanCast
+// CHECK: [[TEMP_BASE_ADR:%.*]] = init_existential_addr [[TEMP_BASE]] : $*CanCast, $CanCastStruct<Base>
+// CHECK-NOT: begin_access
+// CHECK: copy_addr %1 to [initialization] [[TEMP_BASE_ADR]] : $*CanCastStruct<Base>
+// CHECK-NOT: begin_access
+// CHECK: [[TEMP_SUB_ADR:%.*]] = init_enum_data_addr [[TEMP_SUB]] : $*Optional<CanCastStruct<T>>, #Optional.some!enumelt.1
+// CHECK-NOT: begin_access
+// CHECK: checked_cast_addr_br take_always CanCast in [[TEMP_BASE]] : $*CanCast to CanCastStruct<T> in [[TEMP_SUB_ADR]] : $*CanCastStruct<T>
+// CHECK-NOT: begin_access
+// CHECK: [[TEMP_DATA:%.*]] = unchecked_take_enum_data_addr [[TEMP_SUB]] : $*Optional<CanCastStruct<T>>, #Optional.some!enumelt.1
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unsafe] [[TEMP_DATA]] : $*CanCastStruct<T>
+// CHECK: [[BASE_ADR:%.*]] = struct_element_addr [[ACCESS]] : $*CanCastStruct<T>, #CanCastStruct.base
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [[BASE_ADR]] to [initialization] [[OUT_ENUM]] : $*T
+// CHECK: end_access [[ACCESS]] : $*CanCastStruct<T>
+// CHECK-NOT: begin_access
+// CHECK: inject_enum_addr %0 : $*Optional<T>, #Optional.some!enumelt.1
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify13CanCastStructV5unboxqd__Sgys8HashableRd__lF'
+
+// --- open existential
+protocol Q : PBar {}
+
+func testOpenExistential(p: PBar) {
+ let q0 = p as? Q
+ if q0 != nil, let q = q0 {
+ q.bar()
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify19testOpenExistential1pyAA4PBar_p_tF : $@convention(thin) (@in_guaranteed PBar) -> () {
+// CHECK: bb0(%0 : @trivial $*PBar):
+// CHECK: [[Q0:%.*]] = alloc_stack $Optional<Q>, let, name "q0"
+// CHECK: [[PBAR:%.*]] = alloc_stack $PBar
+// CHECK-NOT: begin_access
+// CHECK: copy_addr %0 to [initialization] [[PBAR]] : $*PBar
+// CHECK-NOT: begin_access
+// CHECK: [[Q0_DATA:%.*]] = init_enum_data_addr [[Q0]] : $*Optional<Q>, #Optional.some!enumelt.1
+// CHECK-NOT: begin_access
+// CHECK: checked_cast_addr_br take_always PBar in [[PBAR]] : $*PBar to Q in [[Q0_DATA]] : $*Q, bb1, bb2
+// CHECK-NOT: begin_access
+// CHECK: inject_enum_addr [[Q0]] : $*Optional<Q>, #Optional.some!enumelt.1
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}<Q>([[Q0]], {{.*}}) : $@convention(method) <τ_0_0> (@in_guaranteed Optional<τ_0_0>, _OptionalNilComparisonType, @thin Optional<τ_0_0>.Type) -> Bool
+// CHECK: [[Q:%.*]] = alloc_stack $Q, let, name "q"
+// CHECK: [[OPT_Q:%.*]] = alloc_stack $Optional<Q>
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [[Q0]] to [initialization] [[OPT_Q]] : $*Optional<Q>
+// CHECK-NOT: begin_access
+// CHECK: switch_enum_addr [[OPT_Q]] : $*Optional<Q>, case #Optional.some!enumelt.1: bb
+// CHECK-NOT: begin_access
+// CHECK: [[OPT_Q_ADR:%.*]] = unchecked_take_enum_data_addr [[OPT_Q]] : $*Optional<Q>, #Optional.some!enumelt.1
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [take] [[OPT_Q_ADR]] to [initialization] [[Q]] : $*Q
+// CHECK-NOT: begin_access
+// CHECK: [[Q_ADR:%.*]] = open_existential_addr immutable_access [[Q]] : $*Q to $*@opened("{{.*}}") Q
+// CHECK: witness_method $@opened("{{.*}}") Q, #PBar.bar!1
+// CHECK: apply %{{.*}}<@opened("{{.*}}") Q>([[Q_ADR]])
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify19testOpenExistential1pyAA4PBar_p_tF'
+
+// --- local existential
+func getP() -> P {
+ struct S : P {}
+ return S()
+}
+
+func testLocalExistential() {
+ var p = getP()
+ takesClosure { p = getP() }
+ _ = p
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify20testLocalExistentialyyF : $@convention(thin) () -> () {
+// CHECK: alloc_box ${ var P }, var, name "p"
+// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var P }, 0
+// CHECK-NOT: begin_access
+// CHECK: apply %{{.*}}([[PROJ]]) : $@convention(thin) () -> @out P
+// CHECK-NOT: begin_access
+// CHECK: partial_apply [callee_guaranteed] %{{.*}}([[PROJ]]) : $@convention(thin) (@inout_aliasable P) -> ()
+// CHECK-NOT: begin_access
+// CHECK: apply
+// CHECK: [[TMP:%.*]] = alloc_stack $P
+// CHECK: [[UNINIT:%.*]] = mark_uninitialized [var] [[TMP]] : $*P
+// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PROJ]] : $*P
+// CHECK: [[COPY:%.*]] = alloc_stack $P
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [[ACCESS]] to [initialization] [[COPY]] : $*P
+// CHECK: end_access
+// CHECK-NOT: begin_access
+// CHECK: copy_addr [take] [[COPY]] to [[UNINIT]] : $*P
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify20testLocalExistentialyyF'
+
+// --- address-only argument.
+protocol UsesSelf {
+ func bar(_: Self)
+}
+
+extension UsesSelf {
+ static func testSelf(a: Self, b: Self) {
+ a.bar(b)
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify8UsesSelfPAAE04testE01a1byx_xtFZ : $@convention(method) <Self where Self : UsesSelf> (@in_guaranteed Self, @in_guaranteed Self, @thick Self.Type) -> () {
+// CHECK: bb0(%0 : @trivial $*Self, %1 : @trivial $*Self, %2 : @trivial $@thick Self.Type):
+// CHECK: apply %{{.*}}<Self>(%1, %0) : $@convention(witness_method: UsesSelf) <τ_0_0 where τ_0_0 : UsesSelf> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> ()
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify8UsesSelfPAAE04testE01a1byx_xtFZ'
+
+// --- autoclosure
+struct StructWithLayout {
+ internal init() {
+ _sanityCheck(MemoryLayout.size(ofValue: self) >= 0)
+ }
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify16StructWithLayoutVACycfC : $@convention(method) (@thin StructWithLayout.Type) -> StructWithLayout {
+// CHECK: bb0(%0 : @trivial $@thin StructWithLayout.Type):
+// CHECK: alloc_box ${ var StructWithLayout }, var, name "self"
+// CHECK: mark_uninitialized [rootself] %{{.*}} : ${ var StructWithLayout }
+// CHECK: [[PROJ:%.*]] = project_box %{{.*}} : ${ var StructWithLayout }, 0
+// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] %{{.*}}([[PROJ]]) : $@convention(thin) (@inout_aliasable StructWithLayout) -> Bool
+// CHECK: [[CLOSURE:%.*]] = convert_escape_to_noescape [[PA]] : $@callee_guaranteed () -> Bool to $@noescape @callee_guaranteed () -> Bool
+// call default argument
+// CHECK: apply %{{.*}}() : $@convention(thin) () -> StaticString
+// call StaticString.init
+// CHECK: apply
+// call UInt.init(_builtinIntegerLiteral:)
+// CHECK: apply
+// call _sanityCheck(_:_:file:line:)
+// CHECK: apply %{{.*}}([[CLOSURE]], {{.*}})
+// CHECK: load [trivial] [[PROJ]] : $*StructWithLayout
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify16StructWithLayoutVACycfC'
+
+// --- pointer_to_address
+// Verification should ignore this case.
+func testPointerInit(x: Int, y: UnsafeMutablePointer<Int>) {
+ y.pointee = x
+}
+// CHECK-LABEL: sil hidden @$S20access_marker_verify15testPointerInit1x1yySi_SpySiGtF : $@convention(thin) (Int, UnsafeMutablePointer<Int>) -> () {
+// CHECK: bb0(%0 : @trivial $Int, %1 : @trivial $UnsafeMutablePointer<Int>):
+// call addressor
+// CHECK: [[POINTEE:%.*]] = apply %{{.*}}<Int>(%1) : $@convention(method) <τ_0_0> (UnsafeMutablePointer<τ_0_0>) -> UnsafeMutablePointer<τ_0_0>
+// CHECK: [[RAWPTR:%.*]] = struct_extract [[POINTEE]] : $UnsafeMutablePointer<Int>, #UnsafeMutablePointer._rawValue
+// CHECK: [[ADR:%.*]] = pointer_to_address [[RAWPTR]] : $Builtin.RawPointer to [strict] $*Int
+// CHECK-NOT: begin_access
+// CHECK: assign %0 to [[ADR]] : $*Int
+// CHECK-LABEL: } // end sil function '$S20access_marker_verify15testPointerInit1x1yySi_SpySiGtF'
diff --git a/test/SILOptimizer/plus_zero_array_element_propagation.sil b/test/SILOptimizer/plus_zero_array_element_propagation.sil
new file mode 100644
index 0000000..8973b9a
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_array_element_propagation.sil
@@ -0,0 +1,387 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -array-element-propagation %s | %FileCheck %s
+sil_stage canonical
+
+import Builtin
+import Swift
+
+struct MyInt {
+ @sil_stored var _value: Builtin.Int64
+}
+
+struct MyBool {}
+struct _MyDependenceToken {}
+
+struct _MyBridgeStorage {
+ @sil_stored var rawValue : Builtin.BridgeObject
+}
+
+struct _MyArrayBuffer<T> {
+ @sil_stored var _storage : _MyBridgeStorage
+}
+
+
+struct MyArray<T> {
+ @sil_stored var _buffer : _MyArrayBuffer<T>
+}
+
+sil @swift_bufferAllocate : $@convention(thin)() -> @owned AnyObject
+sil [_semantics "array.uninitialized"] @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+sil [_semantics "array.props.isNativeTypeChecked"] @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+sil [_semantics "array.check_subscript"] @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+sil [_semantics "array.get_element"] @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+sil [_semantics "array.get_element"] @getElement2 : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> MyInt
+sil @unknown_array_use : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+sil [_semantics "array.uninitialized"] @arrayAdoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin Array<MyInt>.Type) -> @owned (Array<MyInt>, UnsafeMutablePointer<MyInt>)
+sil @arrayInit : $@convention(method) (@thin Array<MyInt>.Type) -> @owned Array<MyInt>
+sil [_semantics "array.append_contentsOf"] @arrayAppendContentsOf : $@convention(method) (@owned Array<MyInt>, @inout Array<MyInt>) -> ()
+
+// CHECK-LABEL: sil @propagate01
+// CHECK: struct $MyInt
+// CHECK: [[V0:%.*]] = integer_literal $Builtin.Int64, 0
+// CHECK: [[I0:%.*]] = struct $MyInt ([[V0]] : $Builtin.Int64)
+// CHECK: [[V1:%.*]] = integer_literal $Builtin.Int64, 1
+// CHECK: [[I1:%.*]] = struct $MyInt ([[V1]] : $Builtin.Int64)
+// CHECK: [[V2:%.*]] = integer_literal $Builtin.Int64, 2
+// CHECK: [[I2:%.*]] = struct $MyInt ([[V2]] : $Builtin.Int64)
+// CHECK: [[S0:%.*]] = alloc_stack $MyInt
+// CHECK: [[HFUN:%.*]] = function_ref @hoistableIsNativeTypeChecked
+// CHECK-NOT: apply [[HFUN]]
+// CHECK: [[CFUN:%.*]] = function_ref @checkSubscript
+// CHECK-NOT: apply [[CFUN]]
+// CHECK: [[GFUN:%.*]] = function_ref @getElement
+// CHECK-NOT: apply [[GFUN]]
+// CHECK-NOT: apply [[HFUN]]
+// CHECK-NOT: apply [[CFUN]]
+// CHECK-NOT: apply [[GFUN]]
+// CHECK: store [[I0]] to [[S0]]
+// CHECK: [[S1:%.*]] = alloc_stack $MyInt
+// CHECK: store [[I1]] to [[S1]]
+// CHECK: [[S2:%.*]] = alloc_stack $MyInt
+// CHECK: store [[I2]] to [[S2]]
+// CHECK: return
+
+sil @propagate01 : $@convention(thin) () -> () {
+ %0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
+ %1 = integer_literal $Builtin.Int64, 3
+ %2 = struct $MyInt (%1 : $Builtin.Int64)
+ %3 = apply %0() : $@convention(thin) () -> @owned AnyObject
+ %4 = metatype $@thin MyArray<MyInt>.Type
+ %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %7 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 0
+ %8 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 1
+ debug_value %7 : $MyArray<MyInt>
+ debug_value %8 : $UnsafeMutablePointer<MyInt>
+ %9 = struct_extract %8 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
+ %10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyInt
+ %11 = integer_literal $Builtin.Int64, 0
+ %12 = struct $MyInt (%11 : $Builtin.Int64)
+ store %12 to %10 : $*MyInt
+ %13 = integer_literal $Builtin.Word, 1
+ %14 = index_addr %10 : $*MyInt, %13 : $Builtin.Word
+ %15 = integer_literal $Builtin.Int64, 1
+ %16 = struct $MyInt (%15 : $Builtin.Int64)
+ store %16 to %14 : $*MyInt
+ %17 = integer_literal $Builtin.Word, 2
+ %18 = index_addr %10 : $*MyInt, %17 : $Builtin.Word
+ %19 = integer_literal $Builtin.Int64, 2
+ %20 = struct $MyInt (%19 : $Builtin.Int64)
+ store %20 to %18 : $*MyInt
+ %23 = struct_extract %7 : $MyArray<MyInt>, #MyArray._buffer
+ %24 = struct_extract %23 : $_MyArrayBuffer<MyInt>, #_MyArrayBuffer._storage
+ %25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
+ %26 = alloc_stack $MyInt
+ debug_value %7 : $MyArray<MyInt>
+ %27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %28 = apply %27(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ debug_value %28 : $MyBool // id: %104
+ %29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %30 = apply %29(%12, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ debug_value %30 : $_MyDependenceToken
+ %31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ %32 = apply %31(%26, %12, %28, %30, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ %35 = alloc_stack $MyInt
+ debug_value %16 : $MyInt
+ debug_value %7 : $MyArray<MyInt>
+ debug_value %28 : $MyBool
+ strong_retain %25 : $Builtin.BridgeObject
+ %36 = apply %29(%16, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ debug_value %36 : $_MyDependenceToken
+ %37 = apply %31(%35, %16, %28, %36, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ %44 = alloc_stack $MyInt
+ debug_value %7 : $MyArray<MyInt>
+ debug_value %28 : $MyBool
+ strong_retain %25 : $Builtin.BridgeObject
+ %45 = apply %29(%20, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ debug_value %45 : $_MyDependenceToken
+ %46 = apply %31(%44, %20, %28, %45, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ %52 = tuple ()
+ dealloc_stack %44 : $*MyInt
+ dealloc_stack %35 : $*MyInt
+ dealloc_stack %26 : $*MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ return %52 : $()
+}
+
+// CHECK-LABEL: sil @propagate_with_get_element_returning_direct_result
+// CHECK: struct $MyInt
+// CHECK: [[V0:%.*]] = integer_literal $Builtin.Int64, 0
+// CHECK: [[I0:%.*]] = struct $MyInt ([[V0]] : $Builtin.Int64)
+// CHECK: [[V1:%.*]] = integer_literal $Builtin.Int64, 1
+// CHECK: [[I1:%.*]] = struct $MyInt ([[V1]] : $Builtin.Int64)
+// CHECK: [[V2:%.*]] = integer_literal $Builtin.Int64, 2
+// CHECK: [[I2:%.*]] = struct $MyInt ([[V2]] : $Builtin.Int64)
+// CHECK: [[S0:%.*]] = alloc_stack $MyInt
+// CHECK: [[HFUN:%.*]] = function_ref @hoistableIsNativeTypeChecked
+// CHECK-NOT: apply [[HFUN]]
+// CHECK: [[CFUN:%.*]] = function_ref @checkSubscript
+// CHECK-NOT: apply [[CFUN]]
+// CHECK: [[GFUN:%.*]] = function_ref @getElement
+// CHECK-NOT: apply [[GFUN]]
+// CHECK-NOT: apply [[HFUN]]
+// CHECK-NOT: apply [[CFUN]]
+// CHECK-NOT: apply [[GFUN]]
+// CHECK: store [[I0]] to [[S0]]
+// CHECK: [[S1:%.*]] = alloc_stack $MyInt
+// CHECK: store [[I1]] to [[S1]]
+// CHECK: [[S2:%.*]] = alloc_stack $MyInt
+// CHECK: store [[I2]] to [[S2]]
+// CHECK: return
+
+sil @propagate_with_get_element_returning_direct_result : $@convention(thin) () -> () {
+ %0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
+ %1 = integer_literal $Builtin.Int64, 3
+ %2 = struct $MyInt (%1 : $Builtin.Int64)
+ %3 = apply %0() : $@convention(thin) () -> @owned AnyObject
+ %4 = metatype $@thin MyArray<MyInt>.Type
+ %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %7 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 0
+ %8 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 1
+ debug_value %7 : $MyArray<MyInt>
+ debug_value %8 : $UnsafeMutablePointer<MyInt>
+ %9 = struct_extract %8 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
+ %10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyInt
+ %11 = integer_literal $Builtin.Int64, 0
+ %12 = struct $MyInt (%11 : $Builtin.Int64)
+ store %12 to %10 : $*MyInt
+ %13 = integer_literal $Builtin.Word, 1
+ %14 = index_addr %10 : $*MyInt, %13 : $Builtin.Word
+ %15 = integer_literal $Builtin.Int64, 1
+ %16 = struct $MyInt (%15 : $Builtin.Int64)
+ store %16 to %14 : $*MyInt
+ %17 = integer_literal $Builtin.Word, 2
+ %18 = index_addr %10 : $*MyInt, %17 : $Builtin.Word
+ %19 = integer_literal $Builtin.Int64, 2
+ %20 = struct $MyInt (%19 : $Builtin.Int64)
+ store %20 to %18 : $*MyInt
+ %23 = struct_extract %7 : $MyArray<MyInt>, #MyArray._buffer
+ %24 = struct_extract %23 : $_MyArrayBuffer<MyInt>, #_MyArrayBuffer._storage
+ %25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
+ %26 = alloc_stack $MyInt
+ debug_value %7 : $MyArray<MyInt>
+ %27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %28 = apply %27(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ debug_value %28 : $MyBool // id: %104
+ %29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %30 = apply %29(%12, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ debug_value %30 : $_MyDependenceToken
+ %31 = function_ref @getElement2 : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> MyInt
+ %32 = apply %31(%12, %28, %30, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> MyInt
+ store %32 to %26 : $*MyInt
+ %35 = alloc_stack $MyInt
+ debug_value %16 : $MyInt
+ debug_value %7 : $MyArray<MyInt>
+ debug_value %28 : $MyBool
+ strong_retain %25 : $Builtin.BridgeObject
+ %36 = apply %29(%16, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ debug_value %36 : $_MyDependenceToken
+ %37 = apply %31(%16, %28, %36, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> MyInt
+ store %37 to %35 : $*MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ %44 = alloc_stack $MyInt
+ debug_value %7 : $MyArray<MyInt>
+ debug_value %28 : $MyBool
+ strong_retain %25 : $Builtin.BridgeObject
+ %45 = apply %29(%20, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ debug_value %45 : $_MyDependenceToken
+ %46 = apply %31(%20, %28, %45, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> MyInt
+ store %46 to %44 : $*MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ %52 = tuple ()
+ dealloc_stack %44 : $*MyInt
+ dealloc_stack %35 : $*MyInt
+ dealloc_stack %26 : $*MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ return %52 : $()
+}
+
+// CHECK-LABEL: sil @repeated_initialization
+// CHECK: [[GFUN:%.*]] = function_ref @getElement
+// CHECK: apply [[GFUN]]
+// CHECK: apply [[GFUN]]
+// CHECK: return
+
+sil @repeated_initialization : $@convention(thin) () -> () {
+ %0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
+ %1 = integer_literal $Builtin.Int64, 2
+ %2 = struct $MyInt (%1 : $Builtin.Int64)
+ %3 = apply %0() : $@convention(thin) () -> @owned AnyObject
+ %4 = metatype $@thin MyArray<MyInt>.Type
+ %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %7 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 0
+ %8 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 1
+ %9 = struct_extract %8 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
+ %10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyInt
+ %11 = integer_literal $Builtin.Int64, 0
+ %12 = struct $MyInt (%11 : $Builtin.Int64)
+ store %12 to %10 : $*MyInt
+ %13 = integer_literal $Builtin.Word, 0
+ %14 = index_addr %10 : $*MyInt, %13 : $Builtin.Word
+ %15 = integer_literal $Builtin.Int64, 1
+ %16 = struct $MyInt (%15 : $Builtin.Int64)
+ store %16 to %14 : $*MyInt
+ %23 = struct_extract %7 : $MyArray<MyInt>, #MyArray._buffer
+ %24 = struct_extract %23 : $_MyArrayBuffer<MyInt>, #_MyArrayBuffer._storage
+ %25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
+ %26 = alloc_stack $MyInt
+ %27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %28 = apply %27(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %30 = apply %29(%12, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ %32 = apply %31(%26, %12, %28, %30, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ %35 = alloc_stack $MyInt
+ strong_retain %25 : $Builtin.BridgeObject
+ %36 = apply %29(%16, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %37 = apply %31(%35, %16, %28, %36, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ %52 = tuple ()
+ dealloc_stack %35 : $*MyInt
+ dealloc_stack %26 : $*MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ return %52 : $()
+}
+
+// CHECK-LABEL: sil @unknown_use
+// CHECK: [[GFUN:%.*]] = function_ref @getElement
+// CHECK: apply [[GFUN]]
+// CHECK: return
+
+sil @unknown_use : $@convention(thin) () -> () {
+ %0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
+ %1 = integer_literal $Builtin.Int64, 2
+ %2 = struct $MyInt (%1 : $Builtin.Int64)
+ %3 = apply %0() : $@convention(thin) () -> @owned AnyObject
+ %4 = metatype $@thin MyArray<MyInt>.Type
+ %5 = function_ref @adoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin MyArray<MyInt>.Type) -> @owned (MyArray<MyInt>, UnsafeMutablePointer<MyInt>)
+ %7 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 0
+ %8 = tuple_extract %6 : $(MyArray<MyInt>, UnsafeMutablePointer<MyInt>), 1
+ %9 = struct_extract %8 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
+ %10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyInt
+ %11 = integer_literal $Builtin.Int64, 0
+ %12 = struct $MyInt (%11 : $Builtin.Int64)
+ store %12 to %10 : $*MyInt
+ %23 = struct_extract %7 : $MyArray<MyInt>, #MyArray._buffer
+ %24 = struct_extract %23 : $_MyArrayBuffer<MyInt>, #_MyArrayBuffer._storage
+ %25 = struct_extract %24 : $_MyBridgeStorage, #_MyBridgeStorage.rawValue
+ %26 = alloc_stack $MyInt
+ %27 = function_ref @hoistableIsNativeTypeChecked : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %28 = apply %27(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %29 = function_ref @checkSubscript : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %30 = apply %29(%12, %28, %7) : $@convention(method) (MyInt, MyBool, @guaranteed MyArray<MyInt>) -> _MyDependenceToken
+ %31 = function_ref @getElement : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ %32 = apply %31(%26, %12, %28, %30, %7) : $@convention(method) (MyInt, MyBool, _MyDependenceToken, @guaranteed MyArray<MyInt>) -> @out MyInt
+ %33 = function_ref @unknown_array_use : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %34 = apply %33(%7) : $@convention(method) (@guaranteed MyArray<MyInt>) -> MyBool
+ %52 = tuple ()
+ dealloc_stack %26 : $*MyInt
+ strong_release %25 : $Builtin.BridgeObject
+ return %52 : $()
+}
+
+// CHECK-LABEL: sil @append_contentsOf_int
+// CHECK: [[ASFUN:%.*]] = function_ref @arrayAdoptStorage
+// CHECK-NEXT: [[ARR:%.*]] = apply [[ASFUN]]
+// CHECK-NEXT: [[OWNER:%.*]] = tuple_extract [[ARR]]{{.*}}, 0
+// CHECK-NOT: apply [[ACFUN]]
+// CHECK: [[AEFUN:%.*]] = function_ref @$SSa6appendyyxF
+// CHECK-NEXT: [[STACK:%.*]] = alloc_stack $MyInt
+// CHECK-NEXT: store %{{[0-9]+}} to [[STACK]]
+// CHECK-NEXT: apply [[AEFUN]]<MyInt>([[STACK]]
+// CHECK-NEXT: dealloc_stack [[STACK]]
+// CHECK-NEXT: release_value [[OWNER]]
+// CHECK: return
+sil @append_contentsOf_int : $@convention(thin) () -> () {
+ %0 = function_ref @swift_bufferAllocate : $@convention(thin) () -> @owned AnyObject
+ %1 = integer_literal $Builtin.Int64, 1
+ %2 = struct $MyInt (%1 : $Builtin.Int64)
+ %3 = apply %0() : $@convention(thin) () -> @owned AnyObject
+ %4 = metatype $@thin Array<MyInt>.Type
+ %5 = function_ref @arrayAdoptStorage : $@convention(thin) (@owned AnyObject, MyInt, @thin Array<MyInt>.Type) -> @owned (Array<MyInt>, UnsafeMutablePointer<MyInt>)
+ %6 = apply %5(%3, %2, %4) : $@convention(thin) (@owned AnyObject, MyInt, @thin Array<MyInt>.Type) -> @owned (Array<MyInt>, UnsafeMutablePointer<MyInt>)
+ %7 = tuple_extract %6 : $(Array<MyInt>, UnsafeMutablePointer<MyInt>), 0
+ %8 = tuple_extract %6 : $(Array<MyInt>, UnsafeMutablePointer<MyInt>), 1
+ %9 = struct_extract %8 : $UnsafeMutablePointer<MyInt>, #UnsafeMutablePointer._rawValue
+ %10 = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*MyInt
+ %11 = integer_literal $Builtin.Int64, 27
+ %12 = struct $MyInt (%11 : $Builtin.Int64)
+ store %12 to %10 : $*MyInt
+ %13 = alloc_stack $Array<MyInt>
+ %14 = metatype $@thin Array<MyInt>.Type
+ %15 = function_ref @arrayInit : $@convention(method) (@thin Array<MyInt>.Type) -> @owned Array<MyInt>
+ %16 = apply %15(%14) : $@convention(method) (@thin Array<MyInt>.Type) -> @owned Array<MyInt>
+ store %16 to %13 : $*Array<MyInt>
+ %17 = function_ref @arrayAppendContentsOf : $@convention(method) (@owned Array<MyInt>, @inout Array<MyInt>) -> ()
+ %18 = apply %17(%7, %13) : $@convention(method) (@owned Array<MyInt>, @inout Array<MyInt>) -> ()
+ dealloc_stack %13 : $*Array<MyInt>
+ %19 = tuple ()
+ return %19 : $()
+}
+
+class Hello {
+}
+
+sil [_semantics "array.uninitialized"] @adoptStorageHello : $@convention(method) (@owned _ContiguousArrayStorage<Hello>, MyInt, @thin Array<Hello>.Type) -> (@owned Array<Hello>, UnsafeMutablePointer<Hello>)
+sil [_semantics "array.append_contentsOf"] @arrayAppendContentsOfHello : $@convention(method) (@owned Array<Hello>, @inout Array<Hello>) -> ()
+
+// CHECK-LABEL: sil @append_contentsOf_class
+// CHECK: [[ASFUN:%.*]] = function_ref @adoptStorageHello
+// CHECK-NEXT: [[ARR:%.*]] = apply [[ASFUN]]
+// CHECK-NEXT: [[OWNER:%.*]] = tuple_extract [[ARR]]{{.*}}, 0
+// CHECK: strong_retain %1 : $Hello
+// CHECK-NEXT: store %1 to %{{[0-9]+}} : $*Hello
+// CHECK-NOT: apply
+// CHECK: [[AEFUN:%.*]] = function_ref @$SSa6appendyyxF
+// CHECK-NEXT: strong_retain %1 : $Hello
+// CHECK-NEXT: [[STACK:%.*]] = alloc_stack $Hello
+// CHECK-NEXT: store %1 to [[STACK]]
+// CHECK-NEXT: apply [[AEFUN]]<Hello>([[STACK]], %0)
+// CHECK-NEXT: dealloc_stack [[STACK]]
+// CHECK-NEXT: strong_release %1
+// CHECK-NEXT: release_value [[OWNER]]
+// CHECK-NEXT: return
+sil @append_contentsOf_class : $@convention(thin) (@inout Array<Hello>, @owned Hello) -> @owned Hello {
+bb0(%0 : $*Array<Hello>, %1 : $Hello):
+ %4 = integer_literal $Builtin.Word, 1
+ %5 = integer_literal $Builtin.Int64, 1
+ %6 = struct $MyInt (%5 : $Builtin.Int64)
+ %7 = alloc_ref [tail_elems $Hello * %4 : $Builtin.Word] $_ContiguousArrayStorage<Hello>
+ %8 = metatype $@thin Array<Hello>.Type
+ %9 = function_ref @adoptStorageHello : $@convention(method) (@owned _ContiguousArrayStorage<Hello>, MyInt, @thin Array<Hello>.Type) -> (@owned Array<Hello>, UnsafeMutablePointer<Hello>)
+ %10 = apply %9(%7, %6, %8) : $@convention(method) (@owned _ContiguousArrayStorage<Hello>, MyInt, @thin Array<Hello>.Type) -> (@owned Array<Hello>, UnsafeMutablePointer<Hello>)
+ %11 = tuple_extract %10 : $(Array<Hello>, UnsafeMutablePointer<Hello>), 0
+ %12 = tuple_extract %10 : $(Array<Hello>, UnsafeMutablePointer<Hello>), 1
+ %13 = struct_extract %12 : $UnsafeMutablePointer<Hello>, #UnsafeMutablePointer._rawValue
+ %22 = pointer_to_address %13 : $Builtin.RawPointer to [strict] $*Hello
+ strong_retain %1 : $Hello
+ store %1 to %22 : $*Hello
+ %25 = function_ref @arrayAppendContentsOfHello : $@convention(method) (@owned Array<Hello>, @inout Array<Hello>) -> ()
+ %26 = apply %25(%11, %0) : $@convention(method) (@owned Array<Hello>, @inout Array<Hello>) -> ()
+ return %1 : $Hello
+}
diff --git a/test/SILOptimizer/plus_zero_bridged_casts_folding.swift b/test/SILOptimizer/plus_zero_bridged_casts_folding.swift
new file mode 100644
index 0000000..5ef60d6
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_bridged_casts_folding.swift
@@ -0,0 +1,949 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+// Check that casts between bridged types are replaced by more
+// efficient code sequences.
+//
+// In particular, checked_cast_* and unconditional_checked_* instructions,
+// which are pretty expensive at run-time (e.g. because they use
+// runtime _dynamicCast calls and check conformances at run-time),
+// should be replaced by invocations of specialized bridging functions,
+// which make use of statically known compile-time conformances and
+// do not perform any conformance checks at run-time.
+
+import Foundation
+
+public func forcedCast<NS, T>(_ ns: NS) -> T {
+ return ns as! T
+}
+
+public func condCast<NS, T>(_ ns: NS) -> T? {
+ return ns as? T
+}
+
+// Check optimizations of casts from NSString to String
+
+var nsString: NSString = "string"
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testForcedCastNStoSwiftStringSSyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSS10FoundationE26_forceBridgeFromObjectiveC_6resultySo8NSStringC_SSSgztFZ : $@convention(method) (@guaranteed NSString, @inout Optional<String>, @thin String.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftString() -> String {
+ var o: String = forcedCast(nsString)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding27testCondCastNStoSwiftStringSSSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSS10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo8NSStringC_SSSgztFZ : $@convention(method) (@guaranteed NSString, @inout Optional<String>, @thin String.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftString() -> String? {
+ var o: String? = condCast(nsString)
+ return o
+}
+
+
+// Check optimizations of casts from NSNumber to Int
+
+var nsIntNumber = NSNumber(value: 1)
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastNSNumberToSwiftIntSiyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSi10FoundationE26_forceBridgeFromObjectiveC_6resultySo8NSNumberC_SiSgztFZ : $@convention(method) (@guaranteed NSNumber, @inout Optional<Int>, @thin Int.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNSNumberToSwiftInt() -> Int {
+ var o: Int = forcedCast(nsIntNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastNSNumberToSwiftIntSiSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSi10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo8NSNumberC_SiSgztFZ : $@convention(method) (@guaranteed NSNumber, @inout Optional<Int>, @thin Int.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNSNumberToSwiftInt() -> Int? {
+ var o: Int? = condCast(nsIntNumber)
+ return o
+}
+
+// Check optimizations of casts from NSNumber to Double
+
+var nsDoubleNumber = NSNumber(value: 1.234)
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding35testForcedCastNSNumberToSwiftDoubleSdyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSd10FoundationE26_forceBridgeFromObjectiveC_6resultySo8NSNumberC_SdSgztFZ : $@convention(method) (@guaranteed NSNumber, @inout Optional<Double>, @thin Double.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNSNumberToSwiftDouble() -> Double {
+ var o: Double = forcedCast(nsDoubleNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding33testCondCastNSNumberToSwiftDoubleSdSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSd10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo8NSNumberC_SdSgztFZ : $@convention(method) (@guaranteed NSNumber, @inout Optional<Double>, @thin Double.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNSNumberToSwiftDouble() -> Double? {
+ var o: Double? = condCast(nsDoubleNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding38testForcedCastNSIntNumberToSwiftDoubleSdyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSd10FoundationE26_forceBridgeFromObjectiveC_6resultySo8NSNumberC_SdSgztFZ : $@convention(method) (@guaranteed NSNumber, @inout Optional<Double>, @thin Double.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNSIntNumberToSwiftDouble() -> Double {
+ var o: Double = forcedCast(nsIntNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding36testCondCastNSIntNumberToSwiftDoubleSdSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSd10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo8NSNumberC_SdSgztFZ : $@convention(method) (@guaranteed NSNumber, @inout Optional<Double>, @thin Double.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNSIntNumberToSwiftDouble() -> Double? {
+ var o: Double? = condCast(nsIntNumber)
+ return o
+}
+
+
+
+// Check optimization of casts from NSArray to Swift Array
+
+var nsArrInt: NSArray = [1, 2, 3, 4]
+var nsArrDouble: NSArray = [1.1, 2.2, 3.3, 4.4]
+var nsArrString: NSArray = ["One", "Two", "Three", "Four"]
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testForcedCastNStoSwiftArrayIntSaySiGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSa10FoundationE26_forceBridgeFromObjectiveC_6resultySo7NSArrayC_SayxGSgztFZ : $@convention(method) <τ_0_0> (@guaranteed NSArray, @inout Optional<Array<τ_0_0>>, @thin Array<τ_0_0>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftArrayInt() -> [Int] {
+ var arr: [Int] = forcedCast(nsArrInt)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testCondCastNStoSwiftArrayIntSaySiGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSa10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo7NSArrayC_SayxGSgztFZ : $@convention(method) <τ_0_0> (@guaranteed NSArray, @inout Optional<Array<τ_0_0>>, @thin Array<τ_0_0>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftArrayInt() -> [Int]? {
+ var arrOpt: [Int]? = condCast(nsArrInt)
+ return arrOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding34testForcedCastNStoSwiftArrayDoubleSaySdGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSa10FoundationE26_forceBridgeFromObjectiveC_6resultySo7NSArrayC_SayxGSgztFZ : $@convention(method) <τ_0_0> (@guaranteed NSArray, @inout Optional<Array<τ_0_0>>, @thin Array<τ_0_0>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftArrayDouble() -> [Double] {
+ var arr: [Double] = forcedCast(nsArrDouble)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testCondCastNStoSwiftArrayDoubleSaySdGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSa10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo7NSArrayC_SayxGSgztFZ : $@convention(method) <τ_0_0> (@guaranteed NSArray, @inout Optional<Array<τ_0_0>>, @thin Array<τ_0_0>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftArrayDouble() -> [Double]? {
+ var arrOpt: [Double]? = condCast(nsArrDouble)
+ return arrOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding34testForcedCastNStoSwiftArrayStringSaySSGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$SSa10FoundationE26_forceBridgeFromObjectiveC_6resultySo7NSArrayC_SayxGSgztFZ : $@convention(method) <τ_0_0> (@guaranteed NSArray, @inout Optional<Array<τ_0_0>>, @thin Array<τ_0_0>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftArrayString() -> [String] {
+ var arr: [String] = forcedCast(nsArrString)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testCondCastNStoSwiftArrayStringSaySSGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$SSa10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo7NSArrayC_SayxGSgztFZ : $@convention(method) <τ_0_0> (@guaranteed NSArray, @inout Optional<Array<τ_0_0>>, @thin Array<τ_0_0>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftArrayString() -> [String]? {
+ var arrOpt: [String]? = condCast(nsArrString)
+ return arrOpt
+}
+
+
+
+// Check optimization of casts from NSDictionary to Swift Dictionary
+
+var nsDictInt: NSDictionary = [1:1, 2:2, 3:3, 4:4]
+var nsDictDouble: NSDictionary = [1.1 : 1.1, 2.2 : 2.2, 3.3 : 3.3, 4.4 : 4.4]
+var nsDictString: NSDictionary = ["One":"One", "Two":"Two", "Three":"Three", "Four":"Four"]
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testForcedCastNStoSwiftDictInts10DictionaryVyS2iGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE26_forceBridgeFromObjectiveC_6resultySo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftDictInt() -> [Int: Int] {
+ var dict: [Int: Int] = forcedCast(nsDictInt)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding28testCondCastNStoSwiftDictInts10DictionaryVyS2iGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftDictInt() -> [Int: Int]? {
+ var dictOpt: [Int: Int]? = condCast(nsDictInt)
+ return dictOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding33testForcedCastNStoSwiftDictDoubles10DictionaryVyS2dGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE26_forceBridgeFromObjectiveC_6resultySo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftDictDouble() -> [Double: Double] {
+ var dict: [Double: Double] = forcedCast(nsDictDouble)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testCondCastNStoSwiftDictDoubles10DictionaryVyS2dGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftDictDouble() -> [Double: Double]? {
+ var dictOpt: [Double: Double]? = condCast(nsDictDouble)
+ return dictOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding33testForcedCastNStoSwiftDictStrings10DictionaryVyS2SGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE26_forceBridgeFromObjectiveC_6resultySo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftDictString() -> [String: String] {
+ var dict: [String: String] = forcedCast(nsDictString)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testCondCastNStoSwiftDictStrings10DictionaryVyS2SGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftDictString() -> [String: String]? {
+ var dictOpt: [String: String]? = condCast(nsDictString)
+ return dictOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding40testForcedCastNSDictStringtoSwiftDictInts10DictionaryVyS2iGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE26_forceBridgeFromObjectiveC_6resultySo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNSDictStringtoSwiftDictInt() -> [Int: Int] {
+ var dictOpt: [Int: Int] = forcedCast(nsDictString)
+ return dictOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding38testCondCastNSDictStringtoSwiftDictInts10DictionaryVyS2iGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss10DictionaryV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo12NSDictionaryC_AByxq_GSgztFZ : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@guaranteed NSDictionary, @inout Optional<Dictionary<τ_0_0, τ_0_1>>, @thin Dictionary<τ_0_0, τ_0_1>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNSDictStringtoSwiftDictInt() -> [Int: Int]? {
+ var dictOpt: [Int: Int]? = condCast(nsDictString)
+ return dictOpt
+}
+
+
+// Check optimization of casts from NSSet to Swift Set
+
+var nsSetInt: NSSet = [1, 2, 3, 4]
+var nsSetDouble: NSSet = [1.1, 2.2, 3.3, 4.4]
+var nsSetString: NSSet = ["One", "Two", "Three", "Four"]
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testForcedCastNStoSwiftSetInts0I0VySiGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss3SetV10FoundationE26_forceBridgeFromObjectiveC_6resultySo5NSSetC_AByxGSgztFZ : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed NSSet, @inout Optional<Set<τ_0_0>>, @thin Set<τ_0_0>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftSetInt() -> Set<Int> {
+ var set: Set<Int> = forcedCast(nsSetInt)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding27testCondCastNStoSwiftSetInts0I0VySiGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss3SetV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo5NSSetC_AByxGSgztFZ : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed NSSet, @inout Optional<Set<τ_0_0>>, @thin Set<τ_0_0>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftSetInt() -> Set<Int>? {
+ var setOpt: Set<Int>? = condCast(nsSetInt)
+ return setOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastNStoSwiftSetDoubles0I0VySdGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss3SetV10FoundationE26_forceBridgeFromObjectiveC_6resultySo5NSSetC_AByxGSgztFZ : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed NSSet, @inout Optional<Set<τ_0_0>>, @thin Set<τ_0_0>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftSetDouble() -> Set<Double> {
+ var set: Set<Double> = forcedCast(nsSetDouble)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastNStoSwiftSetDoubles0I0VySdGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss3SetV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo5NSSetC_AByxGSgztFZ : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed NSSet, @inout Optional<Set<τ_0_0>>, @thin Set<τ_0_0>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftSetDouble() -> Set<Double>? {
+ var setOpt: Set<Double>? = condCast(nsSetDouble)
+ return setOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastNStoSwiftSetStrings0I0VySSGyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @$Ss3SetV10FoundationE26_forceBridgeFromObjectiveC_6resultySo5NSSetC_AByxGSgztFZ : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed NSSet, @inout Optional<Set<τ_0_0>>, @thin Set<τ_0_0>.Type) -> ()
+// CHECK: return
+@inline(never)
+public func testForcedCastNStoSwiftSetString() -> Set<String> {
+ var set: Set<String> = forcedCast(nsSetString)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastNStoSwiftSetStrings0I0VySSGSgyF
+// CHECK-NOT: checked_cast
+// CHECK: function_ref @$Ss3SetV10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo5NSSetC_AByxGSgztFZ : $@convention(method) <τ_0_0 where τ_0_0 : Hashable> (@guaranteed NSSet, @inout Optional<Set<τ_0_0>>, @thin Set<τ_0_0>.Type) -> Bool
+// CHECK: return
+@inline(never)
+public func testCondCastNStoSwiftSetString() -> Set<String>? {
+ var setOpt: Set<String>? = condCast(nsSetString)
+ return setOpt
+}
+
+
+// Check optimizations of casts from String to NSString
+
+var swiftString: String = "string"
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testForcedCastSwiftToNSStringSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSString() -> NSString {
+ var o: NSString = forcedCast(swiftString)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding27testCondCastSwiftToNSStringSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSString() -> NSString? {
+ var o: NSString? = condCast(swiftString)
+ return o
+}
+
+
+// Check optimizations of casts from Int to NSNumber
+
+var swiftIntNumber: Int = 1
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastSwiftIntToNSNumberSo0J0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftIntToNSNumber() -> NSNumber {
+ var o: NSNumber = forcedCast(swiftIntNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastSwiftIntToNSNumberSo0J0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftIntToNSNumber() -> NSNumber? {
+ var o: NSNumber? = condCast(swiftIntNumber)
+ return o
+}
+
+// Check optimizations of casts from Double to NSNumber
+
+var swiftDoubleNumber: Double = 1.234
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding35testForcedCastSwiftDoubleToNSNumberSo0J0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftDoubleToNSNumber() -> NSNumber {
+ var o: NSNumber = forcedCast(swiftDoubleNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding33testCondCastSwiftDoubleToNSNumberSo0J0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftDoubleToNSNumber() -> NSNumber? {
+ var o: NSNumber? = condCast(swiftDoubleNumber)
+ return o
+}
+
+
+// Check optimization of casts from Swift Array to NSArray
+
+var arrInt: [Int] = [1, 2, 3, 4]
+var arrDouble: [Double] = [1.1, 2.2, 3.3, 4.4]
+var arrString: [String] = ["One", "Two", "Three", "Four"]
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testForcedCastSwiftToNSArrayIntSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSArrayInt() -> NSArray {
+ var arr: NSArray = forcedCast(arrInt)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testCondCastSwiftToNSArrayIntSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSArrayInt() -> NSArray? {
+ var arrOpt: NSArray? = condCast(arrInt)
+ return arrOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding34testForcedCastSwiftToNSArrayDoubleSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSArrayDouble() -> NSArray {
+ var arr: NSArray = forcedCast(arrDouble)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testCondCastSwiftToNSArrayDoubleSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSArrayDouble() -> NSArray? {
+ var arrOpt: NSArray? = condCast(arrDouble)
+ return arrOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding34testForcedCastSwiftToNSArrayStringSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSArrayString() -> NSArray {
+ var arr: NSArray = forcedCast(arrString)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testCondCastSwiftToNSArrayStringSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSArrayString() -> NSArray? {
+ var arrOpt: NSArray? = condCast(arrString)
+ return arrOpt
+}
+
+
+// Check optimization of casts from Swift Dict to NSDict
+
+var dictInt: [Int: Int] = [1:1, 2:2, 3:3, 4:4]
+var dictDouble: [Double: Double] = [1.1 : 1.1, 2.2 : 2.2, 3.3 : 3.3, 4.4 : 4.4]
+var dictString: [String: String] = ["One":"One", "Two":"Two", "Three":"Three", "Four":"Four"]
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testForcedCastSwiftToNSDictIntSo12NSDictionaryCyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSDictInt() -> NSDictionary {
+ var dict: NSDictionary = forcedCast(dictInt)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding28testCondCastSwiftToNSDictIntSo12NSDictionaryCSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSDictInt() -> NSDictionary? {
+ var dictOpt: NSDictionary? = condCast(dictInt)
+ return dictOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding33testForcedCastSwiftToNSDictDoubleSo12NSDictionaryCyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSDictDouble() -> NSDictionary {
+ var dict: NSDictionary = forcedCast(dictDouble)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testCondCastSwiftToNSDictDoubleSo12NSDictionaryCSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSDictDouble() -> NSDictionary? {
+ var dictOpt: NSDictionary? = condCast(dictDouble)
+ return dictOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding33testForcedCastSwiftToNSDictStringSo12NSDictionaryCyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSDictString() -> NSDictionary {
+ var dict: NSDictionary = forcedCast(dictString)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testCondCastSwiftToNSDictStringSo12NSDictionaryCSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSDictString() -> NSDictionary? {
+ var dictOpt: NSDictionary? = condCast(dictString)
+ return dictOpt
+}
+
+
+// Check optimization of casts from Swift Set to NSSet
+
+var setInt: Set<Int> = [1, 2, 3, 4]
+var setDouble: Set<Double> = [1.1, 2.2, 3.3, 4.4]
+var setString: Set<String> = ["One", "Two", "Three", "Four"]
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testForcedCastSwiftToNSSetIntSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSSetInt() -> NSSet {
+ var set: NSSet = forcedCast(setInt)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding27testCondCastSwiftToNSSetIntSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSSetInt() -> NSSet? {
+ var setOpt: NSSet? = condCast(setInt)
+ return setOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastSwiftToNSSetDoubleSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSSetDouble() -> NSSet {
+ var set: NSSet = forcedCast(setDouble)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastSwiftToNSSetDoubleSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSSetDouble() -> NSSet? {
+ var setOpt: NSSet? = condCast(setDouble)
+ return setOpt
+}
+
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastSwiftToNSSetStringSo0I0CyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testForcedCastSwiftToNSSetString() -> NSSet {
+ var set: NSSet = forcedCast(setString)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastSwiftToNSSetStringSo0I0CSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: return
+@inline(never)
+public func testCondCastSwiftToNSSetString() -> NSSet? {
+ var setOpt: NSSet? = condCast(setString)
+ return setOpt
+}
+
+// Casts involving generics cannot be optimized.
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding25testForcedCastFromGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: unconditional_checked
+// CHECK: return
+@inline(never)
+public func testForcedCastFromGeneric<T>(_ x: T) -> NSString {
+ var set: NSString = x as! NSString
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding23testForcedCastToGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: unconditional_checked
+// CHECK: return
+@inline(never)
+public func testForcedCastToGeneric<T>(_ x: T) -> T {
+ var set: T = nsString as! T
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding23testCondCastFromGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: checked_cast_addr_br
+// CHECK: return
+@inline(never)
+public func testCondCastFromGeneric<T>(_ x: T) -> NSString? {
+ var setOpt: NSString? = x as? NSString
+ return setOpt
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding21testCondCastToGeneric{{[_0-9a-zA-Z]*}}F
+// CHECK: checked_cast_addr_br
+// CHECK: return
+@inline(never)
+public func testCondCastToGeneric<T>(_ x: T) -> T? {
+ var setOpt: T? = nsString as? T
+ return setOpt
+}
+
+
+// Run-time tests
+
+//// ObjC -> Swift
+
+// Arrays
+print("NS to Swift arrays: Start")
+print(testForcedCastNStoSwiftArrayInt())
+print(testCondCastNStoSwiftArrayInt())
+
+print(testForcedCastNStoSwiftArrayDouble())
+print(testCondCastNStoSwiftArrayDouble())
+
+print(testForcedCastNStoSwiftArrayString())
+print(testCondCastNStoSwiftArrayString())
+print("NS to Swift arrays: End")
+
+// Dicts
+print("NS to Swift dictionaries: Start")
+print(testForcedCastNStoSwiftDictInt())
+print(testCondCastNStoSwiftDictInt())
+
+print(testForcedCastNStoSwiftDictDouble())
+print(testCondCastNStoSwiftDictDouble())
+
+print(testForcedCastNStoSwiftDictString())
+print(testCondCastNStoSwiftDictString())
+print(testCondCastNSDictStringtoSwiftDictInt())
+// This line should crash at run-time
+//print(testForcedCastNSDictStringtoSwiftDictInt())
+print("NS to Swift dictionaries: End")
+
+// Sets
+print("NS to Swift sets: Start")
+print(testForcedCastNStoSwiftSetInt())
+print(testCondCastNStoSwiftSetInt())
+
+print(testForcedCastNStoSwiftSetDouble())
+print(testCondCastNStoSwiftSetDouble())
+
+print(testForcedCastNStoSwiftSetString())
+print(testCondCastNStoSwiftSetString())
+print("NS to Swift sets: End")
+
+
+// Basic types
+
+print("NS to Swift basic types: Start")
+print(testForcedCastNSNumberToSwiftInt())
+print(testCondCastNSNumberToSwiftInt())
+
+print(testForcedCastNSNumberToSwiftDouble())
+print(testCondCastNSNumberToSwiftDouble())
+
+print(testForcedCastNSIntNumberToSwiftDouble())
+print(testCondCastNSIntNumberToSwiftDouble())
+
+print(testForcedCastNStoSwiftString())
+print(testCondCastNStoSwiftString())
+print("NS to Swift basic types: End")
+
+//// Swift -> ObjC
+
+// Basic types
+
+print("Swift to NS basic types: Start")
+print(testForcedCastSwiftIntToNSNumber())
+print(testCondCastSwiftIntToNSNumber())
+
+print(testForcedCastSwiftDoubleToNSNumber())
+print(testCondCastSwiftDoubleToNSNumber())
+
+print(testForcedCastSwiftToNSString())
+print(testCondCastSwiftToNSString())
+print("Swift to NS basic types: End")
+
+// Arrays
+print("Swift to NS arrays: Start")
+
+print(testForcedCastSwiftToNSArrayInt())
+print(testCondCastSwiftToNSArrayInt())
+
+print(testForcedCastSwiftToNSArrayDouble())
+print(testCondCastSwiftToNSArrayDouble())
+
+print(testForcedCastSwiftToNSArrayString())
+print(testCondCastSwiftToNSArrayString())
+
+print("Swift to NS arrays: End")
+
+
+// Dicts
+print("Swift to NS dictionaries: Start")
+
+print(testForcedCastSwiftToNSDictInt())
+print(testCondCastSwiftToNSDictInt())
+
+print(testForcedCastSwiftToNSDictDouble())
+print(testCondCastSwiftToNSDictDouble())
+
+print(testForcedCastSwiftToNSDictString())
+print(testCondCastSwiftToNSDictString())
+
+print("Swift to NS dictionaries: End")
+
+// Sets
+print("Swift to NS sets: Start")
+
+print(testForcedCastSwiftToNSSetInt())
+print(testCondCastSwiftToNSSetInt())
+
+print(testForcedCastSwiftToNSSetDouble())
+print(testCondCastSwiftToNSSetDouble())
+
+print(testForcedCastSwiftToNSSetString())
+print(testCondCastSwiftToNSSetString())
+
+print("Swift to NS sets: End")
+
+// Check optimizations of casts from String to CFString
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testForcedCastSwiftToCFStringSo0I3RefayF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSString to $CFString
+// CHECK: end{{.*}}$S21bridged_casts_folding29testForcedCastSwiftToCFStringSo0I3RefayF
+@inline(never)
+public func testForcedCastSwiftToCFString() -> CFString {
+ let o: CFString = forcedCast(swiftString)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding27testCondCastSwiftToCFStringSo0I3RefaSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSString to $CFString
+// CHECK: end{{.*}}$S21bridged_casts_folding27testCondCastSwiftToCFStringSo0I3RefaSgyF
+@inline(never)
+public func testCondCastSwiftToCFString() -> CFString? {
+ let o: CFString? = condCast(swiftString)
+ return o
+}
+
+// Check optimizations of casts from Int to CFNumber
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding32testForcedCastSwiftIntToCFNumberSo0J3RefayF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSNumber to $CFNumber
+// CHECK: end{{.*}}$S21bridged_casts_folding32testForcedCastSwiftIntToCFNumberSo0J3RefayF
+@inline(never)
+public func testForcedCastSwiftIntToCFNumber() -> CFNumber {
+ let o: CFNumber = forcedCast(swiftIntNumber)
+ return o
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testCondCastSwiftIntToCFNumberSo0J3RefaSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSNumber to $CFNumber
+// CHECK: end{{.*}}$S21bridged_casts_folding30testCondCastSwiftIntToCFNumberSo0J3RefaSgyF
+@inline(never)
+public func testCondCastSwiftIntToCFNumber() -> CFNumber? {
+ let o: CFNumber? = condCast(swiftIntNumber)
+ return o
+}
+
+// Check optimization of casts from Swift Array to CFArray
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding31testForcedCastSwiftToCFArrayIntSo0I3RefayF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSArray to $CFArray
+// CHECK: end{{.*}}$S21bridged_casts_folding31testForcedCastSwiftToCFArrayIntSo0I3RefayF
+@inline(never)
+public func testForcedCastSwiftToCFArrayInt() -> CFArray {
+ let arr: CFArray = forcedCast(arrInt)
+ return arr
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testCondCastSwiftToCFArrayIntSo0I3RefaSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSArray to $CFArray
+// CHECK: end{{.*}}$S21bridged_casts_folding29testCondCastSwiftToCFArrayIntSo0I3RefaSgyF
+@inline(never)
+public func testCondCastSwiftToCFArrayInt() -> CFArray? {
+ let arrOpt: CFArray? = condCast(arrInt)
+ return arrOpt
+}
+
+// Check optimization of casts from Swift Dict to CFDictionary
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding30testForcedCastSwiftToCFDictIntSo15CFDictionaryRefayF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSDictionary to $CFDictionary
+// CHECK: end{{.*}}$S21bridged_casts_folding30testForcedCastSwiftToCFDictIntSo15CFDictionaryRefayF
+@inline(never)
+public func testForcedCastSwiftToCFDictInt() -> CFDictionary {
+ let dict: CFDictionary = forcedCast(dictInt)
+ return dict
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding28testCondCastSwiftToCFDictIntSo15CFDictionaryRefaSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSDictionary to $CFDictionary
+// CHECK: end{{.*}}$S21bridged_casts_folding28testCondCastSwiftToCFDictIntSo15CFDictionaryRefaSgyF
+@inline(never)
+public func testCondCastSwiftToCFDictInt() -> CFDictionary? {
+ let dictOpt: CFDictionary? = condCast(dictInt)
+ return dictOpt
+}
+
+// Check optimization of casts from Swift Set to CFSet
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding29testForcedCastSwiftToCFSetIntSo0I3RefayF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSSet to $CFSet
+// CHECK: end{{.*}}$S21bridged_casts_folding29testForcedCastSwiftToCFSetIntSo0I3RefayF
+@inline(never)
+public func testForcedCastSwiftToCFSetInt() -> CFSet {
+ let set: CFSet = forcedCast(setInt)
+ return set
+}
+
+// CHECK-LABEL: sil [noinline] @$S21bridged_casts_folding27testCondCastSwiftToCFSetIntSo0I3RefaSgyF
+// CHECK-NOT: unconditional_checked
+// CHECK: function_ref @{{.*}}_bridgeToObjectiveC
+// CHECK: unchecked_ref_cast{{.*}}: $NSSet to $CFSet
+// CHECK: end{{.*}}$S21bridged_casts_folding27testCondCastSwiftToCFSetIntSo0I3RefaSgyF
+@inline(never)
+public func testCondCastSwiftToCFSetInt() -> CFSet? {
+ let setOpt: CFSet? = condCast(setInt)
+ return setOpt
+}
+
+public class NSObjectSubclass : NSObject { }
+
+var anyHashable: AnyHashable = 0
+
+// CHECK-LABEL: $S21bridged_casts_folding29testUncondCastSwiftToSubclassAA08NSObjectI0CyF
+// CHECK: [[GLOBAL:%[0-9]+]] = global_addr @$S21bridged_casts_folding11anyHashables03AnyE0Vv
+// CHECK: [[FUNC:%.*]] = function_ref @$Ss11AnyHashableV10FoundationE19_bridgeToObjectiveCSo8NSObjectCyF
+// CHECK-NEXT: apply [[FUNC]]([[GLOBAL]])
+// CHECK-NEXT: unconditional_checked_cast {{%.*}} : $NSObject to $NSObjectSubclass
+// CHECK: } // end sil function '$S21bridged_casts_folding29testUncondCastSwiftToSubclassAA08NSObjectI0CyF'
+@inline(never)
+public func testUncondCastSwiftToSubclass() -> NSObjectSubclass {
+ return anyHashable as! NSObjectSubclass
+}
+
+class MyThing: Hashable {
+ let name: String
+
+ init(name: String) {
+ self.name = name
+ }
+
+ deinit {
+ Swift.print("Deinit \(name)")
+ }
+
+ var hashValue: Int {
+ return 0
+ }
+
+ static func ==(lhs: MyThing, rhs: MyThing) -> Bool {
+ return false
+ }
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S21bridged_casts_folding26doSomethingWithAnyHashableyys0gH0VF : $@convention(thin) (@in_guaranteed AnyHashable) -> () {
+// CHECK: %2 = alloc_stack $AnyHashable
+// CHECK: copy_addr %0 to [initialization] %2 : $*AnyHashable
+// CHECK: checked_cast_addr_br take_always AnyHashable in %2 : $*AnyHashable to MyThing
+@inline(never)
+func doSomethingWithAnyHashable(_ item: AnyHashable) {
+ _ = item as? MyThing
+}
+
+@inline(never)
+public func testMyThing() {
+ let x = MyThing(name: "B")
+ doSomethingWithAnyHashable(x)
+}
diff --git a/test/SILOptimizer/plus_zero_capture_promotion_generic_context.sil b/test/SILOptimizer/plus_zero_capture_promotion_generic_context.sil
new file mode 100644
index 0000000..8f08930
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_capture_promotion_generic_context.sil
@@ -0,0 +1,124 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-sil -O -Xllvm -sil-fso-enable-generics=false %s | %FileCheck %s
+
+sil_stage raw
+
+import Builtin
+
+typealias Int = Builtin.Int32
+
+// rdar://problem/28945854: When a nongeneric closure was formed inside a
+// generic function, the capture promotion pass would erroneously try to
+// apply the generic caller's substitutions to the nongeneric callee, violating
+// invariants.
+
+// CHECK-LABEL: sil @$S14promotable_boxTf2i_n : $@convention(thin) (Builtin.Int32) -> Builtin.Int32
+
+sil @promotable_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>) -> Int {
+entry(%b : $<τ_0_0> { var τ_0_0 } <Int>):
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ %v = load %a : $*Int
+ return %v : $Int
+}
+
+// CHECK-LABEL: sil {{.*}}@call_promotable_box_from_generic
+// CHECK: [[F:%.*]] = function_ref @$S14promotable_boxTf2i_n
+// CHECK: partial_apply [callee_guaranteed] [[F]](
+
+sil @call_promotable_box_from_generic : $@convention(thin) <T> (@in T, Int) -> @owned @callee_guaranteed () -> Int {
+entry(%0 : $*T, %1 : $Int):
+ destroy_addr %0 : $*T
+ %f = function_ref @promotable_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>) -> Int
+ %b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ store %1 to %a : $*Int
+ %k = partial_apply [callee_guaranteed] %f(%b) : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>) -> Int
+ return %k : $@callee_guaranteed () -> Int
+}
+
+protocol P {}
+
+// CHECK-LABEL: sil @$S22generic_promotable_boxTf2ni_n : $@convention(thin) <T> (@in T, Builtin.Int32) -> Builtin.Int32
+// CHECK: bb0(%0 : $*T, %1 : $Builtin.Int32):
+// CHECK-NEXT: return %1 : $Builtin.Int32
+
+sil @generic_promotable_box : $@convention(thin) <T> (@in T, <τ_0_0> { var τ_0_0 } <Int>) -> Int {
+entry(%0 : $*T, %b : $<τ_0_0> { var τ_0_0 } <Int>):
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ %v = load %a : $*Int
+ return %v : $Int
+}
+
+// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic
+// CHECK: bb0(%0 : $*T, %1 : $*U, %2 : $Builtin.Int32):
+// CHECK-NEXT: destroy_addr %0 : $*T
+// CHECK-NEXT: destroy_addr %1 : $*U
+// CHECK: [[F:%.*]] = function_ref @$S22generic_promotable_boxTf2ni_n : $@convention(thin) <τ_0_0> (@in τ_0_0, Builtin.Int32) -> Builtin.Int32
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[F]]<U>(%2)
+// CHECK-NEXT: return [[CLOSURE]]
+
+sil @call_generic_promotable_box_from_different_generic : $@convention(thin) <T, U: P> (@in T, @in U, Int) -> @owned @callee_guaranteed (@in U) -> Int {
+entry(%0 : $*T, %1 : $*U, %2 : $Int):
+ destroy_addr %0 : $*T
+ destroy_addr %1 : $*U
+ %f = function_ref @generic_promotable_box : $@convention(thin) <V> (@in V, <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ %b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ store %2 to %a : $*Int
+ %k = partial_apply [callee_guaranteed] %f<U>(%b) : $@convention(thin) <V> (@in V, <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ return %k : $@callee_guaranteed (@in U) -> Int
+}
+
+enum E<X> {
+ case None
+ case Some(X)
+}
+
+struct R<T> {
+}
+
+// Check that the capture promotion took place and the function now
+// take argument of a type E<(R<T>) -> Builtin.Int32>, which used
+// to be a slot inside a box.
+// CHECK-LABEL: sil @$S23generic_promotable_box2Tf2nni_n : $@convention(thin) <T> (@in R<T>, @in Builtin.Int32, @owned E<(R<T>) -> Builtin.Int32>) -> ()
+// CHECK: bb0(%0 : $*R<T>, %1 : $*Builtin.Int32, %2 : $E<(R<T>) -> Builtin.Int32>):
+// CHECK-NOT: project_box
+// CHECK: switch_enum %2 : $E<(R<T>) -> Builtin.Int32>
+// CHECK-NOT: project_box
+// CHECK: } // end sil function '$S23generic_promotable_box2Tf2nni_n'
+sil @generic_promotable_box2 : $@convention(thin) <T> (@in R<T>, @in Int, <τ_0_0> { var E<(R<τ_0_0>) -> Int> } <T>) -> () {
+entry(%0: $*R<T>, %1 : $*Int, %b : $<τ_0_0> { var E< (R<τ_0_0>)->Int > } <T>):
+ %a = project_box %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <T>, 0
+ %e = load %a : $*E<(R<T>)->Int>
+ switch_enum %e : $E<(R<T>)->Int>, case #E.Some!enumelt.1 : bb1, default bb2
+
+bb1(%f : $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int):
+ %t = tuple ()
+ apply %f(%1, %0) : $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int
+ br exit
+bb2:
+ br exit
+exit:
+ %r = tuple ()
+ return %r : $()
+}
+
+// Check that alloc_box was eliminated and a specialized version of the
+// closure is invoked.
+// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic2
+// CHECK: bb0(%0 : $*R<T>, %1 : $*E<(R<U>) -> Builtin.Int32>, %2 : $*Builtin.Int32):
+// CHECK: %3 = load %1 : $*E<(R<U>) -> Builtin.Int32>
+// CHECK: [[F:%.*]] = function_ref @$S23generic_promotable_box2Tf2nni_n : $@convention(thin) <τ_0_0> (@in R<τ_0_0>, @in Builtin.Int32, @owned E<(R<τ_0_0>) -> Builtin.Int32>) -> ()
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[F]]<U>(%2, %3)
+// CHECK-NEXT: return [[CLOSURE]]
+
+sil @call_generic_promotable_box_from_different_generic2 : $@convention(thin) <T, U: P> (@in R<T>, @in E<(R<U>)->Int>, @in Int) -> @owned @callee_guaranteed (@in R<U>) -> () {
+entry(%0 : $*R<T>, %1 : $*E<(R<U>)->Int>, %2 : $*Int):
+ destroy_addr %0 : $*R<T>
+ %f = function_ref @generic_promotable_box2 : $@convention(thin) <V> (@in R<V>, @in Int, <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> ()
+ %b = alloc_box $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>
+ %a = project_box %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>, 0
+ copy_addr [take] %1 to [initialization] %a : $*E<(R<U>)->Int>
+ %k = partial_apply [callee_guaranteed] %f<U>(%2, %b) : $@convention(thin) <V> (@in R<V>, @in Int, <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> ()
+ return %k : $@callee_guaranteed (@in R<U>) -> ()
+}
diff --git a/test/SILOptimizer/plus_zero_capture_promotion_generic_context_ownership.sil b/test/SILOptimizer/plus_zero_capture_promotion_generic_context_ownership.sil
new file mode 100644
index 0000000..77ac818
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_capture_promotion_generic_context_ownership.sil
@@ -0,0 +1,131 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -emit-sil -O -Xllvm -sil-fso-enable-generics=false %s | %FileCheck %s
+
+sil_stage raw
+
+import Builtin
+
+typealias Int = Builtin.Int32
+
+// rdar://problem/28945854: When a nongeneric closure was formed inside a
+// generic function, the capture promotion pass would erroneously try to
+// apply the generic caller's substitutions to the nongeneric callee, violating
+// invariants.
+
+// CHECK-LABEL: sil @$S14promotable_boxTf2i_n : $@convention(thin) (Builtin.Int32) -> Builtin.Int32
+sil @promotable_box : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int {
+entry(%b : @owned $<τ_0_0> { var τ_0_0 } <Int>):
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ %v = load [trivial] %a : $*Int
+ destroy_value %b : $<τ_0_0> { var τ_0_0 } <Int>
+ return %v : $Int
+}
+
+// CHECK-LABEL: sil {{.*}}@call_promotable_box_from_generic
+// CHECK: [[F:%.*]] = function_ref @$S14promotable_boxTf2i_n
+// CHECK: partial_apply [callee_guaranteed] [[F]](
+
+sil @call_promotable_box_from_generic : $@convention(thin) <T> (@in T, Int) -> @owned @callee_guaranteed () -> Int {
+entry(%0 : @trivial $*T, %1 : @trivial $Int):
+ destroy_addr %0 : $*T
+ %f = function_ref @promotable_box : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ %b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ store %1 to [trivial] %a : $*Int
+ %k = partial_apply [callee_guaranteed] %f(%b) : $@convention(thin) (@owned <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ return %k : $@callee_guaranteed () -> Int
+}
+
+protocol P {}
+
+// CHECK-LABEL: sil @$S22generic_promotable_boxTf2ni_n : $@convention(thin) <T> (@in T, Builtin.Int32) -> Builtin.Int32
+// CHECK: bb0([[ARG0:%.*]] : $*T, [[ARG1:%.*]] : $Builtin.Int32):
+// CHECK-NEXT: return [[ARG1]] : $Builtin.Int32
+
+sil @generic_promotable_box : $@convention(thin) <T> (@in T, @owned <τ_0_0> { var τ_0_0 } <Int>) -> Int {
+entry(%0 : @trivial $*T, %b : @owned $<τ_0_0> { var τ_0_0 } <Int>):
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ %v = load [trivial] %a : $*Int
+ destroy_value %b : $<τ_0_0> { var τ_0_0 } <Int>
+ return %v : $Int
+}
+
+// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic
+// CHECK: bb0([[ARG0:%.*]] : $*T, [[ARG1:%.*]] : $*U, [[ARG2:%.*]] : $Builtin.Int32):
+// CHECK-NEXT: destroy_addr [[ARG0]] : $*T
+// CHECK-NEXT: destroy_addr [[ARG1]] : $*U
+// CHECK: [[F:%.*]] = function_ref @$S22generic_promotable_boxTf2ni_n : $@convention(thin) <τ_0_0> (@in τ_0_0, Builtin.Int32) -> Builtin.Int32
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[F]]<U>([[ARG2]])
+// CHECK-NEXT: return [[CLOSURE]]
+
+sil @call_generic_promotable_box_from_different_generic : $@convention(thin) <T, U: P> (@in T, @in U, Int) -> @owned @callee_guaranteed (@in U) -> Int {
+entry(%0 : @trivial $*T, %1 : @trivial $*U, %2 : @trivial $Int):
+ destroy_addr %0 : $*T
+ destroy_addr %1 : $*U
+ %f = function_ref @generic_promotable_box : $@convention(thin) <V> (@in V, @owned <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ %b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ %a = project_box %b : $<τ_0_0> { var τ_0_0 } <Int>, 0
+ store %2 to [trivial] %a : $*Int
+ %k = partial_apply [callee_guaranteed] %f<U>(%b) : $@convention(thin) <V> (@in V, @owned <τ_0_0> { var τ_0_0 } <Int>) -> Int
+ return %k : $@callee_guaranteed (@in U) -> Int
+}
+
+enum E<X> {
+ case None
+ case Some(X)
+}
+
+struct R<T> {
+}
+
+// Check that the capture promotion took place and the function now
+// take argument of a type E<(R<T>) -> Builtin.Int32>, which used
+// to be a slot inside a box.
+// CHECK-LABEL: sil @$S23generic_promotable_box2Tf2nni_n : $@convention(thin) <T> (@in R<T>, @in Builtin.Int32, @owned E<(R<T>) -> Builtin.Int32>) -> ()
+// CHECK: bb0([[ARG0:%.*]] : $*R<T>, [[ARG1:%.*]] : $*Builtin.Int32, [[ARG2:%.*]] : $E<(R<T>) -> Builtin.Int32>):
+// CHECK-NOT: project_box
+// CHECK: switch_enum [[ARG2]] : $E<(R<T>) -> Builtin.Int32>
+// CHECK-NOT: project_box
+// CHECK: } // end sil function '$S23generic_promotable_box2Tf2nni_n'
+sil @generic_promotable_box2 : $@convention(thin) <T> (@in R<T>, @in Int, @owned <τ_0_0> { var E<(R<τ_0_0>) -> Int> } <T>) -> () {
+entry(%0 : @trivial $*R<T>, %1 : @trivial $*Int, %b : @owned $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <T>):
+ %a = project_box %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <T>, 0
+ %e = load [copy] %a : $*E<(R<T>)->Int>
+ switch_enum %e : $E<(R<T>)->Int>, case #E.Some!enumelt.1 : bb1, default bb2
+
+bb1(%f : @owned $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int):
+ %bf = begin_borrow %f : $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int
+ apply %bf(%1, %0) : $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int
+ end_borrow %bf from %f : $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int , $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int
+ destroy_value %f : $@callee_guaranteed (@in_guaranteed R<T>) -> @out Int
+ br exit
+
+bb2(%original : @owned $E<(R<T>)->Int>):
+ destroy_value %original : $E<(R<T>)->Int>
+ br exit
+
+exit:
+ destroy_value %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <T>
+ %r = tuple ()
+ return %r : $()
+}
+
+// Check that alloc_box was eliminated and a specialized version of the
+// closure is invoked.
+// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic2
+// CHECK: bb0([[ARG0:%.*]] : $*R<T>, [[ARG1:%.*]] : $*E<(R<U>) -> Builtin.Int32>, [[ARG2:%.*]] : $*Builtin.Int32):
+// CHECK: %3 = load [[ARG1]] : $*E<(R<U>) -> Builtin.Int32>
+// CHECK: [[F:%.*]] = function_ref @$S23generic_promotable_box2Tf2nni_n : $@convention(thin) <τ_0_0> (@in R<τ_0_0>, @in Builtin.Int32, @owned E<(R<τ_0_0>) -> Builtin.Int32>) -> ()
+// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[F]]<U>(%2, %3)
+// CHECK-NEXT: return [[CLOSURE]]
+
+sil @call_generic_promotable_box_from_different_generic2 : $@convention(thin) <T, U: P> (@in R<T>, @in E<(R<U>)->Int>, @in Int) -> @owned @callee_guaranteed (@in R<U>) -> () {
+entry(%0 : @trivial $*R<T>, %1 : @trivial $*E<(R<U>)->Int>, %2 : @trivial $*Int):
+ destroy_addr %0 : $*R<T>
+ %f = function_ref @generic_promotable_box2 : $@convention(thin) <V> (@in R<V>, @in Int, @owned <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> ()
+ %b = alloc_box $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>
+ %a = project_box %b : $<τ_0_0> { var E<(R<τ_0_0>)->Int> } <U>, 0
+ copy_addr [take] %1 to [initialization] %a : $*E<(R<U>)->Int>
+ %k = partial_apply [callee_guaranteed] %f<U>(%2, %b) : $@convention(thin) <V> (@in R<V>, @in Int, @owned <τ_0_0> { var E<(R<τ_0_0>)->Int> } <V>) -> ()
+ return %k : $@callee_guaranteed (@in R<U>) -> ()
+}
diff --git a/test/SILOptimizer/plus_zero_cast_folding_no_bridging.sil b/test/SILOptimizer/plus_zero_cast_folding_no_bridging.sil
new file mode 100644
index 0000000..4b4c661
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_cast_folding_no_bridging.sil
@@ -0,0 +1,103 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -O -emit-sil %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+// We want to check that casts between two types which are both Swift types or
+// both are ObjC types are not optimized by the cast optimizer into casts
+// to/from ObjC.
+
+sil_stage raw
+
+import Builtin
+import Swift
+import SwiftShims
+import Foundation
+
+
+// CHECK-LABEL: sil @testSwiftToSwift : $@convention(thin) (@in Set<Int>, @guaranteed Set<Int>)
+// CHECK: bb0
+// CHECK-NOT: checked_cast_addr_br
+// CHECK-NOT: _bridgeToObjectiveC
+// CHECK-NOT: _conditionallyBridgeFromObjectiveC_bridgeable
+// CHECK: return
+sil @testSwiftToSwift : $@convention(thin) (@in Set<Int>, @guaranteed Set<Int>) -> @owned Set<Int> {
+bb0(%0 : $*Set<Int>, %1 : $Set<Int>):
+ %3 = alloc_stack $Set<Int>
+ copy_addr %0 to [initialization] %3 : $*Set<Int>
+ %5 = alloc_stack $Set<Int>
+ checked_cast_addr_br take_always Set<Int> in %3 : $*Set<Int> to Set<Int> in %5 : $*Set<Int>, bb1, bb3
+
+bb1:
+ destroy_addr %0 : $*Set<Int>
+ %8 = load %5 : $*Set<Int>
+ br bb2(%8 : $Set<Int>)
+
+bb2(%14 : $Set<Int>):
+ dealloc_stack %5 : $*Set<Int>
+ dealloc_stack %3 : $*Set<Int>
+ return %14 : $Set<Int>
+
+bb3:
+ br bb2(%1 : $Set<Int>)
+}
+
+// CHECK-LABEL: sil @testObjCToObjC : $@convention(thin) (NSSet, NSSet)
+// CHECK: bb0
+// CHECK-NOT: checked_cast_br
+// CHECK-NOT: BridgeFromObjectiveC
+// CHECK-NOT: bridgeToObjectiveC
+// CHECK: return
+sil @testObjCToObjC : $@convention(thin) (NSSet, NSSet) -> @owned NSSet {
+bb0(%0 : $NSSet, %1 : $NSSet):
+ checked_cast_br %0 : $NSSet to $NSSet, bb1, bb3
+
+bb1(%2 : $NSSet):
+ br bb2(%2 : $NSSet)
+
+bb2(%14 : $NSSet):
+ return %14 : $NSSet
+
+bb3:
+ br bb2(%1 : $NSSet)
+}
+
+sil @fail : $@convention(thin) () -> Never
+
+// CHECK-LABEL: sil @testCFToObjC
+// CHECK: bb0(
+// CHECK-NEXT: [[T0:%.*]] = load %1 : $*CFString
+// CHECK-NEXT: [[T1:%.*]] = unchecked_ref_cast [[T0]] : $CFString to $NSString
+// CHECK-NEXT: store [[T1]] to %0 : $*NSString
+sil @testCFToObjC : $@convention(thin) (@in CFString) -> @out NSString {
+bb0(%0 : $*NSString, %1 : $*CFString):
+ checked_cast_addr_br take_always CFString in %1 : $*CFString to NSString in %0 : $*NSString, bb1, bb2
+
+bb1:
+ %ret = tuple ()
+ return %ret : $()
+
+bb2:
+ %fn = function_ref @fail : $@convention(thin) () -> Never
+ apply %fn() : $@convention(thin) () -> Never
+ unreachable
+}
+
+// CHECK-LABEL: sil @testCFToSwift
+// CHECK: bb0(
+// CHECK-NEXT: [[T0:%.*]] = load %1 : $*CFString
+// CHECK-NEXT: [[T1:%.*]] = unchecked_ref_cast [[T0]] : $CFString to $NSString
+// CHECK: [[FN:%.*]] = function_ref @$SSS10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo8NSStringC_SSSgztFZ : $@convention(method) (@guaranteed NSString, @inout Optional<String>, @thin String.Type) -> Bool
+// CHECK: apply [[FN]]([[T1]], {{.*}}, {{.*}})
+sil @testCFToSwift : $@convention(thin) (@in CFString) -> @out String {
+bb0(%0 : $*String, %1 : $*CFString):
+ checked_cast_addr_br take_always CFString in %1 : $*CFString to String in %0 : $*String, bb1, bb2
+
+bb1:
+ %ret = tuple ()
+ return %ret : $()
+
+bb2:
+ %fn = function_ref @fail : $@convention(thin) () -> Never
+ apply %fn() : $@convention(thin) () -> Never
+ unreachable
+}
diff --git a/test/SILOptimizer/plus_zero_cast_folding_objc_generics.swift b/test/SILOptimizer/plus_zero_cast_folding_objc_generics.swift
new file mode 100644
index 0000000..effe201
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_cast_folding_objc_generics.swift
@@ -0,0 +1,29 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -O -emit-sil %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+import objc_generics
+
+// CHECK-LABEL: sil shared [noinline] @$S26cast_folding_objc_generics26testObjCGenericParamChangeySo12GenericClassCySo8NSStringCGADySo15NSMutableStringCGFTf4n_g : $@convention(thin) (@guaranteed GenericClass<NSMutableString>) -> GenericClass<NSString> {
+// CHECK: upcast
+// CHECK-NOT: int_trap
+@inline(never)
+public func testObjCGenericParamChange(_ a: GenericClass<NSMutableString>) -> GenericClass<NSString> {
+ return a as! GenericClass<NSString>
+}
+
+// CHECK-LABEL: sil shared [noinline] @$S26cast_folding_objc_generics34testObjCGenericParamChangeSubclassySo07GenericJ0CySo8NSStringCGSo0K5ClassCySo15NSMutableStringCGFTf4n_g : $@convention(thin) (@guaranteed GenericClass<NSMutableString>) -> GenericSubclass<NSString> {
+// CHECK: unconditional_checked_cast
+// CHECK-NOT: int_trap
+@inline(never)
+public func testObjCGenericParamChangeSubclass(_ a: GenericClass<NSMutableString>) -> GenericSubclass<NSString> {
+ return a as! GenericSubclass<NSString>
+}
+
+// CHECK-LABEL: sil shared [noinline] @$S26cast_folding_objc_generics36testObjCGenericParamChangeSuperclassySo12GenericClassCySo8NSStringCGSo0K8SubclassCySo15NSMutableStringCGFTf4n_g : $@convention(thin) (@guaranteed GenericSubclass<NSMutableString>) -> GenericClass<NSString> {
+// CHECK: upcast
+// CHECK-NOT: int_trap
+@inline(never)
+public func testObjCGenericParamChangeSuperclass(_ a: GenericSubclass<NSMutableString>) -> GenericClass<NSString> {
+ return a as! GenericClass<NSString>
+}
diff --git a/test/SILOptimizer/plus_zero_cast_folding_objc_no_foundation.swift b/test/SILOptimizer/plus_zero_cast_folding_objc_no_foundation.swift
new file mode 100644
index 0000000..5648147
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_cast_folding_objc_no_foundation.swift
@@ -0,0 +1,67 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -O -emit-sil %s | %FileCheck %s
+// REQUIRES: objc_interop
+
+// TODO: Update optimizer for id-as-Any changes.
+
+// Note: no 'import Foundation'
+
+struct PlainStruct {}
+
+// CHECK-LABEL: sil hidden [noinline] @$S31cast_folding_objc_no_foundation23testAnyObjectToArrayIntySbyXlF : $@convention(thin) (@guaranteed AnyObject) -> Bool {
+// CHECK: bb0(%0 : $AnyObject):
+// CHECK: [[SOURCE:%.*]] = alloc_stack $AnyObject
+// CHECK: [[TARGET:%.*]] = alloc_stack $Array<Int>
+// CHECK: checked_cast_addr_br take_always AnyObject in [[SOURCE]] : $*AnyObject to Array<Int> in [[TARGET]] : $*Array<Int>, bb1, bb2
+@inline(never)
+func testAnyObjectToArrayInt(_ a: AnyObject) -> Bool {
+ return a is [Int]
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S31cast_folding_objc_no_foundation26testAnyObjectToArrayStringySbyXlF : $@convention(thin) (@guaranteed AnyObject) -> Bool {
+// CHECK: bb0(%0 : $AnyObject):
+// CHECK: [[SOURCE:%.*]] = alloc_stack $AnyObject
+// CHECK: [[TARGET:%.*]] = alloc_stack $Array<String>
+// CHECK: checked_cast_addr_br take_always AnyObject in [[SOURCE]] : $*AnyObject to Array<String> in [[TARGET]] : $*Array<String>, bb1, bb2
+@inline(never)
+func testAnyObjectToArrayString(_ a: AnyObject) -> Bool {
+ return a is [String]
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S31cast_folding_objc_no_foundation30testAnyObjectToArrayNotBridgedySbyXlF : $@convention(thin) (@guaranteed AnyObject) -> Bool {
+// CHECK: bb0(%0 : $AnyObject):
+// CHECK: [[SOURCE:%.*]] = alloc_stack $AnyObject
+// CHECK: [[TARGET:%.*]] = alloc_stack $Array<PlainStruct>
+// CHECK: checked_cast_addr_br take_always AnyObject in [[SOURCE]] : $*AnyObject to Array<PlainStruct> in [[TARGET]] : $*Array<PlainStruct>, bb1, bb2
+@inline(never)
+func testAnyObjectToArrayNotBridged(_ a: AnyObject) -> Bool {
+ return a is [PlainStruct]
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S31cast_folding_objc_no_foundation25testAnyObjectToDictionaryySbyXlF : $@convention(thin) (@guaranteed AnyObject) -> Bool {
+// CHECK: bb0(%0 : $AnyObject):
+// CHECK: [[SOURCE:%.*]] = alloc_stack $AnyObject
+// CHECK: [[TARGET:%.*]] = alloc_stack $Dictionary<Int, String>
+// CHECK: checked_cast_addr_br take_always AnyObject in [[SOURCE]] : $*AnyObject to Dictionary<Int, String> in [[TARGET]] : $*Dictionary<Int, String>, bb1, bb2
+@inline(never)
+func testAnyObjectToDictionary(_ a: AnyObject) -> Bool {
+ return a is [Int: String]
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S31cast_folding_objc_no_foundation21testAnyObjectToStringySbyXlF : $@convention(thin) (@guaranteed AnyObject) -> Bool {
+// CHECK: bb0(%0 : $AnyObject):
+// CHECK: [[SOURCE:%.*]] = alloc_stack $AnyObject
+// CHECK: [[TARGET:%.*]] = alloc_stack $String
+// CHECK: checked_cast_addr_br take_always AnyObject in [[SOURCE]] : $*AnyObject to String in [[TARGET]] : $*String, bb1, bb2
+@inline(never)
+func testAnyObjectToString(_ a: AnyObject) -> Bool {
+ return a is String
+}
+
+class SomeObject {}
+
+print(testAnyObjectToArrayInt(SomeObject()))
+print(testAnyObjectToArrayString(SomeObject()))
+print(testAnyObjectToArrayNotBridged(SomeObject()))
+print(testAnyObjectToDictionary(SomeObject()))
+print(testAnyObjectToString(SomeObject()))
diff --git a/test/SILOptimizer/plus_zero_devirt_covariant_return.swift b/test/SILOptimizer/plus_zero_devirt_covariant_return.swift
new file mode 100644
index 0000000..8c12f8d
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_covariant_return.swift
@@ -0,0 +1,351 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -O -Xllvm -disable-sil-cm-rr-cm=0 -Xllvm -sil-inline-generics=false -primary-file %s -emit-sil -sil-inline-threshold 1000 -Xllvm -sil-disable-pass=ObjectOutliner -sil-verify-all | %FileCheck %s
+
+// Make sure that we can dig all the way through the class hierarchy and
+// protocol conformances with covariant return types correctly. The verifier
+// should trip if we do not handle things correctly.
+//
+// TODO: this is not working right now: rdar://problem/33461095
+// As a side-test it also checks if all allocs can be promoted to the stack.
+
+// CHECK-LABEL: sil hidden @$S23devirt_covariant_return6driveryyF : $@convention(thin) () -> () {
+// CHECK: bb0
+// CHECK: alloc_ref
+// CHECK: alloc_ref
+// CHECK: function_ref @unknown1a : $@convention(thin) () -> ()
+// CHECK: apply
+// CHECK: function_ref @defenestrate : $@convention(thin) () -> ()
+// CHECK: apply
+// CHECK: function_ref @unknown2a : $@convention(thin) () -> ()
+// CHECK: apply
+// CHECK: apply
+// CHECK: function_ref @unknown3a : $@convention(thin) () -> ()
+// CHECK: apply
+// CHECK: apply
+// CHECK: tuple
+// CHECK: return
+
+@_silgen_name("unknown1a")
+func unknown1a() -> ()
+@_silgen_name("unknown1b")
+func unknown1b() -> ()
+@_silgen_name("unknown2a")
+func unknown2a() -> ()
+@_silgen_name("unknown2b")
+func unknown2b() -> ()
+@_silgen_name("unknown3a")
+func unknown3a() -> ()
+@_silgen_name("unknown3b")
+func unknown3b() -> ()
+@_silgen_name("defenestrate")
+func defenestrate() -> ()
+
+class B<T> {
+ // We do not specialize typealias's correctly now.
+ //typealias X = B
+ func doSomething() -> B<T> {
+ unknown1a()
+ return self
+ }
+
+ // See comment in protocol P
+ //class func doSomethingMeta() {
+ // unknown1b()
+ //}
+
+ func doSomethingElse() {
+ defenestrate()
+ }
+}
+
+class B2<T> : B<T> {
+ // When we have covariance in protocols, change this to B2.
+ // We do not specialize typealias correctly now.
+ //typealias X = B
+ override func doSomething() -> B2<T> {
+ unknown2a()
+ return self
+ }
+
+ // See comment in protocol P
+ //override class func doSomethingMeta() {
+ // unknown2b()
+ //}
+}
+
+class B3<T> : B2<T> {
+ override func doSomething() -> B3<T> {
+ unknown3a()
+ return self
+ }
+}
+
+func WhatShouldIDo<T>(_ b : B<T>) -> B<T> {
+ b.doSomething().doSomethingElse()
+ return b
+}
+
+func doSomethingWithB<T>(_ b : B<T>) {
+
+}
+
+struct S {}
+
+func driver() -> () {
+ let b = B<S>()
+ let b2 = B2<S>()
+ let b3 = B3<S>()
+
+ WhatShouldIDo(b)
+ WhatShouldIDo(b2)
+ WhatShouldIDo(b3)
+}
+
+driver()
+
+public class Bear {
+ public init?(fail: Bool) {
+ if fail { return nil }
+ }
+
+ // Check that devirtualizer can handle convenience initializers, which have covariant optional
+ // return types.
+ // CHECK-LABEL: sil @$S23devirt_covariant_return4BearC{{[_0-9a-zA-Z]*}}fc
+ // CHECK: checked_cast_br [exact] %{{.*}} : $Bear to $PolarBear
+ // CHECK: upcast %{{.*}} : $Optional<PolarBear> to $Optional<Bear>
+ // CHECK: }
+ public convenience init?(delegateFailure: Bool, failAfter: Bool) {
+ self.init(fail: delegateFailure)
+ if failAfter { return nil }
+ }
+}
+
+final class PolarBear: Bear {
+
+ override init?(fail: Bool) {
+ super.init(fail: fail)
+ }
+
+ init?(chainFailure: Bool, failAfter: Bool) {
+ super.init(fail: chainFailure)
+ if failAfter { return nil }
+ }
+}
+
+
+
+
+class Payload {
+ let value: Int32
+ init(_ n: Int32) {
+ value = n
+ }
+
+ func getValue() -> Int32 {
+ return value
+ }
+}
+
+final class Payload1: Payload {
+ override init(_ n: Int32) {
+ super.init(n)
+ }
+}
+
+class C {
+ func doSomething() -> Payload? {
+ return Payload(1)
+ }
+}
+
+
+final class C1:C {
+ // Override base method, but return a non-optional result
+ override func doSomething() -> Payload {
+ return Payload(2)
+ }
+}
+
+final class C2:C {
+ // Override base method, but return a non-optional result of a type,
+ // which is derived from the expected type.
+ override func doSomething() -> Payload1 {
+ return Payload1(2)
+ }
+}
+
+// Check that the Optional return value from doSomething
+// gets properly unwrapped into a Payload object and then further
+// devirtualized.
+// CHECK-LABEL: sil hidden [noinline] @$S23devirt_covariant_return7driver1ys5Int32VAA2C1CF
+// CHECK: integer_literal $Builtin.Int32, 2
+// CHECK: struct $Int32 (%{{.*}} : $Builtin.Int32)
+// CHECK-NOT: class_method
+// CHECK-NOT: function_ref
+// CHECK: return
+@inline(never)
+func driver1(_ c: C1) -> Int32 {
+ return c.doSomething().getValue()
+}
+
+// Check that the Optional return value from doSomething
+// gets properly unwrapped into a Payload object and then further
+// devirtualized.
+// CHECK-LABEL: sil hidden [noinline] @$S23devirt_covariant_return7driver3ys5Int32VAA1CCF
+// CHECK: bb{{[0-9]+}}(%{{[0-9]+}} : $C2):
+// CHECK-NOT: bb{{.*}}:
+// check that for C2, we convert the non-optional result into an optional and then cast.
+// CHECK: enum $Optional
+// CHECK-NEXT: upcast
+// CHECK: return
+@inline(never)
+func driver3(_ c: C) -> Int32 {
+ return c.doSomething()!.getValue()
+}
+
+public class D {
+ let v: Int32
+ init(_ n: Int32) {
+ v = n
+ }
+}
+
+public class D1 : D {
+
+ public func foo() -> D? {
+ return nil
+ }
+
+ public func boo() -> Int32 {
+ return foo()!.v
+ }
+}
+
+let sD = D(0)
+
+public class D2: D1 {
+ // Override base method, but return a non-optional result
+ override public func foo() -> D {
+ return sD
+ }
+}
+
+// Check that the boo call gets properly devirtualized and that
+// that D2.foo() is inlined thanks to this.
+// CHECK-LABEL: sil hidden [noinline] @$S23devirt_covariant_return7driver2ys5Int32VAA2D2CF
+// CHECK-NOT: class_method
+// CHECK: checked_cast_br [exact] %{{.*}} : $D1 to $D2
+// CHECK: bb2
+// CHECK: global_addr
+// CHECK: load
+// CHECK: ref_element_addr
+// CHECK: bb3
+// CHECK: class_method
+// CHECK: }
+@inline(never)
+func driver2(_ d: D2) -> Int32 {
+ return d.boo()
+}
+
+class AA {
+}
+
+class BB : AA {
+}
+
+class CCC {
+ @inline(never)
+ func foo(_ b: BB) -> (AA, AA) {
+ return (b, b)
+ }
+}
+
+class DDD : CCC {
+ @inline(never)
+ override func foo(_ b: BB) -> (BB, BB) {
+ return (b, b)
+ }
+}
+
+
+class EEE : CCC {
+ @inline(never)
+ override func foo(_ b: BB) -> (AA, AA) {
+ return (b, b)
+ }
+}
+
+// Check that c.foo() is devirtualized, because the optimizer can handle the casting the return type
+// correctly, i.e. it can cast (BBB, BBB) into (AAA, AAA)
+// CHECK-LABEL: sil hidden [noinline] @$S23devirt_covariant_return37testDevirtOfMethodReturningTupleTypes_1bAA2AAC_AEtAA3CCCC_AA2BBCtF
+// CHECK: checked_cast_br [exact] %{{.*}} : $CCC to $CCC
+// CHECK: checked_cast_br [exact] %{{.*}} : $CCC to $DDD
+// CHECK: checked_cast_br [exact] %{{.*}} : $CCC to $EEE
+// CHECK: class_method
+// CHECK: }
+@inline(never)
+func testDevirtOfMethodReturningTupleTypes(_ c: CCC, b: BB) -> (AA, AA) {
+ return c.foo(b)
+}
+
+
+class AAAA {
+}
+
+class BBBB : AAAA {
+}
+
+class CCCC {
+ let a: BBBB
+ var foo : (AAAA, AAAA) {
+ @inline(never)
+ get {
+ return (a, a)
+ }
+ }
+ init(x: BBBB) { a = x }
+}
+
+class DDDD : CCCC {
+ override var foo : (BBBB, BBBB) {
+ @inline(never)
+ get {
+ return (a, a)
+ }
+ }
+}
+
+// Check devirtualization of methods with optional results, where
+// optional results need to be casted.
+// CHECK-LABEL: sil [noinline] @{{.*}}testOverridingMethodWithOptionalResult
+// CHECK: checked_cast_br [exact] %{{.*}} : $F to $F
+// CHECK: checked_cast_br [exact] %{{.*}} : $F to $G
+// CHECK: switch_enum
+// CHECK: checked_cast_br [exact] %{{.*}} : $F to $H
+// CHECK: switch_enum
+@inline(never)
+public func testOverridingMethodWithOptionalResult(_ f: F) -> (F?, Int)? {
+ return f.foo()
+}
+
+
+public class F {
+ @inline(never)
+ public func foo() -> (F?, Int)? {
+ return (F(), 1)
+ }
+}
+
+public class G: F {
+ @inline(never)
+ override public func foo() -> (G?, Int)? {
+ return (G(), 2)
+ }
+}
+
+public class H: F {
+ @inline(never)
+ override public func foo() -> (H?, Int)? {
+ return nil
+ }
+}
diff --git a/test/SILOptimizer/plus_zero_devirt_default_case.swift b/test/SILOptimizer/plus_zero_devirt_default_case.swift
new file mode 100644
index 0000000..c6eeaa8
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_default_case.swift
@@ -0,0 +1,276 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-NORMAL %s
+// RUN: %target-swift-frontend -O -module-name devirt_default_case -emit-sil -enable-testing %s | %FileCheck -check-prefix=CHECK -check-prefix=CHECK-TESTABLE %s
+
+@_silgen_name("action")
+func action(_ n:Int) -> ()
+
+// public class
+open class Base1 {
+ @inline(never) func inner() { action(1)}
+ func middle() { inner() }
+// Check that call to Base1.middle cannot be devirtualized
+//
+// CHECK-LABEL: sil @$S19devirt_default_case5Base1C5outer{{[_0-9a-zA-Z]*}}F
+// CHECK: class_method
+// CHECK: } // end sil function '$S19devirt_default_case5Base1C5outer{{[_0-9a-zA-Z]*}}F'
+ public func outer() {
+ middle()
+ }
+}
+
+// public class
+open class Derived1 : Base1 {
+ override func inner() { action(2) }
+ @inline(never) final override func middle() { inner() }
+}
+
+// private class
+private class Base2 {
+ @inline(never) func inner() { action(3)}
+ func middle() { inner() }
+ func outer() { middle() }
+}
+
+// private class
+private class Derived2 : Base2 {
+ override func inner() { action(4) }
+ @inline(never) final override func middle() { inner() }
+}
+
+
+// Check that call to Base2.middle can be devirtualized
+//
+// CHECK-LABEL: sil @$S19devirt_default_case9callOuteryS2iF
+// CHECK: function_ref @$S19devirt_default_case5Base233_{{.*}}5inner
+// CHECK: function_ref @$S19devirt_default_case8Derived233_{{.*}}6middle
+// CHECK-NOT: class_method
+// CHECK: } // end sil function '$S19devirt_default_case9callOuteryS2iF'
+public func callOuter(_ x: Int) -> Int {
+
+ var o:Base2
+
+ if x == 1 {
+ o = Base2()
+ } else {
+ o = Derived2()
+ }
+
+ o.outer()
+ return x
+}
+
+// internl class
+class Base3 {
+ @inline(never) func inner() { action(5)}
+ @inline(never) func middle() { inner() }
+// Check that call to Base3.middle can be devirtualized when not compiling
+// for testing.
+//
+// CHECK-LABEL: sil{{( hidden)?}} [noinline] @$S19devirt_default_case5Base3C5outeryyF : $@convention(method) (@guaranteed Base3) -> () {
+// CHECK: function_ref @$S19devirt_default_case5Base3C6middleyyF
+// CHECK: function_ref @$S19devirt_default_case8Derived333_{{.*}}6middle
+// CHECK-NORMAL-NOT: class_method
+// CHECK-TESTABLE: class_method %0 : $Base3, #Base3.middle!1
+// CHECK: } // end sil function '$S19devirt_default_case5Base3C5outeryyF'
+ @inline(never) func outer() {
+ middle()
+ }
+}
+
+// private class
+private class Derived3 : Base3 {
+ override func inner() { action(6) }
+ @inline(never) final override func middle() { inner() }
+ override func outer() {
+ }
+}
+
+class A2 { @inline(never) func f() -> Int { return 0 } }
+class B2 : A2 {}
+class C2 : A2 {}
+class D2: B2 {}
+class E2 :C2 {}
+
+class A3 { @inline(never) func f() -> Int { return 0 } }
+class B3 : A3 { @inline(never) override func f() -> Int { return 1 }}
+class C3 : A3 {}
+class D3: C3 {}
+class E3 :C3 {}
+
+// CHECK-TESTABLE: sil{{( hidden)?}} [noinline] @$S19devirt_default_case3fooySiAA2A3CF
+
+public func testfoo1() -> Int {
+ return foo(E2())
+}
+
+
+public func testfoo3() -> Int {
+ return foo(E3())
+}
+
+// Check that call to A3.f() can be devirtualized.
+//
+// CHECK-NORMAL: sil hidden [noinline] @$S19devirt_default_case3fooySiAA2A3CF
+// CHECK-NORMAL: function_ref @$S19devirt_default_case2B3C1fSiyFTf4d_n
+// CHECK-NORMAL: function_ref @$S19devirt_default_case2A3C1fSiyFTf4d_n
+// CHECK-NORMAL-NOT: class_method
+// CHECK: } // end sil function '$S19devirt_default_case3fooySiAA2A3CF'
+
+class Base4 {
+ @inline(never)
+ func test() {
+// Check that call to foo() can be devirtualized
+//
+// CHECK-LABEL: sil{{( hidden)?}} [noinline] @$S19devirt_default_case5Base4C4testyyF
+// CHECK: function_ref @$S19devirt_default_case5Base4C3fooyyFTf4d_n
+// CHECK: function_ref @$S19devirt_default_case8Derived4C3fooyyFTf4d_n
+// CHECK-NORMAL-NOT: class_method
+// CHECK-TESTABLE: class_method %0 : $Base4, #Base4.foo!1
+// CHECK: } // end sil function '$S19devirt_default_case5Base4C4testyyF'
+ foo()
+ }
+
+ @inline(never) func foo() { }
+}
+
+
+// A, C,D,E all use the same implementation.
+// B has its own implementation.
+@inline(never)
+func foo(_ a: A3) -> Int {
+ return a.f()
+}
+
+class Derived4 : Base4 {
+ @inline(never) override func foo() { }
+}
+
+open class Base5 {
+ @inline(never)
+ open func test() {
+ foo()
+ }
+
+ @inline(never) public final func foo() { }
+}
+
+class Derived5 : Base5 {
+}
+
+open class C6 {
+ func bar() -> Int { return 1 }
+}
+
+class D6 : C6 {
+ override func bar() -> Int { return 2 }
+}
+
+@inline(never)
+func check_static_class_devirt(_ c: C6) -> Int {
+// Check that C.bar() and D.bar() are devirtualized.
+//
+// CHECK-LABEL: sil{{( hidden)?}} [noinline] @$S19devirt_default_case019check_static_class_A0ySiAA2C6CF
+// CHECK: checked_cast_br [exact] %0 : $C6 to $C6
+// CHECK: checked_cast_br [exact] %0 : $C6 to $D6
+// CHECK: class_method
+// CHECK: } // end sil function '$S19devirt_default_case019check_static_class_A0ySiAA2C6CF'
+ return c.bar()
+}
+
+public func test_check_static_class_devirt() -> Int {
+ return check_static_class_devirt(D6())
+}
+
+
+class A7 { @inline(never) func foo() -> Bool { return false } }
+class B7 : A7 { @inline(never) override func foo() -> Bool { return true } }
+
+public func test_check_call_on_downcasted_instance() -> Bool {
+ return check_call_on_downcasted_instance(B7())
+}
+
+@inline(never)
+func callIt(_ b3: Base3, _ b4: Base4, _ b5: Base5) {
+ b3.outer()
+ b4.test()
+ b5.test()
+}
+
+public func externalEntryPoint() {
+ callIt(Base3(), Base4(), Base5())
+}
+
+open class M {
+ func foo() -> Int32 {
+ return 0
+ }
+}
+
+
+open class M1: M {
+ @inline(never)
+ override func foo() -> Int32 {
+ return 1
+ }
+}
+
+internal class M2: M1 {
+ @inline(never)
+ override func foo() -> Int32 {
+ return 2
+ }
+}
+
+internal class M3: M1 {
+ @inline(never)
+ override func foo() -> Int32 {
+ return 3
+ }
+}
+
+internal class M22: M2 {
+ @inline(never)
+ override func foo() -> Int32 {
+ return 22
+ }
+}
+
+internal class M222: M22 {
+ @inline(never)
+ override func foo() -> Int32 {
+ return 222
+ }
+}
+
+internal class M33: M3 {
+ @inline(never)
+ override func foo() -> Int32 {
+ return 33
+ }
+}
+
+
+// Check that speculative devirtualization tries to devirtualize the first N
+// alternatives, if it has too many.
+// The alternatives should be taken in a breadth-first order, starting with
+// the static type of the instance.
+
+@inline(never)
+public func testSpeculativeDevirtualizationWithTooManyAlternatives(_ c:M1) -> Int32{
+ return c.foo()
+}
+
+
+@inline(never)
+func foo(_ a: A2) -> Int {
+ return a.f()
+}
+
+@inline(never)
+func check_call_on_downcasted_instance(_ a: A7) -> Bool {
+ if a is B7 {
+ return (a as! B7).foo()
+ }
+ return a.foo()
+}
diff --git a/test/SILOptimizer/plus_zero_devirt_nested_class.swift b/test/SILOptimizer/plus_zero_devirt_nested_class.swift
new file mode 100644
index 0000000..936d6d9
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_nested_class.swift
@@ -0,0 +1,31 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s
+
+fileprivate class Outer<T> {
+ class Inner<U> : Base<T, U> {
+ @_optimize(none)
+ override func method<V>(v: V) {}
+ }
+}
+
+fileprivate class Base<T, U> {
+ @_optimize(none)
+ func method<V>(v: V) {}
+}
+
+fileprivate class Derived<T, U> : Outer<T>.Inner<U> {}
+
+@_transparent
+fileprivate func bar<T, U, V>(b: Base<T, U>, v: V) {
+ b.method(v: v)
+}
+
+fileprivate func foo<T, U, V>(d: Outer<T>.Inner<U>, v: V) {
+ bar(b: d, v: v)
+}
+
+foo(d: Outer<Int>.Inner<Int>(), v: 0)
+
+// CHECK-LABEL: sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32
+// CHECK: function_ref @$S19devirt_nested_class5Outer{{.*}}LC5InnerC6method1vyqd0___tlF : $@convention(method) <τ_0_0><τ_1_0><τ_2_0> (@in_guaranteed τ_2_0, @guaranteed Outer<τ_0_0>.Inner<τ_1_0>) -> ()
+// CHECK: return
diff --git a/test/SILOptimizer/plus_zero_devirt_protocol_method_invocations.swift b/test/SILOptimizer/plus_zero_devirt_protocol_method_invocations.swift
new file mode 100644
index 0000000..2b1a325
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_protocol_method_invocations.swift
@@ -0,0 +1,266 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
+
+protocol PPP {
+ func f()
+}
+
+protocol QQQ : PPP {
+}
+
+protocol RRR : QQQ {
+}
+
+struct S : RRR {}
+
+extension QQQ {
+ @_optimize(none)
+ func f() {}
+}
+
+// Test that all witness_method instructions are devirtualized.
+// This test used to crash the compiler because it uses inherited conformances.
+// CHECK-LABEL: sil @$S34devirt_protocol_method_invocations24testInheritedConformanceyyF : $@convention(thin) () -> ()
+// CHECK-NOT: witness_method
+// CHECK-NOT: class_method
+// CHECK: apply
+// CHECK: // end sil function '$S34devirt_protocol_method_invocations24testInheritedConformanceyyF'
+public func testInheritedConformance() {
+ (S() as QQQ).f()
+}
+
+// Test that a witness_method instruction using an indirectly-inherited conformance
+// is devirtualized.
+//
+// This test used to crash the compiler because it uses inherited conformances.
+// CHECK-LABEL: sil @$S34devirt_protocol_method_invocations34testIndirectlyInheritedConformanceyyF : $@convention(thin) () -> ()
+// CHECK-NOT: witness_method
+// CHECK: apply
+// CHECK: // end sil function '$S34devirt_protocol_method_invocations34testIndirectlyInheritedConformanceyyF'
+public func testIndirectlyInheritedConformance() {
+ (S() as RRR).f()
+}
+
+
+public protocol Foo {
+ func foo(_ x:Int) -> Int
+}
+
+public extension Foo {
+ func boo(_ x:Int) -> Int32 {
+ return 2222 + Int32(x)
+ }
+
+ func getSelf() -> Self {
+ return self
+ }
+}
+
+var gg = 1111
+
+open class C : Foo {
+ @inline(never)
+ open func foo(_ x:Int) -> Int {
+ gg += 1
+ return gg + x
+ }
+}
+
+@_transparent
+func callfoo(_ f: Foo) -> Int {
+ return f.foo(2) + f.foo(2)
+}
+
+@_transparent
+func callboo(_ f: Foo) -> Int32 {
+ return f.boo(2) + f.boo(2)
+}
+
+@_transparent
+func callGetSelf(_ f: Foo) -> Foo {
+ return f.getSelf()
+}
+
+// Check that methods returning Self are not devirtualized and do not crash the compiler.
+// CHECK-LABEL: sil [noinline] @$S34devirt_protocol_method_invocations05test_a1_b11_extension_C33_invocation_with_self_return_typeyAA3Foo_pAA1CCF
+// CHECK: init_existential_addr
+// CHECK: open_existential_addr
+// CHECK: return
+@inline(never)
+public func test_devirt_protocol_extension_method_invocation_with_self_return_type(_ c: C) -> Foo {
+ return callGetSelf(c)
+}
+
+// Check that calls to f.foo() get devirtualized and are not invoked
+// via the expensive witness_method instruction.
+// To achieve that the information about a concrete type C should
+// be propagated from init_existential_addr into witness_method and
+// apply instructions.
+
+// CHECK-LABEL: sil [noinline] @$S34devirt_protocol_method_invocations05test_a1_b1_C11_invocationySiAA1CCF
+// CHECK-NOT: witness_method
+// CHECK: checked_cast
+// CHECK-NOT: checked_cast
+// CHECK: bb1(
+// CHECK-NOT: checked_cast
+// CHECK: return
+// CHECK: bb2(
+// CHECK-NOT: checked_cast
+// CHECK: function_ref
+// CHECK: apply
+// CHECK: apply
+// CHECK: br bb1(
+// CHECK: bb3
+// CHECK-NOT: checked_cast
+// CHECK: apply
+// CHECK: apply
+// CHECK: br bb1(
+
+// Check that calls of a method boo() from the protocol extension
+// get devirtualized and are not invoked via the expensive witness_method instruction
+// or by passing an existential as a parameter.
+// To achieve that the information about a concrete type C should
+// be propagated from init_existential_addr into apply instructions.
+// In fact, the call is expected to be inlined and then constant-folded
+// into a single integer constant.
+
+// CHECK-LABEL: sil [noinline] @$S34devirt_protocol_method_invocations05test_a1_b11_extension_C11_invocationys5Int32VAA1CCF
+// CHECK-NOT: checked_cast
+// CHECK-NOT: open_existential
+// CHECK-NOT: witness_method
+// CHECK-NOT: apply
+// CHECK: integer_literal
+// CHECK: return
+
+// CHECK: sil @$S34devirt_protocol_method_invocations12test24114020SiyF
+// CHECK: [[T0:%.*]] = integer_literal $Builtin.Int{{.*}}, 1
+// CHECK: [[T1:%.*]] = struct $Int ([[T0]] : $Builtin.Int{{.*}})
+// CHECK: return [[T1]]
+
+// CHECK: sil @$S34devirt_protocol_method_invocations14testExMetatypeSiyF
+// CHECK: [[T0:%.*]] = builtin "sizeof"<Int>
+// CHECK: [[T1:%.*]] = builtin {{.*}}([[T0]]
+// CHECK: [[T2:%.*]] = struct $Int ([[T1]] : {{.*}})
+// CHECK: return [[T2]] : $Int
+
+@inline(never)
+public func test_devirt_protocol_method_invocation(_ c: C) -> Int {
+ return callfoo(c)
+}
+
+@inline(never)
+public func test_devirt_protocol_extension_method_invocation(_ c: C) -> Int32 {
+ return callboo(c)
+}
+
+
+// Make sure that we are not crashing with an assertion due to specialization
+// of methods with the Self return type as an argument.
+// rdar://20868966
+protocol Proto {
+ func f() -> Self
+}
+
+class CC : Proto {
+ func f() -> Self { return self }
+}
+
+func callDynamicSelfExistential(_ p: Proto) {
+ p.f()
+}
+
+public func testSelfReturnType() {
+ callDynamicSelfExistential(CC())
+}
+
+
+// Make sure that we are not crashing with an assertion due to specialization
+// of methods with the Self return type.
+// rdar://20955745.
+protocol CP : class { func f() -> Self }
+func callDynamicSelfClassExistential(_ cp: CP) { cp.f() }
+class PP : CP {
+ func f() -> Self { return self }
+}
+
+callDynamicSelfClassExistential(PP())
+
+// Make sure we handle indirect conformances.
+// rdar://24114020
+protocol Base {
+ var x: Int { get }
+}
+protocol Derived : Base {
+}
+struct SimpleBase : Derived {
+ var x: Int
+}
+public func test24114020() -> Int {
+ let base: Derived = SimpleBase(x: 1)
+ return base.x
+}
+
+protocol StaticP {
+ static var size: Int { get }
+}
+struct HasStatic<T> : StaticP {
+ static var size: Int { return MemoryLayout<T>.size }
+}
+public func testExMetatype() -> Int {
+ let type: StaticP.Type = HasStatic<Int>.self
+ return type.size
+}
+
+// rdar://32288618
+public func testExMetatypeVar() -> Int {
+ var type: StaticP.Type = HasStatic<Int>.self
+ return type.size
+}
+
+// IRGen used to crash on the testPropagationOfConcreteTypeIntoExistential method.
+// rdar://26286278
+
+protocol MathP {
+ var sum: Int32 { get nonmutating set }
+ func done()
+}
+
+extension MathP {
+ @inline(never)
+ func plus() -> Self {
+ sum += 1
+ return self
+ }
+
+ @inline(never)
+ func minus() {
+ sum -= 1
+ if sum == 0 {
+ done()
+ }
+ }
+}
+
+protocol MathA : MathP {}
+
+public final class V {
+ var a: MathA
+
+ init(a: MathA) {
+ self.a = a
+ }
+}
+
+// Check that all witness_method invocations are devirtualized.
+// CHECK-LABEL: sil [noinline] @$S34devirt_protocol_method_invocations44testPropagationOfConcreteTypeIntoExistential1v1xyAA1VC_s5Int32VtF
+// CHECK-NOT: witness_method
+// CHECK-NOT: class_method
+// CHECK: return
+@inline(never)
+public func testPropagationOfConcreteTypeIntoExistential(v: V, x: Int32) {
+ let y = v.a.plus()
+ defer {
+ y.minus()
+ }
+}
+
diff --git a/test/SILOptimizer/plus_zero_devirt_speculative_nested.swift b/test/SILOptimizer/plus_zero_devirt_speculative_nested.swift
new file mode 100644
index 0000000..bc6a9e8
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_speculative_nested.swift
@@ -0,0 +1,32 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend %s -parse-as-library -O -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend %s -parse-as-library -Osize -emit-sil
+//
+// Test speculative devirtualization.
+
+public class Outer<T> {
+ final class Inner : Base {
+ @inline(never) override func update() {
+ }
+ }
+}
+
+public class Base {
+ @inline(never) func update() { }
+}
+
+// FIXME: We don't speculate to the override Outer<T>.Inner.update() here,
+// because we cannot express the cast -- the cast "returns" a new archetype
+// T, much like an opened existential.
+//
+// But at least, we shouldn't crash.
+
+// CHECK-LABEL: sil @$S25devirt_speculative_nested3foo1xyAA4BaseC_tF : $@convention(thin) (@guaranteed Base) -> ()
+// CHECK: checked_cast_br [exact] %0 : $Base to $Base
+// CHECK: function_ref @$S25devirt_speculative_nested4BaseC6updateyyF
+// CHECK: class_method %0 : $Base, #Base.update!1
+// CHECK: return
+
+public func foo(x: Base) {
+ x.update()
+}
diff --git a/test/SILOptimizer/plus_zero_devirt_value_metatypes.swift b/test/SILOptimizer/plus_zero_devirt_value_metatypes.swift
new file mode 100644
index 0000000..b324eab
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_value_metatypes.swift
@@ -0,0 +1,63 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -O %s | %FileCheck %s
+
+open class A {
+ @inline(never)
+ class func foo() {
+ }
+}
+
+
+class B: A {
+ @inline(never)
+ override class func foo() {}
+}
+
+// CHECK-LABEL: sil @$S22devirt_value_metatypes17testValueMetatypeyyAA1ACF
+// CHECK: value_metatype $@thick A.Type
+// CHECK: checked_cast_br
+// CHECK: checked_cast_br
+// CHECK: class_method
+// CHECK: }
+public func testValueMetatype(_ x:A) {
+ type(of: x).foo()
+}
+
+open class C {
+ @inline(never)
+ class func foo() -> Int { return 0 }
+}
+
+open class D : C {
+ @inline(never)
+ override class func foo() -> Int { return 1 }
+}
+
+// CHECK-LABEL: sil @$S22devirt_value_metatypes5testDySiAA1DCF
+// CHECK-NOT: value_metatype %
+// D.foo is an internal method, D has no subclasses and it is a wmo compilation,
+// therefore D.foo method invocation can be devirtualized.
+// CHECK: function_ref @$S22devirt_value_metatypes1DC3fooSiyFZTf4d_n
+// CHECK-NOT: value_metatype %
+// CHECK-NOT: checked_cast_br
+// CHECK-NOT: class_method
+// CHECK: }
+public func testD(_ x: D) -> Int {
+ return (type(of: x) as C.Type).foo()
+}
+
+
+public final class E : C {
+ @inline(never)
+ override class func foo() -> Int { return 1 }
+}
+
+// CHECK-LABEL: sil @$S22devirt_value_metatypes5testEySiAA1ECF
+// CHECK-NOT: value_metatype $@thick E.Type
+// CHECK_NOT: checked_cast_br
+// CHECK: function_ref
+// CHECK: apply
+// CHECK: return
+public func testE(_ x: E) -> Int {
+ return (type(of: x) as C.Type).foo()
+}
diff --git a/test/SILOptimizer/plus_zero_devirt_witness_method_conformance.swift b/test/SILOptimizer/plus_zero_devirt_witness_method_conformance.swift
new file mode 100644
index 0000000..f3da042
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_devirt_witness_method_conformance.swift
@@ -0,0 +1,20 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -emit-ir -primary-file %s | %FileCheck %s
+// This is a swift file because the crash doesn't reproduce with SIL.
+@inline(never)
+func callFoo<T: X>(_ x: T) {
+ x.foo()
+}
+public func a(y: Sub) {
+ callFoo(y)
+ // specialization of callFoo for Sub:
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @"$S33devirt_witness_method_conformance7callFooyyxAA1XRzlFAA3SubC_Tg5"({{.*}}) local_unnamed_addr
+}
+protocol X {
+ func foo()
+}
+extension X {
+ func foo() {}
+}
+public class Base: X {}
+public class Sub: Base {}
diff --git a/test/SILOptimizer/plus_zero_let_properties_opts.swift b/test/SILOptimizer/plus_zero_let_properties_opts.swift
new file mode 100644
index 0000000..12be391
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_let_properties_opts.swift
@@ -0,0 +1,356 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend %s -O -emit-sil | %FileCheck -check-prefix=CHECK-WMO %s
+// RUN: %target-swift-frontend -primary-file %s -O -emit-sil | %FileCheck %s
+
+// Test propagation of non-static let properties with compile-time constant values.
+
+// TODO: Once this optimization can remove the propagated fileprivate/internal let properties or
+// mark them as ones without a storage, new tests should be added here to check for this
+// functionality.
+
+// FIXME: This test is written in Swift instead of SIL, because there are some problems
+// with SIL deserialization (rdar://22636911)
+
+// Check that initializers do not contain a code to initialize fileprivate or
+// internal (if used with WMO) properties, because their values are propagated into
+// their uses and they cannot be accessed from other modules. Therefore the
+// initialization code could be removed.
+// Specifically, the initialization code for Prop1, Prop2 and Prop3 can be removed.
+
+// CHECK-WMO-LABEL: sil @$S19let_properties_opts3FooC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (Int32, @owned Foo) -> @owned Foo
+// CHECK-WMO-NOT: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop1
+// CHECK-WMO-NOT: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop2
+// CHECK-WMO-NOT: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop3
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop0
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop1
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop2
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop3
+// CHECK-WMO: return
+
+// CHECK-WMO-LABEL: sil @$S19let_properties_opts3FooC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (Int64, @owned Foo) -> @owned Foo
+// CHECK-WMO-NOT: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop1
+// CHECK-WMO-NOT: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop2
+// CHECK-WMO-NOT: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop3
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop0
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop1
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop2
+// CHECK-WMO: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop3
+// CHECK-WMO: return
+
+// Check that initializers do not contain a code to initialize fileprivate properties,
+// because their values are propagated into their uses and they cannot be accessed
+// from other modules. Therefore the initialization code could be removed.
+// Specifically, the initialization code for Prop2 can be removed.
+
+// CHECK-LABEL: sil @$S19let_properties_opts3FooC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (Int32, @owned Foo) -> @owned Foo
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop0
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop1
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop2
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop3
+// CHECK: return
+
+// CHECK-LABEL: sil @$S19let_properties_opts3FooC{{[_0-9a-zA-Z]*}}fc : $@convention(method) (Int64, @owned Foo) -> @owned Foo
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop0
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop1
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop2
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo, #Foo.Prop3
+// CHECK: return
+
+public class Foo {
+ public let Prop0: Int32 = 1
+ let Prop1: Int32 = 1 + 4/2 + 8
+ fileprivate let Prop2: Int32 = 3*7
+ internal let Prop3: Int32 = 4*8
+ public init(i:Int32) {}
+ public init(i:Int64) {}
+}
+
+public class Foo1 {
+ let Prop1: Int32
+ fileprivate let Prop2: Int32 = 3*7
+ internal let Prop3: Int32 = 4*8
+ public init(i:Int32) {
+ Prop1 = 11
+ }
+
+ public init(i:Int64) {
+ Prop1 = 1111
+ }
+}
+
+public struct Boo {
+ public let Prop0: Int32 = 1
+ let Prop1: Int32 = 1 + 4/2 + 8
+ fileprivate let Prop2: Int32 = 3*7
+ internal let Prop3: Int32 = 4*8
+ public init(i:Int32) {}
+ public init(i:Int64) {}
+}
+
+public class Foo2 {
+ internal let x: Int32
+ @inline(never)
+ init(count: Int32) {
+ if count < 2 {
+ x = 5
+ } else {
+ x = 10
+ }
+ }
+}
+
+public class C {}
+
+struct Boo3 {
+ //public
+ let Prop0: Int32
+ let Prop1: Int32
+ fileprivate let Prop2: Int32
+ internal let Prop3: Int32
+
+ @inline(__always)
+ init(_ f1: C, _ f2: C) {
+ self.Prop0 = 0
+ self.Prop1 = 1
+ self.Prop2 = 2
+ self.Prop3 = 3
+ }
+
+ init(_ v: C) {
+ self.Prop0 = 10
+ self.Prop1 = 11
+ self.Prop2 = 12
+ self.Prop3 = 13
+ }
+}
+
+// The initializer of this struct can be defined elsewhere,
+// e.g. in an extension of this struct in a different module.
+public struct StructWithOnlyPublicLetProperties {
+ public let Prop0: Int32
+ public let Prop1: Int32
+
+ init(_ v: Int32, _ u: Int32) {
+ Prop0 = 10
+ Prop1 = 11
+ }
+}
+
+// The initializer of this struct cannot be defined outside
+// of the current module, because it contains an internal stored
+// property, which is impossible to initialize outside of this module.
+public struct StructWithPublicAndInternalLetProperties {
+ public let Prop0: Int32
+ internal let Prop1: Int32
+
+ init(_ v: Int32, _ u: Int32) {
+ Prop0 = 10
+ Prop1 = 11
+ }
+}
+
+// The initializer of this struct cannot be defined elsewhere,
+// because it contains a fileprivate stored property, which is
+// impossible to initialize outside of this file.
+public struct StructWithPublicAndInternalAndPrivateLetProperties {
+ public let Prop0: Int32
+ internal let Prop1: Int32
+ fileprivate let Prop2: Int32
+
+ init(_ v: Int32, _ u: Int32) {
+ Prop0 = 10
+ Prop1 = 11
+ Prop2 = 12
+ }
+}
+
+
+// Check that Foo1.Prop1 is not constant-folded, because its value is unknown, since it is initialized differently
+// by Foo1 initializers.
+
+// CHECK-LABEL: sil @$S19let_properties_opts13testClassLet1ys5Int32VAA4Foo1CF : $@convention(thin) (@guaranteed Foo1) -> Int32
+// bb0
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo1, #Foo1.Prop1
+// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo1, #Foo1.Prop2
+// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo1, #Foo1.Prop3
+// CHECK: return
+public func testClassLet1(_ f: Foo1) -> Int32 {
+ return f.Prop1 + f.Prop2 + f.Prop3
+}
+
+// Check that Foo1.Prop1 is not constant-folded, because its value is unknown, since it is initialized differently
+// by Foo1 initializers.
+
+// CHECK-LABEL: sil @$S19let_properties_opts13testClassLet1ys5Int32VAA4Foo1CzF : $@convention(thin) (@inout Foo1) -> Int32
+// bb0
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo1, #Foo1.Prop1
+// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo1, #Foo1.Prop2
+// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo1, #Foo1.Prop3
+// CHECK: return
+public func testClassLet1(_ f: inout Foo1) -> Int32 {
+ return f.Prop1 + f.Prop2 + f.Prop3
+}
+
+// Check that return expressions in all subsequent functions can be constant folded, because the values of let properties
+// are known to be constants of simple types.
+
+// CHECK: sil @$S19let_properties_opts12testClassLetys5Int32VAA3FooCF : $@convention(thin) (@guaranteed Foo) -> Int32
+// CHECK: bb0
+// CHECK: integer_literal $Builtin.Int32, 75
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+public func testClassLet(_ f: Foo) -> Int32 {
+ return f.Prop1 + f.Prop1 + f.Prop2 + f.Prop3
+}
+
+// CHECK-LABEL: sil @$S19let_properties_opts12testClassLetys5Int32VAA3FooCzF : $@convention(thin) (@inout Foo) -> Int32
+// CHECK: bb0
+// CHECK: integer_literal $Builtin.Int32, 75
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+public func testClassLet(_ f: inout Foo) -> Int32 {
+ return f.Prop1 + f.Prop1 + f.Prop2 + f.Prop3
+}
+
+// CHECK-LABEL: sil @$S19let_properties_opts18testClassPublicLetys5Int32VAA3FooCF : $@convention(thin) (@guaranteed Foo) -> Int32
+// CHECK: bb0
+// CHECK: integer_literal $Builtin.Int32, 1
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+public func testClassPublicLet(_ f: Foo) -> Int32 {
+ return f.Prop0
+}
+
+// CHECK-LABEL: sil @$S19let_properties_opts13testStructLetys5Int32VAA3BooVF : $@convention(thin) (Boo) -> Int32
+// CHECK: bb0
+// CHECK: integer_literal $Builtin.Int32, 75
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+public func testStructLet(_ b: Boo) -> Int32 {
+ return b.Prop1 + b.Prop1 + b.Prop2 + b.Prop3
+}
+
+// CHECK-LABEL: sil @$S19let_properties_opts13testStructLetys5Int32VAA3BooVzF : $@convention(thin) (@inout Boo) -> Int32
+// CHECK: bb0
+// CHECK: integer_literal $Builtin.Int32, 75
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+public func testStructLet(_ b: inout Boo) -> Int32 {
+ return b.Prop1 + b.Prop1 + b.Prop2 + b.Prop3
+}
+
+// CHECK-LABEL: sil @$S19let_properties_opts19testStructPublicLetys5Int32VAA3BooVF : $@convention(thin) (Boo) -> Int32
+// CHECK: bb0
+// CHECK: integer_literal $Builtin.Int32, 1
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+public func testStructPublicLet(_ b: Boo) -> Int32 {
+ return b.Prop0
+}
+
+// Check that f.x is not constant folded, because the initializer of Foo2 has multiple
+// assignments to the property x with different values.
+// CHECK-LABEL: sil @$S19let_properties_opts13testClassLet2ys5Int32VAA4Foo2CF : $@convention(thin) (@guaranteed Foo2) -> Int32
+// bb0
+// CHECK: ref_element_addr %{{[0-9]+}} : $Foo2, #Foo2.x
+// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo2, #Foo2.x
+// CHECK-NOT: ref_element_addr %{{[0-9]+}} : $Foo2, #Foo2.x
+// CHECK: return
+public func testClassLet2(_ f: Foo2) -> Int32 {
+ return f.x + f.x
+}
+
+// Check that the sum of properties is not folded into a constant.
+// CHECK-WMO-LABEL: sil hidden [noinline] @$S19let_properties_opts27testStructWithMultipleInitsys5Int32VAA4Boo3V_AFtF : $@convention(thin) (Boo3, Boo3) -> Int32
+// CHECK-WMO: bb0
+// No constant folding should have been performed.
+// CHECK-WMO-NOT: integer_literal $Builtin.Int32, 92
+// CHECK-WMO: struct_extract
+// CHECK-WMO: }
+@inline(never)
+func testStructWithMultipleInits( _ boos1: Boo3, _ boos2: Boo3) -> Int32 {
+ let count1 = boos1.Prop0 + boos1.Prop1 + boos1.Prop2 + boos1.Prop3
+ let count2 = boos2.Prop0 + boos2.Prop1 + boos2.Prop2 + boos2.Prop3
+ return count1 + count2
+}
+
+public func testStructWithMultipleInitsAndInlinedInitializer() {
+ let things = [C()]
+ // This line results in inlining of the initializer Boo3(C, C) and later
+ // removal of this initializer by the dead function elimination pass.
+ // As a result, only one initializer, Boo3(C) is seen by the Let Properties Propagation
+ // pass. This pass may think that there is only one initializer and take the
+ // values of let properties assigned there as constants and try to propagate
+ // those values into uses. But this is wrong! The pass should be clever enough
+ // to detect all stores to the let properties, including those outside of
+ // initializers, e.g. inside inlined initializers. And if it detects all such
+ // stores it should understand that values of let properties in Boo3 are not
+ // statically known constant initializers with the same value and thus
+ // cannot be propagated.
+ let boos1 = things.map { Boo3($0, C()) }
+ let boos2 = things.map(Boo3.init)
+ print(testStructWithMultipleInits(boos1[0], boos2[0]))
+}
+
+// Since all properties are public, they can be initialized in a
+// different module.
+// Their values are not known and cannot be propagated.
+
+// CHECK-LABEL: sil @$S19let_properties_opts31testStructPropertyAccessibilityys5Int32VAA0E27WithOnlyPublicLetPropertiesVF
+// CHECK: struct_extract %0 : $StructWithOnlyPublicLetProperties, #StructWithOnlyPublicLetProperties.Prop0
+// CHECK: return
+
+// CHECK-WMO-LABEL: sil @$S19let_properties_opts31testStructPropertyAccessibilityys5Int32VAA0E27WithOnlyPublicLetPropertiesVF
+// CHECK-WMO: struct_extract %0 : $StructWithOnlyPublicLetProperties, #StructWithOnlyPublicLetProperties.Prop0
+// CHECK-WMO: return
+public func testStructPropertyAccessibility(_ b: StructWithOnlyPublicLetProperties) -> Int32 {
+ return b.Prop0 + b.Prop1
+}
+
+// Properties can be initialized in a different file in the same module.
+// Their values are not known and cannot be propagated,
+// unless it is a WMO compilation.
+
+// CHECK-LABEL: sil @$S19let_properties_opts31testStructPropertyAccessibilityys5Int32VAA0E34WithPublicAndInternalLetPropertiesVF
+// CHECK: struct_extract %0 : $StructWithPublicAndInternalLetProperties, #StructWithPublicAndInternalLetProperties.Prop0
+// CHECK-NOT: integer_literal $Builtin.Int32, 21
+// CHECK: return
+
+// CHECK-WMO-LABEL: sil @$S19let_properties_opts31testStructPropertyAccessibilityys5Int32VAA0E34WithPublicAndInternalLetPropertiesVF
+// CHECK-WMO: integer_literal $Builtin.Int32, 21
+// CHECK-WMO-NEXT: struct $Int32
+// CHECK-WMO-NEXT: return
+public func testStructPropertyAccessibility(_ b: StructWithPublicAndInternalLetProperties) -> Int32 {
+ return b.Prop0 + b.Prop1
+}
+
+// Properties can be initialized only in this file, because one of the
+// properties is fileprivate.
+// Therefore their values are known and can be propagated.
+
+// CHECK: sil @$S19let_properties_opts31testStructPropertyAccessibilityys5Int32VAA0e21WithPublicAndInternalK20PrivateLetPropertiesVF
+// CHECK: integer_literal $Builtin.Int32, 33
+// CHECK-NEXT: struct $Int32
+// CHECK-NEXT: return
+
+// CHECK-WMO-LABEL: sil @$S19let_properties_opts31testStructPropertyAccessibilityys5Int32VAA0e21WithPublicAndInternalK20PrivateLetPropertiesVF
+// CHECK-WMO: integer_literal $Builtin.Int32, 33
+// CHECK-WMO-NEXT: struct $Int32
+// CHECK-WMO-NEXT: return
+public func testStructPropertyAccessibility(_ b: StructWithPublicAndInternalAndPrivateLetProperties) -> Int32 {
+ return b.Prop0 + b.Prop1 + b.Prop2
+}
+
+// Force use of initializers, otherwise they got removed by the dead-function-elimination pass
+// and the values of let properties cannot be determined.
+public func useInitializers() -> StructWithOnlyPublicLetProperties {
+ return StructWithOnlyPublicLetProperties(1, 1)
+}
+
+public func useInitializers() -> StructWithPublicAndInternalLetProperties {
+ return StructWithPublicAndInternalLetProperties(1, 1)
+}
+
+public func useInitializers() -> StructWithPublicAndInternalAndPrivateLetProperties {
+ return StructWithPublicAndInternalAndPrivateLetProperties(1, 1)
+}
diff --git a/test/SILOptimizer/plus_zero_mandatory_inlining.swift b/test/SILOptimizer/plus_zero_mandatory_inlining.swift
new file mode 100644
index 0000000..3dec6cb
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_mandatory_inlining.swift
@@ -0,0 +1,177 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -enable-sil-ownership -sil-verify-all -primary-file %s -emit-sil -o - -verify | %FileCheck %s
+
+// These tests are deliberately shallow, because I do not want to depend on the
+// specifics of SIL generation, which might change for reasons unrelated to this
+// pass
+
+func foo(_ x: Float) -> Float {
+ return bar(x);
+}
+
+// CHECK-LABEL: sil hidden @$S18mandatory_inlining3foo{{[_0-9a-zA-Z]*}}F
+// CHECK: bb0(%0 : $Float):
+// CHECK-NEXT: debug_value %0 : $Float, let, name "x"
+// CHECK-NEXT: return %0
+
+@_transparent func bar(_ x: Float) -> Float {
+ return baz(x)
+}
+
+// CHECK-LABEL: sil hidden [transparent] @$S18mandatory_inlining3bar{{[_0-9a-zA-Z]*}}F
+ // CHECK-NOT: function_ref
+ // CHECK-NOT: apply
+ // CHECK: return
+
+@_transparent func baz(_ x: Float) -> Float {
+ return x
+}
+
+// CHECK-LABEL: sil hidden [transparent] @$S18mandatory_inlining3baz{{[_0-9a-zA-Z]*}}F
+// CHECK: return
+
+func spam(_ x: Int) -> Int {
+ return x
+}
+
+// CHECK-LABEL: sil hidden @$S18mandatory_inlining4spam{{[_0-9a-zA-Z]*}}F
+
+@_transparent func ham(_ x: Int) -> Int {
+ return spam(x)
+}
+
+// CHECK-LABEL: sil hidden [transparent] @$S18mandatory_inlining3ham{{[_0-9a-zA-Z]*}}F
+ // CHECK: function_ref @$S18mandatory_inlining4spam{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply
+ // CHECK: return
+
+func eggs(_ x: Int) -> Int {
+ return ham(x)
+}
+
+// CHECK-LABEL: sil hidden @$S18mandatory_inlining4eggs{{[_0-9a-zA-Z]*}}F
+ // CHECK: function_ref @$S18mandatory_inlining4spam{{[_0-9a-zA-Z]*}}F
+ // CHECK: apply
+ // CHECK: return
+
+@_transparent func call_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
+ return x()
+}
+
+func test_auto_closure_with_capture(_ x: Bool) -> Bool {
+ return call_auto_closure(x)
+}
+
+// This should be fully inlined and simply return x; however, there's a lot of
+// non-SSA cruft that I don't want this test to depend on, so I'm just going
+// to verify that it doesn't have any function applications left
+
+// CHECK-LABEL: sil hidden @{{.*}}test_auto_closure_with_capture
+ // CHECK-NOT: = apply
+ // CHECK: return
+
+func test_auto_closure_without_capture() -> Bool {
+ return call_auto_closure(false)
+}
+
+// This should be fully inlined and simply return false, which is easier to check for
+
+// CHECK-LABEL: sil hidden @$S18mandatory_inlining33test_auto_closure_without_captureSbyF
+ // CHECK: [[FV:%.*]] = integer_literal $Builtin.Int1, 0
+ // CHECK: [[FALSE:%.*]] = struct $Bool ([[FV:%.*]] : $Builtin.Int1)
+ // CHECK: return [[FALSE]]
+
+infix operator &&& : LogicalConjunctionPrecedence
+infix operator ||| : LogicalDisjunctionPrecedence
+
+@_transparent func &&& (lhs: Bool, rhs: @autoclosure () -> Bool) -> Bool {
+ if lhs {
+ return rhs()
+ }
+
+ return false
+}
+
+@_transparent func ||| (lhs: Bool, rhs: @autoclosure () -> Bool) -> Bool {
+ if lhs {
+ return true
+ }
+
+ return rhs()
+}
+
+func test_chained_short_circuit(_ x: Bool, y: Bool, z: Bool) -> Bool {
+ return x &&& (y ||| z)
+}
+
+// The test below just makes sure there are no uninlined [transparent] calls
+// left (i.e. the autoclosure and the short-circuiting boolean operators are
+// recursively inlined properly)
+
+// CHECK-LABEL: sil hidden @$S18mandatory_inlining26test_chained_short_circuit{{[_0-9a-zA-Z]*}}F
+ // CHECK-NOT: = apply [transparent]
+ // CHECK: return
+
+
+// Union element constructors should be inlined automatically.
+enum X {
+ case onetransp
+ case twotransp
+}
+
+func testInlineUnionElement() -> X {
+ return X.onetransp
+ // CHECK-LABEL: sil hidden @$S18mandatory_inlining22testInlineUnionElementAA1XOyF
+ // CHECK: enum $X, #X.onetransp!enumelt
+ // CHECK-NOT: = apply
+ // CHECK: return
+}
+
+
+
+@_transparent
+func call_let_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
+ return x()
+}
+
+// CHECK-LABEL: sil hidden @{{.*}}test_let_auto_closure_with_value_capture
+// CHECK: bb0(%0 : $Bool):
+// CHECK-NEXT: debug_value %0 : $Bool
+// CHECK-NEXT: return %0 : $Bool
+// CHECK-LABEL: // end sil function '{{.*}}test_let_auto_closure_with_value_capture
+func test_let_auto_closure_with_value_capture(_ x: Bool) -> Bool {
+ return call_let_auto_closure(x)
+}
+
+
+class C {}
+
+// CHECK-LABEL: sil hidden [transparent] @$S18mandatory_inlining25class_constrained_generic{{[_0-9a-zA-Z]*}}F
+@_transparent
+func class_constrained_generic<T : C>(_ o: T) -> AnyClass? {
+ // CHECK: return
+ return T.self
+}
+
+// CHECK-LABEL: sil hidden @$S18mandatory_inlining6invokeyyAA1CCF : $@convention(thin) (@guaranteed C) -> () {
+func invoke(_ c: C) {
+ // CHECK-NOT: function_ref @$S18mandatory_inlining25class_constrained_generic{{[_0-9a-zA-Z]*}}F
+ // CHECK-NOT: apply
+ // CHECK: init_existential_metatype
+ _ = class_constrained_generic(c)
+ // CHECK: return
+}
+
+// Make sure we don't crash.
+@_transparent
+public func mydo(_ what: @autoclosure () -> ()) {
+ what()
+}
+public class A {
+ public func bar() {}
+ public func foo(_ act: (@escaping () ->()) -> ()) {
+ act { [unowned self] in
+ mydo( self.bar() )
+ }
+ }
+}
diff --git a/test/SILOptimizer/plus_zero_performance_inliner.sil b/test/SILOptimizer/plus_zero_performance_inliner.sil
new file mode 100644
index 0000000..e19b0c9
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_performance_inliner.sil
@@ -0,0 +1,972 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -inline -sil-combine | %FileCheck %s
+
+sil_stage canonical
+
+import Builtin
+import Swift
+
+/////////////////////
+// Inlining Tests //
+/////////////////////
+
+// *NOTE* These tests currently validate whether or not we
+// visit nodes in the correct order since we do not explore inlined
+// code for more apply inst to inline. After that point, we will
+// probably need to do one of the following:
+//
+// 1. Introduce a flag to turn off the exploration behavior.
+// 2. Introduce some sort of debug output that displays the callgraph
+// traversal order.
+
+// Node -> Node
+
+sil @test1_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "umul_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+// CHECK-LABEL: sil @test1
+// CHECK: bb0([[INPUT:%[0-9]+]] : $Builtin.Int64)
+// CHECK: integer_literal $Builtin.Int1, 0
+// CHECK: [[MUL_TUPLE_RESULT:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[INPUT]] : {{.*}}, [[INPUT]]
+// CHECK: [[MUL_RESULT:%[0-9]+]] = tuple_extract [[MUL_TUPLE_RESULT]]
+// CHECK: return [[MUL_RESULT]]
+sil @test1 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test1_multiply_leaf : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %2 = apply %1 (%0) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ return %2 : $Builtin.Int64
+}
+
+// Node
+// / \
+// v v
+// Node -> Node
+
+// CHECK-LABEL: sil @test2_add_leaf
+
+sil @test2_add_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "uadd_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test2_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "umul_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test2_add_then_multiply : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test2_add_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %2 = apply %1(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %3 = function_ref @test2_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %4 = apply %3(%2) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ return %4 : $Builtin.Int64
+}
+
+// CHECK-LABEL: sil @test2 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+// bb0([[INPUT:%[0-9]+]] : $Builtin.Int64):
+// CHECK: [[UADD_RESULT_TUPLE:%[0-9]+]] = builtin "uadd_with_overflow_Int64"([[INPUT]] : {{.*}}, [[INPUT]]
+// CHECK: [[UADD_RESULT:%[0-9]+]] = tuple_extract [[UADD_RESULT_TUPLE]] : $(Builtin.Int64, Builtin.Int1), 0
+// CHECK: [[UADD_RESULT_TUPLE2:%[0-9]+]] = builtin "uadd_with_overflow_Int64"([[UADD_RESULT]] : {{.*}}, [[UADD_RESULT]]
+// CHECK: [[UADD_RESULT2:%[0-9]+]] = tuple_extract [[UADD_RESULT_TUPLE2]]
+// CHECK: [[UMUL_RESULT_TUPLE:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[UADD_RESULT2]] : {{.*}}, [[UADD_RESULT2]]
+// CHECK: [[UMUL_RESULT:%[0-9]+]] = tuple_extract [[UMUL_RESULT_TUPLE]]
+// CHECK: return [[UMUL_RESULT]] : $Builtin.Int64
+sil @test2 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test2_add_leaf: $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %2 = apply %1 (%0) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %3 = function_ref @test2_add_then_multiply : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %4 = apply %3 (%2) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ return %4 : $Builtin.Int64
+}
+
+// Node
+// / \
+// v v
+// Node Node
+// \ /
+// v v
+// Node
+
+// CHECK-LABEL: sil @test3_add_leaf
+
+sil @test3_add_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "uadd_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test3_sub_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = integer_literal $Builtin.Int64, 1
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "usub_with_overflow_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test3_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "umul_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test3_add_then_multiply : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test3_add_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %2 = apply %1(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %3 = function_ref @test3_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %4 = apply %3(%2) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ return %4 : $Builtin.Int64
+}
+
+sil @test3_sub_then_multiply : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test3_sub_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %2 = apply %1(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %3 = function_ref @test3_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %4 = apply %3(%2) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ return %4 : $Builtin.Int64
+}
+
+// CHECK-LABEL: sil @test3 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+// CHECK: bb0([[INPUT:%[0-9]+]] : $Builtin.Int64):
+// CHECK: [[LITERAL1:%[0-9]+]] = integer_literal {{.*}}, 1
+// CHECK: [[USUB_RESULT_TUPLE:%[0-9]+]] = builtin "usub_with_overflow_Int64"([[INPUT]] : {{.*}}, [[LITERAL1]] : {{.*}}
+// CHECK: [[USUB_RESULT:%[0-9]+]] = tuple_extract [[USUB_RESULT_TUPLE]]
+// CHECK: [[UMUL_RESULT_TUPLE:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[USUB_RESULT]] : {{.*}}, [[USUB_RESULT]]
+// CHECK: [[UMUL_RESULT:%[0-9]+]] = tuple_extract [[UMUL_RESULT_TUPLE]]
+// CHECK: [[UADD_RESULT_TUPLE:%[0-9]+]] = builtin "uadd_with_overflow_Int64"([[UMUL_RESULT]] : {{.*}}, [[UMUL_RESULT]]
+// CHECK: [[UADD_RESULT:%[0-9]+]] = tuple_extract [[UADD_RESULT_TUPLE]]
+// CHECK: [[UMUL_RESULT_TUPLE2:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[UADD_RESULT]] : {{.*}}, [[UADD_RESULT]]
+// CHECK: [[UMUL_RESULT:%[0-9]+]] = tuple_extract [[UMUL_RESULT_TUPLE2]]
+// CHECK: return [[UMUL_RESULT]]
+sil @test3 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test3_sub_then_multiply : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %2 = apply %1 (%0) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %3 = function_ref @test3_add_then_multiply : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %4 = apply %3 (%2) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ return %4 : $Builtin.Int64
+}
+
+// Node
+// / \
+// v v
+// Node -> Node
+// \ /
+// v v
+// Node
+
+// CHECK-LABEL: sil @test4_add_leaf
+
+sil @test4_add_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "uadd_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test4_sub_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "usub_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test4_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %2 = integer_literal $Builtin.Int1, 0
+ %3 = builtin "umul_with_overflow_Int64"(%0 : $Builtin.Int64, %0 : $Builtin.Int64, %2 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
+ %4 = tuple_extract %3 : $(Builtin.Int64, Builtin.Int1), 0
+ return %4: $Builtin.Int64
+}
+
+sil @test4_add_then_multiply : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test4_add_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %2 = apply %1(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %3 = function_ref @test4_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %4 = apply %3(%2) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ return %4 : $Builtin.Int64
+}
+
+sil @test4_add_then_multiply_then_multiply : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test4_add_then_multiply : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %2 = apply %1(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %3 = function_ref @test4_multiply_leaf : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %4 = apply %3(%2) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ return %4 : $Builtin.Int64
+}
+
+// CHECK-LABEL: sil @test4 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+// CHECK: bb0([[INPUT:%[0-9]+]] : $Builtin.Int64):
+// CHECK: [[UADD_RESULT_TUPLE:%[0-9]+]] = builtin "uadd_with_overflow_Int64"([[INPUT]] : {{.*}}, [[INPUT]]
+// CHECK: [[UADD_RESULT:%[0-9]+]] = tuple_extract [[UADD_RESULT_TUPLE]]
+// CHECK: [[UMUL_RESULT_TUPLE:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[UADD_RESULT]] : {{.*}}, [[UADD_RESULT]]
+// CHECK: [[UMUL_RESULT:%[0-9]+]] = tuple_extract [[UMUL_RESULT_TUPLE]]
+
+// CHECK: [[UADD_RESULT_TUPLE2:%[0-9]+]] = builtin "uadd_with_overflow_Int64"([[UMUL_RESULT]] : {{.*}}, [[UMUL_RESULT]]
+// CHECK: [[UADD_RESULT2:%[0-9]+]] = tuple_extract [[UADD_RESULT_TUPLE2]]
+// CHECK: [[UMUL_RESULT_TUPLE2:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[UADD_RESULT2]] : {{.*}}, [[UADD_RESULT2]]
+// CHECK: [[UMUL_RESULT2:%[0-9]+]] = tuple_extract [[UMUL_RESULT_TUPLE2]]
+
+// CHECK: [[UMUL_RESULT_TUPLE3:%[0-9]+]] = builtin "umul_with_overflow_Int64"([[UMUL_RESULT2]] : {{.*}}, [[UMUL_RESULT2]]
+// CHECK: [[UMUL_RESULT3:%[0-9]+]] = tuple_extract [[UMUL_RESULT_TUPLE3]]
+// CHECK: return [[UMUL_RESULT3]] : $Builtin.Int64
+sil @test4 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test4_add_then_multiply : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %2 = apply %1 (%0) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %3 = function_ref @test4_add_then_multiply_then_multiply : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ %4 = apply %3 (%2) : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64)
+ return %4 : $Builtin.Int64
+}
+
+// Circular Inline.
+
+// CHECK-LABEL: sil @test5
+// CHECK: bb0([[INPUT:%[0-9]+]] : $Builtin.Int64):
+// CHECK: [[FUN:%[0-9]+]] = function_ref @test5 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+// CHECK: [[FUN_RESULT:%[0-9]+]] = apply [[FUN]]([[INPUT]]) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+// CHECK: return [[FUN_RESULT]] : $Builtin.Int64
+sil @test5 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $Builtin.Int64):
+ %1 = function_ref @test5 : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ %2 = apply %1(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64
+ return %2 : $Builtin.Int64
+}
+
+//////////////////////
+// Apply Type Tests //
+//////////////////////
+
+// CHECK-LABEL: sil @generic_function
+sil @generic_function : $@convention(thin) <T> (@in T, @in T) -> Builtin.Int8 {
+bb0(%0 : $*T, %1 : $*T):
+ %2 = integer_literal $Builtin.Int8, 2
+ return %2 : $Builtin.Int8
+}
+
+// IGNORE-THIS-CHECK-LABEL: sil @ignore_applies_with_substitutions
+
+// We can't deserialize apply_inst with subst lists. When radar://14443304
+// is fixed then we should uncomment this test.
+
+// sil @ignore_applies_with_substitutions : $@convention(thin) (Builtin.Int64) -> Builtin.Int8 {
+// bb0(%0 : $Builtin.Int64):
+// %1 = function_ref @generic_function : $@convention(thin) <T> (@in T, @in T) -> Builtin.Int8
+// %2 = apply %1<T = Builtin.Int64>(%0, %0) : $@convention(thin) <T> (@in T, @in T) -> Builtin.Int8
+// return %2 : $Builtin.Int8
+// }
+
+// CHECK-LABEL: sil @trivial_fun
+
+sil @trivial_fun : $@convention(thin) () -> (Builtin.Int64) {
+ %0 = integer_literal $Builtin.Int64, 32
+ return %0 : $Builtin.Int64
+}
+
+protocol P {}
+extension Int64: P {}
+
+// We can inline function_refs with witness_method calling convention.
+sil @trivial_witness_method : $@convention(witness_method: P) (@inout Int64) -> Int64 {
+bb0(%0 : $*Int64):
+ %1 = load %0 : $*Int64
+ return %1 : $Int64
+}
+
+// CHECK-LABEL: sil @trivial_witness_method_caller : $@convention(thin) () -> ()
+// CHECK-NOT: apply .*@convention(witness_method
+// CHECK: return
+sil @trivial_witness_method_caller : $@convention(thin) () -> () {
+ %0 = alloc_box ${ var Int64 }, var, name "x"
+ %1 = project_box %0 : ${ var Int64 }, 0
+ %2 = function_ref @$Ss5Int64V22_builtinIntegerLiteralABBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Int64.Type) -> Int64 // user: %5
+ %3 = metatype $@thin Int64.Type
+ %4 = integer_literal $Builtin.Int2048, 0
+ %5 = apply %2(%4, %3) : $@convention(method) (Builtin.Int2048, @thin Int64.Type) -> Int64
+ store %5 to %1 : $*Int64
+ %6 = function_ref @trivial_witness_method : $@convention(witness_method: P) (@inout Int64) -> Int64
+ %7 = apply %6 (%1) : $@convention(witness_method: P) (@inout Int64) -> Int64
+ %8 = tuple()
+ return %8 : $()
+}
+
+// Int64.init(_builtinIntegerLiteral:)
+sil [transparent] [serialized] @$Ss5Int64V22_builtinIntegerLiteralABBi2048__tcfC : $@convention(method) (Builtin.Int2048, @thin Int64.Type) -> Int64
+
+
+// We can inline function_refs with c calling convention.
+sil @trivial_c : $@convention(c) (@inout Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $*Builtin.Int64):
+ %1 = load %0 : $*Builtin.Int64
+ return %1 : $Builtin.Int64
+}
+
+// CHECK-LABEL: sil @trivial_c_caller : $@convention(thin) () -> ()
+// CHECK-NOT: apply
+// CHECK: return
+sil @trivial_c_caller : $@convention(thin) () -> () {
+ %0 = alloc_stack $Builtin.Int64
+ %1 = integer_literal $Builtin.Int64, 0
+ store %1 to %0 : $*Builtin.Int64
+ %2 = function_ref @trivial_c : $@convention(c) (@inout Builtin.Int64) -> Builtin.Int64
+ apply %2 (%0) : $@convention(c) (@inout Builtin.Int64) -> Builtin.Int64
+ dealloc_stack %0 : $*Builtin.Int64
+ %3 = tuple()
+ return %3 : $()
+}
+
+// We can inline function_refs with objc_method calling convention.
+//
+// ObjC calls are unable to be devirtualized since at runtime the call
+// could change. But there is no reason in principal why we could not
+// (if there existed something like sealed classes in objc perhaps?),
+// inline a function_ref to such a call.
+sil @trivial_objc : $@convention(objc_method) (@inout Builtin.Int64) -> Builtin.Int64 {
+bb0(%0 : $*Builtin.Int64):
+ %1 = load %0 : $*Builtin.Int64
+ return %1 : $Builtin.Int64
+}
+
+// CHECK-LABEL: sil @trivial_objc_caller : $@convention(thin) () -> ()
+// CHECK-NOT: apply
+// CHECK: return
+sil @trivial_objc_caller : $@convention(thin) () -> () {
+ %0 = alloc_stack $Builtin.Int64
+ %1 = integer_literal $Builtin.Int64, 0
+ store %1 to %0 : $*Builtin.Int64
+ %2 = function_ref @trivial_objc : $@convention(objc_method) (@inout Builtin.Int64) -> Builtin.Int64
+ apply %2 (%0) : $@convention(objc_method) (@inout Builtin.Int64) -> Builtin.Int64
+ dealloc_stack %0 : $*Builtin.Int64
+ %3 = tuple()
+ return %3 : $()
+}
+
+//////////
+// Misc //
+//////////
+
+// Make sure SILCloner does not get into an infinite loop here.
+sil @_TFsoi1xFT3lhsVs5UWord3rhsS__S_ : $@convention(thin) (UInt32, UInt32) -> UInt32 {
+bb0(%0 : $UInt32, %1 : $UInt32):
+ %3 = struct_extract %0 : $UInt32, #UInt32._value // user: %5
+ %4 = struct_extract %1 : $UInt32, #UInt32._value // user: %5
+ %5 = builtin "xor_Int32"(%3 : $Builtin.Int32, %4 : $Builtin.Int32) : $Builtin.Int32 // user: %6
+ %6 = struct $UInt32 (%5 : $Builtin.Int32) // user: %7
+ return %6 : $UInt32 // id: %7
+}
+
+sil @_TFsop1tFT1aVs5UWord_S_ : $@convention(thin) (UInt32) -> UInt32 {
+bb0(%0 : $UInt32):
+ // function_ref Swift.^ [infix] (lhs : Swift.UInt32, rhs : Swift.UInt32) -> Swift.UInt32
+ %1 = function_ref @_TFsoi1xFT3lhsVs5UWord3rhsS__S_ : $@convention(thin) (UInt32, UInt32) -> UInt32 // user: %6
+ // function_ref Swift.~ [prefix] (a : Swift.UInt32) -> Swift.UInt32
+ %2 = function_ref @_TFsop1tFT1aVs5UWord_S_ : $@convention(thin) (UInt32) -> UInt32 // user: %5
+ %3 = integer_literal $Builtin.Int32, 0 // user: %4
+ %4 = struct $UInt32 (%3 : $Builtin.Int32) // user: %5
+ %5 = apply %2(%4) : $@convention(thin) (UInt32) -> UInt32 // user: %6
+ %6 = apply %1(%0, %5) : $@convention(thin) (UInt32, UInt32) -> UInt32 // user: %7
+ return %6 : $UInt32 // id: %7
+}
+
+// Transparent function may inline private functions.
+//
+sil private @private_ret_undef : $@convention(thin) () -> () {
+entry:
+ return undef : $()
+}
+
+sil @uses_private : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @private_ret_undef : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// CHECK-LABEL: sil [transparent] @transparent_uses_uses_private : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref @uses_private
+// CHECK: return
+sil [transparent] @transparent_uses_uses_private : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @uses_private : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// Test fragile-resilient inlining rules:
+// Everything is allowed except inlining of a resilient function into a fragile function.
+
+sil @resilient_function : $@convention(thin) () -> () {
+entry:
+ return undef : $()
+}
+
+sil [serialized] @fragile_function : $@convention(thin) () -> () {
+entry:
+ return undef : $()
+}
+
+// CHECK-LABEL: sil [serialized] @fragile_calls_resilient : $@convention(thin) () -> () {
+// CHECK: function_ref @resilient_function
+// CHECK: return
+sil [serialized] @fragile_calls_resilient : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @resilient_function : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// CHECK-LABEL: sil [serialized] @fragile_calls_fragile : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref @resilient_function
+// CHECK: return
+sil [serialized] @fragile_calls_fragile : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @fragile_function : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// CHECK-LABEL: sil @resilient_calls_fragile : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref @resilient_function
+// CHECK: return
+sil @resilient_calls_fragile : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @fragile_function : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// CHECK-LABEL: sil @resilient_calls_resilient : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref @resilient_function
+// CHECK: return
+sil @resilient_calls_resilient : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @resilient_function : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// CHECK-LABEL: sil @calls_self
+// CHECK-NEXT: bb0:
+// CHECK: function_ref @calls_self
+// CHECK-NEXT: apply
+// CHECK-NEXT: return
+sil @calls_self : $@convention(thin) () -> () {
+entry:
+ %f = function_ref @calls_self : $@convention(thin) () -> ()
+ %z = apply %f() : $@convention(thin) () -> ()
+ return %z : $()
+}
+
+// Visibility Tests
+// These tests stem from a time where visibility had an influence
+// on the inlining. This is no longer the case so we just check
+// if everything can be inlined, regardless of visibility.
+
+sil_global private @private_global : $Builtin.Word
+sil private @private_function : $@convention(thin) () -> () {
+ %0 = integer_literal $Builtin.Int32, 0
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_private_global : $@convention(thin) () -> () {
+ %0 = global_addr @private_global : $*Builtin.Word
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_private_function : $@convention(thin) () -> () {
+ %0 = function_ref @private_function : $@convention(thin) () -> ()
+ %1 = tuple()
+ return %1 : $()
+}
+
+sil_global shared @shared_global : $Builtin.Word
+sil shared @shared_function : $@convention(thin) () -> () {
+ %0 = integer_literal $Builtin.Int32, 1
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_shared_global : $@convention(thin) () -> () {
+ %0 = global_addr @shared_global : $*Builtin.Word
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_shared_function : $@convention(thin) () -> () {
+ %0 = function_ref @shared_function : $@convention(thin) () -> ()
+ %1 = tuple()
+ return %1 : $()
+}
+
+sil_global hidden @hidden_global : $Builtin.Word
+sil hidden @hidden_function : $@convention(thin) () -> () {
+ %0 = integer_literal $Builtin.Int32, 2
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_hidden_global : $@convention(thin) () -> () {
+ %0 = global_addr @hidden_global : $*Builtin.Word
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_hidden_function : $@convention(thin) () -> () {
+ %0 = function_ref @hidden_function : $@convention(thin) () -> ()
+ %1 = tuple()
+ return %1 : $()
+}
+
+sil_global @public_global : $Builtin.Word
+sil @public_function : $@convention(thin) () -> () {
+ %0 = integer_literal $Builtin.Int32, 4
+ %1 = tuple()
+ return %1 : $()
+}
+
+sil @references_public_global : $@convention(thin) () -> () {
+ %0 = global_addr @public_global : $*Builtin.Word
+ %1 = tuple()
+ return %1 : $()
+}
+sil @references_public_function : $@convention(thin) () -> () {
+ %0 = function_ref @public_function : $@convention(thin) () -> ()
+ %1 = tuple()
+ return %1 : $()
+}
+
+// CHECK-LABEL: sil private @private_function_test : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref
+// CHECK: return
+sil private @private_function_test : $@convention(thin) () -> () {
+ %0 = function_ref @references_public_function : $@convention(thin) () -> ()
+ %1 = function_ref @references_shared_function : $@convention(thin) () -> ()
+ %2 = function_ref @references_hidden_function : $@convention(thin) () -> ()
+ %3 = function_ref @references_private_function : $@convention(thin) () -> ()
+ %4 = function_ref @references_public_global : $@convention(thin) () -> ()
+ %5 = function_ref @references_shared_global : $@convention(thin) () -> ()
+ %6 = function_ref @references_hidden_global : $@convention(thin) () -> ()
+ %7 = function_ref @references_private_global : $@convention(thin) () -> ()
+ apply %0() : $@convention(thin) () -> ()
+ apply %1() : $@convention(thin) () -> ()
+ apply %2() : $@convention(thin) () -> ()
+ apply %3() : $@convention(thin) () -> ()
+ apply %4() : $@convention(thin) () -> ()
+ apply %5() : $@convention(thin) () -> ()
+ apply %6() : $@convention(thin) () -> ()
+ apply %7() : $@convention(thin) () -> ()
+ %8 = tuple()
+ return %8 : $()
+}
+
+// CHECK-LABEL: sil shared @shared_function_test : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref
+// CHECK: return
+sil shared @shared_function_test : $@convention(thin) () -> () {
+ %0 = function_ref @references_public_function : $@convention(thin) () -> ()
+ %1 = function_ref @references_shared_function : $@convention(thin) () -> ()
+ %2 = function_ref @references_hidden_function : $@convention(thin) () -> ()
+ %3 = function_ref @references_private_function : $@convention(thin) () -> ()
+ %4 = function_ref @references_public_global : $@convention(thin) () -> ()
+ %5 = function_ref @references_shared_global : $@convention(thin) () -> ()
+ %6 = function_ref @references_hidden_global : $@convention(thin) () -> ()
+ %7 = function_ref @references_private_global : $@convention(thin) () -> ()
+ apply %0() : $@convention(thin) () -> ()
+ apply %1() : $@convention(thin) () -> ()
+ apply %2() : $@convention(thin) () -> ()
+ apply %3() : $@convention(thin) () -> ()
+ apply %4() : $@convention(thin) () -> ()
+ apply %5() : $@convention(thin) () -> ()
+ apply %6() : $@convention(thin) () -> ()
+ apply %7() : $@convention(thin) () -> ()
+ %8 = tuple()
+ return %8 : $()
+}
+
+// CHECK-LABEL: sil hidden @hidden_function_test : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref
+// CHECK: return
+sil hidden @hidden_function_test : $@convention(thin) () -> () {
+ %0 = function_ref @references_public_function : $@convention(thin) () -> ()
+ %1 = function_ref @references_shared_function : $@convention(thin) () -> ()
+ %2 = function_ref @references_hidden_function : $@convention(thin) () -> ()
+ %3 = function_ref @references_private_function : $@convention(thin) () -> ()
+ %4 = function_ref @references_public_global : $@convention(thin) () -> ()
+ %5 = function_ref @references_shared_global : $@convention(thin) () -> ()
+ %6 = function_ref @references_hidden_global : $@convention(thin) () -> ()
+ %7 = function_ref @references_private_global : $@convention(thin) () -> ()
+ apply %0() : $@convention(thin) () -> ()
+ apply %1() : $@convention(thin) () -> ()
+ apply %2() : $@convention(thin) () -> ()
+ apply %3() : $@convention(thin) () -> ()
+ apply %4() : $@convention(thin) () -> ()
+ apply %5() : $@convention(thin) () -> ()
+ apply %6() : $@convention(thin) () -> ()
+ apply %7() : $@convention(thin) () -> ()
+ %8 = tuple()
+ return %8 : $()
+}
+
+// CHECK-LABEL: sil @public_function_test : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref
+// CHECK: return
+sil @public_function_test : $@convention(thin) () -> () {
+ %0 = function_ref @references_public_function : $@convention(thin) () -> ()
+ %1 = function_ref @references_shared_function : $@convention(thin) () -> ()
+ %2 = function_ref @references_hidden_function : $@convention(thin) () -> ()
+ %3 = function_ref @references_private_function : $@convention(thin) () -> ()
+ %4 = function_ref @references_public_global : $@convention(thin) () -> ()
+ %5 = function_ref @references_shared_global : $@convention(thin) () -> ()
+ %6 = function_ref @references_hidden_global : $@convention(thin) () -> ()
+ %7 = function_ref @references_private_global : $@convention(thin) () -> ()
+ apply %0() : $@convention(thin) () -> ()
+ apply %1() : $@convention(thin) () -> ()
+ apply %2() : $@convention(thin) () -> ()
+ apply %3() : $@convention(thin) () -> ()
+ apply %4() : $@convention(thin) () -> ()
+ apply %5() : $@convention(thin) () -> ()
+ apply %6() : $@convention(thin) () -> ()
+ apply %7() : $@convention(thin) () -> ()
+ %8 = tuple()
+ return %8 : $()
+}
+
+// CHECK-LABEL: sil hidden_external @hidden_external_function_test : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref
+// CHECK: return
+sil hidden_external @hidden_external_function_test : $@convention(thin) () -> () {
+ %0 = function_ref @references_public_function : $@convention(thin) () -> ()
+ %1 = function_ref @references_shared_function : $@convention(thin) () -> ()
+ %2 = function_ref @references_hidden_function : $@convention(thin) () -> ()
+ %3 = function_ref @references_private_function : $@convention(thin) () -> ()
+ %4 = function_ref @references_public_global : $@convention(thin) () -> ()
+ %5 = function_ref @references_shared_global : $@convention(thin) () -> ()
+ %6 = function_ref @references_hidden_global : $@convention(thin) () -> ()
+ %7 = function_ref @references_private_global : $@convention(thin) () -> ()
+ apply %0() : $@convention(thin) () -> ()
+ apply %1() : $@convention(thin) () -> ()
+ apply %2() : $@convention(thin) () -> ()
+ apply %3() : $@convention(thin) () -> ()
+ apply %4() : $@convention(thin) () -> ()
+ apply %5() : $@convention(thin) () -> ()
+ apply %6() : $@convention(thin) () -> ()
+ apply %7() : $@convention(thin) () -> ()
+ %8 = tuple()
+ return %8 : $()
+}
+
+// CHECK-LABEL: sil public_external @public_external_function_test : $@convention(thin) () -> () {
+// CHECK-NOT: function_ref
+// CHECK: return
+sil public_external @public_external_function_test : $@convention(thin) () -> () {
+ %0 = function_ref @references_public_function : $@convention(thin) () -> ()
+ %1 = function_ref @references_shared_function : $@convention(thin) () -> ()
+ %2 = function_ref @references_hidden_function : $@convention(thin) () -> ()
+ %3 = function_ref @references_private_function : $@convention(thin) () -> ()
+ %4 = function_ref @references_public_global : $@convention(thin) () -> ()
+ %5 = function_ref @references_shared_global : $@convention(thin) () -> ()
+ %6 = function_ref @references_hidden_global : $@convention(thin) () -> ()
+ %7 = function_ref @references_private_global : $@convention(thin) () -> ()
+ apply %0() : $@convention(thin) () -> ()
+ apply %1() : $@convention(thin) () -> ()
+ apply %2() : $@convention(thin) () -> ()
+ apply %3() : $@convention(thin) () -> ()
+ apply %4() : $@convention(thin) () -> ()
+ apply %5() : $@convention(thin) () -> ()
+ apply %6() : $@convention(thin) () -> ()
+ apply %7() : $@convention(thin) () -> ()
+ %8 = tuple()
+ return %8 : $()
+}
+
+// CHECK-LABEL: @caller_of_noinline
+sil @caller_of_noinline : $@convention(thin) () -> () {
+bb0:
+ // CHECK: function_ref @noinline_callee
+ // CHECK: apply
+ %0 = function_ref @noinline_callee : $@convention(thin) () -> Int
+ %1 = apply %0() : $@convention(thin) () -> Int
+ %2 = tuple ()
+ return %2 : $()
+}
+// CHECK-LABEL: [noinline] @noinline_callee
+sil [noinline] @noinline_callee : $@convention(thin) () -> Int {
+bb0:
+ %0 = function_ref @_TFSi33_convertFromBuiltinIntegerLiteralfMSiFBi2048_Si : $@convention(thin) (Builtin.Int2048, @thin Int.Type) -> Int
+ %1 = metatype $@thin Int.Type
+ %2 = integer_literal $Builtin.Int2048, 0
+ %3 = apply %0(%2, %1) : $@convention(thin) (Builtin.Int2048, @thin Int.Type) -> Int
+ return %3 : $Int
+}
+sil [transparent] @_TFSi33_convertFromBuiltinIntegerLiteralfMSiFBi2048_Si : $@convention(thin) (Builtin.Int2048, @thin Int.Type) -> Int
+
+sil @unknown_function : $@convention(thin) () -> ()
+
+sil @coldcall : $@convention(thin) () -> () {
+bb0:
+ // make it a non-trivial function
+ %f = function_ref @unknown_function : $@convention(thin) () -> ()
+ %a1 = apply %f() : $@convention(thin) () -> ()
+ %a2 = apply %f() : $@convention(thin) () -> ()
+ %a3 = apply %f() : $@convention(thin) () -> ()
+ %a4 = apply %f() : $@convention(thin) () -> ()
+ %a5 = apply %f() : $@convention(thin) () -> ()
+ %a6 = apply %f() : $@convention(thin) () -> ()
+ %a7 = apply %f() : $@convention(thin) () -> ()
+ %a8 = apply %f() : $@convention(thin) () -> ()
+ %a9 = apply %f() : $@convention(thin) () -> ()
+ %a10 = apply %f() : $@convention(thin) () -> ()
+ %a11 = apply %f() : $@convention(thin) () -> ()
+ %a12 = apply %f() : $@convention(thin) () -> ()
+ %a13 = apply %f() : $@convention(thin) () -> ()
+ %a14 = apply %f() : $@convention(thin) () -> ()
+ %a15 = apply %f() : $@convention(thin) () -> ()
+ %a16 = apply %f() : $@convention(thin) () -> ()
+ %a17 = apply %f() : $@convention(thin) () -> ()
+ %a18 = apply %f() : $@convention(thin) () -> ()
+ %a19 = apply %f() : $@convention(thin) () -> ()
+ %a20 = apply %f() : $@convention(thin) () -> ()
+ %a21 = apply %f() : $@convention(thin) () -> ()
+ %a22 = apply %f() : $@convention(thin) () -> ()
+ %0 = tuple () // user: %1
+ return %0 : $() // id: %1
+}
+
+// Generic call to "branchHint" for use in specialized @slowPath
+sil public_external [transparent] [_semantics "branchhint"] @_TFs11_branchHintUs7Boolean__FTQ_Sb_Sb : $@convention(thin)(Bool, Bool) -> Bool {
+bb0(%0 : $Bool, %1 : $Bool):
+ return %0 : $Bool
+}
+
+// Specialized call to "slowPath" for use in @coldcall_caller
+sil shared [noinline] [transparent] [_semantics "slowpath"] @_TTSgSbSbs7Boolean___TFs9_slowPathUs7Boolean__FQ_Sb : $@convention(thin) (Bool) -> Bool {
+bb0(%0 : $Bool):
+ %3 = integer_literal $Builtin.Int1, 0
+ %4 = struct $Bool (%3 : $Builtin.Int1)
+ %5 = function_ref @_TFs11_branchHintUs7Boolean__FTQ_Sb_Sb : $@convention(thin) (Bool, Bool) -> Bool
+ %6 = apply %5(%0, %4) : $@convention(thin) (Bool, Bool) -> Bool
+ return %6 : $Bool
+}
+
+// CHECK-LABEL: @coldcall_caller
+// CHECK: slowPath
+// CHECK-LABEL: bb1:
+// CHECK: function_ref @coldcall
+// CHECK: apply
+// CHECK-LABEL: bb2:
+sil @coldcall_caller : $@convention(thin) (Int32) -> () {
+bb0(%0 : $Int32):
+ %1 = alloc_stack $Bool // users: %7, %9, %11
+ %2 = integer_literal $Builtin.Int32, 0 // user: %5
+ %4 = struct_extract %0 : $Int32, #Int32._value // user: %5
+ %5 = builtin "cmp_eq_Word"(%4 : $Builtin.Int32, %2 : $Builtin.Int32) : $Builtin.Int1 // user: %6
+ %6 = struct $Bool (%5 : $Builtin.Int1) // user: %7
+ store %6 to %1 : $*Bool // id: %7
+ %8 = function_ref @_TTSgSbSbs7Boolean___TFs9_slowPathUs7Boolean__FQ_Sb : $@convention(thin) (Bool) -> Bool // user: %9
+ %9 = apply %8(%6) : $@convention(thin) (Bool) -> Bool // user: %10
+ %10 = struct_extract %9 : $Bool, #Bool._value // user: %12
+ dealloc_stack %1 : $*Bool // id: %11
+ cond_br %10, bb1, bb2 // id: %12
+
+bb1: // Preds: bb0
+ %13 = function_ref @coldcall : $@convention(thin) () -> () // user: %14
+ %14 = apply %13() : $@convention(thin) () -> ()
+ br bb2 // id: %15
+
+bb2: // Preds: bb0 bb1
+ %16 = tuple () // user: %17
+ return %16 : $() // id: %17
+}
+
+sil @slowHelper : $@convention(thin) () -> () {
+bb0:
+ // make it a non-trivial function
+ %f = function_ref @unknown_function : $@convention(thin) () -> ()
+ %a1 = apply %f() : $@convention(thin) () -> ()
+ %a2 = apply %f() : $@convention(thin) () -> ()
+ %a3 = apply %f() : $@convention(thin) () -> ()
+ %a4 = apply %f() : $@convention(thin) () -> ()
+ %a5 = apply %f() : $@convention(thin) () -> ()
+ %a6 = apply %f() : $@convention(thin) () -> ()
+ %a7 = apply %f() : $@convention(thin) () -> ()
+ %a8 = apply %f() : $@convention(thin) () -> ()
+ %a9 = apply %f() : $@convention(thin) () -> ()
+ %a10 = apply %f() : $@convention(thin) () -> ()
+ %a11 = apply %f() : $@convention(thin) () -> ()
+ %a12 = apply %f() : $@convention(thin) () -> ()
+ %a13 = apply %f() : $@convention(thin) () -> ()
+ %a14 = apply %f() : $@convention(thin) () -> ()
+ %a15 = apply %f() : $@convention(thin) () -> ()
+ %a16 = apply %f() : $@convention(thin) () -> ()
+ %a17 = apply %f() : $@convention(thin) () -> ()
+ %a18 = apply %f() : $@convention(thin) () -> ()
+ %a19 = apply %f() : $@convention(thin) () -> ()
+ %a20 = apply %f() : $@convention(thin) () -> ()
+ %a21 = apply %f() : $@convention(thin) () -> ()
+ %a22 = apply %f() : $@convention(thin) () -> ()
+ %t = tuple ()
+ return %t : $()
+}
+
+sil [transparent] [_semantics "fastpath"] @fastPathHelper : $@convention(thin) (Bool) -> Bool
+
+// fastpath.closedTest0 () -> ()
+// From <rdar://problem/17611447> _fastPath kills optimizer
+// First test that the inliner is not inlining the slow call.
+// Then test that same calls is not inlined when transparent.
+// CHECK-LABEL: @testNoInlineSlow
+// CHECK-LABEL: bb0:
+// CHECK: function_ref @fastPathHelper
+// CHECK-LABEL: bb1:
+// CHECK: function_ref @slowHelper
+// CHECK-LABEL: bb2:
+sil @testNoInlineSlow : $@convention(thin) () -> () {
+bb0:
+ %f1 = function_ref @fastPathHelper : $@convention(thin) (Bool) -> Bool
+ %v9 = alloc_stack $Bool
+ %v12 = integer_literal $Builtin.Int1, 0
+ %v16 = struct $Bool (%v12 : $Builtin.Int1)
+ store %v16 to %v9 : $*Bool // id: %17
+ %v18 = apply %f1(%v16) : $@convention(thin) (Bool) -> Bool
+ %v19 = struct_extract %v18 : $Bool, #Bool._value
+ dealloc_stack %v9 : $*Bool // id: %20
+ cond_br %v19, bb2, bb1 // id: %21
+
+bb1:
+ %f2 = function_ref @slowHelper : $@convention(thin) () -> ()
+ %r2 = apply %f2() : $@convention(thin) () -> ()
+ br bb2
+
+bb2:
+ %t3 = tuple ()
+ return %t3 : $()
+}
+
+// CHECK-LABEL: @testInlineSlowTransparent
+// CHECK-LABEL: bb0:
+// CHECK: function_ref @fastPathHelper
+// CHECK-LABEL: bb1:
+// CHECK: function_ref @slowHelper
+// CHECK-LABEL: bb2:
+sil @testInlineSlowTransparent : $@convention(thin) () -> () {
+bb0:
+ %f1 = function_ref @fastPathHelper : $@convention(thin) (Bool) -> Bool
+ %v9 = alloc_stack $Bool
+ %v12 = integer_literal $Builtin.Int1, 0
+ %v16 = struct $Bool (%v12 : $Builtin.Int1)
+ store %v16 to %v9 : $*Bool // id: %17
+ %v18 = apply %f1(%v16) : $@convention(thin) (Bool) -> Bool
+ %v19 = struct_extract %v18 : $Bool, #Bool._value
+ dealloc_stack %v9 : $*Bool // id: %20
+ cond_br %v19, bb2, bb1 // id: %21
+
+bb1:
+ %f2 = function_ref @slowHelper : $@convention(thin) () -> ()
+ %r2 = apply %f2() : $@convention(thin) () -> ()
+ br bb2
+
+bb2:
+ %t3 = tuple ()
+ return %t3 : $()
+}
+
+// Attempt to ensure that calling the devirtualizer on a try_apply
+// from the performance inliner doesn't result in an assert/crash.
+
+class C {
+ @inline(never) func callThrowing<T>(other: T, closure: @escaping () throws -> T) -> T
+}
+
+// CHECK-LABEL: sil [noinline] @callThrowing
+sil [noinline] @callThrowing : $@convention(method) <T> (@in_guaranteed T, @guaranteed @callee_owned () -> (@out T, @error Error), @guaranteed C) -> @out T {
+bb0(%0 : $*T, %1 : $*T, %2 : $@callee_owned () -> (@out T, @error Error), %3 : $C):
+ strong_retain %2 : $@callee_owned () -> (@out T, @error Error)
+ try_apply %2(%0) : $@callee_owned () -> (@out T, @error Error), normal bb1, error bb4
+
+bb1(%6 : $()):
+ br bb2
+
+bb2:
+ strong_release %2 : $@callee_owned () -> (@out T, @error Error)
+ destroy_addr %1 : $*T
+ %10 = tuple ()
+ return %10 : $()
+
+bb3:
+ copy_addr %1 to [initialization] %0 : $*T
+ strong_release %15 : $Error
+ br bb2
+
+bb4(%15 : $Error):
+ br bb3
+}
+
+
+// CHECK-LABEL: sil @callNonThrowing
+sil @callNonThrowing : $@convention(thin) (@owned C) -> Int32 {
+bb0(%0 : $C):
+ %1 = integer_literal $Builtin.Int32, 1
+ %2 = struct $Int32 (%1 : $Builtin.Int32)
+ %3 = alloc_stack $Int32
+ store %2 to %3 : $*Int32
+ %5 = function_ref @theClosure : $@convention(thin) () -> (Int32, @error Error)
+ %6 = thin_to_thick_function %5 : $@convention(thin) () -> (Int32, @error Error) to $@callee_owned () -> (Int32, @error Error)
+ %7 = function_ref @reabstractionThunk : $@convention(thin) (@owned @callee_owned () -> (Int32, @error Error)) -> (@out Int32, @error Error)
+ %8 = partial_apply %7(%6) : $@convention(thin) (@owned @callee_owned () -> (Int32, @error Error)) -> (@out Int32, @error Error)
+ %9 = alloc_stack $Int32
+ %10 = function_ref @callThrowing : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @guaranteed @callee_owned () -> (@out τ_0_0, @error Error), @guaranteed C) -> @out τ_0_0
+ %11 = apply %10<Int32>(%9, %3, %8, %0) : $@convention(method) <τ_0_0> (@in_guaranteed τ_0_0, @guaranteed @callee_owned () -> (@out τ_0_0, @error Error), @guaranteed C) -> @out τ_0_0
+ %12 = load %9 : $*Int32
+ dealloc_stack %9 : $*Int32
+ dealloc_stack %3 : $*Int32
+ strong_release %0 : $C
+// CHECK: return
+ return %12 : $Int32
+}
+
+
+// CHECK-LABEL: sil @theClosure
+sil @theClosure : $@convention(thin) () -> (Int32, @error Error) {
+bb0:
+ %0 = integer_literal $Builtin.Int32, 0
+ %1 = struct $Int32 (%0 : $Builtin.Int32)
+ return %1 : $Int32
+}
+
+// CHECK-LABEL: sil [transparent] [reabstraction_thunk] @reabstractionThunk
+sil [transparent] [reabstraction_thunk] @reabstractionThunk : $@convention(thin) (@owned @callee_owned () -> (Int32, @error Error)) -> (@out Int32, @error Error) {
+bb0(%0 : $*Int32, %1 : $@callee_owned () -> (Int32, @error Error)):
+ try_apply %1() : $@callee_owned () -> (Int32, @error Error), normal bb1, error bb2
+
+bb1(%3 : $Int32):
+ store %3 to %0 : $*Int32
+ %5 = tuple ()
+ return %5 : $()
+
+bb2(%7 : $Error):
+ %8 = builtin "willThrow"(%7 : $Error) : $()
+ throw %7 : $Error
+}
+
+sil_vtable C {
+ #C.callThrowing!1: @callThrowing
+}
diff --git a/test/SILOptimizer/plus_zero_spec_archetype_method.swift b/test/SILOptimizer/plus_zero_spec_archetype_method.swift
new file mode 100644
index 0000000..f76cf39
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_spec_archetype_method.swift
@@ -0,0 +1,45 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=FunctionSignatureOpts -disable-arc-opts -emit-sil -primary-file %s | %FileCheck %s
+
+// We can't deserialize apply_inst with subst lists. When radar://14443304
+// is fixed then we should convert this test to a SIL test.
+
+protocol pingable {
+ func ping()
+}
+
+class ABC : pingable {
+ @inline(never)
+ func ping() {}
+}
+
+@inline(never)
+func generic_call<T : pingable>(x x: T) {
+ x.ping()
+}
+
+struct A<B> : pingable {
+ @inline(never)
+ func ping() {}
+}
+
+@inline(never)
+func useFoo<T>(x x: T) {
+ let a = A<T>()
+ generic_call(x: a)
+}
+
+//CHECK-LABEL: sil @$S21spec_archetype_method21interesting_code_hereyyF
+//CHECK: function_ref @$S21spec_archetype_method12generic_call{{[_0-9a-zA-Z]*}}FAA3ABCC_Tg5
+//CHECK-NEXT: apply
+//CHECK: function_ref @$S21spec_archetype_method6useFoo{{[_0-9a-zA-Z]*}}FAA3ABCC_Tg5 : $@convention(thin) (@in_guaranteed ABC) -> ()
+//CHECK-NEXT: apply
+//CHECK: return
+public
+func interesting_code_here() {
+ let x = ABC()
+ // Make sure that we can specialize the function generic_call that has a
+ // generic call to x.ping().
+ generic_call(x: x)
+ useFoo(x: x)
+}
diff --git a/test/SILOptimizer/plus_zero_specialize_anyobject.swift b/test/SILOptimizer/plus_zero_specialize_anyobject.swift
new file mode 100644
index 0000000..5d5326c
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_anyobject.swift
@@ -0,0 +1,23 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -sil-inline-threshold 0 -emit-sil -primary-file %s | %FileCheck %s
+
+// rdar://problem/20338028
+protocol PA: class { }
+protocol PB { associatedtype B: PA }
+
+class CA: PA { }
+class CB: PB { typealias B = CA }
+
+struct S<A: PB> {
+ @_transparent
+ func crash() -> Bool {
+ let a: A.B? = nil
+ return a === a
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S20specialize_anyobject6callit{{[_0-9a-zA-Z]*}}F
+func callit(s: S<CB>) {
+ // CHECK: function_ref @$Ss3eeeoiySbyXlSg_ABtF : $@convention(thin) (@guaranteed Optional<AnyObject>, @guaranteed Optional<AnyObject>) -> Bool
+ s.crash()
+}
diff --git a/test/SILOptimizer/plus_zero_specialize_cg_update_crash.sil b/test/SILOptimizer/plus_zero_specialize_cg_update_crash.sil
new file mode 100644
index 0000000..01b0190
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_cg_update_crash.sil
@@ -0,0 +1,33 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -module-name TestMod %S/Inputs/TestMod.sil -emit-module-path %t/TestMod.swiftmodule
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -inline -I %t %s | %FileCheck %s
+
+// Test if the CG is updated correctly during specialization and
+// there is no crash because of a missing CG node for a deserialized function.
+
+sil_stage canonical
+
+import Builtin
+import TestMod
+
+struct MyStruct {
+}
+
+sil @_TF7TestMod10genlibfuncurFq_q_ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+sil @_TF7TestMod11genlibfunc2urFq_q_ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+
+// CHECK-LABEL: sil @testit
+sil @testit : $@convention(thin) () -> MyStruct {
+bb0:
+ %x0 = function_ref @_TF7TestMod10genlibfuncurFq_q_ : $@convention(thin) <X> (@in_guaranteed X) -> @out X
+ %13 = function_ref @_TF7TestMod11genlibfunc2urFq_q_ : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ %14 = alloc_stack $MyStruct
+ %16 = alloc_stack $MyStruct
+ %17 = apply %13<MyStruct>(%16, %14) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> @out τ_0_0
+ %18 = struct $MyStruct ()
+ dealloc_stack %16 : $*MyStruct
+ dealloc_stack %14 : $*MyStruct
+ return %18 : $MyStruct
+}
+
diff --git a/test/SILOptimizer/plus_zero_specialize_checked_cast_branch.swift b/test/SILOptimizer/plus_zero_specialize_checked_cast_branch.swift
new file mode 100644
index 0000000..4f6073d
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_checked_cast_branch.swift
@@ -0,0 +1,338 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -O -sil-inline-threshold 0 %s -o - | %FileCheck %s
+
+class C {}
+class D : C {}
+class E {}
+
+struct NotUInt8 { var value: UInt8 }
+struct NotUInt64 { var value: UInt64 }
+
+var b = NotUInt8(value: 0)
+var c = C()
+var d = D()
+var e = E()
+var f = NotUInt64(value: 0)
+var o : AnyObject = c
+
+////////////////////////
+// Arch to Arch Casts //
+////////////////////////
+public func ArchetypeToArchetypeCast<T1, T2>(t1 : T1, t2 : T2) -> T2 {
+ if let x = t1 as? T2 {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+// x -> y where x and y are unrelated.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA1ECTg5 : $@convention(thin) (@in_guaranteed C, @in_guaranteed E) -> @owned E {
+// CHECK: bb0
+// CHECK-NOT: bb1
+// CHECK: %2 = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail %2 : $Builtin.Int1
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch28ArchetypeToConcreteCastUInt81tAA03NotI0Vx_tlFAE_Tg5 : $@convention(thin) (NotUInt8) -> NotUInt8 {
+// CHECK: bb0
+// CHECK: return %0 : $NotUInt8
+
+// CHECK-LABEL: sil shared [thunk] [always_inline] @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAE_Tg5 : $@convention(thin) (@in_guaranteed C) -> @owned C {
+// CHECK: bb0
+// CHECK: [[REF:%.*]] = function_ref @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAE_Tg5Tf4n_g : $@convention(thin) (@in_guaranteed C) -> C
+// CHECK: [[RET:%.*]] = apply [[REF]](%0) : $@convention(thin) (@in_guaranteed C) -> C
+// CHECK: strong_retain [[RET]]
+// CHECK: return [[RET]] : $C
+
+// CHECK-LABEL: sil shared [thunk] [always_inline] @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA1DC_Tg5 : $@convention(thin) (@in_guaranteed D) -> @owned C {
+// CHECK: bb0
+// CHECK: [[REF:%.*]] = function_ref @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA1DC_Tg5Tf4n_g : $@convention(thin) (@in_guaranteed D) -> C
+// CHECK: [[RET:%.*]] = apply [[REF]](%0) : $@convention(thin) (@in_guaranteed D) -> C
+// CHECK: strong_retain [[RET]]
+// CHECK: return [[RET]] : $C
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastE1tAA1ECx_tlFAA1CC_Tg5 : $@convention(thin) (@in_guaranteed C) -> @owned E {
+// CHECK: bb0
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// x -> x where x is not a class.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA8NotUInt8V_AFTg5Tf4nd_n : $@convention(thin) (NotUInt8) -> NotUInt8 {
+// CHECK: bb0
+// CHECK-NOT: bb1
+// CHECK: return %0 : $NotUInt8
+
+// x -> y where x,y are not classes and x is a different type from y.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA8NotUInt8V_AA0J6UInt64VTg5Tf4dd_n : $@convention(thin) () -> NotUInt64 {
+// CHECK: bb0
+// CHECK-NOT: bb1
+// CHECK: %0 = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail %0 : $Builtin.Int1
+// CHECK: unreachable
+
+// x -> y where x is not a class but y is.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA8NotUInt8V_AA1CCTg5Tf4dn_n : $@convention(thin) (@in_guaranteed C) -> @owned C {
+// CHECK: bb0
+// CHECK-NOT: bb1
+// CHECK: %1 = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail %1 : $Builtin.Int1
+// CHECK: unreachable
+
+// y -> x where x is a class but y is not.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1CC_AA8NotUInt8VTg5Tf4nd_n : $@convention(thin) (@in_guaranteed C) -> NotUInt8 {
+// CHECK: bb0
+// CHECK-NOT: bb1
+// CHECK: %1 = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail %1 : $Builtin.Int1
+// CHECK: unreachable
+
+// y -> x where x is a super class of y.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch011ArchetypeToE4Cast2t12t2q_x_q_tr0_lFAA1DC_AA1CCTg5Tf4nn_g : $@convention(thin) (@in_guaranteed D, @in_guaranteed C) -> C {
+// CHECK: [[T0:%.*]] = load %0 : $*D
+// CHECK: [[T1:%.*]] = upcast [[T0]] : $D to $C
+// CHECK: return [[T1]] : $C
+
+
+_ = ArchetypeToArchetypeCast(t1: c, t2: d)
+_ = ArchetypeToArchetypeCast(t1: c, t2: c)
+_ = ArchetypeToArchetypeCast(t1: b, t2: b)
+_ = ArchetypeToArchetypeCast(t1: b, t2: f)
+_ = ArchetypeToArchetypeCast(t1: b, t2: c)
+_ = ArchetypeToArchetypeCast(t1: c, t2: b)
+_ = ArchetypeToArchetypeCast(t1: d, t2: c)
+_ = ArchetypeToArchetypeCast(t1: c, t2: e)
+
+///////////////////////////
+// Archetype To Concrete //
+///////////////////////////
+
+func ArchetypeToConcreteCastUInt8<T>(t : T) -> NotUInt8 {
+ if let x = t as? NotUInt8 {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+func ArchetypeToConcreteCastC<T>(t : T) -> C {
+ if let x = t as? C {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+func ArchetypeToConcreteCastD<T>(t : T) -> D {
+ if let x = t as? D {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+func ArchetypeToConcreteCastE<T>(t : T) -> E {
+ if let x = t as? E {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+_ = ArchetypeToConcreteCastUInt8(t: b)
+
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch28ArchetypeToConcreteCastUInt81tAA03NotI0Vx_tlFAA0J6UInt64V_Tg5Tf4d_n : $@convention(thin) () -> NotUInt8 {
+// CHECK: bb0
+// CHECK-NOT: checked_cast_br
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA8NotUInt8V_Tg5Tf4d_n : $@convention(thin) () -> @owned C {
+// CHECK: bb0
+// CHECK-NOT: checked_cast_br
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastC1tAA1CCx_tlFAA1DC_Tg5Tf4n_g : $@convention(thin) (@in_guaranteed D) -> C {
+// CHECK: bb0
+// CHECK: [[LOAD:%.*]] = load %0 : $*D
+// CHECK: [[CAST:%.*]] = upcast [[LOAD]] : $D to $C
+// CHECK: return [[CAST]]
+
+// x -> y where x is a super class of y.
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ArchetypeToConcreteCastD1tAA1DCx_tlFAA1CC_Tg5Tf4n_g : $@convention(thin) (@in_guaranteed C) -> D {
+// CHECK: [[LOAD:%.*]] = load %0 : $*C
+// CHECK: checked_cast_br [[LOAD]] : $C to $D,
+// CHECK: bb1([[T0:%.*]] : $D):
+// CHECK: return [[T0]] : $D
+// CHECK: bb2:
+// CHECK: integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail
+// CHECK: unreachable
+
+_ = ArchetypeToConcreteCastUInt8(t: c)
+_ = ArchetypeToConcreteCastUInt8(t: f)
+_ = ArchetypeToConcreteCastC(t: c)
+_ = ArchetypeToConcreteCastC(t: b)
+_ = ArchetypeToConcreteCastC(t: d)
+_ = ArchetypeToConcreteCastC(t: e)
+_ = ArchetypeToConcreteCastD(t: c)
+_ = ArchetypeToConcreteCastE(t: c)
+
+///////////////////////////
+// Concrete To Archetype //
+///////////////////////////
+
+func ConcreteToArchetypeCastUInt8<T>(t: NotUInt8, t2: T) -> T {
+ if let x = t as? T {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+func ConcreteToArchetypeCastC<T>(t: C, t2: T) -> T {
+ if let x = t as? T {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+func ConcreteToArchetypeCastD<T>(t: D, t2: T) -> T {
+ if let x = t as? T {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAF_Tg5Tf4nd_n : $@convention(thin) (NotUInt8) -> NotUInt8
+// CHECK: bb0
+// CHECK: return %0
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAA1CC_Tg5Tf4dn_n : $@convention(thin) (@in_guaranteed C) -> @owned C {
+// CHECK: bb0
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch28ConcreteToArchetypeCastUInt81t2t2xAA03NotI0V_xtlFAA0K6UInt64V_Tg5Tf4dd_n : $@convention(thin) () -> NotUInt64
+// CHECK: bb0
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAF_Tg5Tf4nn_g : $@convention(thin) (@guaranteed C, @in_guaranteed C) -> C {
+// CHECK: bb0
+// CHECK: return %0
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAA8NotUInt8V_Tg5Tf4dd_n : $@convention(thin) () -> NotUInt8
+// CHECK: bb0
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAA1DC_Tg5Tf4nn_g : $@convention(thin) (@guaranteed C, @in_guaranteed D) -> D {
+// CHECK: bb0
+// CHECK: checked_cast_br %0 : $C to $D
+// CHECK: bb1
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ConcreteToArchetypeCastC1t2t2xAA1CC_xtlFAA1EC_Tg5Tf4dn_n : $@convention(thin) (@in_guaranteed E) -> @owned E {
+// CHECK: bb0
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch24ConcreteToArchetypeCastD1t2t2xAA1DC_xtlFAA1CC_Tg5Tf4nn_g : $@convention(thin) (@guaranteed D, @in_guaranteed C) -> C {
+// CHECK: bb0
+// CHECK: [[T0:%.*]] = upcast %0 : $D to $C
+// CHECK: return [[T0]]
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch21SuperToArchetypeCastC1c1txAA1CC_xtlFAF_Tg5Tf4nn_g : $@convention(thin) (@guaranteed C, @in_guaranteed C) -> C {
+// CHECK: bb0
+// CHECK-NOT: bb1
+// CHECK: return %0 : $C
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch21SuperToArchetypeCastC1c1txAA1CC_xtlFAA1DC_Tg5Tf4nn_g : $@convention(thin) (@guaranteed C, @in_guaranteed D) -> D {
+// CHECK: bb0
+// CHECK: checked_cast_br %0 : $C to $D, bb1, bb2
+// CHECK: bb1(
+// CHECK: return
+// CHECK: bb2
+// CHECK: integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail
+// CHECK: unreachable
+
+_ = ConcreteToArchetypeCastUInt8(t: b, t2: b)
+_ = ConcreteToArchetypeCastUInt8(t: b, t2: c)
+_ = ConcreteToArchetypeCastUInt8(t: b, t2: f)
+_ = ConcreteToArchetypeCastC(t: c, t2: c)
+_ = ConcreteToArchetypeCastC(t: c, t2: b)
+_ = ConcreteToArchetypeCastC(t: c, t2: d)
+_ = ConcreteToArchetypeCastC(t: c, t2: e)
+_ = ConcreteToArchetypeCastD(t: d, t2: c)
+
+////////////////////////
+// Super To Archetype //
+////////////////////////
+
+func SuperToArchetypeCastC<T>(c : C, t : T) -> T {
+ if let x = c as? T {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+func SuperToArchetypeCastD<T>(d : D, t : T) -> T {
+ if let x = d as? T {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch21SuperToArchetypeCastC1c1txAA1CC_xtlFAA8NotUInt8V_Tg5Tf4dd_n : $@convention(thin) () -> NotUInt8 {
+// CHECK: bb0
+// CHECK: [[TRUE:%.*]] = integer_literal $Builtin.Int1, -1
+// CHECK: cond_fail [[TRUE]]
+// CHECK: unreachable
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch21SuperToArchetypeCastD1d1txAA1DC_xtlFAA1CC_Tg5Tf4nn_g : $@convention(thin) (@guaranteed D, @in_guaranteed C) -> C {
+// CHECK: bb0
+// CHECK: [[T0:%.*]] = upcast %0 : $D to $C
+// CHECK: return [[T0]]
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch21SuperToArchetypeCastD1d1txAA1DC_xtlFAF_Tg5Tf4nn_g : $@convention(thin) (@guaranteed D, @in_guaranteed D) -> D {
+// CHECK: bb0
+// CHECK: return %0 : $D
+
+_ = SuperToArchetypeCastC(c: c, t: c)
+_ = SuperToArchetypeCastC(c: c, t: d)
+_ = SuperToArchetypeCastC(c: c, t: b)
+_ = SuperToArchetypeCastD(d: d, t: c)
+_ = SuperToArchetypeCastD(d: d, t: d)
+
+//////////////////////////////
+// Existential To Archetype //
+//////////////////////////////
+
+func ExistentialToArchetypeCast<T>(o : AnyObject, t : T) -> T {
+ if let x = o as? T {
+ return x
+ }
+ _preconditionFailure("??? Profit?")
+}
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFAA1CC_Tg5Tf4nn_g : $@convention(thin) (@guaranteed AnyObject, @in_guaranteed C) -> C {
+// CHECK: bb0
+// CHECK: checked_cast_br %0 : $AnyObject to $C
+// CHECK: bb1
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFAA8NotUInt8V_Tg5Tf4nd_n : $@convention(thin) (@guaranteed AnyObject) -> NotUInt8 {
+// CHECK: bb0
+// CHECK: checked_cast_addr_br take_always AnyObject in {{%.*}} : $*AnyObject to NotUInt8 in {{%.*}} : $*NotUInt8,
+// CHECK: bb1
+
+// CHECK-LABEL: sil shared @$S30specialize_checked_cast_branch26ExistentialToArchetypeCast1o1txyXl_xtlFyXl_Tg5Tf4nn_g : $@convention(thin) (@guaranteed AnyObject, @in_guaranteed AnyObject) -> AnyObject
+// CHECK: bb0
+// CHECK-NOT: checked_cast_br %
+// CHECK: return %0 : $AnyObject
+// CHECK-NOT: checked_cast_br %
+
+_ = ExistentialToArchetypeCast(o: o, t: c)
+_ = ExistentialToArchetypeCast(o: o, t: b)
+_ = ExistentialToArchetypeCast(o: o, t: o)
diff --git a/test/SILOptimizer/plus_zero_specialize_dynamic_self.swift b/test/SILOptimizer/plus_zero_specialize_dynamic_self.swift
new file mode 100644
index 0000000..4348be6
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_dynamic_self.swift
@@ -0,0 +1,30 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sil -O -primary-file %s | %FileCheck %s
+
+protocol P {}
+
+extension P {
+ @_optimize(none) func method1() {}
+
+ @inline(__always) func method2() { method1() }
+}
+
+class C<T> : P {
+ // CHECK-LABEL: sil shared [always_inline] @$S23specialize_dynamic_self1CC11returnsSelfACyxGXDyFSi_Tg5 : $@convention(method) (@guaranteed C<Int>) -> @owned C<Int>
+ // CHECK: [[RESULT:%.*]] = alloc_stack $C<Int>
+ // CHECK: [[FN:%.*]] = function_ref @$S23specialize_dynamic_self1PPAAE7method1yyF : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
+ // CHECK: apply [[FN]]<@dynamic_self C<Int>>([[RESULT]]) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> ()
+ // CHECK: return %0 : $C<Int>
+ @inline(__always)
+ final func returnsSelf() -> Self {
+ method2()
+ return self
+ }
+}
+
+// CHECK-LABEL: sil hidden @$S23specialize_dynamic_self8usesCInt1cyAA1CCySiG_tF : $@convention(thin) (@guaranteed C<Int>) -> () {
+// CHECK: function_ref @$S23specialize_dynamic_self1CC11returnsSelfACyxGXDyFSi_Tg5 : $@convention(method) (@guaranteed C<Int>) -> @owned C<Int>
+// CHECK: return
+func usesCInt(c: C<Int>) {
+ _ = c.returnsSelf()
+}
diff --git a/test/SILOptimizer/plus_zero_specialize_inherited_multifile.swift b/test/SILOptimizer/plus_zero_specialize_inherited_multifile.swift
new file mode 100644
index 0000000..387094d
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_inherited_multifile.swift
@@ -0,0 +1,19 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -primary-file %s %S/Inputs/specialize_inherited_multifile.swift -O -emit-sil -sil-verify-all | %FileCheck %s
+
+@_optimize(none) func takesBase<T : Base>(t: T) {}
+
+@inline(never) func takesHasAssocType<T : HasAssocType>(t: T) {
+ takesBase(t: t.value)
+}
+
+// Make sure the ConcreteDerived : Base conformance is available here.
+
+// CHECK-LABEL: sil shared [noinline] @$S30specialize_inherited_multifile17takesHasAssocType1tyx_tAA0efG0RzlFAA08ConcreteefG0C_Tg5 : $@convention(thin) (@in_guaranteed ConcreteHasAssocType) -> ()
+// CHECK: [[FN:%.*]] = function_ref @$S30specialize_inherited_multifile9takesBase1tyx_tAA0E0RzlF
+// CHECK: apply [[FN]]<ConcreteDerived>({{%.*}})
+// CHECK: return
+
+public func takesConcreteHasAssocType(c: ConcreteHasAssocType) {
+ takesHasAssocType(t: c)
+}
diff --git a/test/SILOptimizer/plus_zero_specialize_partial_apply.swift b/test/SILOptimizer/plus_zero_specialize_partial_apply.swift
new file mode 100644
index 0000000..9297335
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_partial_apply.swift
@@ -0,0 +1,245 @@
+// REQUIRES: plus_zero_runtime
+// First check the SIL.
+// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=FunctionSignatureOpts -module-name=test -emit-sil -primary-file %s | %FileCheck %s
+
+// Also do an end-to-end test to check all components, including IRGen.
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -O -Xllvm -sil-disable-pass=FunctionSignatureOpts -module-name=test %s -o %t/a.out
+// RUN: %target-run %t/a.out | %FileCheck %s -check-prefix=CHECK-OUTPUT
+// REQUIRES: executable_test
+
+struct MyError : Error {
+ let _code : Int
+ init(_ xx: Int) {
+ _code = xx
+ }
+}
+
+// We need a reabstraction thunk to convert from direct args/result to indirect
+// args/result, which is expected in the returned closure.
+
+// CHECK-LABEL: sil shared [noinline] @$S4test16generic_get_funcyxxcx_SbtlFSi_Tg5 : $@convention(thin) (Int, Bool) -> @owned @callee_guaranteed (@in_guaranteed Int) -> @out Int {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test16generic_get_funcyxxcx_SbtlF0B0L_yxxlFSi_TG5 : $@convention(thin) (@in_guaranteed Int, Bool, @guaranteed <τ_0_0> { var τ_0_0 } <Int>) -> @out Int
+// CHECK: [[PA:%[0-9]+]] = partial_apply [callee_guaranteed] [[F]](%1, %{{[0-9]+}}) : $@convention(thin) (@in_guaranteed Int, Bool, @guaranteed <τ_0_0> { var τ_0_0 } <Int>) -> @out Int
+// CHECK: return [[PA]] : $@callee_guaranteed (@in_guaranteed Int) -> @out Int
+@inline(never)
+func generic_get_func<T>(_ t1: T, _ b: Bool) -> (T) -> T {
+
+ @inline(never)
+ func generic(_ t2: T) -> T {
+ return b ? t1 : t2
+ }
+
+ return generic
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S4test7testit1yS2icSbF : $@convention(thin) (Bool) -> @owned @callee_guaranteed (Int) -> Int {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test16generic_get_funcyxxcx_SbtlFSi_Tg5 : $@convention(thin) (Int, Bool) -> @owned @callee_guaranteed (@in_guaranteed Int) -> @out Int
+// CHECK: [[CL:%[0-9]+]] = apply [[F]](%{{[0-9]+}}, %0) : $@convention(thin) (Int, Bool) -> @owned @callee_guaranteed (@in_guaranteed Int) -> @out Int
+// CHECK: [[TH:%[0-9]+]] = function_ref @$SS2iIegnr_S2iIegyd_TR : $@convention(thin) (Int, @guaranteed @callee_guaranteed (@in_guaranteed Int) -> @out Int) -> Int
+// CHECK: [[RET:%[0-9]+]] = partial_apply [callee_guaranteed] [[TH]]([[CL]])
+// CHECK: return [[RET]] : $@callee_guaranteed (Int) -> Int
+@inline(never)
+func testit1(_ b: Bool) -> (Int) -> Int {
+ return generic_get_func(27, b)
+}
+
+
+@inline(never)
+func generic2<T>(_ t1: T, t2: T, b: Bool) -> T {
+ return b ? t1 : t2
+}
+
+// No reabstraction thunk is needed because the returned closure expects direct
+// args/result anyway.
+
+// CHECK-LABEL: sil hidden [noinline] @$S4test17concrete_get_funcS2i_SiSbtcyF : $@convention(thin) () -> @owned @callee_guaranteed (Int, Int, Bool) -> Int {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test8generic2_2t21bxx_xSbtlFSi_Tg5 : $@convention(thin) (Int, Int, Bool) -> Int
+// CHECK: [[RET:%[0-9]+]] = thin_to_thick_function [[F]] : $@convention(thin) (Int, Int, Bool) -> Int to $@callee_guaranteed (Int, Int, Bool) -> Int
+// CHECK: return [[RET]] : $@callee_guaranteed (Int, Int, Bool) -> Int
+@inline(never)
+func concrete_get_func() -> (Int, Int, Bool) -> Int {
+ return generic2
+}
+
+@inline(never)
+func testit2() -> (Int, Int, Bool) -> Int {
+ return concrete_get_func()
+}
+
+
+@inline(never)
+func generic3<T>(_ t1: T, _ t2: T, _ b: Bool) -> T {
+ return b ? t1 : t2
+}
+
+// No reabstraction thunk is needed because we directly apply the returned closure.
+
+// CHECK-LABEL: sil hidden [noinline] @$S4test7testit3ySiSbF : $@convention(thin) (Bool) -> Int {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test8generic3yxx_xSbtlFSi_Tg5 : $@convention(thin) (Int, Int, Bool) -> Int
+// CHECK: [[RET:%[0-9]+]] = apply [[F]]({{.*}}) : $@convention(thin) (Int, Int, Bool) -> Int
+// CHECK: return [[RET]] : $Int
+@inline(never)
+func testit3(_ b: Bool) -> Int {
+ return generic3(270, 28, b)
+}
+
+// The same three test cases again, but with throwing functions.
+
+// We need a reabstraction thunk to convert from direct args/result to indirect
+// args/result, which is expected in the returned closure.
+
+// CHECK-LABEL: sil shared [noinline] @$S4test25generic_get_func_throwingyxxKcSblFSi_Tg5 : $@convention(thin) (Bool) -> @owned @callee_guaranteed (@in_guaranteed Int) -> (@out Int, @error Error) {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_TG5 : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error Error)
+// CHECK: [[PA:%[0-9]+]] = partial_apply [callee_guaranteed] [[F]](%0) : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error Error)
+// CHECK: return [[PA]] : $@callee_guaranteed (@in_guaranteed Int) -> (@out Int, @error Error)
+@inline(never)
+func generic_get_func_throwing<T>(_ b: Bool) -> (T) throws -> T {
+
+ @inline(never)
+ func generic(_ t2: T) throws -> T {
+ if b {
+ throw MyError(123)
+ }
+ return t2
+ }
+
+ return generic
+}
+
+// CHECK-LABEL: sil hidden [noinline] @$S4test16testit1_throwingyS2iKcSbF : $@convention(thin) (Bool) -> @owned @callee_guaranteed (Int) -> (Int, @error Error) {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test25generic_get_func_throwingyxxKcSblFSi_Tg5 : $@convention(thin) (Bool) -> @owned @callee_guaranteed (@in_guaranteed Int) -> (@out Int, @error Error)
+// CHECK: [[CL:%[0-9]+]] = apply [[F]](%0) : $@convention(thin) (Bool) -> @owned @callee_guaranteed (@in_guaranteed Int) -> (@out Int, @error Error)
+// CHECK: [[TH:%[0-9]+]] = function_ref @$SS2is5Error_pIegnrzo_S2isAA_pIegydzo_TR : $@convention(thin) (Int, @guaranteed @callee_guaranteed (@in_guaranteed Int) -> (@out Int, @error Error)) -> (Int, @error Error)
+// CHECK: [[RET:%[0-9]+]] = partial_apply [callee_guaranteed] [[TH]]([[CL]])
+// CHECK: return [[RET]] : $@callee_guaranteed (Int) -> (Int, @error Error)
+@inline(never)
+func testit1_throwing(_ b: Bool) -> (Int) throws -> Int {
+ return generic_get_func_throwing(b)
+}
+
+
+@inline(never)
+func generic2_throwing<T>(_ t1: T, b: Bool) throws -> T {
+ if b {
+ throw MyError(124)
+ }
+ return t1
+}
+
+// No reabstraction thunk is needed because the returned closure expects direct
+// args/result anyway.
+
+// CHECK-LABEL: sil hidden [noinline] @$S4test26concrete_get_func_throwingS2i_SbtKcyF : $@convention(thin) () -> @owned @callee_guaranteed (Int, Bool) -> (Int, @error Error) {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test17generic2_throwing_1bxx_SbtKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error Error)
+// CHECK: [[RET:%[0-9]+]] = thin_to_thick_function [[F]] : $@convention(thin) (Int, Bool) -> (Int, @error Error) to $@callee_guaranteed (Int, Bool) -> (Int, @error Error)
+// CHECK: return [[RET]] : $@callee_guaranteed (Int, Bool) -> (Int, @error Error)
+@inline(never)
+func concrete_get_func_throwing() -> (Int, Bool) throws -> Int {
+ return generic2_throwing
+}
+
+@inline(never)
+func testit2_throwing() -> (Int, Bool) throws -> Int {
+ return concrete_get_func_throwing()
+}
+
+
+
+@inline(never)
+func generic3_throwing<T>(_ t1: T, _ b: Bool) throws -> T {
+ if b {
+ throw MyError(125)
+ }
+ return t1
+}
+
+// No reabstraction thunk is needed because we directly apply the returned closure.
+
+// CHECK-LABEL: sil hidden [noinline] @$S4test16testit3_throwingySiSbF : $@convention(thin) (Bool) -> Int {
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test17generic3_throwingyxx_SbtKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error Error)
+// CHECK: try_apply [[F]](%{{[0-9]+}}, %0) : $@convention(thin) (Int, Bool) -> (Int, @error Error), normal bb{{[0-9]+}}, error bb{{[0-9]+}}
+// CHECK: }
+@inline(never)
+func testit3_throwing(_ b: Bool) -> Int {
+ do {
+ return try generic3_throwing(271, b)
+ } catch {
+ return error._code
+ }
+}
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$S4test16generic_get_funcyxxcx_SbtlF0B0L_yxxlFSi_TG5 : $@convention(thin) (@in_guaranteed Int, Bool, @guaranteed <τ_0_0> { var τ_0_0 } <Int>) -> @out Int {
+// CHECK: bb0(%0 : $*Int, %1 : $*Int, %2 : $Bool, %3 : $<τ_0_0> { var τ_0_0 } <Int>):
+// CHECK: [[LD:%[0-9]+]] = load %1 : $*Int
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test16generic_get_funcyxxcx_SbtlF0B0L_yxxlFSi_Tg5 : $@convention(thin) (Int, Bool, @guaranteed <τ_0_0> { var τ_0_0 } <Int>) -> Int
+// CHECK: [[RET:%[0-9]+]] = apply [[F]]([[LD]], %2, %3)
+// CHECK: store [[RET]] to %0 : $*Int
+// CHECK: return %{{[0-9]*}} : $()
+
+// CHECK-LABEL: sil shared [transparent] [thunk] @$S4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_TG5 : $@convention(thin) (@in_guaranteed Int, Bool) -> (@out Int, @error Error) {
+// CHECK: bb0(%0 : $*Int, %1 : $*Int, %2 : $Bool):
+// CHECK: [[LD:%[0-9]+]] = load %1 : $*Int
+// CHECK: [[F:%[0-9]+]] = function_ref @$S4test25generic_get_func_throwingyxxKcSblF0B0L_yxxKlFSi_Tg5 : $@convention(thin) (Int, Bool) -> (Int, @error Error)
+// CHECK: try_apply [[F]]([[LD]], %2) : $@convention(thin) (Int, Bool) -> (Int, @error Error), normal bb1, error bb2
+// CHECK: bb1([[NORMAL:%[0-9]+]] : $Int):
+// CHECK: store [[NORMAL]] to %0 : $*Int
+// CHECK: return %{{[0-9]*}} : $()
+// CHECK: bb2([[ERROR:%[0-9]+]] : $Error):
+// CHECK: throw [[ERROR]] : $Error
+
+
+// The main program.
+// Check if the generated executable produces the correct output.
+
+// CHECK-OUTPUT: 18
+print(testit1(false)(18))
+// CHECK-OUTPUT: 27
+print(testit1(true)(18))
+
+// CHECK-OUTPUT: 4
+print(testit2()(3, 4, false))
+// CHECK-OUTPUT: 3
+print(testit2()(3, 4, true))
+
+// CHECK-OUTPUT: 28
+print(testit3(false))
+// CHECK-OUTPUT: 270
+print(testit3(true))
+
+var x: Int
+do {
+ x = try testit1_throwing(false)(19)
+} catch {
+ x = error._code
+}
+// CHECK-OUTPUT: 19
+print(x)
+do {
+ x = try testit1_throwing(true)(19)
+} catch {
+ x = error._code
+}
+// CHECK-OUTPUT: 123
+print(x)
+
+do {
+ x = try testit2_throwing()(20, false)
+} catch {
+ x = error._code
+}
+// CHECK-OUTPUT: 20
+print(x)
+do {
+ x = try testit2_throwing()(20, true)
+} catch {
+ x = error._code
+}
+// CHECK-OUTPUT: 124
+print(x)
+
+// CHECK-OUTPUT: 271
+print(testit3_throwing(false))
+// CHECK-OUTPUT: 125
+print(testit3_throwing(true))
+
diff --git a/test/SILOptimizer/plus_zero_specialize_same_type_constraint.swift b/test/SILOptimizer/plus_zero_specialize_same_type_constraint.swift
new file mode 100644
index 0000000..f8db643
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_same_type_constraint.swift
@@ -0,0 +1,54 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -emit-sil -primary-file %s | %FileCheck %s
+
+protocol FirstChild {}
+
+protocol FirstParent {
+ associatedtype Child : FirstChild
+
+ var firstChild: Child { get }
+}
+
+protocol SecondChild {}
+
+protocol SecondParent {
+ associatedtype Child : SecondChild
+
+ var secondChild: Child { get }
+}
+
+@_optimize(none)
+func takesFirstChild<T : FirstChild>(t: T) {}
+
+@_optimize(none)
+func takesSecondChild<T : SecondChild>(t: T) {}
+
+@inline(never)
+func doStuff<First : FirstParent, Second : SecondParent>(f: First, s: Second)
+ where First.Child == Second.Child {
+ takesFirstChild(t: f.firstChild)
+ takesSecondChild(t: f.firstChild)
+
+ takesFirstChild(t: s.secondChild)
+ takesSecondChild(t: s.secondChild)
+}
+
+struct ConcreteChild : FirstChild, SecondChild {}
+
+struct ConcreteFirstParent<T> : FirstParent {
+ var firstChild: ConcreteChild { return ConcreteChild() }
+}
+
+struct ConcreteSecondParent<T> : SecondParent {
+ var secondChild: ConcreteChild { return ConcreteChild() }
+}
+
+doStuff(f: ConcreteFirstParent<ConcreteChild>(),
+ s: ConcreteSecondParent<ConcreteChild>())
+
+// CHECK-LABEL: sil shared [noinline] @$S31specialize_same_type_constraint7doStuff1f1syx_q_tAA11FirstParentRzAA06SecondH0R_5ChildQy_AGRtzr0_lFAA08ConcretegH0VyAA0kJ0VG_AA0kiH0VyAMGTg5Tf4dd_n : $@convention(thin) () -> () {
+// CHECK: [[FIRST:%.*]] = function_ref @$S31specialize_same_type_constraint15takesFirstChild1tyx_tAA0fG0RzlF
+// CHECK: apply [[FIRST]]<ConcreteChild>({{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : FirstChild> (@in_guaranteed τ_0_0) -> ()
+// CHECK: [[SECOND:%.*]] = function_ref @$S31specialize_same_type_constraint16takesSecondChild1tyx_tAA0fG0RzlF
+// CHECK: apply [[SECOND]]<ConcreteChild>({{.*}}) : $@convention(thin) <τ_0_0 where τ_0_0 : SecondChild> (@in_guaranteed τ_0_0) -> ()
+// CHECK: return
diff --git a/test/SILOptimizer/plus_zero_specialize_self.swift b/test/SILOptimizer/plus_zero_specialize_self.swift
new file mode 100644
index 0000000..b181e3e
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_self.swift
@@ -0,0 +1,20 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -O -sil-inline-threshold 0 -emit-sil -primary-file %s | %FileCheck %s
+
+// CHECK-NOT: generic specialization <Swift.AnyObject, Self> of specialize_self.cast <A, B>(A) -> Swift.Optional<B>
+
+// CHECK-LABEL: specialize_self.cast<A, B>(A) -> Swift.Optional<B>
+// CHECK-NEXT: sil hidden @$S15specialize_self4cast{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T, R> (@in_guaranteed T) -> @out Optional<R>
+func cast<T,R>(_ x: T) -> R? {
+ return x as? R
+}
+
+// CHECK-LABEL: static specialize_self.Base.returnIfSelf(Swift.AnyObject) -> Swift.Optional<Self>
+// CHECK-NEXT: sil hidden @$S15specialize_self4BaseC12returnIfSelf{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (@guaranteed AnyObject, @thick Base.Type) -> @owned Optional<Base>
+// CHECK: [[CAST:%[0-9]+]] = function_ref @$S15specialize_self4cast{{[_0-9a-zA-Z]*}}F
+// CHECK: apply [[CAST]]<AnyObject, @dynamic_self Base>
+class Base {
+ class func returnIfSelf(_ x: AnyObject) -> Self? {
+ return cast(x)
+ }
+}
diff --git a/test/SILOptimizer/plus_zero_specialize_self_conforming.swift b/test/SILOptimizer/plus_zero_specialize_self_conforming.swift
new file mode 100644
index 0000000..1c01bc2
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_self_conforming.swift
@@ -0,0 +1,25 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -O -primary-file %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+@objc protocol P {}
+
+@_optimize(none)
+func takesP<T : P>(_: T) {}
+
+@inline(__always)
+func callsTakesP<T : P>(_ t: T) {
+ takesP(t)
+}
+
+// CHECK-LABEL: sil hidden @$S26specialize_self_conforming16callsTakesPWithPyyAA1P_pF : $@convention(thin) (@guaranteed P) -> () {
+// CHECK: [[FN:%.*]] = function_ref @$S26specialize_self_conforming6takesPyyxAA1PRzlF : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> ()
+// CHECK: apply [[FN]]<P>(%0) : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@guaranteed τ_0_0) -> ()
+// CHECK: return
+
+func callsTakesPWithP(_ p: P) {
+ callsTakesP(p)
+}
diff --git a/test/SILOptimizer/plus_zero_specialize_unconditional_checked_cast.swift b/test/SILOptimizer/plus_zero_specialize_unconditional_checked_cast.swift
new file mode 100644
index 0000000..6f6977d
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialize_unconditional_checked_cast.swift
@@ -0,0 +1,381 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil -o - -O %s | %FileCheck %s
+
+//////////////////
+// Declarations //
+//////////////////
+
+public class C {}
+public class D : C {}
+public class E {}
+
+public struct NotUInt8 { var value: UInt8 }
+public struct NotUInt64 { var value: UInt64 }
+
+var b = NotUInt8(value: 0)
+var c = C()
+var d = D()
+var e = E()
+var f = NotUInt64(value: 0)
+var o : AnyObject = c
+
+////////////////////////////
+// Archetype To Archetype //
+////////////////////////////
+
+@inline(never)
+public func ArchetypeToArchetype<T1, T2>(t t: T1, t2: T2) -> T2 {
+ return t as! T2
+}
+
+ArchetypeToArchetype(t: b, t2: b)
+ArchetypeToArchetype(t: c, t2: c)
+ArchetypeToArchetype(t: b, t2: c)
+ArchetypeToArchetype(t: c, t2: b)
+ArchetypeToArchetype(t: c, t2: d)
+ArchetypeToArchetype(t: d, t2: c)
+ArchetypeToArchetype(t: c, t2: e)
+ArchetypeToArchetype(t: b, t2: f)
+
+// x -> x where x is not a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA8NotUInt8V{{.*}}Tg5 : $@convention(thin) (NotUInt8, NotUInt8) -> NotUInt8 {
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+
+// x -> x where x is a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA1CC{{.*}}Tg5 : $@convention(thin) (@in_guaranteed C, @in_guaranteed C) -> @owned C {
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+
+// x -> y where x is not a class but y is.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA8NotUInt8V_AA1CCTg5 : $@convention(thin) (NotUInt8, @in_guaranteed C) -> @owned C {
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK-NOT: unconditional_checked_cast_addr
+// CHECK: builtin "int_trap"
+// CHECK-NOT: unconditional_checked_cast_addr
+
+// y -> x where x is not a class but y is.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA1CC_AA8NotUInt8VTg5 : $@convention(thin) (@in_guaranteed C, NotUInt8) -> NotUInt8 {
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+// CHECK: builtin "int_trap"
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+
+// x -> y where x is a super class of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA1CC_AA1DCTg5 : $@convention(thin) (@in_guaranteed C, @in_guaranteed D) -> @owned D {
+// CHECK: [[STACK:%[0-9]+]] = alloc_stack $C
+// TODO: This should be optimized to an unconditional_checked_cast without the need of alloc_stack: rdar://problem/24775038
+// CHECK: unconditional_checked_cast_addr C in [[STACK]] : $*C to D in
+
+// y -> x where x is a super class of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA1DC_AA1CCTg5 : $@convention(thin) (@in_guaranteed D, @in_guaranteed C) -> @owned C {
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+// CHECK: upcast {{%[0-9]+}} : $D to $C
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+
+// x -> y where x and y are unrelated classes.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA1CC_AA1ECTg5 : $@convention(thin) (@in_guaranteed C, @in_guaranteed E) -> @owned E {
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+// CHECK: builtin "int_trap"
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+
+// x -> y where x and y are unrelated non classes.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast011ArchetypeToE0{{[_0-9a-zA-Z]*}}FAA8NotUInt8V_AA0H6UInt64VTg5 : $@convention(thin) (NotUInt8, NotUInt64) -> NotUInt64 {
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+// CHECK: builtin "int_trap"
+// CHECK-NOT: unconditional_checked_cast archetype_to_archetype
+
+
+///////////////////////////
+// Archetype To Concrete //
+///////////////////////////
+
+@inline(never)
+public func ArchetypeToConcreteConvertUInt8<T>(t t: T) -> NotUInt8 {
+ return t as! NotUInt8
+}
+ArchetypeToConcreteConvertUInt8(t: b)
+ArchetypeToConcreteConvertUInt8(t: c)
+ArchetypeToConcreteConvertUInt8(t: f)
+
+// x -> x where x is not a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ArchetypeToConcreteConvertUInt8{{[_0-9a-zA-Z]*}}3Not{{.*}}Tg5 : $@convention(thin) (NotUInt8) -> NotUInt8 {
+// CHECK: bb0
+// CHECK-NEXT: debug_value %0
+// CHECK-NEXT: return %0
+
+// x -> y where y is a class but x is not.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ArchetypeToConcreteConvertUInt8{{[_0-9a-zA-Z]*}}FAA1CC_Tg5
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+// x -> y where x,y are not classes and x is a different type from y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ArchetypeToConcreteConvertUInt8{{[_0-9a-zA-Z]*}}3Not{{.*}}Tg5
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+// x -> x where x is a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertC{{[_0-9a-zA-Z]*}}Tg5 : $@convention(thin) (@in_guaranteed C) -> @owned C {
+// CHECK: bb0
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: %2 = load %0 : $*C
+// CHECK: return %2
+
+// x -> y where x is a class but y is not.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertC{{[_0-9a-zA-Z]*}}FAA8NotUInt8V_Tg5
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+// x -> y where x,y are classes and x is a super class of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertC{{[_0-9a-zA-Z]*}}FAA1DC_Tg5 : $@convention(thin) (@in_guaranteed D) -> @owned C {
+// CHECK: bb0
+// CHECK-NEXT: debug_value_addr %0
+// CHECK-NEXT: %2 = load %0 : $*D
+// CHECK: [[UC:%[0-9]+]] = upcast %2
+// CHECK: return [[UC]]
+
+// x -> y where x,y are classes, but x is unrelated to y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertC{{[_0-9a-zA-Z]*}}FAA1EC_Tg5
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+@inline(never)
+public func ArchetypeToConcreteConvertC<T>(t t: T) -> C {
+ return t as! C
+}
+
+ArchetypeToConcreteConvertC(t: c)
+ArchetypeToConcreteConvertC(t: b)
+ArchetypeToConcreteConvertC(t: d)
+ArchetypeToConcreteConvertC(t: e)
+
+@inline(never)
+public func ArchetypeToConcreteConvertD<T>(t t: T) -> D {
+ return t as! D
+}
+
+ArchetypeToConcreteConvertD(t: c)
+
+// x -> y where x,y are classes and x is a sub class of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertD{{[_0-9a-zA-Z]*}}FAA1CC_Tg5 : $@convention(thin) (@in_guaranteed C) -> @owned D {
+// CHECK: bb0(%0 : $*C):
+// CHECK-DAG: [[STACK_C:%[0-9]+]] = alloc_stack $C
+// CHECK-DAG: store {{.*}} to [[STACK_C]]
+// CHECK-DAG: [[STACK_D:%[0-9]+]] = alloc_stack $D
+// TODO: This should be optimized to an unconditional_checked_cast without the need of alloc_stack: rdar://problem/24775038
+// CHECK-DAG: unconditional_checked_cast_addr C in [[STACK_C]] : $*C to D in [[STACK_D]] : $*D
+// CHECK-DAG: [[LOAD:%[0-9]+]] = load [[STACK_D]]
+// CHECK: return [[LOAD]]
+
+@inline(never)
+public func ArchetypeToConcreteConvertE<T>(t t: T) -> E {
+ return t as! E
+}
+
+ArchetypeToConcreteConvertE(t: c)
+
+// x -> y where x,y are classes, but y is unrelated to x. The idea is
+// to make sure that the fact that y is concrete does not affect the
+// result.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ArchetypeToConcreteConvertE{{[_0-9a-zA-Z]*}}FAA1CC_Tg5
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+
+///////////////////////////
+// Concrete to Archetype //
+///////////////////////////
+
+@inline(never)
+public func ConcreteToArchetypeConvertUInt8<T>(t t: NotUInt8, t2: T) -> T {
+ return t as! T
+}
+
+ConcreteToArchetypeConvertUInt8(t: b, t2: b)
+ConcreteToArchetypeConvertUInt8(t: b, t2: c)
+ConcreteToArchetypeConvertUInt8(t: b, t2: f)
+
+// x -> x where x is not a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ConcreteToArchetypeConvertUInt8{{[_0-9a-zA-Z]*}}3Not{{.*}}Tg5 : $@convention(thin) (NotUInt8, NotUInt8) -> NotUInt8 {
+// CHECK: bb0(%0 : $NotUInt8, %1 : $NotUInt8):
+// CHECK-NEXT: debug_value %0
+// CHECK-NEXT: return %0
+
+// x -> y where x is not a class but y is a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ConcreteToArchetypeConvertUInt8{{[_0-9a-zA-Z]*}}FAA1CC_Tg5 : $@convention(thin) (NotUInt8, @in_guaranteed C) -> @owned C {
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+// x -> y where x,y are different non class types.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast31ConcreteToArchetypeConvertUInt8{{[_0-9a-zA-Z]*}}Not{{.*}}Tg5 : $@convention(thin) (NotUInt8, NotUInt64) -> NotUInt64 {
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+@inline(never)
+public func ConcreteToArchetypeConvertC<T>(t t: C, t2: T) -> T {
+ return t as! T
+}
+
+ConcreteToArchetypeConvertC(t: c, t2: c)
+ConcreteToArchetypeConvertC(t: c, t2: b)
+ConcreteToArchetypeConvertC(t: c, t2: d)
+ConcreteToArchetypeConvertC(t: c, t2: e)
+
+
+// x -> x where x is a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ConcreteToArchetypeConvertC{{[_0-9a-zA-Z]*}}Tg5 : $@convention(thin) (@guaranteed C, @in_guaranteed C) -> @owned C {
+// CHECK: bb0(%0 : $C, %1 : $*C):
+// CHECK: return %0
+
+// x -> y where x is a class but y is not.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ConcreteToArchetypeConvertC{{[_0-9a-zA-Z]*}}Not{{.*}}Tg5 : $@convention(thin) (@guaranteed C, NotUInt8) -> NotUInt8 {
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+// x -> y where x is a super class of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ConcreteToArchetypeConvertC{{[_0-9a-zA-Z]*}}FAA1DC_Tg5 : $@convention(thin) (@guaranteed C, @in_guaranteed D) -> @owned D {
+// CHECK: bb0(%0 : $C, %1 : $*D):
+// CHECK-DAG: [[STACK_C:%[0-9]+]] = alloc_stack $C
+// CHECK-DAG: store %0 to [[STACK_C]]
+// CHECK-DAG: [[STACK_D:%[0-9]+]] = alloc_stack $D
+// TODO: This should be optimized to an unconditional_checked_cast without the need of alloc_stack: rdar://problem/24775038
+// CHECK-DAG: unconditional_checked_cast_addr C in [[STACK_C]] : $*C to D in [[STACK_D]] : $*D
+// CHECK-DAG: [[LOAD:%[0-9]+]] = load [[STACK_D]]
+// CHECK: return [[LOAD]]
+
+// x -> y where x and y are unrelated classes.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ConcreteToArchetypeConvertC{{[_0-9a-zA-Z]*}}FAA1EC_Tg5 : $@convention(thin) (@guaranteed C, @in_guaranteed E) -> @owned E {
+// CHECK: bb0(%0 : $C, %1 : $*E):
+// CHECK-NEXT: builtin "int_trap"
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+@inline(never)
+public func ConcreteToArchetypeConvertD<T>(t t: D, t2: T) -> T {
+ return t as! T
+}
+
+ConcreteToArchetypeConvertD(t: d, t2: c)
+
+// x -> y where x is a subclass of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast27ConcreteToArchetypeConvertD{{[_0-9a-zA-Z]*}}FAA1CC_Tg5 : $@convention(thin) (@guaranteed D, @in_guaranteed C) -> @owned C {
+// CHECK: bb0(%0 : $D, %1 : $*C):
+// CHECK-DAG: [[UC:%[0-9]+]] = upcast %0
+// CHECK: return [[UC]]
+
+
+////////////////////////
+// Super To Archetype //
+////////////////////////
+
+@inline(never)
+public func SuperToArchetypeC<T>(c c : C, t : T) -> T {
+ return c as! T
+}
+
+SuperToArchetypeC(c: c, t: c)
+SuperToArchetypeC(c: c, t: d)
+SuperToArchetypeC(c: c, t: b)
+
+
+// x -> x where x is a class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast17SuperToArchetypeC{{[_0-9a-zA-Z]*}}Tg5 : $@convention(thin) (@guaranteed C, @in_guaranteed C) -> @owned C {
+// CHECK: bb0(%0 : $C, %1 : $*C):
+// CHECK: return %0
+
+// x -> y where x is a super class of y.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast17SuperToArchetypeC{{[_0-9a-zA-Z]*}}FAA1DC_Tg5 : $@convention(thin) (@guaranteed C, @in_guaranteed D) -> @owned D {
+// CHECK: bb0
+// CHECK: unconditional_checked_cast_addr C in
+
+// x -> y where x is a class and y is not.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast17SuperToArchetypeC{{[_0-9a-zA-Z]*}}FAA8NotUInt8V_Tg5 : $@convention(thin) (@guaranteed C, NotUInt8) -> NotUInt8 {
+// CHECK: bb0
+// CHECK: builtin "int_trap"
+// CHECK: unreachable
+// CHECK-NEXT: }
+
+@inline(never)
+public func SuperToArchetypeD<T>(d d : D, t : T) -> T {
+ return d as! T
+}
+
+SuperToArchetypeD(d: d, t: c)
+SuperToArchetypeD(d: d, t: d)
+
+// *NOTE* The frontend is smart enough to turn this into an upcast. When this
+// test is converted to SIL, this should be fixed appropriately.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast17SuperToArchetypeD{{[_0-9a-zA-Z]*}}FAA1CC_Tg5 : $@convention(thin) (@guaranteed D, @in_guaranteed C) -> @owned C {
+// CHECK-NOT: unconditional_checked_cast super_to_archetype
+// CHECK: upcast
+// CHECK-NOT: unconditional_checked_cast super_to_archetype
+
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast17SuperToArchetypeD{{[_0-9a-zA-Z]*}}Tg5 : $@convention(thin) (@guaranteed D, @in_guaranteed D) -> @owned D {
+// CHECK: bb0(%0 : $D, %1 : $*D):
+// CHECK: return %0
+
+//////////////////////////////
+// Existential To Archetype //
+//////////////////////////////
+
+@inline(never)
+public func ExistentialToArchetype<T>(o o : AnyObject, t : T) -> T {
+ return o as! T
+}
+
+// AnyObject -> Class.
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast22ExistentialToArchetype{{[_0-9a-zA-Z]*}}FAA1CC_Tg5 : $@convention(thin) (@guaranteed AnyObject, @in_guaranteed C) -> @owned C {
+// CHECK: unconditional_checked_cast_addr AnyObject in {{%.*}} : $*AnyObject to C
+
+// AnyObject -> Non Class (should always fail)
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast22ExistentialToArchetype{{[_0-9a-zA-Z]*}}FAA8NotUInt8V_Tg5 : $@convention(thin) (@guaranteed AnyObject, NotUInt8) -> NotUInt8 {
+// CHECK-NOT: builtin "int_trap"()
+// CHECK-NOT: unreachable
+// CHECK: return
+
+// AnyObject -> AnyObject
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast22ExistentialToArchetype{{[_0-9a-zA-Z]*}}yXl{{.*}}Tg5 : $@convention(thin) (@guaranteed AnyObject, @in_guaranteed AnyObject) -> @owned AnyObject {
+// CHECK: bb0(%0 : $AnyObject, %1 : $*AnyObject):
+// CHECK: return %0
+
+ExistentialToArchetype(o: o, t: c)
+ExistentialToArchetype(o: o, t: b)
+ExistentialToArchetype(o: o, t: o)
+
+// Ensure that a downcast from an Optional source is not promoted to a
+// value cast. We could do the promotion, but the optimizer would need
+// to insert the Optional unwrapping logic before the cast.
+//
+// CHECK-LABEL: sil shared [noinline] @$S37specialize_unconditional_checked_cast15genericDownCastyq_x_q_mtr0_lFAA1CCSg_AA1DCTg5 : $@convention(thin) (@in_guaranteed Optional<C>, @thick D.Type) -> @owned D {
+// CHECK: bb0(%0 : $*Optional<C>, %1 : $@thick D.Type):
+// CHECK-DAG: [[STACK_D:%[0-9]+]] = alloc_stack $D
+// CHECK-DAG: [[STACK_C:%[0-9]+]] = alloc_stack $Optional<C>
+// CHECK-DAG: %5 = load %0 : $*Optional<C>
+// CHECK-DAG: store %5 to [[STACK_C]]
+// TODO: This should be optimized to an unconditional_checked_cast without the need of alloc_stack: rdar://problem/24775038
+// CHECK-DAG: unconditional_checked_cast_addr Optional<C> in [[STACK_C]] : $*Optional<C> to D in [[STACK_D]] : $*D
+// CHECK-DAG: [[LOAD:%[0-9]+]] = load [[STACK_D]]
+// CHECK: return [[LOAD]]
+@inline(never)
+public func genericDownCast<T, U>(_ a: T, _ : U.Type) -> U {
+ return a as! U
+}
+
+public func callGenericDownCast(_ c: C?) -> D {
+ return genericDownCast(c, D.self)
+}
+
diff --git a/test/SILOptimizer/plus_zero_specialized_anyobject_conformance.swift b/test/SILOptimizer/plus_zero_specialized_anyobject_conformance.swift
new file mode 100644
index 0000000..5cc511e
--- /dev/null
+++ b/test/SILOptimizer/plus_zero_specialized_anyobject_conformance.swift
@@ -0,0 +1,24 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -O -sil-inline-threshold 0 -emit-sil -primary-file %s | %FileCheck %s
+
+// rdar://problem/31910351
+
+// Check that swift compiler does not crash on this input.
+
+public protocol P {
+ func use<T:AnyObject>(_ t: T)
+}
+
+public class C<T> {
+}
+
+public func callee(_ t: C<Int32>?, _ p: P) {
+ // This call results in a creation of a specialized conformance of C<Int32> to AnyObject.
+ p.use(t!)
+}
+
+// CHECK-LABEL: sil @$S33specialized_anyobject_conformance7caller11pyAA1P_p_tF : $@convention(thin) (@in_guaranteed P) -> () {
+public func caller1(p: P) {
+ callee(C<Int32>(), p)
+}
+
diff --git a/test/SILOptimizer/spec_archetype_method.swift b/test/SILOptimizer/spec_archetype_method.swift
index b206b7a..c1bdc18 100644
--- a/test/SILOptimizer/spec_archetype_method.swift
+++ b/test/SILOptimizer/spec_archetype_method.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=FunctionSignatureOpts -disable-arc-opts -emit-sil -primary-file %s | %FileCheck %s
// We can't deserialize apply_inst with subst lists. When radar://14443304
diff --git a/test/SILOptimizer/specialize_anyobject.swift b/test/SILOptimizer/specialize_anyobject.swift
index 4b6b8f7..3549297 100644
--- a/test/SILOptimizer/specialize_anyobject.swift
+++ b/test/SILOptimizer/specialize_anyobject.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -sil-inline-threshold 0 -emit-sil -primary-file %s | %FileCheck %s
// rdar://problem/20338028
diff --git a/test/SILOptimizer/specialize_cg_update_crash.sil b/test/SILOptimizer/specialize_cg_update_crash.sil
index 4267d5e..317bdce 100644
--- a/test/SILOptimizer/specialize_cg_update_crash.sil
+++ b/test/SILOptimizer/specialize_cg_update_crash.sil
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -parse-stdlib -parse-as-library -module-name TestMod %S/Inputs/TestMod.sil -emit-module-path %t/TestMod.swiftmodule
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -inline -I %t %s | %FileCheck %s
diff --git a/test/SILOptimizer/specialize_checked_cast_branch.swift b/test/SILOptimizer/specialize_checked_cast_branch.swift
index a61de44..87f8234 100644
--- a/test/SILOptimizer/specialize_checked_cast_branch.swift
+++ b/test/SILOptimizer/specialize_checked_cast_branch.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -O -sil-inline-threshold 0 %s -o - | %FileCheck %s
class C {}
diff --git a/test/SILOptimizer/specialize_dynamic_self.swift b/test/SILOptimizer/specialize_dynamic_self.swift
index c801480..835abec 100644
--- a/test/SILOptimizer/specialize_dynamic_self.swift
+++ b/test/SILOptimizer/specialize_dynamic_self.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sil -O -primary-file %s | %FileCheck %s
protocol P {}
diff --git a/test/SILOptimizer/specialize_inherited_multifile.swift b/test/SILOptimizer/specialize_inherited_multifile.swift
index 96da56e..f6921c0 100644
--- a/test/SILOptimizer/specialize_inherited_multifile.swift
+++ b/test/SILOptimizer/specialize_inherited_multifile.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -primary-file %s %S/Inputs/specialize_inherited_multifile.swift -O -emit-sil -sil-verify-all | %FileCheck %s
@_optimize(none) func takesBase<T : Base>(t: T) {}
diff --git a/test/SILOptimizer/specialize_partial_apply.swift b/test/SILOptimizer/specialize_partial_apply.swift
index fafb263..db5172e 100644
--- a/test/SILOptimizer/specialize_partial_apply.swift
+++ b/test/SILOptimizer/specialize_partial_apply.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// First check the SIL.
// RUN: %target-swift-frontend -O -Xllvm -sil-disable-pass=FunctionSignatureOpts -module-name=test -emit-sil -primary-file %s | %FileCheck %s
diff --git a/test/SILOptimizer/specialize_same_type_constraint.swift b/test/SILOptimizer/specialize_same_type_constraint.swift
index fe11b5b..e80cda3 100644
--- a/test/SILOptimizer/specialize_same_type_constraint.swift
+++ b/test/SILOptimizer/specialize_same_type_constraint.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -emit-sil -primary-file %s | %FileCheck %s
protocol FirstChild {}
diff --git a/test/SILOptimizer/specialize_self.swift b/test/SILOptimizer/specialize_self.swift
index 4bc585d..4384da9 100644
--- a/test/SILOptimizer/specialize_self.swift
+++ b/test/SILOptimizer/specialize_self.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -O -sil-inline-threshold 0 -emit-sil -primary-file %s | %FileCheck %s
// CHECK-NOT: generic specialization <Swift.AnyObject, Self> of specialize_self.cast <A, B>(A) -> Swift.Optional<B>
diff --git a/test/SILOptimizer/specialize_self_conforming.swift b/test/SILOptimizer/specialize_self_conforming.swift
index c182da3..847fa94e 100644
--- a/test/SILOptimizer/specialize_self_conforming.swift
+++ b/test/SILOptimizer/specialize_self_conforming.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -O -primary-file %s | %FileCheck %s
// REQUIRES: objc_interop
diff --git a/test/SILOptimizer/specialize_unconditional_checked_cast.swift b/test/SILOptimizer/specialize_unconditional_checked_cast.swift
index d4cbb5a..31ab14a 100644
--- a/test/SILOptimizer/specialize_unconditional_checked_cast.swift
+++ b/test/SILOptimizer/specialize_unconditional_checked_cast.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -Xllvm -sil-disable-pass=FunctionSignatureOpts -emit-sil -o - -O %s | %FileCheck %s
//////////////////
diff --git a/test/SILOptimizer/specialized_anyobject_conformance.swift b/test/SILOptimizer/specialized_anyobject_conformance.swift
index 89f63f7..d127df0 100644
--- a/test/SILOptimizer/specialized_anyobject_conformance.swift
+++ b/test/SILOptimizer/specialized_anyobject_conformance.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -O -sil-inline-threshold 0 -emit-sil -primary-file %s | %FileCheck %s
// rdar://problem/31910351
diff --git a/test/Sanitizers/tsan.swift b/test/Sanitizers/tsan.swift
index 214274a..3b793f5 100644
--- a/test/Sanitizers/tsan.swift
+++ b/test/Sanitizers/tsan.swift
@@ -3,7 +3,11 @@
// REQUIRES: executable_test
// REQUIRES: tsan_runtime
// UNSUPPORTED: OS=tvos
-#if os(OSX) || os(iOS)
+
+// https://bugs.swift.org/browse/SR-6622
+// XFAIL: linux
+
+#if os(macOS) || os(iOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin)
import Glibc
@@ -34,7 +38,7 @@
var racey_x: Int;
for _ in 1...5 {
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
var t : pthread_t?
#else
var t : pthread_t = 0
@@ -45,7 +49,7 @@
return nil
}, nil)
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
threads.append(t!)
#else
threads.append(t)
diff --git a/test/Sanitizers/witness_table_lookup.swift b/test/Sanitizers/witness_table_lookup.swift
index f0120ac..202880e 100644
--- a/test/Sanitizers/witness_table_lookup.swift
+++ b/test/Sanitizers/witness_table_lookup.swift
@@ -3,6 +3,9 @@
// REQUIRES: executable_test
// REQUIRES: tsan_runtime
+// https://bugs.swift.org/browse/SR-6622
+// XFAIL: linux
+
// Check that TSan does not report spurious races in witness table lookup.
func consume(_ x: Any) {}
diff --git a/test/Sema/fixed_ambiguities/plus_zero_rdar27198177.swift b/test/Sema/fixed_ambiguities/plus_zero_rdar27198177.swift
new file mode 100644
index 0000000..39fbc60
--- /dev/null
+++ b/test/Sema/fixed_ambiguities/plus_zero_rdar27198177.swift
@@ -0,0 +1,7 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -verify %s -swift-version 4 | %FileCheck %s
+
+let arr = ["A", "B", "C"]
+let lazy: LazyMapCollection = arr.lazy.map { $0 }
+// CHECK: function_ref @$Ss22LazyCollectionProtocolPsE6filterys0a6FilterB0Vy8ElementsQzGSb7ElementQzcF : $@convention(method) <τ_0_0 where τ_0_0 : LazyCollectionProtocol> (@guaranteed @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> Bool, @in_guaranteed τ_0_0) -> @out LazyFilterCollection<τ_0_0.Elements>
+_ = lazy.filter { $0 > "A" }.count
diff --git a/test/Sema/fixed_ambiguities/plus_zero_rdar33142386.swift b/test/Sema/fixed_ambiguities/plus_zero_rdar33142386.swift
new file mode 100644
index 0000000..ea617e2
--- /dev/null
+++ b/test/Sema/fixed_ambiguities/plus_zero_rdar33142386.swift
@@ -0,0 +1,6 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -verify %s -swift-version 4 | %FileCheck %s
+
+let x: String = "ultimate question"
+// CHECK: function_ref @$Ss26RangeReplaceableCollectionPsE6filteryxSb7ElementQzKXEKF : $@convention(method) <τ_0_0 where τ_0_0 : RangeReplaceableCollection> (@noescape @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> (Bool, @error Error), @in_guaranteed τ_0_0) -> (@out τ_0_0, @error Error)
+_ = x.filter({ $0 == " " }).count < 3
diff --git a/test/Sema/fixed_ambiguities/plus_zero_rdar35623181.swift b/test/Sema/fixed_ambiguities/plus_zero_rdar35623181.swift
new file mode 100644
index 0000000..43e9c26
--- /dev/null
+++ b/test/Sema/fixed_ambiguities/plus_zero_rdar35623181.swift
@@ -0,0 +1,9 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
+
+extension Sequence where Element == String {
+ func record() -> String {
+ // CHECK: function_ref @$Ss20LazySequenceProtocolPsE3mapys0a3MapB0Vy8ElementsQzqd__Gqd__7ElementQzclF : $@convention(method) <τ_0_0 where τ_0_0 : LazySequenceProtocol><τ_1_0> (@guaranteed @callee_guaranteed (@in_guaranteed τ_0_0.Element) -> @out τ_1_0, @in_guaranteed τ_0_0) -> @out LazyMapSequence<τ_0_0.Elements, τ_1_0
+ return lazy.map({ $0 }).joined(separator: ",")
+ }
+}
diff --git a/test/Sema/fixed_ambiguities/plus_zero_rdar36333688.swift b/test/Sema/fixed_ambiguities/plus_zero_rdar36333688.swift
new file mode 100644
index 0000000..81b8f77
--- /dev/null
+++ b/test/Sema/fixed_ambiguities/plus_zero_rdar36333688.swift
@@ -0,0 +1,31 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
+
+infix operator +=+ : AdditionPrecedence
+extension RangeReplaceableCollection {
+ public static func +=+ <
+ Other : Sequence
+ >(lhs: Self, rhs: Other) -> Self
+ where Element == Other.Element {
+ fatalError()
+ }
+
+ public static func +=+ <
+ Other : Sequence
+ >(lhs: Other, rhs: Self) -> Self
+ where Element == Other.Element {
+ fatalError()
+ }
+
+ public static func +=+ <
+ Other : RangeReplaceableCollection
+ >(lhs: Self, rhs: Other) -> Self
+ where Element == Other.Element {
+ fatalError()
+ }
+}
+
+func rdar36333688(_ first: Int, _ rest: Int...) {
+ // CHECK: function_ref @{{.*}} : $@convention(method) <τ_0_0 where τ_0_0 : RangeReplaceableCollection><τ_1_0 where τ_1_0 : RangeReplaceableCollection, τ_0_0.Element == τ_1_0.Element> (@in_guaranteed τ_0_0, @in_guaranteed τ_1_0, @thick τ_0_0.Type) -> @out τ_0_0
+ let _ = [first] +=+ rest
+}
diff --git a/test/Sema/fixed_ambiguities/rdar27198177.swift b/test/Sema/fixed_ambiguities/rdar27198177.swift
index 0cfad49..bd240b3 100644
--- a/test/Sema/fixed_ambiguities/rdar27198177.swift
+++ b/test/Sema/fixed_ambiguities/rdar27198177.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -verify %s -swift-version 4 | %FileCheck %s
let arr = ["A", "B", "C"]
diff --git a/test/Sema/fixed_ambiguities/rdar33142386.swift b/test/Sema/fixed_ambiguities/rdar33142386.swift
index 798fc6b..e6fd493 100644
--- a/test/Sema/fixed_ambiguities/rdar33142386.swift
+++ b/test/Sema/fixed_ambiguities/rdar33142386.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -verify %s -swift-version 4 | %FileCheck %s
let x: String = "ultimate question"
diff --git a/test/Sema/fixed_ambiguities/rdar35623181.swift b/test/Sema/fixed_ambiguities/rdar35623181.swift
index d72f4b6..d3278c8 100644
--- a/test/Sema/fixed_ambiguities/rdar35623181.swift
+++ b/test/Sema/fixed_ambiguities/rdar35623181.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
extension Sequence where Element == String {
diff --git a/test/Sema/fixed_ambiguities/rdar36333688.swift b/test/Sema/fixed_ambiguities/rdar36333688.swift
index b7827cc..3417b6a 100644
--- a/test/Sema/fixed_ambiguities/rdar36333688.swift
+++ b/test/Sema/fixed_ambiguities/rdar36333688.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %target-swift-frontend -emit-sil -verify %s | %FileCheck %s
infix operator +=+ : AdditionPrecedence
diff --git a/test/Serialization/function.swift b/test/Serialization/function.swift
index 6e9074a..93e74be 100644
--- a/test/Serialization/function.swift
+++ b/test/Serialization/function.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_func.swift
// RUN: llvm-bcanalyzer %t/def_func.swiftmodule | %FileCheck %s
diff --git a/test/Serialization/objc.swift b/test/Serialization/objc.swift
index 90bf773..d2ba2bf 100644
--- a/test/Serialization/objc.swift
+++ b/test/Serialization/objc.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_objc.swift -disable-objc-attr-requires-foundation-module
// RUN: llvm-bcanalyzer %t/def_objc.swiftmodule | %FileCheck %s
diff --git a/test/Serialization/plus_zero_function.swift b/test/Serialization/plus_zero_function.swift
new file mode 100644
index 0000000..0332f22
--- /dev/null
+++ b/test/Serialization/plus_zero_function.swift
@@ -0,0 +1,120 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_func.swift
+// RUN: llvm-bcanalyzer %t/def_func.swiftmodule | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -I %t %s | %FileCheck %s -check-prefix=SIL
+
+// CHECK-NOT: FALL_BACK_TO_TRANSLATION_UNIT
+// CHECK-NOT: UnknownCode
+
+import def_func
+
+func useEq<T: EqualOperator>(_ x: T, y: T) -> Bool {
+ return x == y
+}
+
+// SIL: sil @main
+// SIL: [[RAW:%.+]] = global_addr @$S8function3rawSivp : $*Int
+// SIL: [[ZERO:%.+]] = function_ref @$S8def_func7getZeroSiyF : $@convention(thin) () -> Int
+// SIL: [[RESULT:%.+]] = apply [[ZERO]]() : $@convention(thin) () -> Int
+// SIL: store [[RESULT]] to [trivial] [[RAW]] : $*Int
+var raw = getZero()
+
+// Check that 'raw' is an Int
+var cooked : Int = raw
+
+
+// SIL: [[GET_INPUT:%.+]] = function_ref @$S8def_func8getInput1xS2i_tF : $@convention(thin) (Int) -> Int
+// SIL: {{%.+}} = apply [[GET_INPUT]]({{%.+}}) : $@convention(thin) (Int) -> Int
+var raw2 = getInput(x: raw)
+
+// SIL: [[GET_SECOND:%.+]] = function_ref @$S8def_func9getSecond_1yS2i_SitF : $@convention(thin) (Int, Int) -> Int
+// SIL: {{%.+}} = apply [[GET_SECOND]]({{%.+}}, {{%.+}}) : $@convention(thin) (Int, Int) -> Int
+var raw3 = getSecond(raw, y: raw2)
+
+// SIL: [[USE_NESTED:%.+]] = function_ref @$S8def_func9useNested_1nySi1x_Si1yt_SitF : $@convention(thin) (Int, Int, Int) -> ()
+// SIL: {{%.+}} = apply [[USE_NESTED]]({{%.+}}, {{%.+}}, {{%.+}}) : $@convention(thin) (Int, Int, Int) -> ()
+useNested((raw, raw2), n: raw3)
+
+// SIL: [[VA_SIZE:%.+]] = integer_literal $Builtin.Word, 2
+// SIL: {{%.+}} = apply {{%.*}}<Int>([[VA_SIZE]])
+// SIL: [[VARIADIC:%.+]] = function_ref @$S8def_func8variadic1x_ySd_SidtF : $@convention(thin) (Double, @guaranteed Array<Int>) -> ()
+// SIL: {{%.+}} = apply [[VARIADIC]]({{%.+}}, {{%.+}}) : $@convention(thin) (Double, @guaranteed Array<Int>) -> ()
+variadic(x: 2.5, 4, 5)
+
+// SIL: [[VARIADIC:%.+]] = function_ref @$S8def_func9variadic2_1xySid_SdtF : $@convention(thin) (@guaranteed Array<Int>, Double) -> ()
+variadic2(1, 2, 3, x: 5.0)
+
+// SIL: [[SLICE_SIZE:%.+]] = integer_literal $Builtin.Word, 3
+// SIL: {{%.+}} = apply {{%.*}}<Int>([[SLICE_SIZE]])
+// SIL: [[SLICE:%.+]] = function_ref @$S8def_func5slice1xySaySiG_tF : $@convention(thin) (@guaranteed Array<Int>) -> ()
+// SIL: {{%.+}} = apply [[SLICE]]({{%.+}}) : $@convention(thin) (@guaranteed Array<Int>) -> ()
+slice(x: [2, 4, 5])
+
+optional(x: .some(23))
+optional(x: .none)
+
+
+// SIL: [[MAKE_PAIR:%.+]] = function_ref @$S8def_func8makePair{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_0, @out τ_0_1)
+// SIL: {{%.+}} = apply [[MAKE_PAIR]]<Int, Double>({{%.+}}, {{%.+}})
+
+var pair : (Int, Double) = makePair(a: 1, b: 2.5)
+
+// SIL: [[DIFFERENT_A:%.+]] = function_ref @$S8def_func9different{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+// SIL: [[DIFFERENT_B:%.+]] = function_ref @$S8def_func9different{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+
+_ = different(a: 1, b: 2)
+_ = different(a: false, b: false)
+
+// SIL: [[DIFFERENT2_A:%.+]] = function_ref @$S8def_func10different2{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+// SIL: [[DIFFERENT2_B:%.+]] = function_ref @$S8def_func10different2{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
+_ = different2(a: 1, b: 2)
+_ = different2(a: false, b: false)
+
+
+struct IntWrapper1 : Wrapped {
+ typealias Value = Int
+ func getValue() -> Int { return 1 }
+}
+struct IntWrapper2 : Wrapped {
+ typealias Value = Int
+ func getValue() -> Int { return 2 }
+}
+
+// SIL: [[DIFFERENT_WRAPPED:%.+]] = function_ref @$S8def_func16differentWrapped1a1bSbx_q_tAA0D0RzAaER_5ValueQy_AFRtzr0_lF : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Wrapped, τ_0_1 : Wrapped, τ_0_0.Value == τ_0_1.Value> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> Bool
+
+
+_ = differentWrapped(a: IntWrapper1(), b: IntWrapper2())
+
+
+// SIL: {{%.+}} = function_ref @$S8def_func10overloaded1xySi_tF : $@convention(thin) (Int) -> ()
+// SIL: {{%.+}} = function_ref @$S8def_func10overloaded1xySb_tF : $@convention(thin) (Bool) -> ()
+
+overloaded(x: 1)
+overloaded(x: false)
+
+
+// SIL: {{%.+}} = function_ref @primitive : $@convention(thin) () -> ()
+primitive()
+
+
+if raw == 5 {
+ testNoReturnAttr()
+ testNoReturnAttrPoly(x: 5)
+}
+// SIL: {{%.+}} = function_ref @$S8def_func16testNoReturnAttrs5NeverOyF : $@convention(thin) () -> Never
+// SIL: {{%.+}} = function_ref @$S8def_func20testNoReturnAttrPoly{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Never
+
+
+// SIL: sil @$S8def_func16testNoReturnAttrs5NeverOyF : $@convention(thin) () -> Never
+// SIL: sil @$S8def_func20testNoReturnAttrPoly{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> Never
+
+do {
+ try throws1()
+ _ = try throws2(1)
+} catch _ {}
+// SIL: sil @$S8def_func7throws1yyKF : $@convention(thin) () -> @error Error
+// SIL: sil @$S8def_func7throws2{{[_0-9a-zA-Z]*}}F : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error Error)
+
+// LLVM: }
+
diff --git a/test/Serialization/plus_zero_objc.swift b/test/Serialization/plus_zero_objc.swift
new file mode 100644
index 0000000..787e961
--- /dev/null
+++ b/test/Serialization/plus_zero_objc.swift
@@ -0,0 +1,39 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_objc.swift -disable-objc-attr-requires-foundation-module
+// RUN: llvm-bcanalyzer %t/def_objc.swiftmodule | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -I %t %s -o - | %FileCheck %s -check-prefix=SIL
+
+// CHECK-NOT: UnknownCode
+
+import def_objc
+
+// SIL: sil hidden @$S4objc9testProto3objy04def_A09ObjCProto_p_tF : $@convention(thin) (@guaranteed ObjCProto) -> () {
+func testProto(obj obj: ObjCProto) {
+ // SIL: = objc_method {{%.*}} : $@opened({{.*}}) ObjCProto, #ObjCProto.doSomething!1.foreign
+ obj.doSomething()
+}
+
+// SIL: sil hidden @$S4objc9testClass3objy04def_A09ObjCClassC_tF : $@convention(thin) (@guaranteed ObjCClass) -> () {
+func testClass(obj obj: ObjCClass) {
+ // SIL: = objc_method %{{.+}} : $ObjCClass, #ObjCClass.implicitlyObjC!1.foreign
+ obj.implicitlyObjC()
+
+ // SIL: = objc_method %{{.+}} : $@objc_metatype ObjCClass.Type, #ObjCClass.classMethod!1.foreign
+ ObjCClass.classMethod()
+}
+
+// SIL: sil hidden @$S4objc15testNativeClass3objy04def_A012NonObjCClassC_tF : $@convention(thin) (@guaranteed NonObjCClass) -> () {
+func testNativeClass(obj obj: NonObjCClass) {
+ // SIL: = objc_method %{{.+}} : $NonObjCClass, #NonObjCClass.doSomething!1.foreign
+ // SIL: = objc_method %{{.+}} : $NonObjCClass, #NonObjCClass.objcMethod!1.foreign
+ obj.doSomething()
+ obj.objcMethod()
+
+ // SIL: objc_method [[OBJ:%[0-9]+]] : $NonObjCClass, #NonObjCClass.objcProp!getter.1.foreign
+ var x = obj.objcProp
+
+ // SIL: objc_method [[OBJ:%[0-9]+]] : $NonObjCClass, #NonObjCClass.subscript!getter.1.foreign
+ _ = obj[42]
+}
+
diff --git a/test/Serialization/plus_zero_serialize_attr.swift b/test/Serialization/plus_zero_serialize_attr.swift
new file mode 100644
index 0000000..ea32612
--- /dev/null
+++ b/test/Serialization/plus_zero_serialize_attr.swift
@@ -0,0 +1,84 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -parse-as-library -o %t %s
+// RUN: llvm-bcanalyzer %t/serialize_attr.swiftmodule | %FileCheck %s -check-prefix=BCANALYZER
+// RUN: %target-sil-opt -enable-sil-verify-all -disable-sil-linking %t/serialize_attr.swiftmodule | %FileCheck %s
+
+// BCANALYZER-NOT: UnknownCode
+
+// @_semantics
+// -----------------------------------------------------------------------------
+
+//CHECK-DAG: @_semantics("crazy") func foo()
+@_inlineable
+@_versioned
+@_semantics("crazy") func foo() -> Int { return 5}
+
+// @_optimize
+// -----------------------------------------------------------------------------
+
+//CHECK-DAG: @_optimize(none) func test_onone()
+@_inlineable
+@_versioned
+@_optimize(none)
+func test_onone() -> Int { return 5}
+
+//CHECK-DAG: @_optimize(speed) func test_ospeed()
+@_inlineable
+@_versioned
+@_optimize(speed)
+func test_ospeed() -> Int { return 5}
+
+//CHECK-DAG: @_optimize(size) func test_osize()
+@_inlineable
+@_versioned
+@_optimize(size)
+func test_osize() -> Int { return 5}
+
+// @_specialize
+// -----------------------------------------------------------------------------
+
+// These lines should be contiguous.
+// CHECK-DAG: @_specialize(exported: false, kind: full, where T == Int, U == Float)
+// CHECK-DAG: func specializeThis<T, U>(_ t: T, u: U)
+@_inlineable
+@_versioned
+@_specialize(where T == Int, U == Float)
+func specializeThis<T, U>(_ t: T, u: U) {}
+
+public protocol PP {
+ associatedtype PElt
+}
+public protocol QQ {
+ associatedtype QElt
+}
+
+public struct RR : PP {
+ public typealias PElt = Float
+}
+public struct SS : QQ {
+ public typealias QElt = Int
+}
+
+public struct GG<T : PP> {}
+
+// These three lines should be contiguous, however, there is no way to
+// sequence FileCheck directives while using CHECK-DAG as the outer
+// label, and the declaration order is unpredictable.
+//
+// CHECK-DAG: class CC<T> where T : PP {
+// CHECK-DAG: @_specialize(exported: false, kind: full, where T == RR, U == SS)
+// CHECK-DAG: @inline(never) func foo<U>(_ u: U, g: GG<T>) -> (U, GG<T>) where U : QQ
+public class CC<T : PP> {
+ @_inlineable
+ @_versioned
+ @inline(never)
+ @_specialize(where T==RR, U==SS)
+ func foo<U : QQ>(_ u: U, g: GG<T>) -> (U, GG<T>) {
+ return (u, g)
+ }
+}
+
+// CHECK-DAG: sil [serialized] [_specialize exported: false, kind: full, where T == Int, U == Float] [canonical] @$S14serialize_attr14specializeThis_1uyx_q_tr0_lF : $@convention(thin) <T, U> (@in_guaranteed T, @in_guaranteed U) -> () {
+
+// CHECK-DAG: sil [serialized] [noinline] [_specialize exported: false, kind: full, where T == RR, U == SS] [canonical] @$S14serialize_attr2CCC3foo_1gqd___AA2GGVyxGtqd___AHtAA2QQRd__lF : $@convention(method) <T where T : PP><U where U : QQ> (@in_guaranteed U, GG<T>, @guaranteed CC<T>) -> (@out U, GG<T>) {
diff --git a/test/Serialization/plus_zero_transparent-std.swift b/test/Serialization/plus_zero_transparent-std.swift
new file mode 100644
index 0000000..0a92f03
--- /dev/null
+++ b/test/Serialization/plus_zero_transparent-std.swift
@@ -0,0 +1,58 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -parse-stdlib -o %t %S/Inputs/def_transparent_std.swift
+// RUN: llvm-bcanalyzer %t/def_transparent_std.swiftmodule | %FileCheck %s
+// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-sil -sil-debug-serialization -parse-stdlib -I %t %s | %FileCheck %s -check-prefix=SIL
+
+// CHECK-NOT: UnknownCode
+
+import def_transparent_std
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std3foo1x1yBi1_Bi1__Bi1_tF : $@convention(thin) (Builtin.Int1, Builtin.Int1) -> Builtin.Int1 {
+// SIL: = builtin "cmp_eq_Int1"(%0 : $Builtin.Int1, %1 : $Builtin.Int1) : $Builtin.Int1
+func test_foo(x: Builtin.Int1, y: Builtin.Int1) -> Builtin.Int1 {
+ var a = foo(x: x, y: y)
+ return a
+}
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std12assign_tuple1x1yyBi64__Bot_BptF : $@convention(thin) (Builtin.Int64, @guaranteed Builtin.NativeObject, Builtin.RawPointer) -> () {
+// SIL: = tuple (%0 : $Builtin.Int64, %1 : $Builtin.NativeObject)
+// SIL: retain_value
+// SIL: = tuple_extract
+// SIL: = tuple_extract
+// SIL: = pointer_to_address
+// SIL: = tuple
+// SIL: = load
+func test_tuple(x: (Builtin.Int64, Builtin.NativeObject),
+ y: Builtin.RawPointer) {
+ assign_tuple(x: x, y: y)
+}
+
+func test_conversion(c: C, t32: Builtin.Int32) {
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std22class_to_native_object1cBoAA1CC_tF : $@convention(thin) (@guaranteed C) -> @owned Builtin.NativeObject {
+// SIL: bb0(%0 : $C):
+// SIL: unchecked_ref_cast %0 : $C to $Builtin.NativeObject
+// SIL-NEXT: strong_retain
+// SIL-NEXT: return
+ var b = class_to_native_object(c: c)
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std24class_from_native_object1pAA1CCBo_tF : $@convention(thin) (@guaranteed Builtin.NativeObject) -> @owned C {
+// SIL: unchecked_ref_cast %0 : $Builtin.NativeObject to $C
+ var c = class_from_native_object(p: b)
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std20class_to_raw_pointer1cBpAA1CC_tF : $@convention(thin) (@guaranteed C) -> Builtin.RawPointer {
+// SIL: ref_to_raw_pointer %0 : $C to $Builtin.RawPointer
+ var d = class_to_raw_pointer(c: c)
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std22class_from_raw_pointer1pAA1CCBp_tF : $@convention(thin) (Builtin.RawPointer) -> @owned C {
+// SIL: raw_pointer_to_ref %0 : $Builtin.RawPointer to $C
+ var e = class_from_raw_pointer(p: d)
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std5gep321p1iBpBp_Bi32_tF : $@convention(thin) (Builtin.RawPointer, Builtin.Int32) -> Builtin.RawPointer {
+// SIL: index_raw_pointer %0 : $Builtin.RawPointer, %1 : $Builtin.Int32
+ var f = gep32(p: d, i: t32)
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S19def_transparent_std11destroy_obj1xyBp_tF : $@convention(thin) (Builtin.RawPointer) -> () {
+// SIL: pointer_to_address %0 : $Builtin.RawPointer to [strict] $*Builtin.NativeObject
+ destroy_obj(x: d)
+}
diff --git a/test/Serialization/plus_zero_transparent.swift b/test/Serialization/plus_zero_transparent.swift
new file mode 100644
index 0000000..3fd2497
--- /dev/null
+++ b/test/Serialization/plus_zero_transparent.swift
@@ -0,0 +1,73 @@
+// REQUIRES: plus_zero_runtime
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_transparent.swift
+// RUN: llvm-bcanalyzer %t/def_transparent.swiftmodule | %FileCheck %s
+// RUN: %target-swift-frontend -emit-silgen -sil-link-all -I %t %s | %FileCheck %s -check-prefix=SIL
+
+// CHECK-NOT: UnknownCode
+
+import def_transparent
+
+// SIL-LABEL: sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
+// SIL: [[RAW:%.+]] = global_addr @$S11transparent3rawSbvp : $*Bool
+// SIL: [[FUNC:%.+]] = function_ref @$S15def_transparent15testTransparent1xS2b_tF : $@convention(thin) (Bool) -> Bool
+// SIL: [[RESULT:%.+]] = apply [[FUNC]]({{%.+}}) : $@convention(thin) (Bool) -> Bool
+// SIL: store [[RESULT]] to [trivial] [[RAW]] : $*Bool
+var raw = testTransparent(x: false)
+
+// SIL: [[TMP:%.+]] = global_addr @$S11transparent3tmps5Int32Vvp : $*Int32
+// SIL: [[FUNC2:%.+]] = function_ref @$S15def_transparent11testBuiltins5Int32VyF : $@convention(thin) () -> Int32
+// SIL: [[RESULT2:%.+]] = apply [[FUNC2]]() : $@convention(thin) () -> Int32
+// SIL: store [[RESULT2]] to [trivial] [[TMP]] : $*Int32
+var tmp = testBuiltin()
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent15testTransparent1xS2b_tF : $@convention(thin) (Bool) -> Bool {
+// SIL: bb0(%0 : $Bool):
+// SIL: return %0 : $Bool
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent11testBuiltins5Int32VyF : $@convention(thin) () -> Int32 {
+// SIL: bb0:
+// SIL: integer_literal $Builtin.Int32, 300
+// SIL: string_literal utf8 "foo"
+// SIL: return %{{.*}} : $Int32
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent7test_bryyF : $@convention(thin) () -> () {
+// SIL: bb{{.*}}:
+// SIL: cond_br %{{.*}}, bb{{.*}}, bb{{.*}}
+// SIL: bb{{.*}}:
+// SIL: br bb{{.*}}
+func wrap_br() {
+ test_br()
+}
+
+// SIL-LABEL: sil public_external [serialized] [canonical] @$S15def_transparent9do_switch1uyAA9MaybePairO_tF : $@convention(thin) (@guaranteed MaybePair) -> () {
+// SIL: bb0(%0 : $MaybePair):
+// SIL: retain_value %0 : $MaybePair
+// SIL: switch_enum %0 : $MaybePair, case #MaybePair.Neither!enumelt: bb[[CASE1:[0-9]+]], case #MaybePair.Left!enumelt.1: bb[[CASE2:[0-9]+]], case #MaybePair.Right!enumelt.1: bb[[CASE3:[0-9]+]], case #MaybePair.Both!enumelt.1: bb[[CASE4:[0-9]+]]
+// SIL: bb[[CASE4]](%{{.*}} : $(Int32, String)):
+// SIL: bb[[CASE3]](%{{.*}} : $String):
+// SIL: bb[[CASE2]](%{{.*}} : $Int32):
+// SIL: bb[[CASE1]]:
+func test_switch(u: MaybePair) {
+ do_switch(u: u)
+}
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent7WrapperV3ValACs5Int32V_tcfC : $@convention(method) (Int32, @thin Wrapper.Type) -> Wrapper {
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent7WrapperV8getValue{{[_0-9a-zA-Z]*}}F : $@convention(method) (Wrapper) -> Int32 {
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent7WrapperV10valueAgains5Int32Vvg : $@convention(method) (Wrapper) -> Int32 {
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent7WrapperV13getValueAgain{{[_0-9a-zA-Z]*}}F : $@convention(method) (Wrapper) -> Int32 {
+func test_wrapper() {
+ var w = Wrapper(Val: 42)
+
+ print(w.value, terminator: "")
+ print(w.getValue(), terminator: "")
+ print(w.valueAgain, terminator: "")
+ print(w.getValueAgain(), terminator: "")
+}
+
+// SIL-LABEL: sil public_external [transparent] [serialized] [canonical] @$S15def_transparent17open_existentials1p2cpyAA1P_p_AA2CP_ptF
+func test_open_existentials(p: P, cp: CP) {
+ // SIL: open_existential_addr immutable_access [[EXIST:%[0-9]+]] : $*P to $*@opened([[N:".*"]]) P
+ // SIL: open_existential_ref [[EXIST:%[0-9]+]] : $CP to $@opened([[M:".*"]]) CP
+ open_existentials(p: p, cp: cp)
+}
diff --git a/test/Serialization/serialize_attr.swift b/test/Serialization/serialize_attr.swift
index 8456016..501abe1 100644
--- a/test/Serialization/serialize_attr.swift
+++ b/test/Serialization/serialize_attr.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -parse-as-library -o %t %s
// RUN: llvm-bcanalyzer %t/serialize_attr.swiftmodule | %FileCheck %s -check-prefix=BCANALYZER
diff --git a/test/Serialization/transparent-std.swift b/test/Serialization/transparent-std.swift
index 76f887d..1e51fae 100644
--- a/test/Serialization/transparent-std.swift
+++ b/test/Serialization/transparent-std.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -parse-stdlib -o %t %S/Inputs/def_transparent_std.swift
// RUN: llvm-bcanalyzer %t/def_transparent_std.swiftmodule | %FileCheck %s
diff --git a/test/Serialization/transparent.swift b/test/Serialization/transparent.swift
index 72a46a3..89f29dd 100644
--- a/test/Serialization/transparent.swift
+++ b/test/Serialization/transparent.swift
@@ -1,3 +1,4 @@
+// REQUIRES: plus_one_runtime
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t %S/Inputs/def_transparent.swift
// RUN: llvm-bcanalyzer %t/def_transparent.swiftmodule | %FileCheck %s
diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in
index 0b5957b..c8c7a39 100644
--- a/test/lit.site.cfg.in
+++ b/test/lit.site.cfg.in
@@ -36,6 +36,8 @@
config.coverage_mode = "@SWIFT_ANALYZE_CODE_COVERAGE@"
config.lldb_build_root = "@LLDB_BUILD_DIR@"
+# Please remember to handle empty strings and/or unset variables correctly.
+
if "@SWIFT_ASAN_BUILD@" == "TRUE":
config.available_features.add("asan")
else:
@@ -89,10 +91,10 @@
if "@SWIFT_ENABLE_SOURCEKIT_TESTS@" == "TRUE":
config.available_features.add('sourcekit')
-if "@SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS@" == "FALSE":
- config.available_features.add('plus_one_runtime')
-else:
+if "@SWIFT_ENABLE_GUARANTEED_NORMAL_ARGUMENTS@" == "TRUE":
config.available_features.add('plus_zero_runtime')
+else:
+ config.available_features.add('plus_one_runtime')
# Let the main config do the real work.
if config.test_exec_root is None:
diff --git a/test/stdlib/CodableTests.swift b/test/stdlib/CodableTests.swift
index 8498145..566398c 100644
--- a/test/stdlib/CodableTests.swift
+++ b/test/stdlib/CodableTests.swift
@@ -117,7 +117,7 @@
// MARK: - Tests
class TestCodable : TestCodableSuper {
// MARK: - AffineTransform
-#if os(OSX)
+#if os(macOS)
lazy var affineTransformValues: [Int : AffineTransform] = [
#line : AffineTransform.identity,
#line : AffineTransform(),
@@ -776,7 +776,7 @@
"test_UUID_Plist" : TestCodable.test_UUID_Plist,
]
-#if os(OSX)
+#if os(macOS)
tests["test_AffineTransform_JSON"] = TestCodable.test_AffineTransform_JSON
tests["test_AffineTransform_Plist"] = TestCodable.test_AffineTransform_Plist
#endif
diff --git a/test/stdlib/ErrorHandling.swift b/test/stdlib/ErrorHandling.swift
index b733542..ea5d427 100644
--- a/test/stdlib/ErrorHandling.swift
+++ b/test/stdlib/ErrorHandling.swift
@@ -1,9 +1,6 @@
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
-// FIXME: <https://bugs.swift.org/browse/SR-7146> 2 tests are failing on linux in optimized mode
-// UNSUPPORTED: OS=linux-gnu
-
//
// Tests for error handling in standard library APIs.
//
diff --git a/test/stdlib/FloatConstants.swift b/test/stdlib/FloatConstants.swift
index e3847f4..5d40927 100644
--- a/test/stdlib/FloatConstants.swift
+++ b/test/stdlib/FloatConstants.swift
@@ -1,6 +1,6 @@
// RUN: %target-typecheck-verify-swift
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
import Glibc
diff --git a/test/stdlib/FloatingPoint.swift.gyb b/test/stdlib/FloatingPoint.swift.gyb
index 24cd535..6df78cb 100644
--- a/test/stdlib/FloatingPoint.swift.gyb
+++ b/test/stdlib/FloatingPoint.swift.gyb
@@ -577,8 +577,8 @@
%for Self in ['Float', 'Double']:
FloatingPoint.test("${Self}.nextUp, .nextDown/nan") {
let x = ${Self}.nan
- expectBitwiseEqual(x, x.nextUp)
- expectBitwiseEqual(x, x.nextDown)
+ expectTrue(x.nextUp.isNaN)
+ expectTrue(x.nextDown.isNaN)
expectTrue((-x).nextDown.isNaN)
expectTrue((-x).nextUp.isNaN)
}
diff --git a/test/stdlib/MathConstants.swift b/test/stdlib/MathConstants.swift
index fd3c3a0..2ecc54d 100644
--- a/test/stdlib/MathConstants.swift
+++ b/test/stdlib/MathConstants.swift
@@ -1,6 +1,6 @@
// RUN: %target-typecheck-verify-swift
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
import Glibc
diff --git a/test/stdlib/Metal.swift b/test/stdlib/Metal.swift
index cb6d50e..682df24 100644
--- a/test/stdlib/Metal.swift
+++ b/test/stdlib/Metal.swift
@@ -72,7 +72,7 @@
/* Setup */
let device = MTLCreateSystemDefaultDevice()!
- #if os(OSX)
+ #if os(macOS)
let options = MTLResourceOptions.storageModeManaged
#else
let options = MTLResourceOptions.storageModePrivate
@@ -81,7 +81,7 @@
/* Call APIs */
- #if os(OSX)
+ #if os(macOS)
buf.didModifyRange(0..<4)
#endif
buf.addDebugMarker("test marker", range: 0..<4)
@@ -97,7 +97,7 @@
let queue = device.makeCommandQueue()!
let cmdBuf = queue.makeCommandBuffer()!
- #if os(OSX)
+ #if os(macOS)
let options = MTLResourceOptions.storageModeManaged
#else
let options = MTLResourceOptions.storageModePrivate
@@ -162,7 +162,7 @@
let queue = device.makeCommandQueue()!
let cmdBuf = queue.makeCommandBuffer()!
- #if os(OSX)
+ #if os(macOS)
let options = MTLResourceOptions.storageModeManaged
#else
let options = MTLResourceOptions.storageModePrivate
@@ -182,7 +182,7 @@
let encoder = cmdBuf.makeRenderCommandEncoder(descriptor: rpDesc)!
encoder.useResources([buf], usage: MTLResourceUsage.read)
encoder.useHeaps([heap])
- #if os(OSX)
+ #if os(macOS)
encoder.setViewports([MTLViewport()])
encoder.setScissorRects([MTLScissorRect(x:0, y:0, width:1, height:1)])
#endif
diff --git a/test/stdlib/NSStringAPI.swift b/test/stdlib/NSStringAPI.swift
index ac7bd20..cf9afb9 100644
--- a/test/stdlib/NSStringAPI.swift
+++ b/test/stdlib/NSStringAPI.swift
@@ -1329,7 +1329,7 @@
}
func getHomeDir() -> String {
-#if os(OSX)
+#if os(macOS)
return String(cString: getpwuid(getuid()).pointee.pw_dir)
#elseif os(iOS) || os(tvOS) || os(watchOS)
// getpwuid() returns null in sandboxed apps under iOS simulator.
diff --git a/test/stdlib/NSValueBridging.swift.gyb b/test/stdlib/NSValueBridging.swift.gyb
index 685aadf..5b322b8 100644
--- a/test/stdlib/NSValueBridging.swift.gyb
+++ b/test/stdlib/NSValueBridging.swift.gyb
@@ -59,7 +59,7 @@
// For historic reasons, macOS has different NSValue methods for the
// CoreGraphics types from other Apple platforms.
-#if os(OSX)
+#if os(macOS)
${ testCase("CGRect", "CGRect(x: 17, y: 38, width: 6, height: 79)", "rect", "(==)") }
${ testCase("CGPoint", "CGPoint(x: 17, y: 38)", "point", "(==)") }
diff --git a/test/stdlib/Reflection_objc.swift b/test/stdlib/Reflection_objc.swift
index 28286f7..414221c 100644
--- a/test/stdlib/Reflection_objc.swift
+++ b/test/stdlib/Reflection_objc.swift
@@ -15,7 +15,7 @@
import Swift
import Foundation
-#if os(OSX)
+#if os(macOS)
import AppKit
typealias OSImage = NSImage
diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb
index e386aac..67ee2bf 100644
--- a/test/stdlib/Runtime.swift.gyb
+++ b/test/stdlib/Runtime.swift.gyb
@@ -9,7 +9,7 @@
import StdlibUnittest
import SwiftShims
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
import Darwin
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android)
import Glibc
@@ -553,7 +553,7 @@
}
Runtime.test("SwiftError layout constants for LLDB") {
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
#elseif os(Linux)
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
@@ -565,7 +565,7 @@
dlsym(RTLD_DEFAULT, "_swift_lldb_offsetof_SwiftError_typeMetadata")!
let sizeof_SwiftError =
dlsym(RTLD_DEFAULT, "_swift_lldb_sizeof_SwiftError")!
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
+#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
#if arch(i386) || arch(arm)
expectEqual(20, offsetof_SwiftError_typeMetadata.load(as: UInt.self))
expectEqual(36, sizeof_SwiftError.load(as: UInt.self))
@@ -1671,7 +1671,7 @@
// _stdlib_isOSVersionAtLeast is broken for
// watchOS. rdar://problem/20234735
-#if os(OSX) || os(iOS) || os(tvOS) || os(watchOS)
+#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
// This test assumes that no version component on an OS we test upon
// will ever be greater than 1066 and that every major version will always
// be greater than 1.
diff --git a/test/stdlib/TestAffineTransform.swift b/test/stdlib/TestAffineTransform.swift
index ad2b07a..a0b384a 100644
--- a/test/stdlib/TestAffineTransform.swift
+++ b/test/stdlib/TestAffineTransform.swift
@@ -12,7 +12,7 @@
import Foundation
-#if os(OSX)
+#if os(macOS)
#if FOUNDATION_XCTEST
import XCTest
diff --git a/test/stdlib/TestURL.swift b/test/stdlib/TestURL.swift
index 637e043..8c0128c 100644
--- a/test/stdlib/TestURL.swift
+++ b/test/stdlib/TestURL.swift
@@ -67,7 +67,7 @@
}
}
-#if os(OSX)
+#if os(macOS)
func testQuarantineProperties() {
// Test the quarantine stuff; it has special logic
if #available(OSX 10.11, iOS 9.0, *) {
@@ -383,7 +383,7 @@
URLTests.test("testBasics") { TestURL().testBasics() }
URLTests.test("testProperties") { TestURL().testProperties() }
URLTests.test("testSetProperties") { TestURL().testSetProperties() }
-#if os(OSX)
+#if os(macOS)
URLTests.test("testQuarantineProperties") { TestURL().testQuarantineProperties() }
#endif
URLTests.test("testMoreSetProperties") { TestURL().testMoreSetProperties() }
diff --git a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake
index 441c019..6b8b3f3 100644
--- a/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake
+++ b/tools/SourceKit/cmake/modules/AddSwiftSourceKit.cmake
@@ -238,9 +238,9 @@
add_dependencies(${name} ${LLVM_COMMON_DEPENDS})
endif()
- target_link_libraries(${name} ${SOURCEKITEXE_LINK_LIBS})
+ target_link_libraries(${name} PRIVATE ${SOURCEKITEXE_LINK_LIBS})
swift_common_llvm_config(${name} ${SOURCEKITEXE_LLVM_COMPONENT_DEPENDS})
- target_link_libraries(${name} ${LLVM_COMMON_LIBS})
+ target_link_libraries(${name} PRIVATE ${LLVM_COMMON_LIBS})
set_target_properties(${name} PROPERTIES FOLDER "SourceKit executables")
if (NOT SWIFT_ASAN_BUILD)
@@ -422,9 +422,9 @@
add_dependencies(${name} ${LLVM_COMMON_DEPENDS})
endif(LLVM_COMMON_DEPENDS)
- target_link_libraries(${name} ${SOURCEKITXPC_LINK_LIBS})
+ target_link_libraries(${name} PRIVATE ${SOURCEKITXPC_LINK_LIBS})
swift_common_llvm_config(${name} ${SOURCEKITXPC_LLVM_COMPONENT_DEPENDS})
- target_link_libraries(${name} ${LLVM_COMMON_LIBS})
+ target_link_libraries(${name} PRIVATE ${LLVM_COMMON_LIBS})
add_dependencies(${framework_target} ${name})
diff --git a/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp b/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp
index b42a3ed..5a12804 100644
--- a/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp
+++ b/tools/SourceKit/lib/Support/ImmutableTextBuffer.cpp
@@ -177,7 +177,8 @@
Length += I.piece().size();
}
- auto MemBuf = llvm::MemoryBuffer::getNewUninitMemBuffer(Length, Filename);
+ auto MemBuf =
+ llvm::WritableMemoryBuffer::getNewUninitMemBuffer(Length, Filename);
char *Ptr = (char*)MemBuf->getBufferStart();
for (RewriteRope::iterator I = Rope.begin(), E = Rope.end(); I != E;
I.MoveToNextPiece()) {
@@ -186,7 +187,7 @@
Ptr += Text.size();
}
- return MemBuf;
+ return std::move(MemBuf);
}
ImmutableTextBufferRef EditableTextBuffer::getBufferForSnapshot(
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
index c756578..7804d6c 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
@@ -156,10 +156,11 @@
}
const char *Position = InputFile->getBufferStart() + CodeCompletionOffset;
- std::unique_ptr<llvm::MemoryBuffer> NewBuffer =
- llvm::MemoryBuffer::getNewUninitMemBuffer(InputFile->getBufferSize() + 1,
+ std::unique_ptr<llvm::WritableMemoryBuffer> NewBuffer =
+ llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
+ InputFile->getBufferSize() + 1,
InputFile->getBufferIdentifier());
- char *NewBuf = const_cast<char*>(NewBuffer->getBufferStart());
+ char *NewBuf = NewBuffer->getBufferStart();
char *NewPos = std::copy(InputFile->getBufferStart(), Position, NewBuf);
*NewPos = '\0';
std::copy(Position, InputFile->getBufferEnd(), NewPos+1);
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/CompactArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/CompactArray.cpp
index 8f9f978..914a4a3 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/CompactArray.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/CompactArray.cpp
@@ -71,10 +71,10 @@
std::unique_ptr<llvm::MemoryBuffer>
CompactArrayBuilderImpl::createBuffer() const {
- std::unique_ptr<llvm::MemoryBuffer> Buf;
- Buf = llvm::MemoryBuffer::getNewUninitMemBuffer(sizeInBytes());
- copyInto(const_cast<char *>(Buf->getBufferStart()), Buf->getBufferSize());
- return Buf;
+ std::unique_ptr<llvm::WritableMemoryBuffer> Buf;
+ Buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(sizeInBytes());
+ copyInto(Buf->getBufferStart(), Buf->getBufferSize());
+ return std::move(Buf);
}
void CompactArrayBuilderImpl::appendTo(SmallVectorImpl<char> &Buf) const {
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
index c03f0d8..c71cb00 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/DocStructureArray.cpp
@@ -249,11 +249,11 @@
// * offset of top structure array (relative to structure array section) (1)
size_t headerSize = sizeof(uint64_t) * 6;
- auto result = llvm::MemoryBuffer::getNewUninitMemBuffer(
+ auto result = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
inheritedTypesBufferSize + attrsBufferSize + elementsBufferSize +
structureArrayBufferSize + structureBufferSize + headerSize);
- char *start = const_cast<char *>(result->getBufferStart());
+ char *start = result->getBufferStart();
char *headerPtr = start;
char *ptr = start + headerSize;
@@ -277,7 +277,7 @@
assert(headerPtr == start + (headerSize - sizeof(topOffset)));
memcpy(headerPtr, &topOffset, sizeof(topOffset));
- return result;
+ return std::move(result);
}
namespace {
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
index 4dedc75..60dffda 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/sourcekitdAPI-XPC.cpp
@@ -245,7 +245,7 @@
CustomBufferKind Kind, std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
std::unique_ptr<llvm::MemoryBuffer> CustomBuf;
- CustomBuf = llvm::MemoryBuffer::getNewUninitMemBuffer(
+ CustomBuf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(
sizeof(uint64_t) + MemBuf->getBufferSize());
char *BufPtr = (char*)CustomBuf->getBufferStart();
*reinterpret_cast<uint64_t*>(BufPtr) = (uint64_t)Kind;
diff --git a/tools/SwiftSyntax/SyntaxNodes.swift.gyb b/tools/SwiftSyntax/SyntaxNodes.swift.gyb
index 7df2872..2d57718 100644
--- a/tools/SwiftSyntax/SyntaxNodes.swift.gyb
+++ b/tools/SwiftSyntax/SyntaxNodes.swift.gyb
@@ -196,7 +196,7 @@
% end
% for trait in TRAITS:
-public protocol ${trait.trait_name}Syntax {
+public protocol ${trait.trait_name}Syntax: Syntax {
% for child in trait.children:
% ret_type = child.type_name
% if child.is_optional:
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index cd9f779..766d3d4 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -13,7 +13,7 @@
)
if(HAVE_UNICODE_LIBEDIT)
- target_link_libraries(swift edit)
+ target_link_libraries(swift PRIVATE edit)
endif()
swift_create_post_build_symlink(swift
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index 1467da4..57a9951 100644
--- a/tools/sil-opt/SILOpt.cpp
+++ b/tools/sil-opt/SILOpt.cpp
@@ -326,7 +326,7 @@
SILOpts.EnableSILOwnership = EnableSILOwnershipOpt;
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
- SILOpts.EnableGuaranteedNormalArguments =
+ SILOpts.EnableGuaranteedNormalArguments |=
EnableGuaranteedNormalArguments;
SILOpts.VerifyExclusivity = VerifyExclusivity;
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index fbf14b9..8a41b3e 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -939,7 +939,7 @@
SDKNodeInitInfo Info(Ctx);
NodeVector Children;
- for (auto Pair : *Node) {
+ for (auto &Pair : *Node) {
switch(parseKeyKind(GetScalarString(Pair.getKey()))) {
case KeyKind::KK_kind:
Kind = parseSDKNodeKind(GetScalarString(Pair.getValue()));
diff --git a/tools/swift-ide-test/CMakeLists.txt b/tools/swift-ide-test/CMakeLists.txt
index e260cab..a3afd93 100644
--- a/tools/swift-ide-test/CMakeLists.txt
+++ b/tools/swift-ide-test/CMakeLists.txt
@@ -14,7 +14,7 @@
# If libxml2 is available, make it available for swift-ide-test.
if(SWIFT_HAVE_LIBXML)
include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
- target_link_libraries(swift-ide-test ${LIBXML2_LIBRARIES})
+ target_link_libraries(swift-ide-test PRIVATE ${LIBXML2_LIBRARIES})
add_definitions(-DSWIFT_HAVE_LIBXML="1")
endif()
@@ -23,4 +23,4 @@
SOURCE "${SWIFT_SOURCE_DIR}/utils/swift-api-dump.py"
DESTINATION "${SWIFT_RUNTIME_OUTPUT_INTDIR}/swift-api-dump.py"
COMMENT "Creating development symlink for swift-api-dump.py.")
-
\ No newline at end of file
+
diff --git a/tools/swift-llvm-opt/LLVMOpt.cpp b/tools/swift-llvm-opt/LLVMOpt.cpp
index a744f42..2a7de50 100644
--- a/tools/swift-llvm-opt/LLVMOpt.cpp
+++ b/tools/swift-llvm-opt/LLVMOpt.cpp
@@ -37,7 +37,7 @@
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeWriterPass.h"
-#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/CommandFlags.def"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
@@ -136,7 +136,7 @@
return TheTarget->createTargetMachine(
TheTriple.getTriple(), CPUStr, FeaturesStr, Options,
- Optional<Reloc::Model>(RelocModel), CMModel, GetCodeGenOptLevel());
+ Optional<Reloc::Model>(RelocModel), getCodeModel(), GetCodeGenOptLevel());
}
static void dumpOutput(llvm::Module &M, llvm::raw_ostream &os) {
@@ -271,14 +271,14 @@
M->setTargetTriple(llvm::Triple::normalize(TargetTriple));
// Figure out what stream we are supposed to write to...
- std::unique_ptr<llvm::tool_output_file> Out;
+ std::unique_ptr<llvm::ToolOutputFile> Out;
// Default to standard output.
if (OutputFilename.empty())
OutputFilename = "-";
std::error_code EC;
Out.reset(
- new llvm::tool_output_file(OutputFilename, EC, llvm::sys::fs::F_None));
+ new llvm::ToolOutputFile(OutputFilename, EC, llvm::sys::fs::F_None));
if (EC) {
errs() << EC.message() << '\n';
return 1;
diff --git a/tools/swift-remoteast-test/CMakeLists.txt b/tools/swift-remoteast-test/CMakeLists.txt
index 9ae0bb0..73f5ac4 100644
--- a/tools/swift-remoteast-test/CMakeLists.txt
+++ b/tools/swift-remoteast-test/CMakeLists.txt
@@ -8,7 +8,7 @@
set_target_properties(swift-remoteast-test PROPERTIES ENABLE_EXPORTS 1)
if(HAVE_UNICODE_LIBEDIT)
- target_link_libraries(swift-remoteast-test edit)
+ target_link_libraries(swift-remoteast-test PRIVATE edit)
endif()
# If building as part of clang, make sure the headers are installed.
diff --git a/tools/swift-stdlib-tool/CMakeLists.txt b/tools/swift-stdlib-tool/CMakeLists.txt
index 0de9578..a585b1b 100644
--- a/tools/swift-stdlib-tool/CMakeLists.txt
+++ b/tools/swift-stdlib-tool/CMakeLists.txt
@@ -2,7 +2,7 @@
swift-stdlib-tool.mm)
find_library(FOUNDATION NAMES Foundation)
-target_link_libraries(swift-stdlib-tool ${FOUNDATION})
+target_link_libraries(swift-stdlib-tool PRIVATE ${FOUNDATION})
swift_install_in_component(compiler
TARGETS swift-stdlib-tool
diff --git a/unittests/AST/CMakeLists.txt b/unittests/AST/CMakeLists.txt
index 5c58c84..12f912d 100644
--- a/unittests/AST/CMakeLists.txt
+++ b/unittests/AST/CMakeLists.txt
@@ -7,6 +7,7 @@
)
target_link_libraries(SwiftASTTests
+ PRIVATE
swiftAST
# FIXME: Circular dependencies.
swiftParse
diff --git a/unittests/Basic/CMakeLists.txt b/unittests/Basic/CMakeLists.txt
index 74613f7..4152a70 100644
--- a/unittests/Basic/CMakeLists.txt
+++ b/unittests/Basic/CMakeLists.txt
@@ -35,6 +35,7 @@
add_dependencies(SwiftBasicTests "${gyb_dependency_targets}")
target_link_libraries(SwiftBasicTests
+ PRIVATE
swiftBasic
clangBasic
)
diff --git a/unittests/Driver/CMakeLists.txt b/unittests/Driver/CMakeLists.txt
index d96dd4a..d85fc16 100644
--- a/unittests/Driver/CMakeLists.txt
+++ b/unittests/Driver/CMakeLists.txt
@@ -3,5 +3,6 @@
)
target_link_libraries(SwiftDriverTests
+ PRIVATE
swiftDriver
)
diff --git a/unittests/IDE/CMakeLists.txt b/unittests/IDE/CMakeLists.txt
index ce0e38f..f55846d 100644
--- a/unittests/IDE/CMakeLists.txt
+++ b/unittests/IDE/CMakeLists.txt
@@ -3,5 +3,6 @@
Placeholders.cpp
)
target_link_libraries(SwiftIDETests
+ PRIVATE
swiftIDE
)
diff --git a/unittests/Parse/CMakeLists.txt b/unittests/Parse/CMakeLists.txt
index b7c2f38..1eb943d 100644
--- a/unittests/Parse/CMakeLists.txt
+++ b/unittests/Parse/CMakeLists.txt
@@ -6,6 +6,7 @@
)
target_link_libraries(SwiftParseTests
+ PRIVATE
swiftSIL
swiftClangImporter
swiftParse
diff --git a/unittests/Reflection/CMakeLists.txt b/unittests/Reflection/CMakeLists.txt
index 91ce58d..0354f0c 100644
--- a/unittests/Reflection/CMakeLists.txt
+++ b/unittests/Reflection/CMakeLists.txt
@@ -4,6 +4,7 @@
add_swift_unittest(SwiftReflectionTests
TypeRef.cpp)
target_link_libraries(SwiftReflectionTests
+ PRIVATE
swiftReflection${SWIFT_PRIMARY_VARIANT_SUFFIX})
endif()
endif()
diff --git a/unittests/SourceKit/Support/CMakeLists.txt b/unittests/SourceKit/Support/CMakeLists.txt
index 5f0e79d..da17a05 100644
--- a/unittests/SourceKit/Support/CMakeLists.txt
+++ b/unittests/SourceKit/Support/CMakeLists.txt
@@ -4,5 +4,6 @@
)
target_link_libraries(SourceKitSupportTests
+ PRIVATE
SourceKitSupport
)
diff --git a/unittests/SourceKit/SwiftLang/CMakeLists.txt b/unittests/SourceKit/SwiftLang/CMakeLists.txt
index fc89375..ca018cc 100644
--- a/unittests/SourceKit/SwiftLang/CMakeLists.txt
+++ b/unittests/SourceKit/SwiftLang/CMakeLists.txt
@@ -6,6 +6,7 @@
)
target_link_libraries(SourceKitSwiftLangTests
+ PRIVATE
SourceKitSwiftLang
)
diff --git a/unittests/SwiftDemangle/CMakeLists.txt b/unittests/SwiftDemangle/CMakeLists.txt
index f080917..9ba1aeb 100644
--- a/unittests/SwiftDemangle/CMakeLists.txt
+++ b/unittests/SwiftDemangle/CMakeLists.txt
@@ -7,6 +7,7 @@
)
target_link_libraries(SwiftDemangleTests
+ PRIVATE
swiftDemangle
)
endif()
diff --git a/unittests/Syntax/CMakeLists.txt b/unittests/Syntax/CMakeLists.txt
index 1b9f0cf..20dc5d4 100644
--- a/unittests/Syntax/CMakeLists.txt
+++ b/unittests/Syntax/CMakeLists.txt
@@ -12,4 +12,5 @@
)
target_link_libraries(SwiftSyntaxTests
+ PRIVATE
swiftSyntax)
diff --git a/unittests/runtime/CMakeLists.txt b/unittests/runtime/CMakeLists.txt
index 5d1c174..e504de1 100644
--- a/unittests/runtime/CMakeLists.txt
+++ b/unittests/runtime/CMakeLists.txt
@@ -56,6 +56,7 @@
# FIXME: cross-compile for all variants.
target_link_libraries(SwiftRuntimeTests
+ PRIVATE
swiftCore${SWIFT_PRIMARY_VARIANT_SUFFIX}
${PLATFORM_TARGET_LINK_LIBRARIES}
${swift_runtime_test_extra_libraries}
diff --git a/unittests/runtime/LongTests/CMakeLists.txt b/unittests/runtime/LongTests/CMakeLists.txt
index 665cf5e..7b77ddb 100644
--- a/unittests/runtime/LongTests/CMakeLists.txt
+++ b/unittests/runtime/LongTests/CMakeLists.txt
@@ -48,6 +48,7 @@
# FIXME: cross-compile for all variants.
target_link_libraries(SwiftRuntimeLongTests
+ PRIVATE
swiftCore${SWIFT_PRIMARY_VARIANT_SUFFIX}
${PLATFORM_TARGET_LINK_LIBRARIES}
${swift_runtime_test_extra_libraries}
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 1f885b3..b7e70e3 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -70,7 +70,7 @@
llvm-num-parallel-lto-link-jobs "" "The number of parallel link jobs to use when compiling llvm"
swift-stdlib-build-type "Debug" "the CMake build variant for Swift"
swift-stdlib-enable-assertions "1" "enable assertions in Swift"
- swift-stdlib-enable-resilience "0" "build the Swift stdlib and overlays with resilience enabled"
+ swift-stdlib-enable-resilience "1" "build the Swift stdlib and overlays with resilience enabled"
swift-stdlib-use-nonatomic-rc "0" "build the Swift stdlib and overlays with nonatomic reference count operations enabled"
lldb-build-type "Debug" "the CMake build variant for LLDB"
lldb-build-with-xcode "1" "Use xcodebuild to build LLDB, instead of CMake"
@@ -2346,6 +2346,15 @@
fi
;;
esac
+ if [[ "${BUILD_TOOLCHAIN_ONLY}" ]]; then
+ cmake_options+=(
+ -DLLDB_INCLUDE_TESTS=NO
+ )
+ else
+ cmake_options+=(
+ -DLLDB_INCLUDE_TESTS=YES
+ )
+ fi
;;
llbuild)
cmake_options=(
@@ -2823,16 +2832,17 @@
fi
call mkdir -p "${results_dir}"
with_pushd "${results_dir}" \
- call env SWIFTCC="$(build_directory $LOCAL_HOST swift)/bin/swiftc" \
- SWIFTLIBS="${swift_build_dir}/lib/swift" \
- "${LLDB_SOURCE_DIR}"/test/dotest.py \
- --executable "${lldb_executable}" \
- ${LLDB_TEST_DEBUG_SERVER} \
- ${LLDB_TEST_SUBDIR_CLAUSE} \
- ${LLDB_TEST_CATEGORIES} \
- ${LLDB_DOTEST_CC_OPTS} \
- ${LLDB_FORMATTER_OPTS} \
- -E "${DOTEST_EXTRA}"
+ call env SWIFTCC="$(build_directory $LOCAL_HOST swift)/bin/swiftc" \
+ SWIFTLIBS="${swift_build_dir}/lib/swift" \
+ "${LLDB_SOURCE_DIR}"/test/dotest.py \
+ --executable "${lldb_executable}" \
+ ${LLDB_TEST_DEBUG_SERVER} \
+ ${LLDB_TEST_SUBDIR_CLAUSE} \
+ ${LLDB_TEST_CATEGORIES} \
+ ${LLDB_DOTEST_CC_OPTS} \
+ ${LLDB_FORMATTER_OPTS} \
+ --build-dir "${lldb_build_dir}/lldb-test-build.noindex" \
+ -E "${DOTEST_EXTRA}"
continue
;;
llbuild)
diff --git a/validation-test/stdlib/FixedPoint.swift.gyb b/validation-test/stdlib/FixedPoint.swift.gyb
index 6cecc0c..f405b05 100644
--- a/validation-test/stdlib/FixedPoint.swift.gyb
+++ b/validation-test/stdlib/FixedPoint.swift.gyb
@@ -51,15 +51,6 @@
if dst <= ((1 << (dst_bits - 1)) - 1):
return dst
return dst - mask - 1
-
-def get_fixed_point_hash(bit_pattern, src_bits, word_bits):
- if src_bits <= word_bits:
- bit_pattern = prepare_bit_pattern(bit_pattern, src_bits, True)
- return prepare_bit_pattern(bit_pattern, word_bits, True)
- if src_bits == word_bits * 2:
- return prepare_bit_pattern(
- bit_pattern ^ (bit_pattern >> 32), word_bits, True)
-
}%
//===----------------------------------------------------------------------===//
@@ -250,8 +241,15 @@
% input = prepare_bit_pattern(bit_pattern, self_ty.bits, self_ty.is_signed)
let input = get${Self}(${input})
let output = getInt(input.hashValue)
- let expected = getInt(${get_fixed_point_hash(input, self_ty.bits, word_bits)})
- expectEqual(expected, output)
+
+ var hasher = _SipHash13(key: _Hasher._secretKey)
+% if prepare_bit_pattern(input, word_bits, self_ty.is_signed) == input:
+ hasher.append(${input} as ${"" if self_ty.is_signed else "U"}Int)
+% else:
+ hasher.append(input)
+% end
+ let expected = getInt(Int(truncatingIfNeeded: hasher.finalize()))
+ expectEqual(expected, output, "input: \(input)")
}
% end
@@ -269,7 +267,6 @@
${gyb.execute_template(
hash_value_test_template,
prepare_bit_pattern=prepare_bit_pattern,
- get_fixed_point_hash=get_fixed_point_hash,
test_bit_patterns=test_bit_patterns,
word_bits=32)}
@@ -278,7 +275,6 @@
${gyb.execute_template(
hash_value_test_template,
prepare_bit_pattern=prepare_bit_pattern,
- get_fixed_point_hash=get_fixed_point_hash,
test_bit_patterns=test_bit_patterns,
word_bits=64)}
diff --git a/validation-test/stdlib/Hashing.swift b/validation-test/stdlib/Hashing.swift
index 0018c42..a88498d 100644
--- a/validation-test/stdlib/Hashing.swift
+++ b/validation-test/stdlib/Hashing.swift
@@ -8,109 +8,65 @@
var HashingTestSuite = TestSuite("Hashing")
-HashingTestSuite.test("_mixUInt32/GoldenValues") {
- expectEqual(0x11b882c9, _mixUInt32(0x0))
- expectEqual(0x60d0aafb, _mixUInt32(0x1))
- expectEqual(0x636847b5, _mixUInt32(0xffff))
- expectEqual(0x203f5350, _mixUInt32(0xffff_ffff))
-
- expectEqual(0xb8747ef6, _mixUInt32(0xa62301f9))
- expectEqual(0xef4eeeb2, _mixUInt32(0xfe1b46c6))
- expectEqual(0xd44c9cf1, _mixUInt32(0xe4daf7ca))
- expectEqual(0xfc1eb1de, _mixUInt32(0x33ff6f5c))
- expectEqual(0x5605f0c0, _mixUInt32(0x13c2a2b8))
- expectEqual(0xd9c48026, _mixUInt32(0xf3ad1745))
- expectEqual(0x471ab8d0, _mixUInt32(0x656eff5a))
- expectEqual(0xfe265934, _mixUInt32(0xfd2268c9))
+func checkHash(
+ for value: UInt64,
+ withKey key: (UInt64, UInt64),
+ expected: UInt64,
+ file: String = #file, line: UInt = #line
+) {
+ var hasher = _Hasher(key: key)
+ hasher.append(bits: value)
+ let hash = hasher.finalize()
+ expectEqual(
+ hash, Int(truncatingIfNeeded: expected),
+ file: file, line: line)
}
-HashingTestSuite.test("_mixInt32/GoldenValues") {
- expectEqual(Int32(bitPattern: 0x11b882c9 as UInt32), _mixInt32(0x0))
+HashingTestSuite.test("_Hasher/CustomKeys") {
+ // This assumes _Hasher implements SipHash-1-3.
+ checkHash(for: 0, withKey: (0, 0), expected: 0xbd60acb658c79e45)
+ checkHash(for: 0, withKey: (0, 1), expected: 0x1ce32b0b44e61175)
+ checkHash(for: 0, withKey: (1, 0), expected: 0x9c44b7c8df2ca74b)
+ checkHash(for: 0, withKey: (1, 1), expected: 0x9653ca0a3b455506)
+ checkHash(for: 0, withKey: (.max, .max), expected: 0x3ab336a4895e4d36)
+
+ checkHash(for: 1, withKey: (0, 0), expected: 0x1e9f734161d62dd9)
+ checkHash(for: 1, withKey: (0, 1), expected: 0xb6fcf32d09f76cba)
+ checkHash(for: 1, withKey: (1, 0), expected: 0xacb556b13007504a)
+ checkHash(for: 1, withKey: (1, 1), expected: 0x7defec680db51d24)
+ checkHash(for: 1, withKey: (.max, .max), expected: 0x212798441870ef6b)
+
+ checkHash(for: .max, withKey: (0, 0), expected: 0x2f205be2fec8e38d)
+ checkHash(for: .max, withKey: (0, 1), expected: 0x3ff7fa33381ecf7b)
+ checkHash(for: .max, withKey: (1, 0), expected: 0x404afd8eb2c4b22a)
+ checkHash(for: .max, withKey: (1, 1), expected: 0x855642d657c1bd46)
+ checkHash(for: .max, withKey: (.max, .max), expected: 0x5b16b7a8181980c2)
}
-HashingTestSuite.test("_mixUInt64/GoldenValues") {
- expectEqual(0xb2b2_4f68_8dc4_164d, _mixUInt64(0x0))
- expectEqual(0x792e_33eb_0685_57de, _mixUInt64(0x1))
- expectEqual(0x9ec4_3423_1b42_3dab, _mixUInt64(0xffff))
- expectEqual(0x4cec_e9c9_01fa_9a84, _mixUInt64(0xffff_ffff))
- expectEqual(0xcba5_b650_bed5_b87c, _mixUInt64(0xffff_ffff_ffff))
- expectEqual(0xe583_5646_3fb8_ac99, _mixUInt64(0xffff_ffff_ffff_ffff))
+HashingTestSuite.test("_Hasher/DefaultKey") {
+ let value: UInt64 = 0x0102030405060708
- expectEqual(0xf5d0079f828d43a5, _mixUInt64(0x94ce7d9319f8d233))
- expectEqual(0x61900a6be9db9c3f, _mixUInt64(0x2728821e8c5b1f7))
- expectEqual(0xf2fd34b1b7d4b46e, _mixUInt64(0xe7f67ec98c64f482))
- expectEqual(0x216199ed628c821, _mixUInt64(0xd7c277b5438873ac))
- expectEqual(0xb1b486ff5f2e0e53, _mixUInt64(0x8399f1d563c42f82))
- expectEqual(0x61acc92bd91c030, _mixUInt64(0x488cefd48a2c4bfd))
- expectEqual(0xa7a52d6e4a8e3ddf, _mixUInt64(0x270a15116c351f95))
- expectEqual(0x98ceedc363c4e56a, _mixUInt64(0xe5fb9b5f6c426a84))
+ let defaultHash = _hashValue(for: value)
+
+ var defaultHasher = _Hasher()
+ defaultHasher.append(bits: value)
+ expectEqual(defaultHasher.finalize(), defaultHash)
+
+ var customHasher = _Hasher(key: _Hasher._secretKey)
+ customHasher.append(bits: value)
+ expectEqual(customHasher.finalize(), defaultHash)
}
-HashingTestSuite.test("_mixUInt64/GoldenValues") {
- expectEqual(Int64(bitPattern: 0xb2b2_4f68_8dc4_164d as UInt64), _mixInt64(0x0))
-}
+HashingTestSuite.test("_Hasher/keyOverride") {
+ let value: UInt64 = 0x0102030405060708
+ let expected = Int(truncatingIfNeeded: 0x661dac5d71c78013 as UInt64)
-HashingTestSuite.test("_mixUInt/GoldenValues") {
-#if arch(i386) || arch(arm)
- expectEqual(0x11b8_82c9, _mixUInt(0x0))
-#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
- expectEqual(0xb2b2_4f68_8dc4_164d, _mixUInt(0x0))
-#else
- fatalError("unimplemented")
-#endif
-}
+ let originalKey = _Hasher._secretKey
+ _Hasher._secretKey = (1, 2)
+ let hash = _hashValue(for: value)
+ _Hasher._secretKey = originalKey
-HashingTestSuite.test("_mixInt/GoldenValues") {
-#if arch(i386) || arch(arm)
- expectEqual(Int(bitPattern: 0x11b8_82c9 as UInt), _mixInt(0x0))
-#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
- expectEqual(Int(bitPattern: 0xb2b2_4f68_8dc4_164d as UInt), _mixInt(0x0))
-#else
- fatalError("unimplemented")
-#endif
-}
-
-HashingTestSuite.test("_squeezeHashValue/Int") {
- // Check that the function can return values that cover the whole range.
- func checkRange(_ r: Int) {
- var results = Set<Int>()
- for _ in 0..<(14 * r) {
- let v = _squeezeHashValue(randInt(), r)
- expectTrue(v < r)
- results.insert(v)
- }
- expectEqual(r, results.count)
- }
- checkRange(1)
- checkRange(2)
- checkRange(4)
- checkRange(8)
- checkRange(16)
-}
-
-HashingTestSuite.test("String/hashValue/topBitsSet") {
-#if _runtime(_ObjC)
-#if arch(x86_64) || arch(arm64)
- // Make sure that we don't accidentally throw away bits by storing the result
- // of NSString.hash into an int in the runtime.
-
- // This is the bit pattern that we xor to NSString's hash value.
- let hashOffset = UInt(bitPattern: 0x429b_1266_0000_0000 as Int)
- let hash = "efghijkl".hashValue
- // When we are not equal to the top bit of the xor'ed hashOffset pattern
- // there where some bits set.
- let topHashBits = UInt(bitPattern: hash) & 0xffff_ffff_0000_0000
- expectTrue(hash > 0)
- expectTrue(topHashBits != hashOffset)
-#endif
-#endif
-}
-
-HashingTestSuite.test("overridePerExecutionHashSeed/overflow") {
- // Test that we don't use checked arithmetic on the seed.
- _HashingDetail.fixedSeedOverride = UInt64.max
- expectEqual(0x4344_dc3a_239c_3e81, _mixUInt64(0xffff_ffff_ffff_ffff))
- _HashingDetail.fixedSeedOverride = 0
+ expectEqual(hash, expected)
}
runAllTests()
diff --git a/validation-test/stdlib/HashingAvalanche.swift b/validation-test/stdlib/HashingAvalanche.swift
index 51b89da..09b3365 100644
--- a/validation-test/stdlib/HashingAvalanche.swift
+++ b/validation-test/stdlib/HashingAvalanche.swift
@@ -47,12 +47,12 @@
// White-box testing: assume that the other N-bit to N-bit mixing functions
// just dispatch to these. (Avalanche test is relatively expensive.)
-HashingTestSuite.test("_mixUInt64/avalanche") {
- avalancheTest(64, _mixUInt64, 0.02)
+HashingTestSuite.test("_Hasher.append(UInt64)/avalanche") {
+ avalancheTest(64, { UInt64(truncatingIfNeeded: _hashValue(for: $0)) }, 0.02)
}
-HashingTestSuite.test("_mixUInt32/avalanche") {
- avalancheTest(32, { UInt64(_mixUInt32(UInt32($0 & 0xffff_ffff))) }, 0.02)
+HashingTestSuite.test("_Hasher.append(UInt32)/avalanche") {
+ avalancheTest(32, { UInt64(truncatingIfNeeded: _hashValue(for: $0)) }, 0.02)
}
runAllTests()
diff --git a/validation-test/stdlib/SipHash.swift b/validation-test/stdlib/SipHash.swift
index cbf5edb..7bda072 100644
--- a/validation-test/stdlib/SipHash.swift
+++ b/validation-test/stdlib/SipHash.swift
@@ -243,12 +243,61 @@
#endif
}
+func loadPartialUnalignedUInt64LE(
+ from p: UnsafeRawPointer,
+ byteCount: Int
+) -> UInt64 {
+ _sanityCheck((0..<8).contains(byteCount))
+ var result: UInt64 = 0
+ if byteCount >= 1 { result |= UInt64(p.load(fromByteOffset: 0, as: UInt8.self)) }
+ if byteCount >= 2 { result |= UInt64(p.load(fromByteOffset: 1, as: UInt8.self)) &<< (8 as UInt64) }
+ if byteCount >= 3 { result |= UInt64(p.load(fromByteOffset: 2, as: UInt8.self)) &<< (16 as UInt64) }
+ if byteCount >= 4 { result |= UInt64(p.load(fromByteOffset: 3, as: UInt8.self)) &<< (24 as UInt64) }
+ if byteCount >= 5 { result |= UInt64(p.load(fromByteOffset: 4, as: UInt8.self)) &<< (32 as UInt64) }
+ if byteCount >= 6 { result |= UInt64(p.load(fromByteOffset: 5, as: UInt8.self)) &<< (40 as UInt64) }
+ if byteCount >= 7 { result |= UInt64(p.load(fromByteOffset: 6, as: UInt8.self)) &<< (48 as UInt64) }
+ return result
+}
+
+func loadPartialUnalignedUInt32LE(
+ from p: UnsafeRawPointer,
+ byteCount: Int
+) -> UInt32 {
+ _sanityCheck((0..<4).contains(byteCount))
+ var result: UInt32 = 0
+ if byteCount >= 1 { result |= UInt32(p.load(fromByteOffset: 0, as: UInt8.self)) }
+ if byteCount >= 2 { result |= UInt32(p.load(fromByteOffset: 1, as: UInt8.self)) &<< (8 as UInt32) }
+ if byteCount >= 3 { result |= UInt32(p.load(fromByteOffset: 2, as: UInt8.self)) &<< (16 as UInt32) }
+ return result
+}
+
+func loadPartialUnalignedUIntLE(
+ from p: UnsafeRawPointer,
+ byteCount: Int
+) -> UInt {
+#if arch(i386) || arch(arm)
+ return UInt(loadPartialUnalignedUInt32LE(from: p, byteCount: byteCount))
+#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
+ return UInt(loadPartialUnalignedUInt64LE(from: p, byteCount: byteCount))
+#endif
+}
+
% for data_type in ['Int', 'Int64', 'Int32']:
func loadUnaligned${data_type}LE(
from p: UnsafeRawPointer
) -> ${data_type} {
return ${data_type}(bitPattern: loadUnalignedU${data_type}LE(from: p))
}
+
+func loadPartialUnaligned${data_type}LE(
+ from p: UnsafeRawPointer,
+ byteCount: Int
+) -> ${data_type} {
+ return ${data_type}(
+ bitPattern: loadPartialUnalignedU${data_type}LE(
+ from: p,
+ byteCount: byteCount))
+}
% end
% for data_type in ['UInt', 'Int', 'UInt64', 'Int64', 'UInt32', 'Int32']:
@@ -257,85 +306,45 @@
) -> ${data_type} {
return ${data_type}(littleEndian: loadUnaligned${data_type}LE(from: p))
}
+func loadPartialUnaligned${data_type}(
+ from p: UnsafeRawPointer,
+ byteCount: Int
+) -> ${data_type} {
+ return ${data_type}(littleEndian:
+ loadPartialUnaligned${data_type}LE(from: p, byteCount: byteCount))
+}
% end
% for (Self, tests) in [
-% ('_SipHash13Context', 'sipHash13Tests'),
-% ('_SipHash24Context', 'sipHash24Tests')
+% ('_SipHash13', 'sipHash13Tests'),
+% ('_SipHash24', 'sipHash24Tests')
% ]:
-SipHashTests.test("${Self}/Oneshot").forEach(in: ${tests}) {
- test in
-
- expectEqual(
- test.output,
- ${Self}.hash(
- data: test.input,
- dataByteCount: test.input.count,
- key: test.key))
-}
-
-SipHashTests.test("${Self}.append(UnsafeRawPointer)")
- .forEach(in: cartesianProduct(${tests}, incrementalPatterns)) {
- test_ in
- let (test, pattern) = test_
-
- var context = ${Self}(key: test.key)
- var startIndex = 0
- var chunkSizeIndex = 0
- while startIndex != test.input.endIndex {
- let chunkSize = min(
- pattern[chunkSizeIndex],
- test.input.endIndex - startIndex)
- context.append(
- Array(test.input[startIndex..<(startIndex+chunkSize)]),
- byteCount: chunkSize)
- startIndex += chunkSize
- chunkSizeIndex += 1
- chunkSizeIndex %= pattern.count
- }
- expectEqual(
- test.output,
- context.finalizeAndReturnHash())
-
- // Check that we can query the hash value more than once.
- expectEqual(
- test.output,
- context.finalizeAndReturnHash())
-}
-
% for data_type in ['UInt', 'Int', 'UInt64', 'Int64', 'UInt32', 'Int32']:
SipHashTests.test("${Self}.append(${data_type})").forEach(in: ${tests}) {
test in
- var context = ${Self}(key: test.key)
+ var hasher = ${Self}(key: test.key)
let chunkSize = MemoryLayout<${data_type}>.size
var startIndex = 0
let endIndex = test.input.count - (test.input.count % chunkSize)
while startIndex != endIndex {
- context.append(
+ hasher.append(
loadUnaligned${data_type}(
from: Array(
test.input[startIndex..<(startIndex+chunkSize)])))
startIndex += chunkSize
}
- context.append(
- Array(test.input.suffix(from: endIndex)),
- byteCount: test.input.count - endIndex)
-
- expectEqual(
- test.output,
- context.finalizeAndReturnHash())
+ let tailCount = test.input.count - endIndex
+ let hash = hasher.finalize(
+ tailBytes: loadPartialUnalignedUInt64(
+ from: Array(test.input.suffix(from: endIndex)),
+ byteCount: tailCount),
+ tailByteCount: tailCount)
+ expectEqual(test.output, hash)
}
% end
-
-SipHashTests.test("${Self}/AppendAfterFinalizing") {
- var context = ${Self}(key: (0, 0))
- _ = context.finalizeAndReturnHash()
- expectCrashLater()
- context.append([], byteCount: 0)
-}
% end
runAllTests()