Merge pull request #12702 from fjricci/objc_interop
Objc interop
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4c199e8..2043392 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,7 +26,7 @@
constraints, which require that the associated type conform to the enclosing
protocol. The standard library protocols have been updated to make use of
recursive constraints. For example, the `SubSequence` associated type of
- follows the enclosing protocol:
+ `Sequence` follows the enclosing protocol:
protocol Sequence {
associatedtype Element
@@ -102,6 +102,8 @@
If you wish to provide your own implementation of `==`/`hashValue`, you still can; a custom implementation will replace the one synthesized by the compiler.
+ **Add new entries to the top of this file, not here!**
+
Swift 4.0
---------
@@ -391,8 +393,6 @@
#define LIMITED (SMALL || TINY) // now imported as Bool.
```
- **Add new entries to the top of this file, not here!**
-
Swift 3.1
---------
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT
index b6244ec..1309040 100644
--- a/CODE_OWNERS.TXT
+++ b/CODE_OWNERS.TXT
@@ -4,49 +4,85 @@
what goes in or not.
The list is sorted by surname and formatted to allow easy grepping and
-beautification by scripts. The fields are: name (N), email (E), web-address
-(W), description (D).
+beautification by scripts. The fields are: name (N), email (E),
+GitHub account (G), description (D).
N: Ben Cohen
E: ben_cohen@apple.com
+G: airspeedswift
D: Swift standard library
+N: Brian Croom
+E: bcroom@apple.com
+G: briancroom
+D: XCTest overlay
+
N: Erik Eckstein
E: eeckstein@apple.com
+G: eeckstein
D: SILOptimizer
N: Xi Ge
E: xi_ge@apple.com
+G: nkcsgexi
D: Markup, Migrator, lib/Syntax
N: Doug Gregor
E: dgregor@apple.com
+G: DougGregor
D: AST, Basic, Parse, Sema
N: Joe Groff
E: jgroff@apple.com
+G: jckarter
D: SIL, SILGen, everything in Swift not covered by someone else
N: Argyrios Kyrzidis
E: kyrtzidis@apple.com
-D: IDE, SourceKit, swift-ide-test
+G: akyrtzi
+D: IDE, Index, SourceKit, swift-ide-test
N: Luke Larson
E: llarson@apple.com
+G: lplarson
D: Swift Benchmark Suite
N: John McCall
E: rjmccall@apple.com
+G: rjmccall
D: Demangler, IRGen, Runtime
+N: Max Moiseev
+E: moiseev@apple.com
+G: moiseev
+D: Apple contact for non-corelibs overlays
+
+N: Tony Parker
+E: anthony.parker@apple.com
+G: parkera
+D: Foundation overlay
+
N: Slava Pestov
E: spestov@apple.com
+G: slavapestov
D: Reflection, SwiftRemoteMirror
+N: Adrian Prantl
+E: aprantl@apple.com
+G: adrian-prantl
+D: Debug info
+
N: Jordan Rose
E: jordan_rose@apple.com
-D: ClangImporter, Serialization, (Objective-)C printer, Driver
+G: jrose-apple
+D: ClangImporter, Serialization, PrintAsObjC, Driver, Frontend
+
+N: Daniel Steffen
+E: dsteffen@apple.com
+G: das
+D: Dispatch overlay
N: Anna Zaks
E: ganna@apple.com
-D: SIL diagnostics passes
+G: AnnaZaks
+D: SIL diagnostics passes, sanitizers
diff --git a/README.md b/README.md
index 8c31bbe..7ef4f79 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@
#### macOS
-To build for macOS, you need [Xcode 9.1](https://developer.apple.com/xcode/downloads/).
+To build for macOS, you need [Xcode 9.2 beta 2](https://developer.apple.com/xcode/downloads/).
The required version of Xcode changes frequently, and is often a beta release.
Check this document or the host information on <https://ci.swift.org> for the
current required version.
diff --git a/benchmark/single-source/CString.swift b/benchmark/single-source/CString.swift
index 9167d97..e54e675 100644
--- a/benchmark/single-source/CString.swift
+++ b/benchmark/single-source/CString.swift
@@ -31,7 +31,7 @@
public func run_StringWithCString(_ N: Int) {
let str = String(repeating: "x", count: 100 * (1 << 16))
for _ in 0 ..< N {
- str.withCString { _ in }
+ str.withCString { blackHole($0) }
}
}
diff --git a/benchmark/single-source/StringTests.swift b/benchmark/single-source/StringTests.swift
index 0ff145a..44d0e18 100644
--- a/benchmark/single-source/StringTests.swift
+++ b/benchmark/single-source/StringTests.swift
@@ -26,9 +26,7 @@
let testString = "prefixedString"
for _ in 0 ..< N {
for _ in 0 ..< 100_000 {
- if !testString.hasPrefix(prefix) {
- CheckResults(false)
- }
+ CheckResults(testString.hasPrefix(getString(prefix)))
}
}
#endif
@@ -41,9 +39,7 @@
let testString = "StringSuffixed"
for _ in 0 ..< N {
for _ in 0 ..< 100_000 {
- if !testString.hasSuffix(suffix) {
- CheckResults(false)
- }
+ CheckResults(testString.hasSuffix(getString(suffix)))
}
}
#endif
@@ -56,9 +52,7 @@
let testString = "❄️prefixedString"
for _ in 0 ..< N {
for _ in 0 ..< 100_000 {
- if !testString.hasPrefix(prefix) {
- CheckResults(false)
- }
+ CheckResults(testString.hasPrefix(getString(prefix)))
}
}
#endif
@@ -71,9 +65,7 @@
let testString = "String❄️Suffixed"
for _ in 0 ..< N {
for _ in 0 ..< 100_000 {
- if !testString.hasSuffix(suffix) {
- CheckResults(false)
- }
+ CheckResults(testString.hasSuffix(getString(suffix)))
}
}
#endif
@@ -89,9 +81,7 @@
let str2 = str1
for _ in 0 ..< N {
for _ in 0 ..< 100_000 {
- if !compareEqual(str1, str2) {
- CheckResults(false)
- }
+ CheckResults(compareEqual(str1, str2))
}
}
}
diff --git a/benchmark/utils/TestsUtils.swift b/benchmark/utils/TestsUtils.swift
index 4d25363..42af8a2 100644
--- a/benchmark/utils/TestsUtils.swift
+++ b/benchmark/utils/TestsUtils.swift
@@ -183,10 +183,17 @@
// Just consume the argument.
// It's important that this function is in another module than the tests
// which are using it.
+@inline(never)
public func blackHole<T>(_ x: T) {
}
// Return the passed argument without letting the optimizer know that.
+@inline(never)
+public func identity<T>(_ x: T) -> T {
+ return x
+}
+
+// Return the passed argument without letting the optimizer know that.
// It's important that this function is in another module than the tests
// which are using it.
@inline(never)
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 91e5cdb..5dd2ae9 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -719,7 +719,7 @@
# On platforms that use ELF binaries we add markers for metadata sections in
# the shared libraries using these object files. This wouldn't be necessary
# if the link was done by the swift binary: rdar://problem/19007002
- if(SWIFTLIB_TARGET_LIBRARY AND
+ if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
"${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
if("${libkind}" STREQUAL "SHARED")
set(arch_subdir "${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}")
@@ -874,7 +874,8 @@
# The section metadata objects are generated sources, and we need to tell CMake
# not to expect to find them prior to their generation.
- if("${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
+ if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
+ "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
if("${libkind}" STREQUAL "SHARED")
set_source_files_properties(${SWIFT_SECTIONS_OBJECT_BEGIN} PROPERTIES GENERATED 1)
set_source_files_properties(${SWIFT_SECTIONS_OBJECT_END} PROPERTIES GENERATED 1)
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index a832224..5c2db0f 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -81,7 +81,9 @@
# HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM
# into swift. The use of this flag pollutes all targets, and we are not able
# to remove it on a per-target basis which breaks cross-compilation.
- string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+ string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+ endif()
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" PACKAGE_VERSION_MAJOR
diff --git a/cmake/modules/SwiftSource.cmake b/cmake/modules/SwiftSource.cmake
index 01ebd19..0e4b414 100644
--- a/cmake/modules/SwiftSource.cmake
+++ b/cmake/modules/SwiftSource.cmake
@@ -256,10 +256,15 @@
"-Xfrontend" "${GROUP_INFO_JSON_FILE}")
endif()
- # Force swift 3 compatibility mode for Standard Library and overlay.
- if (SWIFTFILE_IS_STDLIB OR SWIFTFILE_IS_SDK_OVERLAY)
+ # Force swift 3 compatibility mode for Standard Library.
+ if (SWIFTFILE_IS_STDLIB)
list(APPEND swift_flags "-swift-version" "3")
endif()
+
+ # Force swift 4 compatibility mode for overlays.
+ if (SWIFTFILE_IS_SDK_OVERLAY)
+ list(APPEND swift_flags "-swift-version" "4")
+ endif()
if(SWIFTFILE_IS_SDK_OVERLAY)
list(APPEND swift_flags "-autolink-force-load")
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 97ec635..f56ba09 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -317,6 +317,7 @@
type ::= 'BO' // Builtin.UnknownObject
type ::= 'Bo' // Builtin.NativeObject
type ::= 'Bp' // Builtin.RawPointer
+ type ::= 'Bt' // Builtin.SILToken
type ::= type 'Bv' NATURAL '_' // Builtin.Vec<n>x<type>
type ::= 'Bw' // Builtin.Word
type ::= function-signature 'c' // function type
diff --git a/docs/ABI/TypeMetadata.rst b/docs/ABI/TypeMetadata.rst
index 6fffd9d..e765d8d 100644
--- a/docs/ABI/TypeMetadata.rst
+++ b/docs/ABI/TypeMetadata.rst
@@ -121,20 +121,22 @@
In addition to the `common metadata layout`_ fields, function metadata records
contain the following fields:
-- The function flags are stored at **offset 1**, information contained by flags
- includes 'throws' indicator (8 bits), metadata convention (8 bits)
- and number of arguments (remaining N bits).
-- The **argument vector** begins at **offset 2** and consists of pointers to
- metadata records of the function's arguments.
-- A reference to the **result type** metadata record is stored after the end
- of **argument vector**. If the function has multiple returns, this references a
- `tuple metadata`_ record.
+- The function flags are stored at **offset 1**, information contained by function
+ flags includes flags (8 bits) which _currently_ consists of 'throws' bit and
+ 'parameter flags' bit, function convention (8 bits), and number of parameters (16 bits).
+- A reference to the **result type** metadata record is stored after function
+ flags. If the function has multiple returns, this references a `tuple metadata`_
+ record.
+- The **parameter type vector** follows the result type and consists of
+ NumParameters type metadata pointers corresponding to the types of the parameters.
+- The optional **parameter flags vector** begins after the end of **parameter type vector**
+ and consists of NumParameters unsigned 32-bit integer values representing flags
+ for each parameter such as inout, __shared, variadic and possibly others. This
+ vector is present only if the hasParameterFlags() function flag is set; otherwise
+ all of the parameter flags are assumed to be zero.
- A pointer to each argument's metadata record will be appended separately,
- the lowest bit being set if it is **inout**. Because of pointer alignment,
- the lowest bit will always be free to hold this tag.
-
- If the function takes no arguments, **argument vector** is going to be empty.
+ If the function takes no arguments, **parameter type vector** as well as
+ **parameter flags vector** are going to be empty.
Protocol Metadata
~~~~~~~~~~~~~~~~~
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
index e07f255..e037a74 100644
--- a/docs/ContinuousIntegration.md
+++ b/docs/ContinuousIntegration.md
@@ -9,7 +9,9 @@
- [Smoke Testing](#smoke-testing)
- [Validation Testing](#validation-testing)
- [Linting](#linting)
+ - [Source Compatibility Testing](#source-compatibility-testing)
- [Specific Preset Testing](#specific-preset-testing)
+ - [Testing Compiler Performance](#testing-compiler-performance)
- [Cross Repository Testing](#cross-repository-testing)
- [ci.swift.org bots](#ciswiftorg-bots)
@@ -31,6 +33,7 @@
4. Linting
5. Source Compatibility Testing
6. Specific Preset Testing
+7. Testing Compiler Performance
We describe each in detail below:
diff --git a/docs/SIL.rst b/docs/SIL.rst
index a6753b4..80e0ff8 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -582,6 +582,46 @@
importer only imports non-native methods and types as ``throws``
when it is possible to do this automatically.
+Coroutine Types
+```````````````
+
+A coroutine is a function which can suspend itself and return control to
+its caller without terminating the function. That is, it does not need to
+obey a strict stack discipline.
+
+SIL supports two kinds of coroutine: ``@yield_many`` and ``@yield_once``.
+Either of these attributes may be written before a function type to
+indicate that it is a coroutine type.
+
+A coroutine type may declare any number of *yielded values*, which is to
+say, values which are provided to the caller at a yield point. Yielded
+values are written in the result list of a function type, prefixed by
+the ``@yields`` attribute. A yielded value may have a convention attribute,
+taken from the set of parameter attributes and interpreted as if the yield
+site were calling back to the calling function.
+
+Currently, a coroutine may not have normal results.
+
+Coroutine functions may be used in many of the same ways as normal
+function values. However, they cannot be called with the standard
+``apply`` or ``try_apply`` instructions. A non-throwing yield-once
+coroutine can be called with the ``begin_apply`` instruction. There
+is no support yet for calling a throwing yield-once coroutine or for
+calling a yield-many coroutine of any kind.
+
+Coroutines may contain the special ``yield`` and ``unwind`` instructions.
+
+A ``@yield_many`` coroutine may yield as many times as it desires.
+A ``@yield_once`` coroutine may yield exactly once before returning,
+although it may also ``throw`` before reaching that point.
+
+This coroutine representation is well-suited to coroutines whose control
+flow is tightly integrated with their callers and which intend to pass
+information back and forth. This matches the needs of generalized
+accessor and generator features in Swift. It is not a particularly good
+match for ``async``/``await``-style features; a simpler representation
+would probably do fine for that.
+
Properties of Types
```````````````````
@@ -3100,6 +3140,102 @@
given substitution list. The arguments and return value is
given with these generic substitutions applied.
+begin_apply
+```````````
+::
+
+ sil-instruction ::= 'begin_apply' '[nothrow]'? sil-value
+ sil-apply-substitution-list?
+ '(' (sil-value (',' sil-value)*)? ')'
+ ':' sil-type
+
+ (%anyAddr, %float, %token) = begin_apply %0() : $@yield_once () -> (@yields @inout %Any, @yields Float)
+ // %anyAddr : $*Any
+ // %float : $Float
+ // %token is a token
+
+Transfers control to coroutine ``%0``, passing it the given arguments.
+The rules for the application generally follow the rules for ``apply``,
+except:
+
+- the callee value must have a ``yield_once`` coroutine type,
+
+- control returns to this function not when the coroutine performs a
+ ``return``, but when it performs a ``yield``, and
+
+- the instruction results are derived from the yields of the coroutine
+ instead of its normal results.
+
+The final result of a ``begin_apply`` is a "token", a special value which
+can only be used as the operand of an ``end_apply`` or ``abort_apply``
+instruction. Before this second instruction is executed, the coroutine
+is said to be "suspended", and the token represents a reference to its
+suspended activation record.
+
+The other results of the instruction correspond to the yields in the
+coroutine type. In general, the rules of a yield are similar to the rules
+for a parameter, interpreted as if the coroutine caller (the one
+executing the ``begin_apply``) were being "called" by the ``yield``:
+
+- If a yield has an indirect convention, the corresponding result will
+ have an address type; otherwise it has an object type. For example,
+ a result corresponding to an ``@in Any`` yield will have type ``$Any``.
+
+- The convention attributes are the same as the parameter convention
+ attributes, interpreted as if the ``yield`` were the "call" and the
+ ``begin_apply`` marked the entry to the "callee". For example,
+ an ``@in Any`` yield transferrs ownership of the ``Any`` value
+ reference from the coroutine to the caller, which must destroy
+ or move the value from that position before ending or aborting the
+ coroutine.
+
+A ``begin_apply`` must be uniquely either ended or aborted before
+exiting the function or looping to an earlier portion of the function.
+
+When throwing coroutines are supported, there will need to be a
+``try_begin_apply`` instruction.
+
+abort_apply
+```````````
+::
+
+ sil-instruction ::= 'abort_apply' sil-value
+
+ abort_apply %token
+
+Aborts the given coroutine activation, which is currently suspended at
+a ``yield`` instruction. Transfers control to the coroutine and takes
+the ``unwind`` path from the ``yield``. Control is transferred back
+when the coroutine reaches an ``unwind`` instruction.
+
+The operand must always be the token result of a ``begin_apply``
+instruction, which is why it need not specify a type.
+
+Throwing coroutines will not require a new instruction for aborting
+a coroutine; a coroutine is not allowed to throw when it is being aborted.
+
+end_apply
+`````````
+::
+
+ sil-instruction ::= 'end_apply' sil-value
+
+ end_apply %token
+
+Ends the given coroutine activation, which is currently suspended at
+a ``yield`` instruction. Transfers control to the coroutine and takes
+the ``resume`` path from the ``yield``. Control is transferred back
+when the coroutine reaches a ``return`` instruction.
+
+The operand must always be the token result of a ``begin_apply``
+instruction, which is why it need not specify a type.
+
+``end_apply`` currently has no instruction results. If coroutines were
+allowed to have normal results, they would be producted by ``end_apply``.
+
+When throwing coroutines are supported, there will need to be a
+``try_end_apply`` instruction.
+
partial_apply
`````````````
::
@@ -4698,6 +4834,10 @@
resumes at the normal destination, and the value of the basic block argument
will be the operand of this ``return`` instruction.
+If the current function is a ``yield_once`` coroutine, there must not be
+a path from the entry block to a ``return`` which does not pass through
+a ``yield`` instruction. This rule does not apply in the ``raw`` SIL stage.
+
``return`` does not retain or release its operand or any other values.
A function must not contain more than one ``return`` instruction.
@@ -4713,7 +4853,7 @@
Exits the current function and returns control to the calling
function. The current function must have an error result, and so the
-function must have been invoked with a ``try_apply` instruction.
+function must have been invoked with a ``try_apply`` instruction.
Control will resume in the error destination of that instruction, and
the basic block argument will be the operand of the ``throw``.
@@ -4721,6 +4861,50 @@
A function must not contain more than one ``throw`` instruction.
+yield
+`````
+::
+
+ sil-terminator ::= 'yield' sil-yield-values
+ ',' 'resume' sil-identifier
+ ',' 'unwind' sil-identifier
+ sil-yield-values ::= sil-operand
+ sil-yield-values ::= '(' (sil-operand (',' sil-operand)*)? ')'
+
+Temporarily suspends the current function and provides the given
+values to the calling function. The current function must be a coroutine,
+and the yield values must match the yield types of the coroutine.
+If the calling function resumes the coroutine normally, control passes to
+the ``resume`` destination. If the calling function aborts the coroutine,
+control passes to the ``unwind`` destination.
+
+The ``resume`` and ``unwind`` destination blocks must be uniquely
+referenced by the ``yield`` instruction. This prevents them from becoming
+critical edges.
+
+In a ``yield_once`` coroutine, there must not be a control flow path leading
+from the ``resume`` edge to another ``yield`` instruction in this function.
+This rule does not apply in the ``raw`` SIL stage.
+
+There must not be a control flow path leading from the ``unwind`` edge to
+a ``return`` instruction, to a ``throw`` instruction, or to any block
+reachable from the entry block via a path that does not pass through
+an ``unwind`` edge. That is, the blocks reachable from ``unwind`` edges
+must jointly form a disjoint subfunction of the coroutine.
+
+unwind
+``````
+::
+
+ sil-terminator ::= 'unwind'
+
+Exits the current function and returns control to the calling function,
+completing an unwind from a ``yield``. The current function must be a
+coroutine.
+
+``unwind`` is only permitted in blocks reachable from the ``unwind`` edges
+of ``yield`` instructions.
+
br
``
::
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 0259ba7..69027e2 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -549,11 +549,15 @@
/// Flags in a function type metadata record.
template <typename int_type>
class TargetFunctionTypeFlags {
+ // If we were ever to run out of space for function flags (8 bits)
+ // one of the flag bits could be used to identify that the rest of
+ // the flags is going to be stored somewhere else in the metadata.
enum : int_type {
- NumArgumentsMask = 0x00FFFFFFU,
- ConventionMask = 0x0F000000U,
- ConventionShift = 24U,
- ThrowsMask = 0x10000000U,
+ NumParametersMask = 0x0000FFFFU,
+ ConventionMask = 0x00FF0000U,
+ ConventionShift = 16U,
+ ThrowsMask = 0x01000000U,
+ ParamFlagsMask = 0x02000000U,
};
int_type Data;
@@ -561,8 +565,9 @@
public:
constexpr TargetFunctionTypeFlags() : Data(0) {}
- constexpr TargetFunctionTypeFlags withNumArguments(unsigned numArguments) const {
- return TargetFunctionTypeFlags((Data & ~NumArgumentsMask) | numArguments);
+ constexpr TargetFunctionTypeFlags
+ withNumParameters(unsigned numParams) const {
+ return TargetFunctionTypeFlags((Data & ~NumParametersMask) | numParams);
}
constexpr TargetFunctionTypeFlags<int_type>
@@ -576,11 +581,15 @@
return TargetFunctionTypeFlags<int_type>((Data & ~ThrowsMask) |
(throws ? ThrowsMask : 0));
}
-
- unsigned getNumArguments() const {
- return Data & NumArgumentsMask;
+
+ constexpr TargetFunctionTypeFlags<int_type>
+ withParameterFlags(bool hasFlags) const {
+ return TargetFunctionTypeFlags<int_type>((Data & ~ParamFlagsMask) |
+ (hasFlags ? ParamFlagsMask : 0));
}
-
+
+ unsigned getNumParameters() const { return Data & NumParametersMask; }
+
FunctionMetadataConvention getConvention() const {
return FunctionMetadataConvention((Data&ConventionMask) >> ConventionShift);
}
@@ -588,7 +597,9 @@
bool throws() const {
return bool(Data & ThrowsMask);
}
-
+
+ bool hasParameterFlags() const { return bool(Data & ParamFlagsMask); }
+
int_type getIntValue() const {
return Data;
}
@@ -606,6 +617,56 @@
};
using FunctionTypeFlags = TargetFunctionTypeFlags<size_t>;
+template <typename int_type>
+class TargetParameterTypeFlags {
+ enum : int_type {
+ InOutMask = 1 << 0,
+ SharedMask = 1 << 1,
+ VariadicMask = 1 << 2,
+ };
+ int_type Data;
+
+ constexpr TargetParameterTypeFlags(int_type Data) : Data(Data) {}
+
+public:
+ constexpr TargetParameterTypeFlags() : Data(0) {}
+
+ constexpr TargetParameterTypeFlags<int_type> withInOut(bool isInOut) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~InOutMask) |
+ (isInOut ? InOutMask : 0));
+ }
+
+ constexpr TargetParameterTypeFlags<int_type> withShared(bool isShared) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~SharedMask) |
+ (isShared ? SharedMask : 0));
+ }
+
+ constexpr TargetParameterTypeFlags<int_type>
+ withVariadic(bool isVariadic) const {
+ return TargetParameterTypeFlags<int_type>((Data & ~VariadicMask) |
+ (isVariadic ? VariadicMask : 0));
+ }
+
+ bool isNone() const { return Data == 0; }
+ bool isInOut() const { return Data & InOutMask; }
+ bool isShared() const { return Data & SharedMask; }
+ bool isVariadic() const { return Data & VariadicMask; }
+
+ int_type getIntValue() const { return Data; }
+
+ static TargetParameterTypeFlags<int_type> fromIntValue(int_type Data) {
+ return TargetParameterTypeFlags(Data);
+ }
+
+ bool operator==(TargetParameterTypeFlags<int_type> other) const {
+ return Data == other.Data;
+ }
+ bool operator!=(TargetParameterTypeFlags<int_type> other) const {
+ return Data != other.Data;
+ }
+};
+using ParameterFlags = TargetParameterTypeFlags<uint32_t>;
+
/// Field types and flags as represented in a nominal type's field/case type
/// vector.
class FieldType {
diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h
index 3d52776..0ee1eb5 100644
--- a/include/swift/AST/ASTContext.h
+++ b/include/swift/AST/ASTContext.h
@@ -573,6 +573,7 @@
const CanType TheUnknownObjectType; /// Builtin.UnknownObject
const CanType TheRawPointerType; /// Builtin.RawPointer
const CanType TheUnsafeValueBufferType; /// Builtin.UnsafeValueBuffer
+ const CanType TheSILTokenType; /// Builtin.SILToken
const CanType TheIEEE32Type; /// 32-bit IEEE floating point
const CanType TheIEEE64Type; /// 64-bit IEEE floating point
@@ -884,15 +885,6 @@
GenericSignatureBuilder *builder,
GenericSignature *sig);
- /// Retrieve the inherited name set for the given class.
- const InheritedNameSet *getAllPropertyNames(ClassDecl *classDecl,
- bool forInstance);
-
- /// Retrieve the inherited name set for the given Objective-C class.
- const InheritedNameSet *getAllPropertyNames(
- clang::ObjCInterfaceDecl *classDecl,
- bool forInstance);
-
/// Retrieve a generic signature with a single unconstrained type parameter,
/// like `<T>`.
CanGenericSignature getSingleGenericParameterSignature() const;
diff --git a/include/swift/AST/ASTMangler.h b/include/swift/AST/ASTMangler.h
index 0c931d0..8a99f64 100644
--- a/include/swift/AST/ASTMangler.h
+++ b/include/swift/AST/ASTMangler.h
@@ -46,6 +46,7 @@
enum class SymbolKind {
Default,
DynamicThunk,
+ SwiftDispatchThunk,
SwiftAsObjCThunk,
ObjCAsSwiftThunk,
DirectMethodReferenceThunk,
diff --git a/include/swift/AST/ASTNode.h b/include/swift/AST/ASTNode.h
index 078b5bc..5332fa7 100644
--- a/include/swift/AST/ASTNode.h
+++ b/include/swift/AST/ASTNode.h
@@ -18,7 +18,6 @@
#define SWIFT_AST_AST_NODE_H
#include "llvm/ADT/PointerUnion.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/TypeAlignments.h"
namespace swift {
@@ -48,9 +47,6 @@
void walk(ASTWalker &Walker);
void walk(ASTWalker &&walker) { walk(walker); }
- void walk(SourceEntityWalker &Walker);
- void walk(SourceEntityWalker &&walker) { walk(walker); }
-
/// \brief get the underlying entity as a decl context if it is one,
/// otherwise, return nullptr;
DeclContext *getAsDeclContext() const;
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index c7629da..26e8b05 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -60,6 +60,9 @@
TYPE_ATTR(objc_metatype)
TYPE_ATTR(opened)
TYPE_ATTR(pseudogeneric)
+TYPE_ATTR(yields)
+TYPE_ATTR(yield_once)
+TYPE_ATTR(yield_many)
// SIL metatype attributes.
TYPE_ATTR(thin)
@@ -296,6 +299,10 @@
ImplicitlyUnwrappedOptional,
OnFunc | OnVar | OnSubscript | OnConstructor | RejectByParser, 72)
+DECL_ATTR(_optimize, Optimize,
+ OnFunc | OnConstructor | OnDestructor | OnSubscript | OnVar |
+ UserInaccessible, 73)
+
#undef TYPE_ATTR
#undef DECL_ATTR_ALIAS
#undef SIMPLE_DECL_ATTR
diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h
index 925aa7d..2db33d7 100644
--- a/include/swift/AST/Attr.h
+++ b/include/swift/AST/Attr.h
@@ -21,6 +21,7 @@
#include "swift/Basic/UUID.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/Range.h"
+#include "swift/Basic/OptimizationMode.h"
#include "swift/Basic/Version.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/AttrKind.h"
@@ -925,6 +926,23 @@
}
};
+/// Represents the optimize attribute.
+class OptimizeAttr : public DeclAttribute {
+ OptimizationMode Mode;
+public:
+ OptimizeAttr(SourceLoc atLoc, SourceRange range, OptimizationMode mode)
+ : DeclAttribute(DAK_Optimize, atLoc, range, /*Implicit=*/false),
+ Mode(mode) {}
+
+ OptimizeAttr(OptimizationMode mode)
+ : OptimizeAttr(SourceLoc(), SourceRange(), mode) {}
+
+ OptimizationMode getMode() const { return Mode; }
+ static bool classof(const DeclAttribute *DA) {
+ return DA->getKind() == DAK_Optimize;
+ }
+};
+
/// Represents the side effects attribute.
class EffectsAttr : public DeclAttribute {
EffectsKind Kind;
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index c89e436..5be9bbc 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -458,8 +458,12 @@
/// Whether there is are lazily-loaded conformances for this nominal type.
unsigned HasLazyConformances : 1;
+
+ /// Whether we have already validated all members of the type that
+ /// affect layout.
+ unsigned HasValidatedLayout : 1;
};
- enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 3 };
+ enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 4 };
static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned");
class ProtocolDeclBitfields {
@@ -771,6 +775,9 @@
/// Returns the source range of the entire declaration.
SourceRange getSourceRange() const;
+ /// Returns the source range of the declaration including its attributes.
+ SourceRange getSourceRangeIncludingAttrs() const;
+
SourceLoc TrailingSemiLoc;
LLVM_ATTRIBUTE_DEPRECATED(
@@ -2218,6 +2225,10 @@
getFormalAccessScope(const DeclContext *useDC = nullptr,
bool respectVersionedAttr = false) const;
+
+ /// Copy the formal access level and @_versioned attribute from source.
+ void copyFormalAccessAndVersionedAttrFrom(ValueDecl *source);
+
/// Returns the access level that actually controls how a declaration should
/// be emitted and may be used.
///
@@ -2814,6 +2825,7 @@
NominalTypeDeclBits.AddedImplicitInitializers = false;
ExtensionGeneration = 0;
NominalTypeDeclBits.HasLazyConformances = false;
+ NominalTypeDeclBits.HasValidatedLayout = false;
}
friend class ProtocolType;
@@ -2856,11 +2868,23 @@
return NominalTypeDeclBits.AddedImplicitInitializers;
}
- /// Note that we have attempted to
+ /// Note that we have attempted to add implicit initializers.
void setAddedImplicitInitializers() {
NominalTypeDeclBits.AddedImplicitInitializers = true;
}
-
+
+ /// Determine whether we have already validated any members
+ /// which affect layout.
+ bool hasValidatedLayout() const {
+ return NominalTypeDeclBits.HasValidatedLayout;
+ }
+
+ /// Note that we have attempted to validate any members
+ /// which affect layout.
+ void setHasValidatedLayout() {
+ NominalTypeDeclBits.HasValidatedLayout = true;
+ }
+
/// Compute the type of this nominal type.
void computeType();
@@ -3382,7 +3406,7 @@
/// Synthesize implicit, trivial destructor, add it to this ClassDecl
/// and return it.
- DestructorDecl *addImplicitDestructor();
+ void addImplicitDestructor();
/// Determine whether this class inherits the convenience initializers
/// from its superclass.
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index 52dc174..ffe5f92 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -385,6 +385,10 @@
return false;
}
+ /// Compute a context C such that C is a parent context of A and B.
+ /// If no such context exists, return \c nullptr.
+ static DeclContext *getCommonParentContext(DeclContext *A, DeclContext *B);
+
/// Returns the module context that contains this context.
ModuleDecl *getParentModule() const;
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 41c6cf4..570fc54 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1365,10 +1365,10 @@
ERROR(opened_attribute_expected_rparen,none,
"expected ')' after id value for 'opened' attribute", ())
-// inline
-ERROR(inline_attribute_expect_option,none,
- "expected '%0' option such as 'never'", (StringRef))
-ERROR(inline_attribute_unknown_option,none,
+// inline, optimize
+ERROR(optimization_attribute_expect_option,none,
+ "expected '%0' option such as '%1'", (StringRef, StringRef))
+ERROR(optimization_attribute_unknown_option,none,
"unknown option '%0' for attribute '%1'", (StringRef, StringRef))
// effects
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index a832920..fa41dab 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -474,6 +474,9 @@
"key path cannot reference tuple elements", ())
ERROR(expr_keypath_subscript_index_not_hashable, none,
"subscript index of type %0 in a key path must be Hashable", (Type))
+ERROR(expr_smart_keypath_application_type_mismatch,none,
+ "key path of type %0 cannot be applied to a base of type %1",
+ (Type, Type))
// Selector expressions.
ERROR(expr_selector_no_objc_runtime,none,
@@ -1024,8 +1027,6 @@
ERROR(static_functions_not_mutating,none,
"static functions must not be declared mutating", ())
-ERROR(transparent_stored_property,none,
- "@_transparent cannot be applied to stored properties", ())
ERROR(transparent_in_protocols_not_supported,none,
"@_transparent is not supported on declarations within protocols", ())
ERROR(transparent_in_classes_not_supported,none,
@@ -3183,6 +3184,8 @@
"SIL function types cannot have labeled inputs", ())
ERROR(sil_function_output_label,PointsToFirstBadToken,
"SIL function types cannot have labeled results", ())
+ERROR(sil_non_coro_yields,PointsToFirstBadToken,
+ "non-coroutine SIL function types cannot have @yield results", ())
ERROR(sil_function_repeat_convention,PointsToFirstBadToken,
"repeated %select{parameter|result|callee}0 convention attribute",
(unsigned))
@@ -3703,8 +3706,8 @@
"'%select{@_transparent|@inline(__always)|@_inlineable|%error}1' and must "
"delegate to another initializer", (Type, unsigned))
-ERROR(inlineable_stored_property,
- none, "'@_inlineable' attribute cannot be applied to stored properties", ())
+ERROR(attribute_invalid_on_stored_property,
+ none, "@%0 cannot be applied to stored properties", (StringRef))
ERROR(inlineable_dynamic_not_supported,
none, "'@_inlineable' attribute cannot be applied to 'dynamic' declarations", ())
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 9e8b509..35f9411 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -802,6 +802,16 @@
/// Determine whether the two given types are in the same equivalence class.
bool areInSameEquivalenceClass(Type type1, Type type2);
+ /// Verify the correctness of the given generic signature.
+ ///
+ /// This routine will test that the given generic signature is both minimal
+ /// and canonical, emitting errors if it is not.
+ static void verifyGenericSignature(ASTContext &context,
+ GenericSignature *sig);
+
+ /// Verify all of the generic sigantures in the given module.
+ static void verifyGenericSignaturesInModule(ModuleDecl *module);
+
/// \brief Dump all of the requirements, both specified and inferred.
LLVM_ATTRIBUTE_DEPRECATED(
void dump(),
diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h
index a72fbc5..349f769 100644
--- a/include/swift/AST/IRGenOptions.h
+++ b/include/swift/AST/IRGenOptions.h
@@ -21,6 +21,7 @@
#include "swift/AST/LinkLibrary.h"
#include "swift/Basic/Sanitizers.h"
#include "swift/Basic/OptionSet.h"
+#include "swift/Basic/OptimizationMode.h"
// FIXME: This include is just for llvm::SanitizerCoverageOptions. We should
// split the header upstream so we don't include so much.
#include "llvm/Transforms/Instrumentation.h"
@@ -94,11 +95,7 @@
/// well-formed?
unsigned Verify : 1;
- /// Whether or not to run optimization passes.
- unsigned Optimize : 1;
-
- /// Whether or not to optimize for code size.
- unsigned OptimizeForSize : 1;
+ OptimizationMode OptMode;
/// Which sanitizer is turned on.
OptionSet<SanitizerKind> Sanitizers;
@@ -179,7 +176,7 @@
IRGenOptions()
: DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssembly),
- Verify(true), Optimize(false), OptimizeForSize(false),
+ Verify(true), OptMode(OptimizationMode::NotSet),
Sanitizers(OptionSet<SanitizerKind>()),
DebugInfoKind(IRGenDebugInfoKind::None), UseJIT(false),
DisableLLVMOptzns(false), DisableLLVMARCOpts(false),
@@ -202,9 +199,7 @@
// Get a hash of all options which influence the llvm compilation but are not
// reflected in the llvm module itself.
unsigned getLLVMCodeGenOptionsHash() {
- unsigned Hash = 0;
- Hash = (Hash << 1) | Optimize;
- Hash = (Hash << 1) | OptimizeForSize;
+ unsigned Hash = (unsigned)OptMode;
Hash = (Hash << 1) | DisableLLVMOptzns;
Hash = (Hash << 1) | DisableLLVMARCOpts;
return Hash;
@@ -222,6 +217,14 @@
}
}
+ bool shouldOptimize() const {
+ return OptMode > OptimizationMode::NoOptimization;
+ }
+
+ bool optimizeForSize() const {
+ return OptMode == OptimizationMode::ForSize;
+ }
+
/// Return a hash code of any components from these options that should
/// contribute to a Swift Bridging PCH hash.
llvm::hash_code getPCHHashComponents() const {
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index 377b7e2..4e99b99 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -1173,6 +1173,15 @@
virtual bool isSystemModule() const { return false; }
+ /// Retrieve the set of generic signatures stored within this module.
+ ///
+ /// \returns \c true if this module file supports retrieving all of the
+ /// generic signatures, \c false otherwise.
+ virtual bool getAllGenericSignatures(
+ SmallVectorImpl<GenericSignature*> &genericSignatures) {
+ return false;
+ }
+
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST ||
file->getKind() == FileUnitKind::ClangModule;
diff --git a/include/swift/AST/PrettyStackTrace.h b/include/swift/AST/PrettyStackTrace.h
index 96894b1..9715dd32 100644
--- a/include/swift/AST/PrettyStackTrace.h
+++ b/include/swift/AST/PrettyStackTrace.h
@@ -26,6 +26,7 @@
class ASTContext;
class Decl;
class Expr;
+ class GenericSignature;
class Pattern;
class Stmt;
class TypeRepr;
@@ -129,6 +130,24 @@
virtual void print(llvm::raw_ostream &OS) const;
};
+class PrettyStackTraceGenericSignature : public llvm::PrettyStackTraceEntry {
+ const char *Action;
+ GenericSignature *GenericSig;
+ Optional<unsigned> Requirement;
+
+public:
+ PrettyStackTraceGenericSignature(const char *action,
+ GenericSignature *genericSig,
+ Optional<unsigned> requirement = None)
+ : Action(action), GenericSig(genericSig), Requirement(requirement) { }
+
+ void setRequirement(Optional<unsigned> requirement) {
+ Requirement = requirement;
+ }
+
+ void print(llvm::raw_ostream &out) const override;
+};
+
} // end namespace swift
#endif
diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h
index 3272e45..b434510 100644
--- a/include/swift/AST/PrintOptions.h
+++ b/include/swift/AST/PrintOptions.h
@@ -386,6 +386,7 @@
result.PrintImplicitAttrs = false;
result.ExcludeAttrList.push_back(DAK_Exported);
result.ExcludeAttrList.push_back(DAK_Inline);
+ result.ExcludeAttrList.push_back(DAK_Optimize);
result.ExcludeAttrList.push_back(DAK_Rethrows);
result.PrintOverrideKeyword = false;
result.AccessFilter = AccessLevel::Public;
diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h
index 1ae9e1f..9193c00 100644
--- a/include/swift/AST/ProtocolConformance.h
+++ b/include/swift/AST/ProtocolConformance.h
@@ -251,6 +251,13 @@
/// interface type.
GenericSignature *getGenericSignature() const;
+ /// Get the substitutions associated with this conformance.
+ SubstitutionMap getSubstitutions(ModuleDecl *M) const;
+
+ /// Determine whether the witness table access function for this conformance
+ /// needs to be passed information when called, or if it stands alone.
+ bool witnessTableAccessorRequiresArguments() const;
+
/// Get the underlying normal conformance.
const NormalProtocolConformance *getRootNormalConformance() const;
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index bbd37b9..0c51835 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -20,6 +20,7 @@
#include "swift/Basic/Sanitizers.h"
#include "swift/Basic/OptionSet.h"
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include <string>
@@ -52,16 +53,6 @@
LinkAll
};
- /// Representation of optimization modes.
- enum class SILOptMode: unsigned {
- NotSet,
- None,
- Debug,
- Optimize,
- OptimizeForSize,
- OptimizeUnchecked
- };
-
/// Controls how to perform SIL linking.
LinkingMode LinkMode = LinkNormal;
@@ -91,7 +82,7 @@
bool EmitVerboseSIL = false;
/// Optimization mode being used.
- SILOptMode Optimization = SILOptMode::NotSet;
+ OptimizationMode OptMode = OptimizationMode::NotSet;
enum AssertConfiguration: unsigned {
// Used by standard library code to distinguish between a debug and release
@@ -167,6 +158,10 @@
llvm::hash_code getPCHHashComponents() const {
return llvm::hash_value(0);
}
+
+ bool shouldOptimize() const {
+ return OptMode > OptimizationMode::NoOptimization;
+ }
};
} // end namespace swift
diff --git a/include/swift/AST/TypeMatcher.h b/include/swift/AST/TypeMatcher.h
index c3a9c3b..7f37714 100644
--- a/include/swift/AST/TypeMatcher.h
+++ b/include/swift/AST/TypeMatcher.h
@@ -109,6 +109,7 @@
TRIVIAL_CASE(BuiltinUnknownObjectType)
TRIVIAL_CASE(BuiltinUnsafeValueBufferType)
TRIVIAL_CASE(BuiltinVectorType)
+ TRIVIAL_CASE(SILTokenType)
bool visitTupleType(CanTupleType firstTuple, Type secondType,
Type sugaredFirstType) {
diff --git a/include/swift/AST/TypeNodes.def b/include/swift/AST/TypeNodes.def
index ccfdbce..2821074 100644
--- a/include/swift/AST/TypeNodes.def
+++ b/include/swift/AST/TypeNodes.def
@@ -126,6 +126,7 @@
ARTIFICIAL_TYPE(SILFunction, Type)
ARTIFICIAL_TYPE(SILBlockStorage, Type)
ARTIFICIAL_TYPE(SILBox, Type)
+ARTIFICIAL_TYPE(SILToken, Type)
ABSTRACT_SUGARED_TYPE(SyntaxSugar, Type)
SUGARED_TYPE(ArraySlice, SyntaxSugarType)
SUGARED_TYPE(Optional, SyntaxSugarType)
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 10ca863..fe4a1e2 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -319,8 +319,9 @@
unsigned ExtInfo : 16;
unsigned CalleeConvention : 3;
unsigned HasErrorResult : 1;
+ unsigned CoroutineKind : 2;
};
- enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16+5 };
+ enum { NumSILFunctionTypeBits = NumTypeBaseBits + 16 + 6 };
static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
struct AnyMetatypeTypeBitfields {
@@ -3175,6 +3176,42 @@
return !(*this == rhs);
}
};
+
+using YieldConvention = ParameterConvention;
+
+/// The type and convention of a value yielded from a yield-once or
+/// yield-many coroutine.
+class SILYieldInfo : public SILParameterInfo {
+public:
+ SILYieldInfo() {}
+ SILYieldInfo(CanType type, YieldConvention conv)
+ : SILParameterInfo(type, conv) {
+ }
+
+ SILYieldInfo getWithType(CanType type) const {
+ return SILYieldInfo(type, getConvention());
+ }
+
+ template<typename F>
+ SILYieldInfo map(const F &fn) const {
+ return getWithType(fn(getType()));
+ }
+};
+
+/// SILCoroutineKind - What kind of coroutine is this SILFunction?
+enum class SILCoroutineKind : uint8_t {
+ /// This function is not a coroutine. It may have arbitrary normal
+ /// results and may not have yield results.
+ None,
+
+ /// This function is a yield-once coroutine (used by e.g. accessors).
+ /// It must not have normal results and may have arbitrary yield results.
+ YieldOnce,
+
+ /// This function is a yield-many coroutine (used by e.g. generators).
+ /// It must not have normal results and may have arbitrary yield results.
+ YieldMany,
+};
class SILFunctionType;
typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
@@ -3334,16 +3371,20 @@
private:
unsigned NumParameters;
- unsigned NumResults : 16; // Not including the ErrorResult.
- unsigned NumIndirectFormalResults : 16; // Subset of NumResults.
+
+ // These are *normal* results if this is not a coroutine and *yield* results
+ // otherwise.
+ unsigned NumAnyResults : 16; // Not including the ErrorResult.
+ unsigned NumAnyIndirectFormalResults : 16; // Subset of NumAnyResults.
// The layout of a SILFunctionType in memory is:
// SILFunctionType
// SILParameterInfo[NumParameters]
- // SILResultInfo[NumResults]
- // SILResultInfo? // if hasErrorResult()
- // CanType? // if NumResults > 1, formal result cache
- // CanType? // if NumResults > 1, all result cache
+ // SILResultInfo[isCoroutine() ? 0 : NumAnyResults]
+ // SILYieldInfo[isCoroutine() ? NumAnyResults : 0]
+ // SILResultInfo? // if hasErrorResult()
+ // CanType? // if !isCoro && NumAnyResults > 1, formal result cache
+ // CanType? // if !isCoro && NumAnyResults > 1, all result cache
CanGenericSignature GenericSig;
Optional<ProtocolConformanceRef> WitnessMethodConformance;
@@ -3354,48 +3395,74 @@
MutableArrayRef<SILResultInfo> getMutableResults() {
auto *ptr = reinterpret_cast<SILResultInfo *>(getMutableParameters().end());
- return MutableArrayRef<SILResultInfo>(ptr, getNumResults());
+ return {ptr, getNumResults()};
}
- SILResultInfo *getEndOfNormalResults() { return getMutableResults().end(); }
+ MutableArrayRef<SILYieldInfo> getMutableYields() {
+ auto *ptr = reinterpret_cast<SILYieldInfo *>(getMutableParameters().end());
+ return {ptr, getNumYields()};
+ }
+
+ /// Return a pointer past the end of the formal results, whether they
+ /// are yield-results or normal results.
+ void *getEndOfFormalResults() {
+ return isCoroutine() ? static_cast<void*>(getMutableYields().end())
+ : static_cast<void*>(getMutableResults().end());
+ }
SILResultInfo &getMutableErrorResult() {
assert(hasErrorResult());
- return *getEndOfNormalResults();
+ return *reinterpret_cast<SILResultInfo*>(getEndOfFormalResults());
}
- bool hasResultCache() const { return NumResults > 1; }
+ /// Return a pointer past the end of all of the results, including the
+ /// error result if one is present.
+ void *getEndOfAllResults() {
+ void *end = getEndOfFormalResults();
+ if (hasErrorResult())
+ end = reinterpret_cast<char*>(end) + sizeof(SILResultInfo);
+ return end;
+ }
+
+ /// Do we have slots for caches of the normal-result tuple type?
+ bool hasResultCache() const {
+ return NumAnyResults > 1 && !isCoroutine();
+ }
CanType &getMutableFormalResultsCache() const {
assert(hasResultCache());
- auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfNormalResults()
- + size_t(hasErrorResult());
+ auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
return *reinterpret_cast<CanType*>(ptr);
}
CanType &getMutableAllResultsCache() const {
assert(hasResultCache());
- auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfNormalResults()
- + size_t(hasErrorResult());
+ auto *ptr = const_cast<SILFunctionType *>(this)->getEndOfAllResults();
return *(reinterpret_cast<CanType *>(ptr) + 1);
}
- SILFunctionType(
- GenericSignature *genericSig, ExtInfo ext,
- ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
- ArrayRef<SILResultInfo> normalResults,
- Optional<SILResultInfo> errorResult, const ASTContext &ctx,
- RecursiveTypeProperties properties,
- Optional<ProtocolConformanceRef> witnessMethodConformance = None);
+ SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention calleeConvention,
+ ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yieldResults,
+ ArrayRef<SILResultInfo> normalResults,
+ Optional<SILResultInfo> errorResult,
+ const ASTContext &ctx,
+ RecursiveTypeProperties properties,
+ Optional<ProtocolConformanceRef> witnessMethodConformance);
public:
- static CanSILFunctionType
- get(GenericSignature *genericSig, ExtInfo ext,
- ParameterConvention calleeConvention,
- ArrayRef<SILParameterInfo> interfaceParams,
- ArrayRef<SILResultInfo> interfaceResults,
- Optional<SILResultInfo> interfaceErrorResult, const ASTContext &ctx,
- Optional<ProtocolConformanceRef> witnessMethodConformance = None);
+ static CanSILFunctionType get(GenericSignature *genericSig,
+ ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention calleeConvention,
+ ArrayRef<SILParameterInfo> interfaceParams,
+ ArrayRef<SILYieldInfo> interfaceYields,
+ ArrayRef<SILResultInfo> interfaceResults,
+ Optional<SILResultInfo> interfaceErrorResult,
+ const ASTContext &ctx,
+ Optional<ProtocolConformanceRef> witnessMethodConformance = None);
/// Given that this function type uses a C-language convention, return its
/// formal semantic result type.
@@ -3423,12 +3490,26 @@
return getCalleeConvention() == ParameterConvention::Direct_Guaranteed;
}
+ /// Is this some kind of coroutine?
+ bool isCoroutine() const {
+ return getCoroutineKind() != SILCoroutineKind::None;
+ }
+ SILCoroutineKind getCoroutineKind() const {
+ return SILCoroutineKind(SILFunctionTypeBits.CoroutineKind);
+ }
+
+ /// Return the array of all the yields.
+ ArrayRef<SILYieldInfo> getYields() const {
+ return const_cast<SILFunctionType *>(this)->getMutableYields();
+ }
+ unsigned getNumYields() const { return isCoroutine() ? NumAnyResults : 0; }
+
/// Return the array of all result information. This may contain inter-mingled
/// direct and indirect results.
ArrayRef<SILResultInfo> getResults() const {
return const_cast<SILFunctionType *>(this)->getMutableResults();
}
- unsigned getNumResults() const { return NumResults; }
+ unsigned getNumResults() const { return isCoroutine() ? 0 : NumAnyResults; }
/// Given that this function type has exactly one result, return it.
/// This is a common situation when working with a function with a known
@@ -3458,14 +3539,14 @@
// indirect property, not the SIL indirect property, should be consulted to
// determine whether function reabstraction is necessary.
unsigned getNumIndirectFormalResults() const {
- return NumIndirectFormalResults;
+ return isCoroutine() ? 0 : NumAnyIndirectFormalResults;
}
/// Does this function have any formally indirect results?
bool hasIndirectFormalResults() const {
return getNumIndirectFormalResults() != 0;
}
unsigned getNumDirectFormalResults() const {
- return NumResults - NumIndirectFormalResults;
+ return isCoroutine() ? 0 : NumAnyResults - NumAnyIndirectFormalResults;
}
struct IndirectFormalResultFilter {
@@ -3607,15 +3688,18 @@
LookupConformanceFn conformances);
void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getGenericSignature(), getExtInfo(), getCalleeConvention(),
- getParameters(), getResults(), getOptionalErrorResult());
+ Profile(ID, getGenericSignature(), getExtInfo(), getCoroutineKind(),
+ getCalleeConvention(), getParameters(), getYields(),
+ getResults(), getOptionalErrorResult());
}
static void Profile(llvm::FoldingSetNodeID &ID,
GenericSignature *genericSig,
ExtInfo info,
+ SILCoroutineKind coroutineKind,
ParameterConvention calleeConvention,
ArrayRef<SILParameterInfo> params,
- ArrayRef<SILResultInfo> result,
+ ArrayRef<SILYieldInfo> yields,
+ ArrayRef<SILResultInfo> results,
Optional<SILResultInfo> errorResult);
// Implement isa/cast/dyncast/etc.
@@ -3713,7 +3797,23 @@
}
};
DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILBlockStorageType, Type)
-
+
+/// A singleton 'token' type, which establishes a formal dependency
+/// between two SIL nodes. A token 'value' cannot be abstracted in
+/// SIL: it cannot be returned, yielded, or passed as a function or
+/// block argument.
+class SILTokenType final : public TypeBase {
+ friend class ASTContext;
+ SILTokenType(const ASTContext &C)
+ : TypeBase(TypeKind::SILToken, &C, RecursiveTypeProperties()) {}
+public:
+ // The singleton instance of this type is ASTContext::TheSILTokenType.
+
+ static bool classof(const TypeBase *T) {
+ return T->getKind() == TypeKind::SILToken;
+ }
+};
+DEFINE_EMPTY_CAN_TYPE_WRAPPER(SILTokenType, Type)
/// A type with a special syntax that is always sugar for a library type.
///
diff --git a/include/swift/Basic/OptimizationMode.h b/include/swift/Basic/OptimizationMode.h
new file mode 100644
index 0000000..e57b8e6
--- /dev/null
+++ b/include/swift/Basic/OptimizationMode.h
@@ -0,0 +1,32 @@
+//===-------- OptimizationMode.h - Swift optimization modes -----*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_BASIC_OPTIMIZATIONMODE_H
+#define SWIFT_BASIC_OPTIMIZATIONMODE_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace swift {
+
+// The optimization mode specified on the command line or with function
+// attributes.
+enum class OptimizationMode : uint8_t {
+ NotSet = 0,
+ NoOptimization = 1, // -Onone
+ ForSpeed = 2, // -Ospeed == -O
+ ForSize = 3, // -Osize
+ LastMode = ForSize
+};
+
+} // end namespace swift
+
+#endif // SWIFT_BASIC_OPTIMIZATIONMODE_H
diff --git a/include/swift/Basic/SourceLoc.h b/include/swift/Basic/SourceLoc.h
index 8fd7b6f..295e46c 100644
--- a/include/swift/Basic/SourceLoc.h
+++ b/include/swift/Basic/SourceLoc.h
@@ -96,6 +96,10 @@
bool isValid() const { return Start.isValid(); }
bool isInvalid() const { return !isValid(); }
+ /// Extend this SourceRange to the smallest continuous SourceRange that
+ /// includes both this range and the other one.
+ void widen(SourceRange Other);
+
bool operator==(const SourceRange &other) const {
return Start == other.Start && End == other.End;
}
diff --git a/include/swift/Basic/Statistic.h b/include/swift/Basic/Statistic.h
index 1dd95e0..fff7e4c 100644
--- a/include/swift/Basic/Statistic.h
+++ b/include/swift/Basic/Statistic.h
@@ -105,6 +105,8 @@
};
private:
+ bool currentProcessExitStatusSet;
+ int currentProcessExitStatus;
SmallString<128> StatsFilename;
SmallString<128> TraceFilename;
llvm::TimeRecord StartedTime;
@@ -140,6 +142,7 @@
AlwaysOnDriverCounters &getDriverCounters();
AlwaysOnFrontendCounters &getFrontendCounters();
AlwaysOnFrontendRecursiveSharedTimers &getFrontendRecursiveSharedTimers();
+ void noteCurrentProcessExitStatus(int);
FrontendStatsTracer getStatsTracer(StringRef N,
SourceRange const &R);
void saveAnyFrontendStatsEvents(FrontendStatsTracer const& T,
diff --git a/include/swift/Basic/Statistics.def b/include/swift/Basic/Statistics.def
index 7d323e5..36033a2 100644
--- a/include/swift/Basic/Statistics.def
+++ b/include/swift/Basic/Statistics.def
@@ -40,6 +40,10 @@
/// run-over-run.
DRIVER_STATISTIC(NumDriverJobsSkipped)
+/// Total number of driver processes that exited with EXIT_FAILURE / not with
+/// EXIT_SUCCESS.
+DRIVER_STATISTIC(NumProcessFailures)
+
/// Next 10 statistics count dirtying-events in the driver's dependency graph,
/// which it uses to decide which files are invalid (and thus which files to
/// build). There are two dimensions to each dirtying event:
@@ -69,6 +73,10 @@
/// Driver statistics are collected for frontend processes
#ifdef FRONTEND_STATISTIC
+/// Total number of frontend processes that exited with EXIT_FAILURE / not with
+/// EXIT_SUCCESS.
+FRONTEND_STATISTIC(Frontend, NumProcessFailures)
+
/// Number of source buffers visible in the source manager.
FRONTEND_STATISTIC(AST, NumSourceBuffers)
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 18bf858..95c5117 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -180,6 +180,7 @@
NODE(ReflectionMetadataSuperclassDescriptor)
NODE(GenericTypeParamDecl)
CONTEXT_NODE(CurryThunk)
+CONTEXT_NODE(DispatchThunk)
NODE(ThrowsAnnotation)
NODE(EmptyList)
NODE(FirstElementMarker)
diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index 0bd2c66..576fa9c 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -309,6 +309,17 @@
}
return SourceFile::ImplicitModuleImportKind::Stdlib;
}
+
+ /// Performs input setup common to these tools:
+ /// sil-opt, sil-func-extractor, sil-llvm-gen, and sil-nm.
+ /// Return value includes the buffer so caller can keep it alive.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ setUpInputForSILTool(StringRef InputFilename, StringRef ModuleNameArg,
+ bool alwaysSetModuleToMain,
+ serialization::ExtendedValidationInfo &extendedInfo);
+ bool hasSerializedAST() {
+ return FrontendOpts.InputKind == InputFileKind::IFK_Swift_Library;
+ }
};
/// A class which manages the state and execution of the compiler.
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 76e6733..ce4b982 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -296,15 +296,18 @@
/// too complex.
unsigned SolverExpressionTimeThreshold = 0;
- enum ActionType {
- NoneAction, ///< No specific action
- Parse, ///< Parse only
- Typecheck, ///< Parse and type-check only
- DumpParse, ///< Parse only and dump AST
+ /// The module for which we should verify all of the generic signatures.
+ std::string VerifyGenericSignaturesInModule;
+
+ enum class ActionType {
+ NoneAction, ///< No specific action
+ Parse, ///< Parse only
+ Typecheck, ///< Parse and type-check only
+ DumpParse, ///< Parse only and dump AST
DumpInterfaceHash, ///< Parse and dump the interface token hash.
- EmitSyntax, ///< Parse and dump Syntax tree as JSON
- DumpAST, ///< Parse, type-check, and dump AST
- PrintAST, ///< Parse, type-check, and pretty-print AST
+ EmitSyntax, ///< Parse and dump Syntax tree as JSON
+ DumpAST, ///< Parse, type-check, and dump AST
+ PrintAST, ///< Parse, type-check, and pretty-print AST
/// Parse and dump scope map.
DumpScopeMaps,
@@ -313,30 +316,30 @@
DumpTypeRefinementContexts,
EmitImportedModules, ///< Emit the modules that this one imports
- EmitPCH, ///< Emit PCH of imported bridging header
+ EmitPCH, ///< Emit PCH of imported bridging header
EmitSILGen, ///< Emit raw SIL
- EmitSIL, ///< Emit canonical SIL
+ EmitSIL, ///< Emit canonical SIL
EmitModuleOnly, ///< Emit module only
- MergeModules, ///< Merge modules only
+ MergeModules, ///< Merge modules only
EmitSIBGen, ///< Emit serialized AST + raw SIL
- EmitSIB, ///< Emit serialized AST + canonical SIL
+ EmitSIB, ///< Emit serialized AST + canonical SIL
Immediate, ///< Immediate mode
- REPL, ///< REPL mode
+ REPL, ///< REPL mode
EmitAssembly, ///< Emit assembly
- EmitIR, ///< Emit LLVM IR
- EmitBC, ///< Emit LLVM BC
- EmitObject, ///< Emit object file
+ EmitIR, ///< Emit LLVM IR
+ EmitBC, ///< Emit LLVM BC
+ EmitObject, ///< Emit object file
};
- bool isCreatingSIL() { return RequestedAction >= EmitSILGen; }
+ bool isCreatingSIL() { return RequestedAction >= ActionType::EmitSILGen; }
/// Indicates the action the user requested that the frontend perform.
- ActionType RequestedAction = NoneAction;
+ ActionType RequestedAction = ActionType::NoneAction;
/// Indicates that the input(s) should be parsed as the Swift stdlib.
bool ParseStdlib = false;
diff --git a/include/swift/IDE/RefactoringKinds.def b/include/swift/IDE/RefactoringKinds.def
index ea9b50d..0e6a1ae 100644
--- a/include/swift/IDE/RefactoringKinds.def
+++ b/include/swift/IDE/RefactoringKinds.def
@@ -52,6 +52,8 @@
RANGE_REFACTORING(ExtractRepeatedExpr, "Extract Repeated Expression", extract.expr.repeated)
+RANGE_REFACTORING(MoveMembersToExtension, "Move To Extension", move.members.to.extension)
+
RANGE_REFACTORING(ConvertStringsConcatenationToInterpolation, "Convert to String Interpolation", convert.string-concatenation.interpolation)
#undef CURSOR_REFACTORING
#undef RANGE_REFACTORING
diff --git a/include/swift/AST/SourceEntityWalker.h b/include/swift/IDE/SourceEntityWalker.h
similarity index 94%
rename from include/swift/AST/SourceEntityWalker.h
rename to include/swift/IDE/SourceEntityWalker.h
index fd33571..61f8cc5 100644
--- a/include/swift/AST/SourceEntityWalker.h
+++ b/include/swift/IDE/SourceEntityWalker.h
@@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef SWIFT_AST_SOURCE_ENTITY_WALKER_H
-#define SWIFT_AST_SOURCE_ENTITY_WALKER_H
+#ifndef SWIFT_IDE_SOURCE_ENTITY_WALKER_H
+#define SWIFT_IDE_SOURCE_ENTITY_WALKER_H
#include "swift/AST/ASTWalker.h"
#include "swift/Basic/LLVM.h"
@@ -36,6 +36,7 @@
class Stmt;
class Expr;
class Type;
+ struct ASTNode;
/// An abstract class used to traverse the AST and provide source information.
@@ -61,6 +62,9 @@
/// Walks the provided Expr.
/// \returns true if traversal was aborted, false otherwise.
bool walk(Expr *E);
+ /// Walks the provided ASTNode.
+ /// \returns true if traversal was aborted, false otherwise.
+ bool walk(ASTNode N);
/// This method is called when first visiting a decl, before walking into its
/// children. If it returns false, the subtree is skipped.
@@ -109,9 +113,11 @@
///
/// \param D the referenced decl.
/// \param Range the source range of the source reference.
+ /// \param AccKind whether this is a read, write or read/write access.
/// \param IsOpenBracket this is \c true when the method is called on an
/// open bracket.
virtual bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket);
/// This method is called for each keyword argument in a call expression.
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index f5e1204..4134871 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -19,7 +19,7 @@
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/Module.h"
#include "swift/AST/ASTPrinter.h"
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Token.h"
#include "llvm/ADT/StringRef.h"
#include <memory>
@@ -242,6 +242,7 @@
bool tryResolve(ModuleEntity Mod, SourceLoc Loc);
bool tryResolve(Stmt *St);
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override;
};
@@ -316,7 +317,7 @@
std::vector<ResolvedLoc> resolve(ArrayRef<UnresolvedLoc> Locs, ArrayRef<Token> Tokens);
};
-enum class RangeKind : int8_t{
+enum class RangeKind : int8_t {
Invalid = -1,
SingleExpression,
SingleStatement,
@@ -324,6 +325,8 @@
MultiStatement,
PartOfExpression,
+
+ MultiTypeMemberDecl,
};
struct DeclaredDecl {
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 6631236..31e028f 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -577,16 +577,6 @@
return reinterpret_cast<SILFunction*>(Pointer);
}
- /// Returns true if this function is only serialized, but not necessarily
- /// code-gen'd. These are fragile transparent functions.
- bool isSILOnly() const {
- if (getKind() != Kind::SILFunction)
- return false;
-
- SILFunction *F = getSILFunction();
- return F->isTransparent() && F->isDefinition() && F->isSerialized();
- }
-
SILGlobalVariable *getSILGlobalVariable() const {
assert(getKind() == Kind::SILGlobalVariable);
return reinterpret_cast<SILGlobalVariable*>(Pointer);
@@ -681,7 +671,6 @@
static LinkInfo get(const UniversalLinkageInfo &linkInfo,
StringRef name,
SILLinkage linkage,
- bool isSILOnly,
ForDefinition_t isDefinition,
bool isWeakImported);
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 018ec22..159dbcd 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -76,6 +76,9 @@
HelpText<"Like -verify, but updates the original source file">;
def verify_ignore_unknown: Flag<["-"], "verify-ignore-unknown">,
HelpText<"Allow diagnostics for '<unknown>' location in verify mode">;
+def verify_generic_signatures : Separate<["-"], "verify-generic-signatures">,
+ MetaVarName<"<module-name>">,
+ HelpText<"Verify the generic signatures in the given module">;
def show_diagnostics_after_fatal : Flag<["-"], "show-diagnostics-after-fatal">,
HelpText<"Keep emitting subsequent diagnostics after a fatal error">;
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 0fa561a..4b2f273 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -58,6 +58,7 @@
class SyntaxParsingContext;
struct RawSyntaxInfo;
struct RawTokenSyntax;
+ enum class SyntaxKind;
}// end of syntax namespace
/// Different contexts in which BraceItemList are parsed.
@@ -416,12 +417,7 @@
BacktrackingScope(Parser &P)
: P(P), PP(P.getParserPosition()), DT(P.Diags) {}
- ~BacktrackingScope() {
- if (Backtrack) {
- P.backtrackToPosition(PP);
- DT.abort();
- }
- }
+ ~BacktrackingScope();
void cancelBacktrack() {
Backtrack = false;
@@ -674,6 +670,7 @@
/// \brief Parse a comma separated list of some elements.
ParserStatus parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
bool AllowSepAfterLast, Diag<> ErrorDiag,
+ syntax::SyntaxKind Kind,
std::function<ParserStatus()> callback);
void consumeTopLevelDecl(ParserPosition BeginParserPosition,
@@ -1247,7 +1244,8 @@
SourceLoc &inLoc);
Expr *parseExprAnonClosureArg();
- ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok);
+ ParserResult<Expr> parseExprList(tok LeftTok, tok RightTok,
+ syntax::SyntaxKind Kind);
/// Parse an expression list, keeping all of the pieces separated.
ParserStatus parseExprList(tok leftTok, tok rightTok,
@@ -1258,7 +1256,8 @@
SmallVectorImpl<Identifier> &exprLabels,
SmallVectorImpl<SourceLoc> &exprLabelLocs,
SourceLoc &rightLoc,
- Expr *&trailingClosure);
+ Expr *&trailingClosure,
+ syntax::SyntaxKind Kind);
ParserResult<Expr> parseTrailingClosure(SourceRange calleeRange);
@@ -1276,10 +1275,8 @@
ParserResult<Expr> parseExprCallSuffix(ParserResult<Expr> fn,
bool isExprBasic);
ParserResult<Expr> parseExprCollection(SourceLoc LSquareLoc = SourceLoc());
- ParserResult<Expr> parseExprArray(SourceLoc LSquareLoc,
- ParserResult<Expr> FirstExpr);
- ParserResult<Expr> parseExprDictionary(SourceLoc LSquareLoc,
- ParserResult<Expr> FirstKey);
+ ParserResult<Expr> parseExprArray(SourceLoc LSquareLoc);
+ ParserResult<Expr> parseExprDictionary(SourceLoc LSquareLoc);
UnresolvedDeclRefExpr *parseExprOperator();
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index 920c1d2..fd459d9 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -66,7 +66,7 @@
unsigned getSizeOfHeapObject() {
// This must match sizeof(HeapObject) for the target.
- return sizeof(StoredPointer) + 8;
+ return sizeof(StoredPointer) * 2;
}
void dumpAllSections(std::ostream &OS) {
@@ -483,9 +483,8 @@
case MetadataSourceKind::ClosureBinding: {
unsigned Index = cast<ClosureBindingMetadataSource>(MS)->getIndex();
- // Skip the context's isa pointer (4 or 8 bytes) and reference counts
- // (4 bytes each regardless of platform word size). This is just
- // sizeof(HeapObject) in the target.
+ // Skip the context's HeapObject header
+ // (one word each for isa pointer and reference counts).
//
// Metadata and conformance tables are stored consecutively after
// the heap object header, in the 'necessary bindings' area.
diff --git a/include/swift/Reflection/TypeRef.h b/include/swift/Reflection/TypeRef.h
index d96fc9e..e88adeb 100644
--- a/include/swift/Reflection/TypeRef.h
+++ b/include/swift/Reflection/TypeRef.h
@@ -344,7 +344,7 @@
for (const auto &Param : Parameters) {
ID.addString(Param.getLabel().str());
ID.addPointer(Param.getType());
- ID.addInteger(static_cast<uint32_t>(Param.getFlags().toRaw()));
+ ID.addInteger(static_cast<uint32_t>(Param.getFlags().getIntValue()));
}
ID.addPointer(Result);
ID.addInteger(static_cast<uint64_t>(Flags.getIntValue()));
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index d8ac5a3..e77064b 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -17,7 +17,6 @@
#ifndef SWIFT_REMOTE_METADATAREADER_H
#define SWIFT_REMOTE_METADATAREADER_H
-#include "swift/AST/Types.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Remote/MemoryReader.h"
#include "swift/Demangling/Demangler.h"
@@ -33,9 +32,9 @@
template <typename BuiltType> class FunctionParam {
StringRef Label;
BuiltType Type;
- ParameterTypeFlags Flags;
+ ParameterFlags Flags;
- FunctionParam(StringRef label, BuiltType type, ParameterTypeFlags flags)
+ FunctionParam(StringRef label, BuiltType type, ParameterFlags flags)
: Label(label), Type(type), Flags(flags) {}
public:
@@ -45,7 +44,7 @@
StringRef getLabel() const { return Label; }
BuiltType getType() const { return Type; }
- ParameterTypeFlags getFlags() const { return Flags; }
+ ParameterFlags getFlags() const { return Flags; }
void setLabel(StringRef label) { Label = label; }
void setType(BuiltType type) { Type = type; }
@@ -53,6 +52,7 @@
void setVariadic() { Flags = Flags.withVariadic(true); }
void setShared() { Flags = Flags.withShared(true); }
void setInOut() { Flags = Flags.withInOut(true); }
+ void setFlags(ParameterFlags flags) { Flags = flags; };
FunctionParam withLabel(StringRef label) const {
return FunctionParam(label, Type, Flags);
@@ -62,7 +62,7 @@
return FunctionParam(Label, type, Flags);
}
- FunctionParam withFlags(ParameterTypeFlags flags) const {
+ FunctionParam withFlags(ParameterFlags flags) const {
return FunctionParam(Label, Type, flags);
}
};
@@ -800,38 +800,25 @@
auto Function = cast<TargetFunctionTypeMetadata<Runtime>>(Meta);
std::vector<FunctionParam<BuiltType>> Parameters;
- StoredPointer ArgumentAddress = MetadataAddress +
- sizeof(TargetFunctionTypeMetadata<Runtime>);
- for (StoredPointer i = 0; i < Function->getNumArguments(); ++i,
- ArgumentAddress += sizeof(StoredPointer)) {
- StoredPointer FlaggedArgumentAddress;
- if (!Reader->readInteger(RemoteAddress(ArgumentAddress),
- &FlaggedArgumentAddress))
+ for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) {
+ auto ParamTypeRef = readTypeFromMetadata(Function->getParameter(i));
+ if (!ParamTypeRef)
return BuiltType();
FunctionParam<BuiltType> Param;
-
- // TODO: Use target-agnostic FlaggedPointer to mask this!
- const auto InOutMask = (StoredPointer) 1;
- // FIXME: Add import parameter related flags from metadata
- if ((FlaggedArgumentAddress & InOutMask) != 0)
- Param.setInOut();
-
- FlaggedArgumentAddress &= ~InOutMask;
- if (auto ParamTypeRef = readTypeFromMetadata(FlaggedArgumentAddress)) {
- Param.setType(ParamTypeRef);
- Parameters.push_back(std::move(Param));
- } else {
- return BuiltType();
- }
+ Param.setType(ParamTypeRef);
+ Param.setFlags(Function->getParameterFlags(i));
+ Parameters.push_back(std::move(Param));
}
auto Result = readTypeFromMetadata(Function->ResultType);
if (!Result)
return BuiltType();
- auto flags = FunctionTypeFlags().withConvention(Function->getConvention())
- .withThrows(Function->throws());
+ auto flags = FunctionTypeFlags()
+ .withConvention(Function->getConvention())
+ .withThrows(Function->throws())
+ .withParameterFlags(Function->hasParameterFlags());
auto BuiltFunction =
Builder.createFunctionType(Parameters, Result, flags);
TypeCache[MetadataAddress] = BuiltFunction;
@@ -1195,8 +1182,26 @@
return _readMetadata<TargetExistentialMetatypeMetadata>(address);
case MetadataKind::ForeignClass:
return _readMetadata<TargetForeignClassMetadata>(address);
- case MetadataKind::Function:
- return _readMetadata<TargetFunctionTypeMetadata>(address);
+ case MetadataKind::Function: {
+ StoredSize flagsValue;
+ auto flagsAddr =
+ address + TargetFunctionTypeMetadata<Runtime>::OffsetToFlags;
+ if (!Reader->readInteger(RemoteAddress(flagsAddr), &flagsValue))
+ return nullptr;
+
+ auto flags =
+ TargetFunctionTypeFlags<StoredSize>::fromIntValue(flagsValue);
+
+ using Parameter =
+ ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;
+ auto totalSize = sizeof(TargetFunctionTypeMetadata<Runtime>) +
+ flags.getNumParameters() * sizeof(Parameter);
+
+ if (flags.hasParameterFlags())
+ totalSize += flags.getNumParameters() * sizeof(uint32_t);
+
+ return _readMetadata(address, totalSize);
+ }
case MetadataKind::HeapGenericLocalVariable:
return _readMetadata<TargetGenericBoxHeapMetadata>(address);
case MetadataKind::HeapLocalVariable:
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index 77a4904..eb786f2 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -1745,36 +1745,53 @@
template <typename Runtime>
struct TargetFunctionTypeMetadata : public TargetMetadata<Runtime> {
using StoredSize = typename Runtime::StoredSize;
-
- // TODO: Make this target agnostic
- using Argument = FlaggedPointer<const TargetMetadata<Runtime> *, 0>;
+ using Parameter = ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>;
TargetFunctionTypeFlags<StoredSize> Flags;
/// The type metadata for the result type.
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata> ResultType;
- TargetPointer<Runtime, Argument> getArguments() {
- return reinterpret_cast<TargetPointer<Runtime, Argument>>(this + 1);
+ Parameter *getParameters() { return reinterpret_cast<Parameter *>(this + 1); }
+
+ const Parameter *getParameters() const {
+ return reinterpret_cast<const Parameter *>(this + 1);
}
- TargetPointer<Runtime, const Argument> getArguments() const {
- return reinterpret_cast<TargetPointer<Runtime, const Argument>>(this + 1);
+ Parameter getParameter(unsigned index) const {
+ assert(index < getNumParameters());
+ return getParameters()[index];
}
-
- StoredSize getNumArguments() const {
- return Flags.getNumArguments();
+
+ ParameterFlags getParameterFlags(unsigned index) const {
+ assert(index < getNumParameters());
+ auto flags = hasParameterFlags() ? getParameterFlags()[index] : 0;
+ return ParameterFlags::fromIntValue(flags);
+ }
+
+ StoredSize getNumParameters() const {
+ return Flags.getNumParameters();
}
FunctionMetadataConvention getConvention() const {
return Flags.getConvention();
}
bool throws() const { return Flags.throws(); }
+ bool hasParameterFlags() const { return Flags.hasParameterFlags(); }
static constexpr StoredSize OffsetToFlags = sizeof(TargetMetadata<Runtime>);
static bool classof(const TargetMetadata<Runtime> *metadata) {
return metadata->getKind() == MetadataKind::Function;
}
+
+ uint32_t *getParameterFlags() {
+ return reinterpret_cast<uint32_t *>(getParameters() + getNumParameters());
+ }
+
+ const uint32_t *getParameterFlags() const {
+ return reinterpret_cast<const uint32_t *>(getParameters() +
+ getNumParameters());
+ }
};
using FunctionTypeMetadata = TargetFunctionTypeMetadata<InProcess>;
@@ -2404,7 +2421,9 @@
struct TargetProtocolConformanceRecord {
public:
using WitnessTableAccessorFn
- = const WitnessTable *(const TargetMetadata<Runtime>*);
+ = const WitnessTable *(const TargetMetadata<Runtime>*,
+ const WitnessTable **,
+ size_t);
private:
/// The protocol being conformed to.
@@ -2639,28 +2658,58 @@
/// \brief Fetch a uniqued metadata for a function type.
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
-swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]);
+swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
+ const Metadata *const *parameters,
+ const uint32_t *parameterFlags,
+ const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
- const void *arg0,
- const Metadata *resultMetadata);
+ const Metadata *arg0,
+ const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *
+swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const Metadata *resultMetadata);
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *result);
SWIFT_RUNTIME_EXPORT
const FunctionTypeMetadata *
-swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const void *arg2,
- const Metadata *resultMetadata);
+swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *swift_getFunctionTypeMetadata3(
+ FunctionTypeFlags flags,
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *arg2,
+ const Metadata *result);
+
+SWIFT_RUNTIME_EXPORT
+const FunctionTypeMetadata *swift_getFunctionTypeMetadata3WithFlags(
+ FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *arg2,
+ ParameterFlags flags2,
+ const Metadata *result);
/// \brief Fetch a uniqued metadata for a thin function type.
SWIFT_RUNTIME_EXPORT
@@ -2750,13 +2799,18 @@
SWIFT_RUNTIME_EXPORT
void
swift_instantiateObjCClass(const ClassMetadata *theClass);
-#endif
/// \brief Fetch a uniqued type metadata for an ObjC class.
SWIFT_RUNTIME_EXPORT
const Metadata *
swift_getObjCClassMetadata(const ClassMetadata *theClass);
+/// \brief Get the ObjC class object from class type metadata.
+SWIFT_RUNTIME_EXPORT
+const ClassMetadata *
+swift_getObjCClassFromMetadata(const Metadata *theClass);
+#endif
+
/// \brief Fetch a unique type metadata object for a foreign type.
SWIFT_RUNTIME_EXPORT
const ForeignTypeMetadata *
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index dcdd45f..a07686e 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -759,28 +759,84 @@
ARGS(OpaquePtrTy, SizeTy, TypeMetadataPtrTy),
ATTRS(NoUnwind))
-// Metadata *swift_getFunctionTypeMetadata(const void **args);
+// Metadata *swift_getFunctionTypeMetadata(unsigned long flags,
+// const Metadata **parameters,
+// const uint32_t *parameterFlags,
+// const Metadata *result);
FUNCTION(GetFunctionMetadata, swift_getFunctionTypeMetadata, DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(Int8PtrTy->getPointerTo(0)),
+ ARGS(SizeTy,
+ TypeMetadataPtrTy->getPointerTo(0),
+ Int32Ty->getPointerTo(0),
+ TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
-// Metadata *swift_getFunctionTypeMetadata1(unsigned long flags, const void *arg0, const Metadata *resultMetadata);
+// Metadata *swift_getFunctionTypeMetadata1(unsigned long flags,
+// const Metadata *arg0,
+// const Metadata *resultMetadata);
FUNCTION(GetFunctionMetadata1, swift_getFunctionTypeMetadata1, DefaultCC,
+ RETURNS(TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata1WithFlags(unsigned long flags,
+// const Metadata *arg0,
+// const uint32_t paramFlags,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata1WithFlags, swift_getFunctionTypeMetadata1WithFlags,
+ DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(SizeTy, Int8PtrTy, TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
-// Metadata *swift_getFunctionTypeMetadata2(unsigned long flags, const void *arg0, const void *arg1, const Metadata *resultMetadata);
-FUNCTION(GetFunctionMetadata2, swift_getFunctionTypeMetadata2, DefaultCC,
+// Metadata *swift_getFunctionTypeMetadata2(unsigned long flags,
+// const Metadata *arg0,
+// const Metadata *arg1,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata2, swift_getFunctionTypeMetadata2,
+ DefaultCC,
+ RETURNS(TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata2WithFlags(unsigned long flags,
+// const Metadata *arg0,
+// const uint32_t flags0,
+// const Metadata *arg1,
+// const uint32_t flags1,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata2WithFlags, swift_getFunctionTypeMetadata2WithFlags,
+ DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(SizeTy, Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy, Int32Ty,
+ TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
-// Metadata *swift_getFunctionTypeMetadata3(unsigned long flags, const void *arg0, const void *arg1, const void *arg2, const Metadata *resultMetadata);
-FUNCTION(GetFunctionMetadata3, swift_getFunctionTypeMetadata3, DefaultCC,
+// Metadata *swift_getFunctionTypeMetadata3(unsigned long flags,
+// const Metadata *arg0,
+// const Metadata *arg1,
+// const Metadata *arg2,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata3, swift_getFunctionTypeMetadata3,
+ DefaultCC,
+ RETURNS(TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, TypeMetadataPtrTy, TypeMetadataPtrTy,
+ TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
+// Metadata *swift_getFunctionTypeMetadata3WithFlags(unsigned long flags,
+// const Metadata *arg0,
+// const uint32_t flags0,
+// const Metadata *arg1,
+// const uint32_t flags1,
+// const Metadata *arg2,
+// const uint32_t flags2,
+// const Metadata *resultMetadata);
+FUNCTION(GetFunctionMetadata3WithFlags, swift_getFunctionTypeMetadata3WithFlags,
+ DefaultCC,
RETURNS(TypeMetadataPtrTy),
- ARGS(SizeTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, TypeMetadataPtrTy),
+ ARGS(SizeTy, TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy, Int32Ty,
+ TypeMetadataPtrTy, Int32Ty, TypeMetadataPtrTy),
ATTRS(NoUnwind, ReadNone))
// Metadata *swift_getForeignTypeMetadata(Metadata *nonUnique);
@@ -841,6 +897,12 @@
ARGS(ObjCClassPtrTy),
ATTRS(NoUnwind, ReadNone))
+// Metadata *swift_getObjCClassFromMetadata(objc_class *theClass);
+FUNCTION(GetObjCClassFromMetadata, swift_getObjCClassFromMetadata, DefaultCC,
+ RETURNS(ObjCClassPtrTy),
+ ARGS(TypeMetadataPtrTy),
+ ATTRS(NoUnwind, ReadNone))
+
// Metadata *swift_getTupleTypeMetadata(size_t numElements,
// Metadata * const *elts,
// const char *labels,
diff --git a/include/swift/SIL/SILBasicBlock.h b/include/swift/SIL/SILBasicBlock.h
index ae02555..5de833b 100644
--- a/include/swift/SIL/SILBasicBlock.h
+++ b/include/swift/SIL/SILBasicBlock.h
@@ -227,7 +227,7 @@
void dropAllArguments() { ArgumentList.clear(); }
//===--------------------------------------------------------------------===//
- // Predecessors and Successors
+ // Successors
//===--------------------------------------------------------------------===//
using SuccessorListTy = TermInst::SuccessorListTy;
@@ -242,81 +242,63 @@
return getTerminator()->getSuccessors();
}
- using const_succ_iterator = ConstSuccessorListTy::const_iterator;
- using succ_iterator = SuccessorListTy::iterator;
+ using const_succ_iterator = TermInst::const_succ_iterator;
+ using succ_iterator = TermInst::succ_iterator;
- bool succ_empty() const { return getSuccessors().empty(); }
- succ_iterator succ_begin() { return getSuccessors().begin(); }
- succ_iterator succ_end() { return getSuccessors().end(); }
- const_succ_iterator succ_begin() const { return getSuccessors().begin(); }
- const_succ_iterator succ_end() const { return getSuccessors().end(); }
+ bool succ_empty() const { return getTerminator()->succ_empty(); }
+ succ_iterator succ_begin() { return getTerminator()->succ_begin(); }
+ succ_iterator succ_end() { return getTerminator()->succ_end(); }
+ const_succ_iterator succ_begin() const {
+ return getTerminator()->succ_begin();
+ }
+ const_succ_iterator succ_end() const { return getTerminator()->succ_end(); }
- using succblock_iterator =
- TransformIterator<SILSuccessor *,
- std::function<SILBasicBlock *(const SILSuccessor &)>>;
- using const_succblock_iterator = TransformIterator<
- const SILSuccessor *,
- std::function<const SILBasicBlock *(const SILSuccessor &)>>;
+ using succblock_iterator = TermInst::succblock_iterator;
+ using const_succblock_iterator = TermInst::const_succblock_iterator;
+
succblock_iterator succblock_begin() {
- using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
- FuncTy F(&SILSuccessor::getBB);
- return makeTransformIterator(getSuccessors().begin(), F);
+ return getTerminator()->succblock_begin();
}
succblock_iterator succblock_end() {
- using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
- FuncTy F(&SILSuccessor::getBB);
- return makeTransformIterator(getSuccessors().end(), F);
+ return getTerminator()->succblock_end();
}
const_succblock_iterator succblock_begin() const {
- using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
- FuncTy F(&SILSuccessor::getBB);
- return makeTransformIterator(getSuccessors().begin(), F);
+ return getTerminator()->succblock_begin();
}
const_succblock_iterator succblock_end() const {
- using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
- FuncTy F(&SILSuccessor::getBB);
- return makeTransformIterator(getSuccessors().end(), F);
+ return getTerminator()->succblock_end();
}
SILBasicBlock *getSingleSuccessorBlock() {
- if (succ_empty() || std::next(succ_begin()) != succ_end())
- return nullptr;
- return *succ_begin();
+ return getTerminator()->getSingleSuccessorBlock();
}
const SILBasicBlock *getSingleSuccessorBlock() const {
- return const_cast<SILBasicBlock *>(this)->getSingleSuccessorBlock();
+ return getTerminator()->getSingleSuccessorBlock();
}
/// \brief Returns true if \p BB is a successor of this block.
- bool isSuccessorBlock(SILBasicBlock *BB) const {
- auto Range = getSuccessorBlocks();
- return any_of(Range, [&BB](const SILBasicBlock *SuccBB) -> bool {
- return BB == SuccBB;
- });
+ bool isSuccessorBlock(SILBasicBlock *Block) const {
+ return getTerminator()->isSuccessorBlock(Block);
}
- using SuccessorBlockListTy =
- TransformRange<SuccessorListTy,
- std::function<SILBasicBlock *(const SILSuccessor &)>>;
- using ConstSuccessorBlockListTy =
- TransformRange<ConstSuccessorListTy,
- std::function<const SILBasicBlock *(const SILSuccessor &)>>;
+ using SuccessorBlockListTy = TermInst::SuccessorBlockListTy;
+ using ConstSuccessorBlockListTy = TermInst::ConstSuccessorBlockListTy;
/// Return the range of SILBasicBlocks that are successors of this block.
SuccessorBlockListTy getSuccessorBlocks() {
- using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
- FuncTy F(&SILSuccessor::getBB);
- return makeTransformRange(getSuccessors(), F);
+ return getTerminator()->getSuccessorBlocks();
}
/// Return the range of SILBasicBlocks that are successors of this block.
ConstSuccessorBlockListTy getSuccessorBlocks() const {
- using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
- FuncTy F(&SILSuccessor::getBB);
- return makeTransformRange(getSuccessors(), F);
+ return getTerminator()->getSuccessorBlocks();
}
+ //===--------------------------------------------------------------------===//
+ // Predecessors
+ //===--------------------------------------------------------------------===//
+
using pred_iterator = SILSuccessor::pred_iterator;
bool pred_empty() const { return PredList == nullptr; }
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index da792da..27a8a51 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -381,6 +381,25 @@
SpecializationInfo));
}
+ BeginApplyInst *createBeginApply(
+ SILLocation Loc, SILValue Fn, SubstitutionList Subs,
+ ArrayRef<SILValue> Args, bool isNonThrowing,
+ const GenericSpecializationInformation *SpecializationInfo = nullptr) {
+ return insert(BeginApplyInst::create(getSILDebugLocation(Loc), Fn, Subs,
+ Args, isNonThrowing, silConv, *F,
+ OpenedArchetypes, SpecializationInfo));
+ }
+
+ AbortApplyInst *createAbortApply(SILLocation loc, SILValue beginApply) {
+ return insert(new (getModule()) AbortApplyInst(getSILDebugLocation(loc),
+ beginApply));
+ }
+
+ EndApplyInst *createEndApply(SILLocation loc, SILValue beginApply) {
+ return insert(new (getModule()) EndApplyInst(getSILDebugLocation(loc),
+ beginApply));
+ }
+
BuiltinInst *createBuiltin(SILLocation Loc, Identifier Name, SILType ResultTy,
SubstitutionList Subs,
ArrayRef<SILValue> Args) {
@@ -1218,6 +1237,16 @@
getModule(), getSILDebugLocation(Loc), Operand));
}
+ MultipleValueInstruction *emitDestructureValueOperation(SILLocation Loc,
+ SILValue Operand) {
+ SILType OpTy = Operand->getType();
+ if (OpTy.is<TupleType>())
+ return createDestructureTuple(Loc, Operand);
+ if (OpTy.getStructOrBoundGenericStruct())
+ return createDestructureStruct(Loc, Operand);
+ llvm_unreachable("Can not emit a destructure for this type of operand.");
+ }
+
ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
return insert(new (getModule()) ClassMethodInst(
@@ -1617,6 +1646,18 @@
new (getModule()) ThrowInst(getSILDebugLocation(Loc), errorValue));
}
+ UnwindInst *createUnwind(SILLocation loc) {
+ return insertTerminator(
+ new (getModule()) UnwindInst(getSILDebugLocation(loc)));
+ }
+
+ YieldInst *createYield(SILLocation loc, ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *resumeBB, SILBasicBlock *unwindBB) {
+ return insertTerminator(
+ YieldInst::create(getSILDebugLocation(loc), yieldedValues,
+ resumeBB, unwindBB, getFunction()));
+ }
+
CondBranchInst *
createCondBranch(SILLocation Loc, SILValue Cond, SILBasicBlock *Target1,
SILBasicBlock *Target2,
@@ -1864,6 +1905,53 @@
lowering.emitDestroyValue(*this, Loc, v);
}
+ /// Convenience function for handling begin_borrow instructions in ownership
+ /// and non-ownership SIL. In non-ownership SIL we just forward the input
+ /// value. Otherwise, we emit the begin_borrow instruction.
+ SILValue emitBeginBorrowOperation(SILLocation Loc, SILValue Value) {
+ assert(!Value->getType().isAddress());
+ // If ownership is not enabled in the function, just return our original
+ // value.
+ if (getFunction().hasUnqualifiedOwnership())
+ return Value;
+
+ // If we have a trivial value, just return the value. Trivial values have
+ // lifetimes independent of any other values.
+ //
+ // *NOTE* For now to be conservative since we do not have the ownership
+ // verifier everywhere, we use getType()::isTrivial() instead of
+ // getOwnershipKind().
+ if (Value->getType().isTrivial(getModule())) {
+ return Value;
+ }
+
+ // Otherwise, we have a non-trivial value, perform the borrow.
+ return createBeginBorrow(Loc, Value);
+ }
+
+ /// Convenience function for handling end_borrow instructions in ownership and
+ /// non-ownership SIL. In non-ownership SIL we just early exit. Otherwise, we
+ /// emit the end_borrow.
+ void emitEndBorrowOperation(SILLocation Loc, SILValue Borrowed,
+ SILValue Original) {
+ assert(!Borrowed->getType().isAddress());
+ // If ownership is not enabled, just return.
+ if (getFunction().hasUnqualifiedOwnership())
+ return;
+
+ // If we have a trivial value, just return. Trivial values have lifetimes
+ // independent of any other values.
+ //
+ // *NOTE* For now to be conservative since we do not have the ownership
+ // verifier everywhere, we use getType()::isTrivial() instead of
+ // getOwnershipKind().
+ if (Borrowed->getType().isTrivial(getModule())) {
+ return;
+ }
+
+ createEndBorrow(Loc, Borrowed, Original);
+ }
+
SILValue emitTupleExtract(SILLocation Loc, SILValue Operand, unsigned FieldNo,
SILType ResultTy) {
// Fold tuple_extract(tuple(x,y,z),2)
@@ -1990,6 +2078,35 @@
}
};
+class SavedInsertionPointRAII {
+ SILBuilder &Builder;
+ PointerUnion<SILInstruction *, SILBasicBlock *> SavedIP;
+
+public:
+ SavedInsertionPointRAII(SILBuilder &B, SILInstruction *NewIP)
+ : Builder(B), SavedIP(&*B.getInsertionPoint()) {
+ Builder.setInsertionPoint(NewIP);
+ }
+
+ SavedInsertionPointRAII(SILBuilder &B, SILBasicBlock *NewIP)
+ : Builder(B), SavedIP(B.getInsertionBB()) {
+ Builder.setInsertionPoint(NewIP);
+ }
+
+ SavedInsertionPointRAII(const SavedInsertionPointRAII &) = delete;
+ SavedInsertionPointRAII &operator=(const SavedInsertionPointRAII &) = delete;
+ SavedInsertionPointRAII(SavedInsertionPointRAII &&) = delete;
+ SavedInsertionPointRAII &operator=(SavedInsertionPointRAII &&) = delete;
+
+ ~SavedInsertionPointRAII() {
+ if (SavedIP.is<SILInstruction *>()) {
+ Builder.setInsertionPoint(SavedIP.get<SILInstruction *>());
+ } else {
+ Builder.setInsertionPoint(SavedIP.get<SILBasicBlock *>());
+ }
+ }
+};
+
} // end swift namespace
#endif
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 833719b..0840a54 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -616,6 +616,39 @@
template<typename ImplClass>
void
+SILCloner<ImplClass>::visitBeginApplyInst(BeginApplyInst *Inst) {
+ auto Args = getOpValueArray<8>(Inst->getArguments());
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createBeginApply(getOpLocation(Inst->getLoc()),
+ getOpValue(Inst->getCallee()),
+ getOpSubstitutions(Inst->getSubstitutions()),
+ Args,
+ Inst->isNonThrowing(),
+ GenericSpecializationInformation::create(
+ Inst, getBuilder())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitAbortApplyInst(AbortApplyInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createAbortApply(getOpLocation(Inst->getLoc()),
+ getOpValue(Inst->getOperand())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitEndApplyInst(EndApplyInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createEndApply(getOpLocation(Inst->getLoc()),
+ getOpValue(Inst->getOperand())));
+}
+
+template<typename ImplClass>
+void
SILCloner<ImplClass>::visitFunctionRefInst(FunctionRefInst *Inst) {
SILFunction *OpFunction = getOpFunction(Inst->getReferencedFunction());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
@@ -2118,6 +2151,27 @@
template<typename ImplClass>
void
+SILCloner<ImplClass>::visitUnwindInst(UnwindInst *Inst) {
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createUnwind(getOpLocation(Inst->getLoc())));
+}
+
+template<typename ImplClass>
+void
+SILCloner<ImplClass>::visitYieldInst(YieldInst *Inst) {
+ auto Values = getOpValueArray<8>(Inst->getYieldedValues());
+ auto ResumeBB = getOpBasicBlock(Inst->getResumeBB());
+ auto UnwindBB = getOpBasicBlock(Inst->getUnwindBB());
+
+ getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
+ doPostProcess(Inst,
+ getBuilder().createYield(getOpLocation(Inst->getLoc()), Values,
+ ResumeBB, UnwindBB));
+}
+
+template<typename ImplClass>
+void
SILCloner<ImplClass>::visitBranchInst(BranchInst *Inst) {
auto Args = getOpValueArray<8>(Inst->getArgs());
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
diff --git a/include/swift/SIL/SILDeclRef.h b/include/swift/SIL/SILDeclRef.h
index 4f95c8a..bc3acf9 100644
--- a/include/swift/SIL/SILDeclRef.h
+++ b/include/swift/SIL/SILDeclRef.h
@@ -66,8 +66,6 @@
/// True if the entry point is natively foreign.
bool requiresForeignToNativeThunk(ValueDecl *vd);
-unsigned getNaturalUncurryLevel(ValueDecl *vd);
-
enum ForDefinition_t : bool {
NotForDefinition = false,
ForDefinition = true
@@ -219,6 +217,7 @@
enum class ManglingKind {
Default,
DynamicThunk,
+ SwiftDispatchThunk,
};
/// Produce a mangled form of this constant.
@@ -304,7 +303,7 @@
void print(llvm::raw_ostream &os) const;
void dump() const;
- unsigned getUncurryLevel() const;
+ unsigned getParameterListCount() const;
ResilienceExpansion getResilienceExpansion() const {
return ResilienceExpansion(Expansion);
@@ -345,6 +344,10 @@
/// to foreign C or ObjC calling convention.
bool isNativeToForeignThunk() const;
+ /// True if the decl ref references a method which introduces a new vtable
+ /// entry.
+ bool requiresNewVTableEntry() const;
+
/// Return a SILDeclRef to the declaration overridden by this one, or
/// a null SILDeclRef if there is no override.
SILDeclRef getOverridden() const;
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 2e6ba51..efbd741 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -17,6 +17,7 @@
#ifndef SWIFT_SIL_SILFUNCTION_H
#define SWIFT_SIL_SILFUNCTION_H
+#include "swift/AST/ResilienceExpansion.h"
#include "swift/Basic/ProfileCounter.h"
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILDebugScope.h"
@@ -170,6 +171,10 @@
/// pre-specialization.
unsigned KeepAsPublic : 1;
+ /// If != OptimizationMode::NotSet, the optimization mode specified with an
+ /// function attribute.
+ OptimizationMode OptMode;
+
/// This is the number of uses of this SILFunction inside the SIL.
/// It does not include references from debug scopes.
unsigned RefCount = 0;
@@ -328,6 +333,12 @@
return getLoweredFunctionType()->getRepresentation();
}
+ ResilienceExpansion getResilienceExpansion() const {
+ return (isSerialized()
+ ? ResilienceExpansion::Minimal
+ : ResilienceExpansion::Maximal);
+ }
+
/// Returns true if this function has a calling convention that has a self
/// argument.
bool hasSelfParam() const {
@@ -472,10 +483,26 @@
void addSpecializeAttr(SILSpecializeAttr *Attr);
+
+ /// Get this function's optimization mode or OptimizationMode::NotSet if it is
+ /// not set for this specific function.
+ OptimizationMode getOptimizationMode() const { return OptMode; }
+
+ /// Returns the optimization mode for the function. If no mode is set for the
+ /// function, returns the global mode, i.e. the mode of the module's options.
+ OptimizationMode getEffectiveOptimizationMode() const;
+
+ void setOptimizationMode(OptimizationMode mode) { OptMode = mode; }
+
/// \returns True if the function is optimizable (i.e. not marked as no-opt),
/// or is raw SIL (so that the mandatory passes still run).
bool shouldOptimize() const;
+ /// Returns true if this function should be optimized for size.
+ bool optimizeForSize() const {
+ return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
+ }
+
/// Returns true if this is a function that should have its ownership
/// verified.
bool shouldVerifyOwnership() const;
diff --git a/include/swift/SIL/SILFunctionConventions.h b/include/swift/SIL/SILFunctionConventions.h
index 558541e..d26e981 100644
--- a/include/swift/SIL/SILFunctionConventions.h
+++ b/include/swift/SIL/SILFunctionConventions.h
@@ -45,10 +45,14 @@
static bool isIndirectSILParam(SILParameterInfo param, bool loweredAddresses);
+ static bool isIndirectSILYield(SILYieldInfo yield, bool loweredAddresses);
+
static bool isIndirectSILResult(SILResultInfo result, bool loweredAddresses);
static SILType getSILParamType(SILParameterInfo param, bool loweredAddresses);
+ static SILType getSILYieldType(SILYieldInfo yield, bool loweredAddresses);
+
static SILType getSILResultType(SILResultInfo param, bool loweredAddresses);
public:
@@ -77,6 +81,10 @@
return isIndirectSILParam(param, loweredAddresses);
}
+ bool isSILIndirect(SILYieldInfo yield) const {
+ return isIndirectSILYield(yield, loweredAddresses);
+ }
+
bool isSILIndirect(SILResultInfo result) const {
return isIndirectSILResult(result, loweredAddresses);
}
@@ -85,6 +93,10 @@
return getSILParamType(param, loweredAddresses);
}
+ SILType getSILType(SILYieldInfo yield) const {
+ return getSILYieldType(yield, loweredAddresses);
+ }
+
SILType getSILType(SILResultInfo result) const {
return getSILResultType(result, loweredAddresses);
}
@@ -115,6 +127,10 @@
return silConv.isSILIndirect(param);
}
+ bool isSILIndirect(SILYieldInfo yield) const {
+ return silConv.isSILIndirect(yield);
+ }
+
bool isSILIndirect(SILResultInfo result) const {
return silConv.isSILIndirect(result);
}
@@ -123,6 +139,10 @@
return silConv.getSILType(param);
}
+ SILType getSILType(SILYieldInfo yield) const {
+ return silConv.getSILType(yield);
+ }
+
SILType getSILType(SILResultInfo result) const {
return silConv.getSILType(result);
}
@@ -279,6 +299,28 @@
}
//===--------------------------------------------------------------------===//
+ // SIL yield types.
+ //===--------------------------------------------------------------------===//
+
+ unsigned getNumYields() const { return funcTy->getNumYields(); }
+
+ ArrayRef<SILYieldInfo> getYields() const {
+ return funcTy->getYields();
+ }
+
+ using SILYieldTypeIter =
+ llvm::mapped_iterator<const SILYieldInfo *, SILParameterTypeFunc>;
+ using SILYieldTypeRange = IteratorRange<SILYieldTypeIter>;
+
+ SILYieldTypeRange getYieldSILTypes() const {
+ return makeIteratorRange(
+ SILYieldTypeIter(funcTy->getYields().begin(),
+ SILParameterTypeFunc(silConv)),
+ SILYieldTypeIter(funcTy->getYields().end(),
+ SILParameterTypeFunc(silConv)));
+ }
+
+ //===--------------------------------------------------------------------===//
// SILArgument API, including indirect results and parameters.
//
// The argument indices below relate to full applies in which the caller and
@@ -363,6 +405,11 @@
llvm_unreachable("covered switch isn't covered?!");
}
+inline bool SILModuleConventions::isIndirectSILYield(SILYieldInfo yield,
+ bool loweredAddresses) {
+ return isIndirectSILParam(yield, loweredAddresses);
+}
+
inline bool SILModuleConventions::isIndirectSILResult(SILResultInfo result,
bool loweredAddresses) {
switch (result.getConvention()) {
@@ -386,6 +433,11 @@
: SILType::getPrimitiveObjectType(param.getType());
}
+inline SILType SILModuleConventions::getSILYieldType(SILYieldInfo yield,
+ bool loweredAddresses) {
+ return getSILParamType(yield, loweredAddresses);
+}
+
inline SILType SILModuleConventions::getSILResultType(SILResultInfo result,
bool loweredAddresses) {
return SILModuleConventions::isIndirectSILResult(result, loweredAddresses)
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 1ed4bcb..d27792d 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -133,7 +133,10 @@
public:
SILInstructionResultArray() : Pointer(nullptr), Size(0) {}
SILInstructionResultArray(const SingleValueInstruction *SVI);
- SILInstructionResultArray(ArrayRef<MultipleValueInstructionResult> MVResults);
+ SILInstructionResultArray(ArrayRef<MultipleValueInstructionResult> results);
+
+ template <class Result>
+ SILInstructionResultArray(ArrayRef<Result> results);
SILInstructionResultArray(const SILInstructionResultArray &Other) = default;
SILInstructionResultArray &
@@ -153,8 +156,14 @@
iterator begin() const;
iterator end() const;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ reverse_iterator rbegin() const;
+ reverse_iterator rend() const;
+
using range = llvm::iterator_range<iterator>;
range getValues() const;
+ using reverse_range = llvm::iterator_range<reverse_iterator>;
+ reverse_range getReversedValues() const;
using type_range = llvm::iterator_range<
llvm::mapped_iterator<iterator, std::function<SILType(SILValue)>>>;
@@ -197,9 +206,7 @@
}
};
-class SILInstructionResultArray::iterator
- : public std::iterator<std::bidirectional_iterator_tag, SILValue,
- ptrdiff_t> {
+class SILInstructionResultArray::iterator {
/// Our "parent" array.
///
/// This is actually a value type reference into a SILInstruction of some
@@ -211,14 +218,21 @@
Optional<unsigned> Index;
public:
+ using difference_type = int;
+ using value_type = SILValue;
+ using pointer = void;
+ using reference = SILValue;
+ using iterator_category = std::bidirectional_iterator_tag;
+
iterator() = default;
iterator(const SILInstructionResultArray &Parent,
Optional<unsigned> Index = 0)
: Parent(Parent), Index(Index) {}
SILValue operator*() const { return Parent[Index.getValue()]; }
-
+ SILValue operator*() { return Parent[Index.getValue()]; }
SILValue operator->() const { return operator*(); }
+ SILValue operator->() { return operator*(); }
iterator &operator++() {
++Index.getValue();
@@ -794,6 +808,15 @@
static constexpr uint64_t IndexBitOffset = ValueOwnershipKind::NumBits;
};
+template <class Result>
+SILInstructionResultArray::SILInstructionResultArray(ArrayRef<Result> results)
+ : SILInstructionResultArray(
+ ArrayRef<MultipleValueInstructionResult>(results.data(),
+ results.size())) {
+ static_assert(sizeof(Result) == sizeof(MultipleValueInstructionResult),
+ "MultipleValueInstructionResult subclass has wrong size");
+}
+
/// An instruction that may produce an arbitrary number of values.
class MultipleValueInstruction : public SILInstruction {
friend class SILInstruction;
@@ -825,13 +848,33 @@
}
};
+template <typename...> class InitialTrailingObjects;
+template <typename...> class FinalTrailingObjects;
+
/// A utility mixin class that must be used by /all/ subclasses of
/// MultipleValueInstruction to store their results.
-template <SILInstructionKind Kind, typename Derived, typename DerivedResult,
- typename... OtherTrailingTypes>
-class MultipleValueInstructionTrailingObjects
- : protected llvm::TrailingObjects<Derived, MultipleValueInstruction *,
- DerivedResult, OtherTrailingTypes...> {
+///
+/// The exact ordering of trailing types matters quite a lot because
+/// it's vital that the fields used by preceding numTrailingObjects
+/// implementations be initialized before this base class is (and
+/// conversely that this base class be initialized before any of the
+/// succeeding numTrailingObjects implementations are called).
+template <typename Derived, typename DerivedResult,
+ typename Init = InitialTrailingObjects<>,
+ typename Final = FinalTrailingObjects<>>
+class MultipleValueInstructionTrailingObjects;
+
+template <typename Derived, typename DerivedResult,
+ typename... InitialOtherTrailingTypes,
+ typename... FinalOtherTrailingTypes>
+class MultipleValueInstructionTrailingObjects<Derived, DerivedResult,
+ InitialTrailingObjects<InitialOtherTrailingTypes...>,
+ FinalTrailingObjects<FinalOtherTrailingTypes...>>
+ : protected llvm::TrailingObjects<Derived,
+ InitialOtherTrailingTypes...,
+ MultipleValueInstruction *,
+ DerivedResult,
+ FinalOtherTrailingTypes...> {
static_assert(LLVM_IS_FINAL(DerivedResult),
"Expected DerivedResult to be final");
static_assert(
@@ -844,8 +887,10 @@
protected:
using TrailingObjects =
- llvm::TrailingObjects<Derived, MultipleValueInstruction *, DerivedResult,
- OtherTrailingTypes...>;
+ llvm::TrailingObjects<Derived,
+ InitialOtherTrailingTypes...,
+ MultipleValueInstruction *, DerivedResult,
+ FinalOtherTrailingTypes...>;
friend TrailingObjects;
using TrailingObjects::totalSizeToAlloc;
@@ -905,15 +950,17 @@
}
public:
+ ArrayRef<DerivedResult> getAllResultsBuffer() const {
+ auto *ptr = this->template getTrailingObjects<DerivedResult>();
+ return { ptr, NumResults };
+ }
+
SILInstructionResultArray getAllResults() const {
// Our results start at element 1 since we stash the pointer to our parent
// MultipleValueInstruction in the 0 elt slot. This allows all
// MultipleValueInstructionResult to find their parent
// MultipleValueInstruction by using pointer arithmetic.
- auto *Result = this->template getTrailingObjects<DerivedResult>();
- return SILInstructionResultArray(
- {static_cast<const MultipleValueInstructionResult *>(Result),
- NumResults});
+ return SILInstructionResultArray(getAllResultsBuffer());
};
};
@@ -1558,9 +1605,19 @@
SubstitutionList getSubstitutions() const { return Subs; }
};
-void *allocateApplyInst(SILFunction &F, size_t size, size_t align);
class PartialApplyInst;
+// There's no good reason for the OverloadToken type to be internal
+// or protected, and it makes it very difficult to write our CRTP classes
+// if it is, so pull it out. TODO: just fix LLVM.
+struct TerribleOverloadTokenHack :
+ llvm::trailing_objects_internal::TrailingObjectsBase {
+ template <class T>
+ using Hack = OverloadToken<T>;
+};
+template <class T>
+using OverloadToken = TerribleOverloadTokenHack::Hack<T>;
+
/// ApplyInstBase - An abstract class for different kinds of function
/// application.
template <class Impl, class Base,
@@ -1587,50 +1644,71 @@
/// Used for apply_inst instructions: true if the called function has an
/// error result but is not actually throwing.
- bool NonThrowing: 1;
+ unsigned NonThrowing: 1;
/// The number of call arguments as required by the callee.
unsigned NumCallArguments;
- /// The fixed operand is the callee; the rest are arguments.
- TailAllocatedOperandList<NumStaticOperands> Operands;
+ /// The total number of type-dependent operands.
+ unsigned NumTypeDependentOperands;
- Substitution *getSubstitutionsStorage() {
- return reinterpret_cast<Substitution*>(Operands.asArray().end());
- }
+ Impl &asImpl() { return static_cast<Impl &>(*this); }
+ const Impl &asImpl() const { return static_cast<const Impl &>(*this); }
- const Substitution *getSubstitutionsStorage() const {
- return reinterpret_cast<const Substitution*>(Operands.asArray().end());
+ MutableArrayRef<Substitution> getSubstitutionsBuffer() {
+ return { asImpl().template getTrailingObjects<Substitution>(),
+ NumSubstitutions };
}
protected:
template <class... As>
ApplyInstBase(SILInstructionKind kind, SILDebugLocation DebugLoc, SILValue callee,
- SILType substCalleeType, SubstitutionList substitutions,
+ SILType substCalleeType, SubstitutionList subs,
ArrayRef<SILValue> args,
- ArrayRef<SILValue> TypeDependentOperands,
- const GenericSpecializationInformation *SpecializationInfo,
+ ArrayRef<SILValue> typeDependentOperands,
+ const GenericSpecializationInformation *specializationInfo,
As... baseArgs)
: Base(kind, DebugLoc, baseArgs...), SubstCalleeType(substCalleeType),
- SpecializationInfo(SpecializationInfo),
- NumSubstitutions(substitutions.size()), NonThrowing(false),
+ SpecializationInfo(specializationInfo),
+ NumSubstitutions(subs.size()), NonThrowing(false),
NumCallArguments(args.size()),
- Operands(this, args, TypeDependentOperands, callee) {
- static_assert(sizeof(Impl) == sizeof(*this),
- "subclass has extra storage, cannot use TailAllocatedOperandList");
- memcpy(getSubstitutionsStorage(), substitutions.begin(),
- sizeof(substitutions[0]) * substitutions.size());
+ NumTypeDependentOperands(typeDependentOperands.size()) {
+
+ // Initialize the operands.
+ auto allOperands = getAllOperands();
+ new (&allOperands[Callee]) Operand(this, callee);
+ for (size_t i : indices(args)) {
+ new (&allOperands[NumStaticOperands + i]) Operand(this, args[i]);
+ }
+ for (size_t i : indices(typeDependentOperands)) {
+ new (&allOperands[NumStaticOperands + args.size() + i])
+ Operand(this, typeDependentOperands[i]);
+ }
+
+ // Initialize the substitutions.
+ memcpy(getSubstitutionsBuffer().data(), subs.begin(),
+ sizeof(subs[0]) * subs.size());
}
- static void *allocate(SILFunction &F,
- SubstitutionList substitutions,
- ArrayRef<SILValue> TypeDependentOperands,
- ArrayRef<SILValue> args) {
- return allocateApplyInst(
- F, sizeof(Impl) + decltype(Operands)::getExtraSize(
- args.size() + TypeDependentOperands.size()) +
- sizeof(substitutions[0]) * substitutions.size(),
- alignof(Impl));
+ ~ApplyInstBase() {
+ for (auto &operand : getAllOperands())
+ operand.~Operand();
+ }
+
+ template <class, class...>
+ friend class llvm::TrailingObjects;
+
+ unsigned numTrailingObjects(OverloadToken<Substitution>) const {
+ return NumSubstitutions;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<Operand>) const {
+ return getNumAllOperands();
+ }
+
+ static size_t getNumAllOperands(ArrayRef<SILValue> args,
+ ArrayRef<SILValue> typeDependentOperands) {
+ return NumStaticOperands + args.size() + typeDependentOperands.size();
}
void setNonThrowing(bool isNonThrowing) { NonThrowing = isNonThrowing; }
@@ -1641,7 +1719,7 @@
/// The operand number of the first argument.
static unsigned getArgumentOperandNumber() { return NumStaticOperands; }
- SILValue getCallee() const { return Operands[Callee].get(); }
+ SILValue getCallee() const { return getAllOperands()[Callee].get(); }
/// Gets the referenced function by looking through partial apply,
/// convert_function, and thin to thick function until we find a function_ref.
@@ -1689,31 +1767,58 @@
bool hasSubstitutions() const { return NumSubstitutions != 0; }
/// The substitutions used to bind the generic arguments of this function.
- MutableArrayRef<Substitution> getSubstitutions() {
- return {getSubstitutionsStorage(), NumSubstitutions};
+ SubstitutionList getSubstitutions() const {
+ return { asImpl().template getTrailingObjects<Substitution>(),
+ NumSubstitutions };
}
- SubstitutionList getSubstitutions() const {
- return {getSubstitutionsStorage(), NumSubstitutions};
+ /// Return the total number of operands of this instruction.
+ unsigned getNumAllOperands() const {
+ return NumStaticOperands + NumCallArguments + NumTypeDependentOperands;
+ }
+
+ /// Return all the operands of this instruction, which are (in order):
+ /// - the callee
+ /// - the formal arguments
+ /// - the type-dependency arguments
+ MutableArrayRef<Operand> getAllOperands() {
+ return { asImpl().template getTrailingObjects<Operand>(),
+ getNumAllOperands() };
+ }
+
+ ArrayRef<Operand> getAllOperands() const {
+ return { asImpl().template getTrailingObjects<Operand>(),
+ getNumAllOperands() };
+ }
+
+ /// Check whether the given operand index is a call-argument index
+ /// and, if so, return that index.
+ Optional<unsigned> getArgumentIndexForOperandIndex(unsigned index) {
+ assert(index < getNumAllOperands());
+ if (index < NumStaticOperands) return None;
+ index -= NumStaticOperands;
+ if (index >= NumCallArguments) return None;
+ return index;
}
/// The arguments passed to this instruction.
MutableArrayRef<Operand> getArgumentOperands() {
- return Operands.getDynamicAsArray().slice(0, getNumCallArguments());
+ return getAllOperands().slice(NumStaticOperands, NumCallArguments);
}
ArrayRef<Operand> getArgumentOperands() const {
- return Operands.getDynamicAsArray().slice(0, getNumCallArguments());
+ return getAllOperands().slice(NumStaticOperands, NumCallArguments);
}
/// The arguments passed to this instruction.
OperandValueArrayRef getArguments() const {
- return OperandValueArrayRef(
- Operands.getDynamicAsArray().slice(0, getNumCallArguments()));
+ return OperandValueArrayRef(getArgumentOperands());
}
- /// Returns the number of arguments for this partial apply.
- unsigned getNumArguments() const { return getArguments().size(); }
+ /// Returns the number of arguments being passed by this apply.
+ /// If this is a partial_apply, it can be less than the number of
+ /// parameters.
+ unsigned getNumArguments() const { return NumCallArguments; }
Operand &getArgumentRef(unsigned i) {
return getArgumentOperands()[i];
@@ -1727,20 +1832,12 @@
return getArgumentOperands()[i].set(V);
}
- ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
-
- MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
-
- unsigned getNumCallArguments() const {
- return NumCallArguments;
- }
-
ArrayRef<Operand> getTypeDependentOperands() const {
- return Operands.getDynamicAsArray().slice(NumCallArguments);
+ return getAllOperands().slice(NumStaticOperands + NumCallArguments);
}
MutableArrayRef<Operand> getTypeDependentOperands() {
- return Operands.getDynamicAsArray().slice(NumCallArguments);
+ return getAllOperands().slice(NumStaticOperands + NumCallArguments);
}
const GenericSpecializationInformation *getSpecializationInfo() const {
@@ -1861,9 +1958,10 @@
};
/// ApplyInst - Represents the full application of a function value.
-class ApplyInst
+class ApplyInst final
: public InstructionBase<SILInstructionKind::ApplyInst,
- ApplyInstBase<ApplyInst, SingleValueInstruction>> {
+ ApplyInstBase<ApplyInst, SingleValueInstruction>>,
+ public llvm::TrailingObjects<ApplyInst, Operand, Substitution> {
friend SILBuilder;
ApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
@@ -1891,10 +1989,11 @@
/// PartialApplyInst - Represents the creation of a closure object by partial
/// application of a function value.
-class PartialApplyInst
+class PartialApplyInst final
: public InstructionBase<SILInstructionKind::PartialApplyInst,
ApplyInstBase<PartialApplyInst,
- SingleValueInstruction>> {
+ SingleValueInstruction>>,
+ public llvm::TrailingObjects<PartialApplyInst, Operand, Substitution> {
friend SILBuilder;
PartialApplyInst(SILDebugLocation DebugLoc, SILValue Callee,
@@ -1921,6 +2020,129 @@
}
};
+class BeginApplyInst;
+class BeginApplyResult final : public MultipleValueInstructionResult {
+public:
+ BeginApplyResult(unsigned index, SILType type,
+ ValueOwnershipKind ownershipKind)
+ : MultipleValueInstructionResult(ValueKind::BeginApplyResult,
+ index, type, ownershipKind) {}
+
+ BeginApplyInst *getParent(); // inline below
+ const BeginApplyInst *getParent() const {
+ return const_cast<BeginApplyResult *>(this)->getParent();
+ }
+
+ /// Is this result the token result of the begin_apply, which abstracts
+ /// over the implicit coroutine state?
+ bool isTokenResult() const; // inline below
+
+ static bool classof(const SILNode *N) {
+ return N->getKind() == SILNodeKind::BeginApplyResult;
+ }
+};
+
+/// BeginApplyInst - Represents the beginning of the full application of
+/// a yield_once coroutine (up until the coroutine yields a value back).
+class BeginApplyInst final
+ : public InstructionBase<SILInstructionKind::BeginApplyInst,
+ ApplyInstBase<BeginApplyInst,
+ MultipleValueInstruction>>,
+ public MultipleValueInstructionTrailingObjects<
+ BeginApplyInst, BeginApplyResult,
+ // These must be earlier trailing objects because their
+ // count fields are initialized by an earlier base class.
+ InitialTrailingObjects<Operand, Substitution>> {
+ friend SILBuilder;
+
+ template <class, class...>
+ friend class llvm::TrailingObjects;
+ using InstructionBase::numTrailingObjects;
+ using MultipleValueInstructionTrailingObjects::numTrailingObjects;
+
+ friend class ApplyInstBase<BeginApplyInst, MultipleValueInstruction, false>;
+ using MultipleValueInstructionTrailingObjects::getTrailingObjects;
+
+ BeginApplyInst(SILDebugLocation debugLoc, SILValue callee,
+ SILType substCalleeType,
+ ArrayRef<SILType> allResultTypes,
+ ArrayRef<ValueOwnershipKind> allResultOwnerships,
+ SubstitutionList substitutions,
+ ArrayRef<SILValue> args,
+ ArrayRef<SILValue> typeDependentOperands,
+ bool isNonThrowing,
+ const GenericSpecializationInformation *specializationInfo);
+
+ static BeginApplyInst *
+ create(SILDebugLocation debugLoc, SILValue Callee,
+ SubstitutionList substitutions, ArrayRef<SILValue> args,
+ bool isNonThrowing, Optional<SILModuleConventions> moduleConventions,
+ SILFunction &F, SILOpenedArchetypesState &openedArchetypes,
+ const GenericSpecializationInformation *specializationInfo);
+
+public:
+ using MultipleValueInstructionTrailingObjects::totalSizeToAlloc;
+
+ SILValue getTokenResult() const {
+ return &getAllResultsBuffer().back();
+ }
+
+ SILInstructionResultArray getYieldedValues() const {
+ return getAllResultsBuffer().drop_back();
+ }
+
+ /// Returns true if the called coroutine has an error result but is not
+ /// actually throwing an error.
+ bool isNonThrowing() const {
+ return isNonThrowingApply();
+ }
+};
+
+inline BeginApplyInst *BeginApplyResult::getParent() {
+ auto *Parent = MultipleValueInstructionResult::getParent();
+ return cast<BeginApplyInst>(Parent);
+}
+inline bool BeginApplyResult::isTokenResult() const {
+ return getIndex() == getParent()->getNumResults() - 1;
+}
+
+/// AbortApplyInst - Unwind the full application of a yield_once coroutine.
+class AbortApplyInst
+ : public UnaryInstructionBase<SILInstructionKind::AbortApplyInst,
+ NonValueInstruction> {
+ friend SILBuilder;
+
+ AbortApplyInst(SILDebugLocation debugLoc, SILValue beginApplyToken)
+ : UnaryInstructionBase(debugLoc, beginApplyToken) {
+ assert(isa<BeginApplyResult>(beginApplyToken) &&
+ cast<BeginApplyResult>(beginApplyToken)->isTokenResult());
+ }
+
+public:
+ BeginApplyInst *getBeginApply() const {
+ return cast<BeginApplyResult>(getOperand())->getParent();
+ }
+};
+
+/// EndApplyInst - Resume the full application of a yield_once coroutine
+/// normally.
+class EndApplyInst
+ : public UnaryInstructionBase<SILInstructionKind::EndApplyInst,
+ NonValueInstruction> {
+ friend SILBuilder;
+
+ EndApplyInst(SILDebugLocation debugLoc, SILValue beginApplyToken)
+ : UnaryInstructionBase(debugLoc, beginApplyToken) {
+ assert(isa<BeginApplyResult>(beginApplyToken) &&
+ cast<BeginApplyResult>(beginApplyToken)->isTokenResult());
+ }
+
+public:
+ BeginApplyInst *getBeginApply() const {
+ return cast<BeginApplyResult>(getOperand())->getParent();
+ }
+};
+
//===----------------------------------------------------------------------===//
// Literal instructions.
//===----------------------------------------------------------------------===//
@@ -6157,7 +6379,6 @@
: NonValueInstruction(K, DebugLoc) {}
public:
-
using ConstSuccessorListTy = ArrayRef<SILSuccessor>;
using SuccessorListTy = MutableArrayRef<SILSuccessor>;
@@ -6167,6 +6388,83 @@
return const_cast<TermInst*>(this)->getSuccessors();
}
+ using const_succ_iterator = ConstSuccessorListTy::const_iterator;
+ using succ_iterator = SuccessorListTy::iterator;
+
+ bool succ_empty() const { return getSuccessors().empty(); }
+ succ_iterator succ_begin() { return getSuccessors().begin(); }
+ succ_iterator succ_end() { return getSuccessors().end(); }
+ const_succ_iterator succ_begin() const { return getSuccessors().begin(); }
+ const_succ_iterator succ_end() const { return getSuccessors().end(); }
+
+ unsigned getNumSuccessors() const { return getSuccessors().size(); }
+
+ using succblock_iterator =
+ TransformIterator<SILSuccessor *,
+ std::function<SILBasicBlock *(const SILSuccessor &)>>;
+ using const_succblock_iterator = TransformIterator<
+ const SILSuccessor *,
+ std::function<const SILBasicBlock *(const SILSuccessor &)>>;
+ succblock_iterator succblock_begin() {
+ using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
+ FuncTy F(&SILSuccessor::getBB);
+ return makeTransformIterator(getSuccessors().begin(), F);
+ }
+ succblock_iterator succblock_end() {
+ using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
+ FuncTy F(&SILSuccessor::getBB);
+ return makeTransformIterator(getSuccessors().end(), F);
+ }
+ const_succblock_iterator succblock_begin() const {
+ using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
+ FuncTy F(&SILSuccessor::getBB);
+ return makeTransformIterator(getSuccessors().begin(), F);
+ }
+ const_succblock_iterator succblock_end() const {
+ using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
+ FuncTy F(&SILSuccessor::getBB);
+ return makeTransformIterator(getSuccessors().end(), F);
+ }
+
+ SILBasicBlock *getSingleSuccessorBlock() {
+ if (succ_empty() || std::next(succ_begin()) != succ_end())
+ return nullptr;
+ return *succ_begin();
+ }
+
+ const SILBasicBlock *getSingleSuccessorBlock() const {
+ return const_cast<TermInst *>(this)->getSingleSuccessorBlock();
+ }
+
+ /// \brief Returns true if \p BB is a successor of this block.
+ bool isSuccessorBlock(SILBasicBlock *BB) const {
+ auto Range = getSuccessorBlocks();
+ return any_of(Range, [&BB](const SILBasicBlock *SuccBB) -> bool {
+ return BB == SuccBB;
+ });
+ }
+
+ using SuccessorBlockListTy =
+ TransformRange<SuccessorListTy,
+ std::function<SILBasicBlock *(const SILSuccessor &)>>;
+ using ConstSuccessorBlockListTy =
+ TransformRange<ConstSuccessorListTy, std::function<const SILBasicBlock *(
+ const SILSuccessor &)>>;
+
+ /// Return the range of SILBasicBlocks that are successors of this block.
+ SuccessorBlockListTy getSuccessorBlocks() {
+ using FuncTy = std::function<SILBasicBlock *(const SILSuccessor &)>;
+ FuncTy F(&SILSuccessor::getBB);
+ return makeTransformRange(getSuccessors(), F);
+ }
+
+ /// Return the range of SILBasicBlocks that are successors of this block.
+ ConstSuccessorBlockListTy getSuccessorBlocks() const {
+ using FuncTy = std::function<const SILBasicBlock *(const SILSuccessor &)>;
+ FuncTy F(&SILSuccessor::getBB);
+ return makeTransformRange(getSuccessors(), F);
+ }
+
DEFINE_ABSTRACT_NON_VALUE_INST_BOILERPLATE(TermInst)
bool isBranch() const { return !getSuccessors().empty(); }
@@ -6242,6 +6540,84 @@
}
};
+/// UnwindInst - Continue unwinding out of this function. Currently this is
+/// only used in coroutines as the eventual terminator of the unwind edge
+/// out of a 'yield'.
+class UnwindInst
+ : public InstructionBase<SILInstructionKind::UnwindInst,
+ TermInst> {
+ friend SILBuilder;
+
+ UnwindInst(SILDebugLocation loc)
+ : InstructionBase(loc) {}
+
+public:
+ SuccessorListTy getSuccessors() {
+ // No successors.
+ return SuccessorListTy();
+ }
+
+ ArrayRef<Operand> getAllOperands() const { return {}; }
+ MutableArrayRef<Operand> getAllOperands() { return {}; }
+};
+
+/// YieldInst - Yield control temporarily to the caller of this coroutine.
+///
+/// This is a terminator because the caller can abort the coroutine,
+/// e.g. if an error is thrown and an unwind is provoked.
+class YieldInst
+ : public InstructionBase<SILInstructionKind::YieldInst,
+ TermInst> {
+ friend SILBuilder;
+
+ SILSuccessor DestBBs[2];
+
+ TailAllocatedOperandList<0> Operands;
+
+ YieldInst(SILDebugLocation loc, ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB);
+
+ static YieldInst *create(SILDebugLocation loc,
+ ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB,
+ SILFunction &F);
+
+public:
+ /// Return the normal resume destination of the yield, which is where the
+ /// coroutine resumes when the caller is ready to continue normally.
+ ///
+ /// This must be the unique predecessor edge of the given block.
+ ///
+ /// Control flow along every path from this block must either loop or
+ /// eventually terminate in a 'return', 'throw', or 'unreachable'
+ /// instruction. In a yield_many coroutine, control is permitted to
+ /// first reach a 'yield' instruction; this is prohibited in a
+ /// yield_once coroutine.
+ SILBasicBlock *getResumeBB() const { return DestBBs[0]; }
+
+ /// Return the 'unwind' destination of the yield, which is where the
+ /// coroutine resumes when the caller is unconditionally aborting the
+ /// coroutine.
+ ///
+ /// This must be the unique predecessor edge of the given block.
+ ///
+ /// Control flow along every path from this block must either loop or
+ /// eventually terminate in an 'unwind' or 'unreachable' instruction.
+ /// It is not permitted to reach a 'yield' instruction.
+ SILBasicBlock *getUnwindBB() const { return DestBBs[1]; }
+
+ OperandValueArrayRef getYieldedValues() const {
+ return Operands.asValueArray();
+ }
+
+ ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
+ MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
+
+ SuccessorListTy getSuccessors() {
+ return DestBBs;
+ }
+};
+
/// BranchInst - An unconditional branch.
class BranchInst
: public InstructionBase<SILInstructionKind::BranchInst,
@@ -6890,9 +7266,10 @@
/// TryApplyInst - Represents the full application of a function that
/// can produce an error.
-class TryApplyInst
+class TryApplyInst final
: public InstructionBase<SILInstructionKind::TryApplyInst,
- ApplyInstBase<TryApplyInst, TryApplyInstBase>> {
+ ApplyInstBase<TryApplyInst, TryApplyInstBase>>,
+ public llvm::TrailingObjects<TryApplyInst, Operand, Substitution> {
friend SILBuilder;
TryApplyInst(SILDebugLocation DebugLoc, SILValue callee,
@@ -6926,6 +7303,7 @@
ApplySite(ApplyInst *inst) : Inst(inst) {}
ApplySite(PartialApplyInst *inst) : Inst(inst) {}
ApplySite(TryApplyInst *inst) : Inst(inst) {}
+ ApplySite(BeginApplyInst *inst) : Inst(inst) {}
SILModule &getModule() const {
return Inst->getModule();
@@ -6935,6 +7313,8 @@
switch (node->getKind()) {
case SILNodeKind::ApplyInst:
return ApplySite(cast<ApplyInst>(node));
+ case SILNodeKind::BeginApplyInst:
+ return ApplySite(cast<BeginApplyInst>(node));
case SILNodeKind::TryApplyInst:
return ApplySite(cast<TryApplyInst>(node));
case SILNodeKind::PartialApplyInst:
@@ -6956,11 +7336,13 @@
#define FOREACH_IMPL_RETURN(OPERATION) do { \
switch (Inst->getKind()) { \
- case SILInstructionKind::ApplyInst: \
+ case SILInstructionKind::ApplyInst: \
return cast<ApplyInst>(Inst)->OPERATION; \
- case SILInstructionKind::PartialApplyInst: \
+ case SILInstructionKind::BeginApplyInst: \
+ return cast<BeginApplyInst>(Inst)->OPERATION; \
+ case SILInstructionKind::PartialApplyInst: \
return cast<PartialApplyInst>(Inst)->OPERATION; \
- case SILInstructionKind::TryApplyInst: \
+ case SILInstructionKind::TryApplyInst: \
return cast<TryApplyInst>(Inst)->OPERATION; \
default: \
llvm_unreachable("not an apply instruction!"); \
@@ -7034,7 +7416,7 @@
}
/// The substitutions used to bind the generic arguments of this function.
- MutableArrayRef<Substitution> getSubstitutions() const {
+ SubstitutionList getSubstitutions() const {
FOREACH_IMPL_RETURN(getSubstitutions());
}
@@ -7059,8 +7441,8 @@
}
/// The number of call arguments.
- unsigned getNumCallArguments() const {
- FOREACH_IMPL_RETURN(getNumCallArguments());
+ unsigned getNumArguments() const {
+ FOREACH_IMPL_RETURN(getNumArguments());
}
unsigned getOperandIndexOfFirstArgument() {
@@ -7078,6 +7460,8 @@
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->getArgumentsWithoutSelf();
+ case SILInstructionKind::BeginApplyInst:
+ return cast<BeginApplyInst>(Inst)->getArgumentsWithoutSelf();
case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getArgumentsWithoutSelf();
default:
@@ -7085,14 +7469,12 @@
}
}
- /// Returns the number of arguments for this partial apply.
- unsigned getNumArguments() const { return getArguments().size(); }
-
// Get the callee argument index corresponding to the caller's first applied
// argument. Returns 0 for full applies. May return > 0 for partial applies.
unsigned getCalleeArgIndexOfFirstAppliedArg() const {
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::BeginApplyInst:
case SILInstructionKind::TryApplyInst:
return 0;
case SILInstructionKind::PartialApplyInst:
@@ -7131,6 +7513,8 @@
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->hasSelfArgument();
+ case SILInstructionKind::BeginApplyInst:
+ return cast<BeginApplyInst>(Inst)->hasSelfArgument();
case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->hasSelfArgument();
default:
@@ -7143,6 +7527,8 @@
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->getSelfArgument();
+ case SILInstructionKind::BeginApplyInst:
+ return cast<BeginApplyInst>(Inst)->getSelfArgument();
case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getSelfArgument();
default:
@@ -7155,6 +7541,8 @@
switch (Inst->getKind()) {
case SILInstructionKind::ApplyInst:
return cast<ApplyInst>(Inst)->getSelfArgumentOperand();
+ case SILInstructionKind::BeginApplyInst:
+ return cast<BeginApplyInst>(Inst)->getSelfArgumentOperand();
case SILInstructionKind::TryApplyInst:
return cast<TryApplyInst>(Inst)->getSelfArgumentOperand();
default:
@@ -7179,6 +7567,7 @@
static bool classof(const SILInstruction *inst) {
return (inst->getKind() == SILInstructionKind::ApplyInst ||
+ inst->getKind() == SILInstructionKind::BeginApplyInst ||
inst->getKind() == SILInstructionKind::PartialApplyInst ||
inst->getKind() == SILInstructionKind::TryApplyInst);
}
@@ -7194,12 +7583,15 @@
assert(classof(inst) && "not an apply instruction?");
}
FullApplySite(ApplyInst *inst) : ApplySite(inst) {}
+ FullApplySite(BeginApplyInst *inst) : ApplySite(inst) {}
FullApplySite(TryApplyInst *inst) : ApplySite(inst) {}
static FullApplySite isa(SILNode *node) {
switch (node->getKind()) {
case SILNodeKind::ApplyInst:
return FullApplySite(cast<ApplyInst>(node));
+ case SILNodeKind::BeginApplyInst:
+ return FullApplySite(cast<BeginApplyInst>(node));
case SILNodeKind::TryApplyInst:
return FullApplySite(cast<TryApplyInst>(node));
default:
@@ -7229,6 +7621,7 @@
static bool classof(const SILInstruction *inst) {
return (inst->getKind() == SILInstructionKind::ApplyInst ||
+ inst->getKind() == SILInstructionKind::BeginApplyInst ||
inst->getKind() == SILInstructionKind::TryApplyInst);
}
};
@@ -7289,8 +7682,7 @@
: public UnaryInstructionBase<SILInstructionKind::DestructureStructInst,
MultipleValueInstruction>,
public MultipleValueInstructionTrailingObjects<
- SILInstructionKind::DestructureStructInst, DestructureStructInst,
- DestructureStructResult> {
+ DestructureStructInst, DestructureStructResult> {
friend TrailingObjects;
DestructureStructInst(SILModule &M, SILDebugLocation Loc, SILValue Operand,
@@ -7338,8 +7730,7 @@
: public UnaryInstructionBase<SILInstructionKind::DestructureTupleInst,
MultipleValueInstruction>,
public MultipleValueInstructionTrailingObjects<
- SILInstructionKind::DestructureTupleInst, DestructureTupleInst,
- DestructureTupleResult> {
+ DestructureTupleInst, DestructureTupleResult> {
friend TrailingObjects;
DestructureTupleInst(SILModule &M, SILDebugLocation Loc, SILValue Operand,
diff --git a/include/swift/SIL/SILNodes.def b/include/swift/SIL/SILNodes.def
index 78a6318..6727455 100644
--- a/include/swift/SIL/SILNodes.def
+++ b/include/swift/SIL/SILNodes.def
@@ -215,9 +215,10 @@
VALUE_RANGE(SILArgument, SILPHIArgument, SILFunctionArgument)
ABSTRACT_VALUE(MultipleValueInstructionResult, ValueBase)
+ MULTIPLE_VALUE_INST_RESULT(BeginApplyResult, MultipleValueInstructionResult)
MULTIPLE_VALUE_INST_RESULT(DestructureStructResult, MultipleValueInstructionResult)
MULTIPLE_VALUE_INST_RESULT(DestructureTupleResult, MultipleValueInstructionResult)
- VALUE_RANGE(MultipleValueInstructionResult, DestructureStructResult, DestructureTupleResult)
+ VALUE_RANGE(MultipleValueInstructionResult, BeginApplyResult, DestructureTupleResult)
VALUE(SILUndef, ValueBase)
@@ -498,6 +499,10 @@
TermInst, None, DoesNotRelease)
TERMINATOR(ThrowInst, throw,
TermInst, None, DoesNotRelease)
+ TERMINATOR(YieldInst, yield,
+ TermInst, MayHaveSideEffects, MayRelease)
+ TERMINATOR(UnwindInst, unwind,
+ TermInst, None, DoesNotRelease)
TERMINATOR(TryApplyInst, try_apply,
TermInst, MayHaveSideEffects, MayRelease)
TERMINATOR(BranchInst, br,
@@ -628,6 +633,10 @@
SILInstruction, MayHaveSideEffects, DoesNotRelease)
NON_VALUE_INST(AllocGlobalInst, alloc_global,
SILInstruction, MayHaveSideEffects, DoesNotRelease)
+NON_VALUE_INST(EndApplyInst, end_apply,
+ SILInstruction, MayHaveSideEffects, MayRelease)
+NON_VALUE_INST(AbortApplyInst, abort_apply,
+ SILInstruction, MayHaveSideEffects, MayRelease)
// Runtime failure
// FIXME: Special MemBehavior for runtime failure?
@@ -637,11 +646,13 @@
NODE_RANGE(NonValueInstruction, UnreachableInst, CondFailInst)
ABSTRACT_INST(MultipleValueInstruction, SILInstruction)
+MULTIPLE_VALUE_INST(BeginApplyInst, begin_apply,
+ SILInstruction, MayHaveSideEffects, MayRelease)
MULTIPLE_VALUE_INST(DestructureStructInst, destructure_struct,
SILInstruction, None, DoesNotRelease)
MULTIPLE_VALUE_INST(DestructureTupleInst, destructure_tuple,
SILInstruction, None, DoesNotRelease)
-INST_RANGE(MultipleValueInstruction, DestructureStructInst, DestructureTupleInst)
+INST_RANGE(MultipleValueInstruction, BeginApplyInst, DestructureTupleInst)
NODE_RANGE(SILInstruction, AllocStackInst, DestructureTupleInst)
NODE_RANGE(SILNode, SILPHIArgument, DestructureTupleInst)
diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h
index 5e1e7d5..5d2b135 100644
--- a/include/swift/SIL/SILType.h
+++ b/include/swift/SIL/SILType.h
@@ -539,6 +539,9 @@
/// Get the standard exception type.
static SILType getExceptionType(const ASTContext &C);
+ /// Get the SIL token type.
+ static SILType getSILTokenType(const ASTContext &C);
+
//
// Utilities for treating SILType as a pointer-like type.
//
diff --git a/include/swift/SIL/SILVTableVisitor.h b/include/swift/SIL/SILVTableVisitor.h
index 1f06d80..54c07d9 100644
--- a/include/swift/SIL/SILVTableVisitor.h
+++ b/include/swift/SIL/SILVTableVisitor.h
@@ -43,8 +43,8 @@
void maybeAddMethod(FuncDecl *fd) {
assert(!fd->hasClangNode());
- maybeAddEntry(SILDeclRef(fd, SILDeclRef::Kind::Func),
- fd->needsNewVTableEntry());
+ SILDeclRef constant(fd, SILDeclRef::Kind::Func);
+ maybeAddEntry(constant, constant.requiresNewVTableEntry());
}
void maybeAddConstructor(ConstructorDecl *cd) {
@@ -53,18 +53,14 @@
// Required constructors (or overrides thereof) have their allocating entry
// point in the vtable.
if (cd->isRequired()) {
- bool needsAllocatingEntry = cd->needsNewVTableEntry();
- if (!needsAllocatingEntry)
- if (auto *baseCD = cd->getOverriddenDecl())
- needsAllocatingEntry = !baseCD->isRequired() || baseCD->hasClangNode();
- maybeAddEntry(SILDeclRef(cd, SILDeclRef::Kind::Allocator),
- needsAllocatingEntry);
+ SILDeclRef constant(cd, SILDeclRef::Kind::Allocator);
+ maybeAddEntry(constant, constant.requiresNewVTableEntry());
}
// All constructors have their initializing constructor in the
// vtable, which can be used by a convenience initializer.
- maybeAddEntry(SILDeclRef(cd, SILDeclRef::Kind::Initializer),
- cd->needsNewVTableEntry());
+ SILDeclRef constant(cd, SILDeclRef::Kind::Initializer);
+ maybeAddEntry(constant, constant.requiresNewVTableEntry());
}
void maybeAddEntry(SILDeclRef declRef, bool needsNewEntry) {
diff --git a/include/swift/SIL/SILWitnessTable.h b/include/swift/SIL/SILWitnessTable.h
index 0fe98f9..bba877c 100644
--- a/include/swift/SIL/SILWitnessTable.h
+++ b/include/swift/SIL/SILWitnessTable.h
@@ -169,7 +169,15 @@
Method.Witness = nullptr;
}
};
-
+
+ /// An entry for a conformance requirement that makes the requirement
+ /// conditional. These aren't public, but any witness thunks need to feed them
+ /// into the true witness functions.
+ struct ConditionalConformance {
+ CanType Requirement;
+ ProtocolConformanceRef Conformance;
+ };
+
private:
/// The module which contains the SILWitnessTable.
SILModule &Mod;
@@ -188,6 +196,13 @@
/// table has no witness entries or if it is a declaration.
MutableArrayRef<Entry> Entries;
+ /// Any conditional conformances required for this witness table. These are
+ /// private to this conformance.
+ ///
+ /// (If other private entities are introduced this could/should be switched
+ /// into a private version of Entries.)
+ MutableArrayRef<ConditionalConformance> ConditionalConformances;
+
/// Whether or not this witness table is a declaration. This is separate from
/// whether or not entries is empty since you can have an empty witness table
/// that is not a declaration.
@@ -198,10 +213,10 @@
bool Serialized;
/// Private constructor for making SILWitnessTable definitions.
- SILWitnessTable(SILModule &M, SILLinkage Linkage,
- IsSerialized_t Serialized, StringRef Name,
- NormalProtocolConformance *Conformance,
- ArrayRef<Entry> entries);
+ SILWitnessTable(SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized,
+ StringRef Name, NormalProtocolConformance *Conformance,
+ ArrayRef<Entry> entries,
+ ArrayRef<ConditionalConformance> conditionalConformances);
/// Private constructor for making SILWitnessTable declarations.
SILWitnessTable(SILModule &M, SILLinkage Linkage, StringRef Name,
@@ -211,10 +226,10 @@
public:
/// Create a new SILWitnessTable definition with the given entries.
- static SILWitnessTable *create(SILModule &M, SILLinkage Linkage,
- IsSerialized_t Serialized,
- NormalProtocolConformance *Conformance,
- ArrayRef<Entry> entries);
+ static SILWitnessTable *
+ create(SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized,
+ NormalProtocolConformance *Conformance, ArrayRef<Entry> entries,
+ ArrayRef<ConditionalConformance> conditionalConformances);
/// Create a new SILWitnessTable declaration.
static SILWitnessTable *create(SILModule &M, SILLinkage Linkage,
@@ -245,6 +260,11 @@
/// Return all of the witness table entries.
ArrayRef<Entry> getEntries() const { return Entries; }
+ /// Return all of the conditional conformances.
+ ArrayRef<ConditionalConformance> getConditionalConformances() const {
+ return ConditionalConformances;
+ }
+
/// Clears methods in MethodWitness entries.
/// \p predicate Returns true if the passed entry should be set to null.
template <typename Predicate> void clearMethods_if(Predicate predicate) {
@@ -268,12 +288,28 @@
void setLinkage(SILLinkage l) { Linkage = l; }
/// Change a SILWitnessTable declaration into a SILWitnessTable definition.
- void convertToDefinition(ArrayRef<Entry> newEntries,
- IsSerialized_t isSerialized);
+ void
+ convertToDefinition(ArrayRef<Entry> newEntries,
+ ArrayRef<ConditionalConformance> conditionalConformances,
+ IsSerialized_t isSerialized);
// Whether a conformance should be serialized.
static bool conformanceIsSerialized(ProtocolConformance *conformance);
+ /// Call \c fn on each (split apart) conditional requirement of \c conformance
+ /// that should appear in a witness table, i.e., conformance requirements that
+ /// need witness tables themselves.
+ ///
+ /// The \c unsigned argument to \c fn is a counter for the conditional
+ /// conformances, and should be used for indexing arrays of them.
+ ///
+ /// This acts like \c any_of: \c fn returning \c true will stop the
+ /// enumeration and \c enumerateWitnessTableConditionalConformances will
+ /// return \c true, while \c fn returning \c false will let it continue.
+ static bool enumerateWitnessTableConditionalConformances(
+ const ProtocolConformance *conformance,
+ llvm::function_ref<bool(unsigned, CanType, ProtocolDecl *)> fn);
+
/// Print the witness table.
void print(llvm::raw_ostream &OS, bool Verbose = false) const;
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index c0e63df..370b432 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -79,18 +79,22 @@
}
inline CanSILFunctionType
adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep,
- Optional<ProtocolConformanceRef> witnessMethodConformance) {
+ Optional<ProtocolConformanceRef> witnessMethodConformance,
+ bool UseGuaranteedClosures) {
if (t->getRepresentation() == rep) return t;
auto extInfo = t->getExtInfo().withRepresentation(rep);
-
- return adjustFunctionType(
- t, extInfo, extInfo.hasContext() ? DefaultThickCalleeConvention
- : ParameterConvention::Direct_Unowned,
- witnessMethodConformance);
+ auto contextConvention = UseGuaranteedClosures
+ ? ParameterConvention::Direct_Guaranteed
+ : DefaultThickCalleeConvention;
+ return adjustFunctionType(t, extInfo,
+ extInfo.hasContext()
+ ? contextConvention
+ : ParameterConvention::Direct_Unowned,
+ witnessMethodConformance);
}
inline CanSILFunctionType
-adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep) {
- return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone());
+adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep, bool UseGuaranteedClosures) {
+ return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone(), UseGuaranteedClosures);
}
@@ -271,7 +275,11 @@
return TypeLowering::LoweringStyle::Shallow;
}
- /// Emit a lowered 'release_value' operation.
+ //===--------------------------------------------------------------------===//
+ // DestroyValue
+ //===--------------------------------------------------------------------===//
+
+ /// Emit a lowered destroy value operation.
///
/// This type must be loadable.
virtual void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc,
@@ -286,7 +294,7 @@
return emitDestroyValue(B, loc, value);
}
- /// Emit a lowered 'release_value' operation.
+ /// Emit a lowered destroy value operation.
///
/// This type must be loadable.
void emitLoweredDestroyValueShallow(SILBuilder &B, SILLocation loc,
@@ -294,7 +302,7 @@
emitLoweredDestroyValue(B, loc, value, LoweringStyle::Shallow);
}
- /// Emit a lowered 'release_value' operation.
+ /// Emit a lowered destroy_value operation.
///
/// This type must be loadable.
void emitLoweredDestroyValueDeep(SILBuilder &B, SILLocation loc,
@@ -313,14 +321,18 @@
virtual void emitDestroyValue(SILBuilder &B, SILLocation loc,
SILValue value) const = 0;
- /// Emit a lowered 'retain_value' operation.
+ //===--------------------------------------------------------------------===//
+ // CopyValue
+ //===--------------------------------------------------------------------===//
+
+ /// Emit a lowered copy value operation.
///
/// This type must be loadable.
virtual SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
SILValue value,
LoweringStyle style) const = 0;
- /// Emit a lowered 'retain_value' operation.
+ /// Emit a lowered copy value operation.
///
/// This type must be loadable.
SILValue emitLoweredCopyValueShallow(SILBuilder &B, SILLocation loc,
@@ -328,7 +340,7 @@
return emitLoweredCopyValue(B, loc, value, LoweringStyle::Shallow);
}
- /// Emit a lowered 'retain_value' operation.
+ /// Emit a lowered copy value operation.
///
/// This type must be loadable.
SILValue emitLoweredCopyValueDeep(SILBuilder &B, SILLocation loc,
diff --git a/include/swift/SILOptimizer/PassManager/PassManager.h b/include/swift/SILOptimizer/PassManager/PassManager.h
index 0324d10..7e7af25 100644
--- a/include/swift/SILOptimizer/PassManager/PassManager.h
+++ b/include/swift/SILOptimizer/PassManager/PassManager.h
@@ -97,6 +97,9 @@
/// same function.
bool RestartPipeline = false;
+ /// If true, passes are also run for functions which have
+ /// OptimizationMode::NoOptimization.
+ bool isMandatoryPipeline = false;
/// The IRGen SIL passes. These have to be dynamically added by IRGen.
llvm::DenseMap<unsigned, SILTransform *> IRGenPasses;
@@ -104,12 +107,17 @@
public:
/// C'tor. It creates and registers all analysis passes, which are defined
/// in Analysis.def.
- SILPassManager(SILModule *M, llvm::StringRef Stage = "");
+ ///
+ /// If \p isMandatoryPipeline is true, passes are also run for functions
+ /// which have OptimizationMode::NoOptimization.
+ SILPassManager(SILModule *M, llvm::StringRef Stage = "",
+ bool isMandatoryPipeline = false);
/// C'tor. It creates an IRGen pass manager. Passes can query for the
/// IRGenModule.
SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
- llvm::StringRef Stage = "");
+ llvm::StringRef Stage = "",
+ bool isMandatoryPipeline = false);
const SILOptions &getOptions() const;
diff --git a/include/swift/SILOptimizer/Utils/CFG.h b/include/swift/SILOptimizer/Utils/CFG.h
index 2ce5a80..44b781d 100644
--- a/include/swift/SILOptimizer/Utils/CFG.h
+++ b/include/swift/SILOptimizer/Utils/CFG.h
@@ -125,11 +125,52 @@
bool splitAllCriticalEdges(SILFunction &F, bool OnlyNonCondBr,
DominanceInfo *DT, SILLoopInfo *LI);
+/// \brief Split all cond_br critical edges with non-trivial arguments in the
+/// function updating the dominator tree and loop information (if they are not
+/// set to null).
+///
+/// A current invariant of Ownership SIL is that cond_br can only have critical
+/// edges with non-trivial arguments. This simplifies computation.
+bool splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &F,
+ DominanceInfo *DT,
+ SILLoopInfo *LI);
+
/// \brief Merge a basic block ending in a branch with its successor
/// if possible. If dominance information or loop info is non null update it.
/// Return true if block was merged.
bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT,
SILLoopInfo *LI);
+/// Given a list of \p UserBlocks and a list of \p DefBlocks, find a set of
+/// blocks that together with \p UserBlocks joint-postdominate \p
+/// DefBlocks. This is in a sense finding a set of blocks that "complete" \p
+/// UserBlocks with respect to \p DefBlocks. As an example, for the following
+/// CFG:
+///
+/// +-----+
+/// | Def |
+/// +-----+
+/// | |
+/// v v
+/// +-----+ +-----+
+/// | | | Use |
+/// +-----+ +-----+
+///
+/// the completion of the joint post-dominance set would be the empty
+/// block. This has two main uses:
+///
+/// 1. This can tell you the places where if you were to sink the Def one would
+/// need to insert "compensating code".
+///
+/// 2. It can be used to prove ownership correctness of @owned values by
+/// asserting that the set of UserBlocks has an empty completion, implying they
+/// jointly-post dominate the def.
+///
+/// *NOTE* This completion may not be unique.
+void completeJointPostDominanceSet(
+ ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
+ llvm::SmallVectorImpl<SILBasicBlock *> &Completion);
+
} // end namespace swift
+
#endif
diff --git a/include/swift/SILOptimizer/Utils/SCCVisitor.h b/include/swift/SILOptimizer/Utils/SCCVisitor.h
index c0f2b4f..9ea03d2 100644
--- a/include/swift/SILOptimizer/Utils/SCCVisitor.h
+++ b/include/swift/SILOptimizer/Utils/SCCVisitor.h
@@ -133,8 +133,14 @@
case TermKind::ReturnInst:
case TermKind::SwitchValueInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
llvm_unreachable("Did not expect terminator that does not have args!");
+ case TermKind::YieldInst:
+ for (auto &O : cast<YieldInst>(Term)->getAllOperands())
+ Operands.push_back(O.get());
+ return;
+
case TermKind::TryApplyInst:
for (auto &O : cast<TryApplyInst>(Term)->getAllOperands())
Operands.push_back(O.get());
diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def
index 03f68a3..b772124 100644
--- a/include/swift/Serialization/DeclTypeRecordNodes.def
+++ b/include/swift/Serialization/DeclTypeRecordNodes.def
@@ -162,7 +162,7 @@
TRAILING_INFO(GENERIC_PARAM)
TRAILING_INFO(GENERIC_REQUIREMENT)
TRAILING_INFO(LAYOUT_REQUIREMENT)
-OTHER(GENERIC_ENVIRONMENT, 244)
+OTHER(GENERIC_SIGNATURE, 244)
OTHER(SIL_GENERIC_ENVIRONMENT, 245)
OTHER(LOCAL_DISCRIMINATOR, 248)
diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h
index 8cc53e2..f701536 100644
--- a/include/swift/Serialization/ModuleFile.h
+++ b/include/swift/Serialization/ModuleFile.h
@@ -299,6 +299,9 @@
/// Types referenced by this module.
std::vector<Serialized<Type>> Types;
+ /// Generic signatures referenced by this module.
+ std::vector<Serialized<GenericSignature *>> GenericSignatures;
+
/// Generic environments referenced by this module.
std::vector<Serialized<GenericEnvironment *>> GenericEnvironments;
@@ -818,6 +821,9 @@
/// is loaded instead.
ModuleDecl *getModule(ArrayRef<Identifier> name);
+ /// Returns the generic signature for the given ID.
+ GenericSignature *getGenericSignature(serialization::GenericSignatureID ID);
+
/// Returns the generic signature or environment for the given ID,
/// deserializing it if needed.
///
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 746988f..38fb3d1 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 380; // Last change: IUO decl attribute
+const uint16_t VERSION_MINOR = 385; // Last change: Optimization attribute
using DeclIDField = BCFixed<31>;
@@ -77,6 +77,11 @@
using NormalConformanceID = DeclID;
using NormalConformanceIDField = DeclIDField;
+// GenericSignatureID must be the same as DeclID because it is stored in the
+// same way.
+using GenericSignatureID = DeclID;
+using GenericSignatureIDField = DeclIDField;
+
// GenericEnvironmentID must be the same as DeclID because it is stored in the
// same way.
using GenericEnvironmentID = DeclID;
@@ -156,6 +161,15 @@
// These IDs must \em not be renumbered or reordered without incrementing
// VERSION_MAJOR.
+enum class SILCoroutineKind : uint8_t {
+ None = 0,
+ YieldOnce = 1,
+ YieldMany = 2,
+};
+using SILCoroutineKindField = BCFixed<2>;
+
+// These IDs must \em not be renumbered or reordered without incrementing
+// VERSION_MAJOR.
enum OperatorKind : uint8_t {
Infix = 0,
Prefix,
@@ -729,25 +743,25 @@
TypeIDField, // output
FunctionTypeRepresentationField, // representation
BCFixed<1>, // throws?
- BCArray<TypeIDField> // generic parameters
- // followed by requirements
+ GenericSignatureIDField // generic signture
>;
using SILFunctionTypeLayout = BCRecordLayout<
SIL_FUNCTION_TYPE,
+ SILCoroutineKindField, // coroutine kind
ParameterConventionField, // callee convention
SILFunctionTypeRepresentationField, // representation
BCFixed<1>, // pseudogeneric?
BCFixed<1>, // noescape?
BCFixed<1>, // error result?
BCFixed<30>, // number of parameters
+ BCFixed<30>, // number of yields
BCFixed<30>, // number of results
+ GenericSignatureIDField, // generic signature
BCArray<TypeIDField> // parameter types/conventions, alternating
// followed by result types/conventions, alternating
// followed by error result type/convention
- // followed by generic parameter types
// Optionally a protocol conformance (for witness_methods)
- // Trailed by its generic requirements, if any.
>;
using SILBlockStorageTypeLayout = BCRecordLayout<
@@ -757,10 +771,9 @@
using SILLayoutLayout = BCRecordLayout<
SIL_LAYOUT,
+ GenericSignatureIDField, // generic signature
BCFixed<31>, // number of fields
BCArray<TypeIDWithBitField> // field types with mutability
- // followed by generic parameters
- // trailed by generic requirements, if any
>;
using SILBoxTypeLayout = BCRecordLayout<
@@ -1154,9 +1167,9 @@
DeclIDField // Typealias
>;
- using GenericEnvironmentLayout = BCRecordLayout<
- GENERIC_ENVIRONMENT,
- BCArray<TypeIDField> // sugared interface types
+ using GenericSignatureLayout = BCRecordLayout<
+ GENERIC_SIGNATURE,
+ BCArray<TypeIDField> // generic parameter types
>;
using SILGenericEnvironmentLayout = BCRecordLayout<
@@ -1271,8 +1284,8 @@
using XRefExtensionPathPieceLayout = BCRecordLayout<
XREF_EXTENSION_PATH_PIECE,
ModuleIDField, // module ID
- BCArray<TypeIDField> // for a constrained extension, the type parameters
- // for a constrained extension, requirements follow
+ GenericSignatureIDField // for a constrained extension,
+ // the generic signature
>;
using XRefOperatorOrAccessorPathPieceLayout = BCRecordLayout<
@@ -1388,6 +1401,11 @@
BCFixed<2> // inline value
>;
+ using OptimizeDeclAttrLayout = BCRecordLayout<
+ Optimize_DECL_ATTR,
+ BCFixed<2> // optimize value
+ >;
+
// Encodes a VersionTuple:
//
// Major
@@ -1524,7 +1542,8 @@
NESTED_TYPE_DECLS,
DECL_MEMBER_NAMES,
- LastRecordKind = DECL_MEMBER_NAMES,
+ GENERIC_SIGNATURE_OFFSETS,
+ LastRecordKind = GENERIC_SIGNATURE_OFFSETS,
};
constexpr const unsigned RecordIDFieldWidth = 5;
diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h
index 0978e16..13db711 100644
--- a/include/swift/Serialization/SerializedModuleLoader.h
+++ b/include/swift/Serialization/SerializedModuleLoader.h
@@ -195,6 +195,10 @@
virtual const clang::Module *getUnderlyingClangModule() const override;
+ virtual bool getAllGenericSignatures(
+ SmallVectorImpl<GenericSignature*> &genericSignatures)
+ override;
+
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::SerializedAST;
}
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index e79e188..e52f0ba 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -212,6 +212,8 @@
const SourcePresence Presence)
: Kind(Kind), Layout(Layout), Presence(Presence) {}
+ virtual ~RawSyntax() = default;
+
/// Returns a raw syntax node of the given Kind, specified Layout,
/// and source presence.
static RC<RawSyntax> make(const SyntaxKind Kind, const LayoutList Layout,
diff --git a/include/swift/Syntax/SyntaxFactory.h.gyb b/include/swift/Syntax/SyntaxFactory.h.gyb
index 26f4879..e9f7c09 100644
--- a/include/swift/Syntax/SyntaxFactory.h.gyb
+++ b/include/swift/Syntax/SyntaxFactory.h.gyb
@@ -54,8 +54,16 @@
static Optional<Syntax>
createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements);
+ /// Count the number of children for a given syntax node kind,
+ /// returning a pair of mininum and maximum count of children. The gap
+ /// between these two numbers is the number of optional children.
+ static std::pair<unsigned, unsigned> countChildren(SyntaxKind Kind);
+
static SyntaxKind getUnknownKind(SyntaxKind Kind);
+ static Syntax
+ makeBlankCollectionSyntax(SyntaxKind Kind);
+
% for node in SYNTAX_NODES:
% if node.children:
% child_params = []
diff --git a/include/swift/Syntax/SyntaxParsingContext.h b/include/swift/Syntax/SyntaxParsingContext.h
index 002f9b0..9eba962 100644
--- a/include/swift/Syntax/SyntaxParsingContext.h
+++ b/include/swift/Syntax/SyntaxParsingContext.h
@@ -37,6 +37,12 @@
/// Start and end location of this syntax node.
SourceRange SyntaxRange;
+ /// This location must be valid if this node is an implicit node, e.g.
+ /// an empty statement list collection.
+ /// This location indicates the implicit node should appear before the token
+ /// on the location.
+ SourceLoc BeforeLoc;
+
/// The raw node.
RC<RawSyntax> RawNode;
RawSyntaxInfo(RC<RawSyntax> RawNode): RawNode(RawNode) {}
@@ -57,6 +63,10 @@
return RC<RawSyntaxNode>(cast<RawSyntaxNode>(RawNode));
}
void brigeWithContext(SyntaxContextKind Kind);
+ void setBeforeLoc(SourceLoc Loc) {
+ assert(isImplicit());
+ BeforeLoc = Loc;
+ }
};
enum class SyntaxParsingContextKind: uint8_t {
@@ -75,17 +85,15 @@
ContextInfo &ContextData;
const Token &Tok;
- // Add a token syntax at the given source location to the context; this
- // token node can be used to build more complex syntax nodes in later call
- // back.
- virtual void addTokenSyntax(SourceLoc Loc) = 0;
-
// Get the context kind.
virtual SyntaxParsingContextKind getKind() = 0;
// Create a syntax node of the given kind.
- virtual void makeNode(SyntaxKind Kind) = 0;
+ virtual void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) = 0;
virtual ~SyntaxParsingContext();
+ virtual void setSyntaxKind(SyntaxKind Kind) = 0;
+ virtual void setContextKind(SyntaxContextKind CKind) = 0;
+ virtual void finalize() = 0;
// Disable the building of syntax tree in the current context.
void disable();
@@ -100,8 +108,10 @@
SyntaxParsingContextRoot(SourceFile &File, unsigned BufferID, Token &Tok):
SyntaxParsingContext(File, BufferID, Tok), File(File) {}
~SyntaxParsingContextRoot();
- void addTokenSyntax(SourceLoc Loc) override {};
- void makeNode(SyntaxKind Kind) override {};
+ void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override {};
+ void setSyntaxKind(SyntaxKind Kind) override {};
+ void setContextKind(SyntaxContextKind CKind) override {};
+ void finalize() override {};
SyntaxParsingContextKind getKind() override {
return SyntaxParsingContextKind::Root;
};
@@ -114,12 +124,13 @@
class SyntaxParsingContextChild: public SyntaxParsingContext {
SyntaxParsingContext *Parent;
SyntaxParsingContext *&ContextHolder;
- Optional<SyntaxContextKind> Kind;
+ Optional<SyntaxContextKind> ContextKind;
Optional<SyntaxKind> KnownSyntax;
void makeNodeWhole(SyntaxKind Kind);
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
Optional<SyntaxContextKind> Kind,
Optional<SyntaxKind> KnownSyntax);
+ bool isTopOfContextStack() const { return this == ContextHolder; }
public:
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
SyntaxContextKind Kind): SyntaxParsingContextChild(ContextHolder,
@@ -129,10 +140,15 @@
SyntaxKind KnownSyntax): SyntaxParsingContextChild(ContextHolder,
None, KnownSyntax) {};
+ SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
+ bool Disable = false);
+
~SyntaxParsingContextChild();
- void makeNode(SyntaxKind Kind) override;
- void addTokenSyntax(SourceLoc Loc) override;
+ void makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) override;
+ void finalize() override;
SyntaxParsingContext* getParent() { return Parent; }
+ void setSyntaxKind(SyntaxKind SKind) override;
+ void setContextKind(SyntaxContextKind CKind) override;
SyntaxParsingContextRoot &getRoot();
SyntaxParsingContextKind getKind() override {
return SyntaxParsingContextKind::Child;
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 314321f..cd854df 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -266,16 +266,6 @@
/// The keys are the generic signature builders in \c GenericSignatureBuilders.
llvm::DenseMap<GenericSignatureBuilder *, GenericEnvironment *>
CanonicalGenericEnvironments;
-
- /// The set of property names that show up in the defining module of a
- /// class.
- llvm::DenseMap<std::pair<const ClassDecl *, char>,
- std::unique_ptr<InheritedNameSet>> AllProperties;
-
- /// The set of property names that show up in the defining module of
- /// an Objective-C class.
- llvm::DenseMap<std::pair<const clang::ObjCInterfaceDecl *, char>,
- std::unique_ptr<InheritedNameSet>> AllPropertiesObjC;
/// The single-parameter generic signature with no constraints, <T>.
CanGenericSignature SingleGenericParameterSignature;
@@ -471,6 +461,8 @@
BuiltinRawPointerType(*this)),
TheUnsafeValueBufferType(new (*this, AllocationArena::Permanent)
BuiltinUnsafeValueBufferType(*this)),
+ TheSILTokenType(new (*this, AllocationArena::Permanent)
+ SILTokenType(*this)),
TheIEEE32Type(new (*this, AllocationArena::Permanent)
BuiltinFloatType(BuiltinFloatType::IEEE32,*this)),
TheIEEE64Type(new (*this, AllocationArena::Permanent)
@@ -3787,16 +3779,22 @@
void SILFunctionType::Profile(llvm::FoldingSetNodeID &id,
GenericSignature *genericParams,
ExtInfo info,
+ SILCoroutineKind coroutineKind,
ParameterConvention calleeConvention,
ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yields,
ArrayRef<SILResultInfo> results,
Optional<SILResultInfo> errorResult) {
id.AddPointer(genericParams);
id.AddInteger(info.getFuncAttrKey());
+ id.AddInteger(unsigned(coroutineKind));
id.AddInteger(unsigned(calleeConvention));
id.AddInteger(params.size());
for (auto param : params)
param.profile(id);
+ id.AddInteger(yields.size());
+ for (auto yield : yields)
+ yield.profile(id);
id.AddInteger(results.size());
for (auto result : results)
result.profile(id);
@@ -3806,32 +3804,47 @@
if (errorResult) errorResult->profile(id);
}
-SILFunctionType::SILFunctionType(
- GenericSignature *genericSig, ExtInfo ext,
- ParameterConvention calleeConvention, ArrayRef<SILParameterInfo> params,
- ArrayRef<SILResultInfo> normalResults, Optional<SILResultInfo> errorResult,
- const ASTContext &ctx, RecursiveTypeProperties properties,
- Optional<ProtocolConformanceRef> witnessMethodConformance)
- : TypeBase(TypeKind::SILFunction, &ctx, properties), GenericSig(genericSig),
+SILFunctionType::SILFunctionType(GenericSignature *genericSig, ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention calleeConvention,
+ ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yields,
+ ArrayRef<SILResultInfo> normalResults,
+ Optional<SILResultInfo> errorResult,
+ const ASTContext &ctx,
+ RecursiveTypeProperties properties,
+ Optional<ProtocolConformanceRef> witnessMethodConformance)
+ : TypeBase(TypeKind::SILFunction, &ctx, properties),
+ GenericSig(genericSig),
WitnessMethodConformance(witnessMethodConformance) {
SILFunctionTypeBits.HasErrorResult = errorResult.hasValue();
SILFunctionTypeBits.ExtInfo = ext.Bits;
+ SILFunctionTypeBits.CoroutineKind = unsigned(coroutineKind);
NumParameters = params.size();
- NumResults = normalResults.size();
- NumIndirectFormalResults =
+ if (coroutineKind == SILCoroutineKind::None) {
+ assert(yields.empty());
+ NumAnyResults = normalResults.size();
+ NumAnyIndirectFormalResults =
std::count_if(normalResults.begin(), normalResults.end(),
[](const SILResultInfo &resultInfo) {
return resultInfo.isFormalIndirect();
});
+ memcpy(getMutableResults().data(), normalResults.data(),
+ normalResults.size() * sizeof(SILResultInfo));
+ } else {
+ assert(normalResults.empty());
+ NumAnyResults = yields.size();
+ NumAnyIndirectFormalResults = 0; // unused
+ memcpy(getMutableYields().data(), yields.data(),
+ yields.size() * sizeof(SILYieldInfo));
+ }
assert(!isIndirectFormalParameter(calleeConvention));
SILFunctionTypeBits.CalleeConvention = unsigned(calleeConvention);
memcpy(getMutableParameters().data(), params.data(),
params.size() * sizeof(SILParameterInfo));
- memcpy(getMutableResults().data(), normalResults.data(),
- normalResults.size() * sizeof(SILResultInfo));
if (errorResult)
getMutableErrorResult() = *errorResult;
@@ -3868,6 +3881,13 @@
assert(!result.getType()->hasArchetype()
&& "interface type of result should not contain context archetypes");
}
+ for (auto yield : getYields()) {
+ (void)yield;
+ assert(!yield.getType()->hasError()
+ && "interface type of yield should not contain error types");
+ assert(!yield.getType()->hasArchetype()
+ && "interface type of yield should not contain context archetypes");
+ }
if (hasErrorResult()) {
assert(!getErrorResult().getType()->hasError()
&& "interface type of result should not contain error types");
@@ -3892,14 +3912,22 @@
return CanSILBlockStorageType(storageTy);
}
-CanSILFunctionType SILFunctionType::get(
- GenericSignature *genericSig, ExtInfo ext, ParameterConvention callee,
- ArrayRef<SILParameterInfo> params, ArrayRef<SILResultInfo> normalResults,
- Optional<SILResultInfo> errorResult, const ASTContext &ctx,
- Optional<ProtocolConformanceRef> witnessMethodConformance) {
+CanSILFunctionType SILFunctionType::get(GenericSignature *genericSig,
+ ExtInfo ext,
+ SILCoroutineKind coroutineKind,
+ ParameterConvention callee,
+ ArrayRef<SILParameterInfo> params,
+ ArrayRef<SILYieldInfo> yields,
+ ArrayRef<SILResultInfo> normalResults,
+ Optional<SILResultInfo> errorResult,
+ const ASTContext &ctx,
+ Optional<ProtocolConformanceRef> witnessMethodConformance) {
+ assert(coroutineKind == SILCoroutineKind::None || normalResults.empty());
+ assert(coroutineKind != SILCoroutineKind::None || yields.empty());
+
llvm::FoldingSetNodeID id;
- SILFunctionType::Profile(id, genericSig, ext, callee, params, normalResults,
- errorResult);
+ SILFunctionType::Profile(id, genericSig, ext, coroutineKind, callee,
+ params, yields, normalResults, errorResult);
// Do we already have this generic function type?
void *insertPos;
@@ -3912,6 +3940,7 @@
// Allocate storage for the object.
size_t bytes = sizeof(SILFunctionType)
+ sizeof(SILParameterInfo) * params.size()
+ + sizeof(SILYieldInfo) * yields.size()
+ sizeof(SILResultInfo) * normalResults.size()
+ (errorResult ? sizeof(SILResultInfo) : 0)
+ (normalResults.size() > 1 ? sizeof(CanType) * 2 : 0);
@@ -3922,6 +3951,8 @@
"revisit this if you add new recursive type properties");
for (auto ¶m : params)
properties |= param.getType()->getRecursiveProperties();
+ for (auto &yield : yields)
+ properties |= yield.getType()->getRecursiveProperties();
for (auto &result : normalResults)
properties |= result.getType()->getRecursiveProperties();
if (errorResult)
@@ -3934,9 +3965,10 @@
properties.removeHasDependentMember();
}
- auto fnType = new (mem)
- SILFunctionType(genericSig, ext, callee, params, normalResults,
- errorResult, ctx, properties, witnessMethodConformance);
+ auto fnType =
+ new (mem) SILFunctionType(genericSig, ext, coroutineKind, callee,
+ params, yields, normalResults, errorResult,
+ ctx, properties, witnessMethodConformance);
ctx.Impl.SILFunctionTypes.InsertNode(fnType, insertPos);
return CanSILFunctionType(fnType);
}
@@ -4673,129 +4705,6 @@
return Type();
}
-const InheritedNameSet *ASTContext::getAllPropertyNames(ClassDecl *classDecl,
- bool forInstance) {
- // If this class was defined in Objective-C, perform the lookup based on
- // the Objective-C class.
- if (auto objcClass = dyn_cast_or_null<clang::ObjCInterfaceDecl>(
- classDecl->getClangDecl())) {
- return getAllPropertyNames(
- const_cast<clang::ObjCInterfaceDecl *>(objcClass),
- forInstance);
- }
-
- // If we already have this information, return it.
- auto known = Impl.AllProperties.find({classDecl, forInstance});
- if (known != Impl.AllProperties.end()) return known->second.get();
-
- // Otherwise, get information from our superclass first.
- if (auto resolver = getLazyResolver())
- resolver->resolveSuperclass(classDecl);
-
- const InheritedNameSet *parentSet = nullptr;
- if (auto superclass = classDecl->getSuperclass()) {
- if (auto superclassDecl = superclass->getClassOrBoundGenericClass()) {
- parentSet = getAllPropertyNames(superclassDecl, forInstance);
- }
- }
-
- // Create the set of properties.
- known = Impl.AllProperties.insert(
- { std::pair<const ClassDecl *, char>(classDecl, forInstance),
- llvm::make_unique<InheritedNameSet>(parentSet) }).first;
-
- // Local function to add properties from the given set.
- auto addProperties = [&](DeclRange members) {
- for (auto member : members) {
- auto var = dyn_cast<VarDecl>(member);
- if (!var || var->getName().empty()) continue;
- if (var->isInstanceMember() != forInstance) continue;
-
- known->second->add(var->getName().str());
- }
- };
-
- // Collect property names from the class.
- addProperties(classDecl->getMembers());
-
- // Collect property names from all extensions in the same module as the class.
- auto module = classDecl->getParentModule();
- for (auto ext : classDecl->getExtensions()) {
- if (ext->getParentModule() != module) continue;
- addProperties(ext->getMembers());
- }
-
- return known->second.get();
-}
-
-const InheritedNameSet *ASTContext::getAllPropertyNames(
- clang::ObjCInterfaceDecl *classDecl,
- bool forInstance) {
- classDecl = classDecl->getCanonicalDecl();
-
- // If we already have this information, return it.
- auto known = Impl.AllPropertiesObjC.find({classDecl, forInstance});
- if (known != Impl.AllPropertiesObjC.end()) return known->second.get();
-
- // Otherwise, get information from our superclass first.
- const InheritedNameSet *parentSet = nullptr;
- if (auto superclassDecl = classDecl->getSuperClass()) {
- parentSet = getAllPropertyNames(superclassDecl, forInstance);
- }
-
- // Create the set of properties.
- known = Impl.AllPropertiesObjC.insert(
- { std::pair<const clang::ObjCInterfaceDecl *, char>(classDecl,
- forInstance),
- llvm::make_unique<InheritedNameSet>(parentSet) }).first;
-
- // Local function to add properties from the given set.
- auto addProperties = [&](clang::DeclContext::decl_range members) {
- for (auto member : members) {
- // Add Objective-C property names.
- if (auto property = dyn_cast<clang::ObjCPropertyDecl>(member)) {
- if (forInstance)
- known->second->add(property->getName());
- continue;
- }
-
- // Add no-parameter, non-void method names.
- if (auto method = dyn_cast<clang::ObjCMethodDecl>(member)) {
- if (method->getSelector().isUnarySelector() &&
- !method->getReturnType()->isVoidType() &&
- !method->hasRelatedResultType() &&
- method->isInstanceMethod() == forInstance) {
- known->second->add(method->getSelector().getNameForSlot(0));
- continue;
- }
- }
- }
- };
-
- // Dig out the class definition.
- auto classDef = classDecl->getDefinition();
- if (!classDef) return known->second.get();
-
- // Collect property names from the class definition.
- addProperties(classDef->decls());
-
- // Dig out the module that owns the class definition.
- auto module = classDef->getImportedOwningModule();
- if (module) module = module->getTopLevelModule();
-
- // Collect property names from all categories and extensions in the same
- // module as the class.
- for (auto category : classDef->known_categories()) {
- auto categoryModule = category->getImportedOwningModule();
- if (categoryModule) categoryModule = categoryModule->getTopLevelModule();
- if (module != categoryModule) continue;
-
- addProperties(category->decls());
- }
-
- return known->second.get();
-}
-
CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
if (auto theSig = Impl.SingleGenericParameterSignature)
return theSig;
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index c72c90d..620b828 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -2926,6 +2926,7 @@
TRIVIAL_TYPE_PRINTER(BuiltinBridgeObject, builtin_bridge_object)
TRIVIAL_TYPE_PRINTER(BuiltinUnknownObject, builtin_unknown_object)
TRIVIAL_TYPE_PRINTER(BuiltinUnsafeValueBuffer, builtin_unsafe_value_buffer)
+ TRIVIAL_TYPE_PRINTER(SILToken, sil_token)
void visitBuiltinVectorType(BuiltinVectorType *T, StringRef label) {
printCommon(label, "builtin_vector_type");
diff --git a/lib/AST/ASTMangler.cpp b/lib/AST/ASTMangler.cpp
index 116613a..6cc18c4 100644
--- a/lib/AST/ASTMangler.cpp
+++ b/lib/AST/ASTMangler.cpp
@@ -527,6 +527,7 @@
switch (SKind) {
case SymbolKind::Default: return;
case SymbolKind::DynamicThunk: return appendOperator("TD");
+ case SymbolKind::SwiftDispatchThunk: return appendOperator("Tj");
case SymbolKind::SwiftAsObjCThunk: return appendOperator("To");
case SymbolKind::ObjCAsSwiftThunk: return appendOperator("TO");
case SymbolKind::DirectMethodReferenceThunk: return appendOperator("Td");
@@ -704,6 +705,8 @@
return appendOperator("BO");
case TypeKind::BuiltinUnsafeValueBuffer:
return appendOperator("BB");
+ case TypeKind::SILToken:
+ return appendOperator("Bt");
case TypeKind::BuiltinVector:
appendType(cast<BuiltinVectorType>(tybase)->getElementType());
return appendOperator("Bv",
diff --git a/lib/AST/ASTNode.cpp b/lib/AST/ASTNode.cpp
index e5f70b9..f182f01 100644
--- a/lib/AST/ASTNode.cpp
+++ b/lib/AST/ASTNode.cpp
@@ -76,16 +76,6 @@
else
llvm_unreachable("unsupported AST node");
}
-void ASTNode::walk(SourceEntityWalker &Walker) {
- if (auto *E = this->dyn_cast<Expr*>())
- Walker.walk(E);
- else if (auto *S = this->dyn_cast<Stmt*>())
- Walker.walk(S);
- else if (auto *D = this->dyn_cast<Decl*>())
- Walker.walk(D);
- else
- llvm_unreachable("unsupported AST node");
-}
#define FUNC(T) \
bool ASTNode::is##T(T##Kind Kind) const { \
diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp
index 6a8cebf..02de748 100644
--- a/lib/AST/ASTPrinter.cpp
+++ b/lib/AST/ASTPrinter.cpp
@@ -3255,6 +3255,10 @@
}
}
+ void visitSILTokenType(SILTokenType *T) {
+ Printer << "Builtin.SILToken";
+ }
+
void visitNameAliasType(NameAliasType *T) {
if (Options.PrintForSIL || Options.PrintNameAliasUnderlyingType) {
visit(T->getSinglyDesugaredType());
@@ -3630,6 +3634,20 @@
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
}
+ void printSILCoroutineKind(SILCoroutineKind kind) {
+ switch (kind) {
+ case SILCoroutineKind::None:
+ return;
+ case SILCoroutineKind::YieldOnce:
+ Printer << "@yield_once ";
+ return;
+ case SILCoroutineKind::YieldMany:
+ Printer << "@yield_many ";
+ return;
+ }
+ llvm_unreachable("bad convention");
+ }
+
void printCalleeConvention(ParameterConvention conv) {
switch (conv) {
case ParameterConvention::Direct_Unowned:
@@ -3651,6 +3669,7 @@
}
void visitSILFunctionType(SILFunctionType *T) {
+ printSILCoroutineKind(T->getCoroutineKind());
printFunctionExtInfo(T->getExtInfo(),
T->getWitnessMethodConformanceOrNone());
printCalleeConvention(T->getCalleeConvention());
@@ -3669,11 +3688,19 @@
}
Printer << ") -> ";
- unsigned totalResults = T->getNumResults() + unsigned(T->hasErrorResult());
+ unsigned totalResults =
+ T->getNumYields() + T->getNumResults() + unsigned(T->hasErrorResult());
if (totalResults != 1) Printer << "(";
first = true;
+
+ for (auto yield : T->getYields()) {
+ Printer.printSeparator(first, ", ");
+ Printer << "@yields ";
+ yield.print(Printer, Options);
+ }
+
for (auto result : T->getResults()) {
Printer.printSeparator(first, ", ");
result.print(Printer, Options);
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index d723d43..5456345 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1980,6 +1980,108 @@
abort();
}
}
+
+ void verifyChecked(KeyPathApplicationExpr *E) {
+ PrettyStackTraceExpr debugStack(
+ Ctx, "verifying KeyPathApplicationExpr", E);
+
+ auto baseTy = E->getBase()->getType();
+ auto keyPathTy = E->getKeyPath()->getType();
+ auto resultTy = E->getType();
+
+ if (auto nom = keyPathTy->getAs<NominalType>()) {
+ if (nom->getDecl() == Ctx.getAnyKeyPathDecl()) {
+ // AnyKeyPath application is <T> rvalue T -> rvalue Any?
+ if (baseTy->is<LValueType>()) {
+ Out << "AnyKeyPath application base is not an rvalue\n";
+ abort();
+ }
+ auto resultObjTy = resultTy->getOptionalObjectType();
+ if (!resultObjTy || !resultObjTy->isAny()) {
+ Out << "AnyKeyPath application result must be Any?\n";
+ abort();
+ }
+ return;
+ }
+ } else if (auto bgt = keyPathTy->getAs<BoundGenericType>()) {
+ if (bgt->getDecl() == Ctx.getPartialKeyPathDecl()) {
+ // PartialKeyPath<T> application is rvalue T -> rvalue Any
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "PartialKeyPath application base doesn't match type\n";
+ abort();
+ }
+ if (!resultTy->isAny()) {
+ Out << "PartialKeyPath application result must be Any?\n";
+ abort();
+ }
+ return;
+ } else if (bgt->getDecl() == Ctx.getKeyPathDecl()) {
+ // KeyPath<T, U> application is rvalue T -> rvalue U
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "KeyPath application base doesn't match type\n";
+ abort();
+ }
+ if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+ Out << "KeyPath application result doesn't match type\n";
+ abort();
+ }
+ return;
+ } else if (bgt->getDecl() == Ctx.getWritableKeyPathDecl()) {
+ // WritableKeyPath<T, U> application is
+ // lvalue T -> lvalue U
+ // or rvalue T -> rvalue U
+ if (baseTy->is<LValueType>()) {
+ if (!resultTy->is<LValueType>()) {
+ Out << "WritableKeyPath base and result don't match lvalue-ness\n";
+ abort();
+ }
+ baseTy = baseTy->getRValueType();
+ resultTy = resultTy->getRValueType();
+ }
+
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "WritableKeyPath application base doesn't match type\n";
+ abort();
+ }
+ if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+ Out << "WritableKeyPath application result doesn't match type\n";
+ abort();
+ }
+ return;
+ } else if (bgt->getDecl() == Ctx.getReferenceWritableKeyPathDecl()) {
+ // ReferenceWritableKeyPath<T, U> application is
+ // rvalue T -> lvalue U
+ // or lvalue T -> lvalue U
+ // or rvalue T -> rvalue U
+ if (baseTy->is<LValueType>()) {
+ if (!resultTy->is<LValueType>()) {
+ Out << "ReferenceWritableKeyPath base and result don't "
+ "match lvalue-ness\n";
+ abort();
+ }
+ baseTy = baseTy->getRValueType();
+ resultTy = resultTy->getRValueType();
+ } else {
+ resultTy = resultTy->getRValueType();
+ }
+
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "ReferenceWritableKeyPath application base doesn't "
+ "match type\n";
+ abort();
+ }
+ if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+ Out << "ReferenceWritableKeyPath application result doesn't "
+ "match type\n";
+ abort();
+ }
+ return;
+ }
+ }
+
+ Out << "invalid key path type\n";
+ abort();
+ }
static bool hasEnclosingFunctionContext(DeclContext *dc) {
switch (dc->getContextKind()) {
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index e29a206..50d58a3 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -340,6 +340,7 @@
case DAK_AccessControl:
case DAK_Ownership:
case DAK_Effects:
+ case DAK_Optimize:
if (DeclAttribute::isDeclModifier(getKind())) {
Printer.printKeyword(getAttrName());
} else {
@@ -577,6 +578,18 @@
}
llvm_unreachable("Invalid inline kind");
}
+ case DAK_Optimize: {
+ switch (cast<OptimizeAttr>(this)->getMode()) {
+ case OptimizationMode::NoOptimization:
+ return "_optimize(none)";
+ case OptimizationMode::ForSpeed:
+ return "_optimize(speed)";
+ case OptimizationMode::ForSize:
+ return "_optimize(size)";
+ default:
+ llvm_unreachable("Invalid optimization kind");
+ }
+ }
case DAK_Effects:
switch (cast<EffectsAttr>(this)->getKind()) {
case EffectsKind::ReadNone:
diff --git a/lib/AST/Builtins.cpp b/lib/AST/Builtins.cpp
index cc69513..2559621 100644
--- a/lib/AST/Builtins.cpp
+++ b/lib/AST/Builtins.cpp
@@ -80,6 +80,8 @@
return Context.TheUnknownObjectType;
if (Name == "BridgeObject")
return Context.TheBridgeObjectType;
+ if (Name == "SILToken")
+ return Context.TheSILTokenType;
if (Name == "UnsafeValueBuffer")
return Context.TheUnsafeValueBufferType;
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index df45aec..6cd7c59 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -48,7 +48,6 @@
SyntaxASTMap.cpp
SILLayout.cpp
Stmt.cpp
- SourceEntityWalker.cpp
Substitution.cpp
SubstitutionList.cpp
SubstitutionMap.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index d276857..4233676 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -361,6 +361,15 @@
llvm_unreachable("Unknown decl kind");
}
+SourceRange Decl::getSourceRangeIncludingAttrs() const {
+ auto Range = getSourceRange();
+ for (auto Attr : getAttrs()) {
+ if (Attr->getRange().isValid())
+ Range.widen(Attr->getRange());
+ }
+ return Range;
+}
+
SourceLoc Decl::getLoc() const {
switch (getKind()) {
#define DECL(ID, X) \
@@ -2175,6 +2184,19 @@
llvm_unreachable("unknown access level");
}
+void ValueDecl::copyFormalAccessAndVersionedAttrFrom(ValueDecl *source) {
+ if (!hasAccess()) {
+ setAccess(source->getFormalAccess());
+ }
+
+ // Inherit the @_versioned attribute.
+ if (source->getAttrs().hasAttribute<VersionedAttr>()) {
+ auto &ctx = getASTContext();
+ auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
+ getAttrs().add(clonedAttr);
+ }
+}
+
Type TypeDecl::getDeclaredInterfaceType() const {
if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
return NTD->getDeclaredInterfaceType();
@@ -2680,9 +2702,9 @@
return cast<DestructorDecl>(results.front());
}
-DestructorDecl *ClassDecl::addImplicitDestructor() {
+void ClassDecl::addImplicitDestructor() {
if (hasDestructor() || isInvalid())
- return nullptr;
+ return;
auto *selfDecl = ParamDecl::createSelf(getLoc(), this);
@@ -2690,12 +2712,36 @@
auto *DD = new (ctx) DestructorDecl(getLoc(), selfDecl, this);
DD->setImplicit();
+ DD->setValidationStarted();
// Create an empty body for the destructor.
DD->setBody(BraceStmt::create(ctx, getLoc(), { }, getLoc(), true));
addMember(DD);
setHasDestructor();
- return DD;
+
+ // Propagate access control and versioned-ness.
+ DD->copyFormalAccessAndVersionedAttrFrom(this);
+
+ // Wire up generic environment of DD.
+ DD->setGenericEnvironment(getGenericEnvironmentOfContext());
+
+ // Mark DD as ObjC, as all dtors are.
+ DD->setIsObjC(true);
+ recordObjCMethod(DD);
+
+ // Assign DD the interface type (Self) -> () -> ()
+ ArrayRef<AnyFunctionType::Param> noParams;
+ AnyFunctionType::ExtInfo info;
+ Type selfTy = selfDecl->getInterfaceType();
+ Type voidTy = TupleType::getEmpty(ctx);
+ Type funcTy = FunctionType::get(noParams, voidTy, info);
+ if (auto *sig = DD->getGenericSignature()) {
+ DD->setInterfaceType(
+ GenericFunctionType::get(sig, {selfTy}, funcTy, info));
+ } else {
+ DD->setInterfaceType(
+ FunctionType::get({selfTy}, funcTy, info));
+ }
}
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index e414b58..0c3221c 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -436,6 +436,23 @@
return getParent();
}
+DeclContext *DeclContext::getCommonParentContext(DeclContext *A,
+ DeclContext *B) {
+ if (A == B)
+ return A;
+
+ if (A->isChildContextOf(B))
+ return B;
+
+ // Peel away layers of A until we reach a common parent
+ for (DeclContext *CurDC = A; CurDC; CurDC = CurDC->getParent()) {
+ if (B->isChildContextOf(CurDC))
+ return CurDC;
+ }
+
+ return nullptr;
+}
+
ModuleDecl *DeclContext::getParentModule() const {
const DeclContext *DC = this;
while (!DC->isModuleContext())
diff --git a/lib/AST/GenericSignature.cpp b/lib/AST/GenericSignature.cpp
index 2b31ca1..4279839 100644
--- a/lib/AST/GenericSignature.cpp
+++ b/lib/AST/GenericSignature.cpp
@@ -20,6 +20,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Module.h"
+#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/Types.h"
#include "swift/Basic/STLExtras.h"
#include <functional>
@@ -174,6 +175,18 @@
return getCanonicalSignature() == this;
}
+#ifndef NDEBUG
+/// Determine the canonical ordering of requirements.
+static unsigned getRequirementKindOrder(RequirementKind kind) {
+ switch (kind) {
+ case RequirementKind::Conformance: return 2;
+ case RequirementKind::Superclass: return 0;
+ case RequirementKind::SameType: return 3;
+ case RequirementKind::Layout: return 1;
+ }
+}
+#endif
+
CanGenericSignature GenericSignature::getCanonical(
ArrayRef<GenericTypeParamType *> params,
ArrayRef<Requirement> requirements) {
@@ -197,8 +210,105 @@
Requirement(reqt.getKind(), reqt.getFirstType()->getCanonicalType(),
reqt.getLayoutConstraint()));
}
+
auto canSig = get(canonicalParams, canonicalRequirements,
/*isKnownCanonical=*/true);
+
+#ifndef NDEBUG
+ PrettyStackTraceGenericSignature debugStack("canonicalizing", canSig);
+
+ // Check that the signature is canonical.
+ for (unsigned idx : indices(canonicalRequirements)) {
+ debugStack.setRequirement(idx);
+
+ const auto &reqt = canonicalRequirements[idx];
+
+ // Left-hand side must be canonical in its context.
+ // Check canonicalization of requirement itself.
+ switch (reqt.getKind()) {
+ case RequirementKind::Superclass:
+ assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+ "Left-hand side is not canonical");
+ assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+ "Superclass type isn't canonical in its own context");
+ break;
+
+ case RequirementKind::Layout:
+ assert(canSig->isCanonicalTypeInContext(reqt.getFirstType()) &&
+ "Left-hand side is not canonical");
+ break;
+
+ case RequirementKind::SameType:
+ assert(reqt.getFirstType()->isTypeParameter() &&
+ "Left-hand side must be a type parameter");
+ if (reqt.getSecondType()->isTypeParameter()) {
+ assert(compareDependentTypes(reqt.getFirstType(), reqt.getSecondType())
+ < 0 &&
+ "Out-of-order type parameters in same-type constraint");
+ } else {
+ assert(canSig->isCanonicalTypeInContext(reqt.getSecondType()) &&
+ "Concrete same-type isn't canonical in its own context");
+ }
+ break;
+
+ case RequirementKind::Conformance:
+ assert(reqt.getFirstType()->isTypeParameter() &&
+ "Left-hand side must be a type parameter");
+ assert(isa<ProtocolType>(reqt.getSecondType().getPointer()) &&
+ "Right-hand side of conformance isn't a protocol type");
+ break;
+ }
+
+ // From here on, we're only interested in requirements beyond the first.
+ if (idx == 0) continue;
+
+ // Make sure that the left-hand sides are in nondecreasing order.
+ const auto &prevReqt = canonicalRequirements[idx-1];
+ int compareLHS =
+ compareDependentTypes(prevReqt.getFirstType(), reqt.getFirstType());
+ assert(compareLHS <= 0 && "Out-of-order left-hand sides");
+
+ // If we have two same-type requirements where the left-hand sides differ
+ // but fall into the same equivalence class, we can check the form.
+ if (compareLHS < 0 && reqt.getKind() == RequirementKind::SameType &&
+ prevReqt.getKind() == RequirementKind::SameType &&
+ canSig->areSameTypeParameterInContext(prevReqt.getFirstType(),
+ reqt.getFirstType())) {
+ // If it's a it's a type parameter, make sure the equivalence class is
+ // wired together sanely.
+ if (prevReqt.getSecondType()->isTypeParameter()) {
+ assert(prevReqt.getSecondType()->isEqual(reqt.getFirstType()) &&
+ "same-type constraints within an equiv. class are out-of-order");
+ } else {
+ // Otherwise, the concrete types must match up.
+ assert(prevReqt.getSecondType()->isEqual(reqt.getSecondType()) &&
+ "inconsistent concrete same-type constraints in equiv. class");
+ }
+ }
+
+ // From here on, we only care about cases where the previous and current
+ // requirements have the same left-hand side.
+ if (compareLHS != 0) continue;
+
+ // Check ordering of requirement kinds.
+ assert((getRequirementKindOrder(prevReqt.getKind()) <=
+ getRequirementKindOrder(reqt.getKind())) &&
+ "Requirements for a given kind are out-of-order");
+
+ // From here on, we only care about the same requirement kind.
+ if (prevReqt.getKind() != reqt.getKind()) continue;
+
+ assert(reqt.getKind() == RequirementKind::Conformance &&
+ "Only conformance requirements can have multiples");
+
+ auto prevProto =
+ prevReqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+ auto proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+ assert(ProtocolType::compareProtocols(&prevProto, &proto) < 0 &&
+ "Out-of-order conformance requirements");
+ }
+#endif
+
return CanGenericSignature(canSig);
}
@@ -621,14 +731,12 @@
type1,
ArchetypeResolutionKind::CompleteWellFormed);
assert(equivClass1 && "not a valid dependent type of this signature?");
- assert(!equivClass1->concreteType);
auto equivClass2 =
builder.resolveEquivalenceClass(
type2,
ArchetypeResolutionKind::CompleteWellFormed);
assert(equivClass2 && "not a valid dependent type of this signature?");
- assert(!equivClass2->concreteType);
return equivClass1 == equivClass2;
}
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index 4aada77..f0d7135 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -25,6 +25,7 @@
#include "swift/AST/LazyResolver.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeMatcher.h"
#include "swift/AST/TypeRepr.h"
@@ -2954,36 +2955,30 @@
/// Resolve any unresolved dependent member types using the given builder.
static Type resolveDependentMemberTypes(GenericSignatureBuilder &builder,
- Type type,
- ArchetypeResolutionKind kind) {
+ Type type) {
if (!type->hasTypeParameter()) return type;
- return type.transformRec([&builder,kind](TypeBase *type) -> Optional<Type> {
- if (auto depTy = dyn_cast<DependentMemberType>(type)) {
- if (depTy->getAssocType()) return None;
+ return type.transformRec([&builder](TypeBase *type) -> Optional<Type> {
+ if (!type->isTypeParameter())
+ return None;
- Type newBase =
- resolveDependentMemberTypes(builder, depTy->getBase(), kind);
- if (newBase->is<ErrorType>())
- return ErrorType::get(depTy);
+ // Map the type parameter to an equivalence class.
+ auto equivClass =
+ builder.resolveEquivalenceClass(Type(type),
+ ArchetypeResolutionKind::WellFormed);
+ if (!equivClass)
+ return ErrorType::get(Type(type));
- auto parentEquivClass = builder.resolveEquivalenceClass(newBase, kind);
- if (!parentEquivClass)
- return ErrorType::get(depTy);
+ // If there is a concrete type in this equivalence class, use that.
+ if (equivClass->concreteType) {
+ // .. unless it's recursive.
+ if (equivClass->recursiveConcreteType)
+ return ErrorType::get(Type(type));
- auto memberType =
- parentEquivClass->lookupNestedType(builder, depTy->getName());
- if (!memberType)
- return ErrorType::get(depTy);
-
- if (auto assocType = dyn_cast<AssociatedTypeDecl>(memberType))
- return Type(DependentMemberType::get(newBase, assocType));
-
- // FIXME: Need to substitute here.
- return Type(type);
+ return resolveDependentMemberTypes(builder, equivClass->concreteType);
}
- return None;
+ return equivClass->getAnchor(builder, builder.getGenericParams());
});
}
@@ -3094,9 +3089,7 @@
// FIXME: Generic typealiases contradict the assumption above.
// If there is a type parameter somewhere in this type, resolve it.
if (type->hasTypeParameter()) {
- Type resolved =
- resolveDependentMemberTypes(*this, type,
- ArchetypeResolutionKind::WellFormed);
+ Type resolved = resolveDependentMemberTypes(*this, type);
if (resolved->hasError() && !type->hasError())
return ResolvedType::forUnresolved(nullptr);
@@ -5951,10 +5944,9 @@
diag::redundant_same_type_to_concrete,
diag::same_type_redundancy_here);
- // Resolve any this-far-unresolved dependent types.
+ // Resolve any thus-far-unresolved dependent types.
equivClass->concreteType =
- resolveDependentMemberTypes(*this, equivClass->concreteType,
- ArchetypeResolutionKind::CompleteWellFormed);
+ resolveDependentMemberTypes(*this, equivClass->concreteType);
}
void GenericSignatureBuilder::checkSuperclassConstraints(
@@ -5996,8 +5988,7 @@
// Resolve any this-far-unresolved dependent types.
equivClass->superclass =
- resolveDependentMemberTypes(*this, equivClass->superclass,
- ArchetypeResolutionKind::CompleteWellFormed);
+ resolveDependentMemberTypes(*this, equivClass->superclass);
// If we have a concrete type, check it.
// FIXME: Substitute into the concrete type.
@@ -6374,7 +6365,7 @@
// over-minimizing.
if (allowBuilderToMove && !Impl->HadAnyError &&
!Impl->HadAnyRedundantConstraints) {
- // Register this generic signature builer as the canonical builder for the
+ // Register this generic signature builder as the canonical builder for the
// given signature.
Context.registerGenericSignatureBuilder(sig, std::move(*this));
}
@@ -6412,3 +6403,77 @@
/*allowBuilderToMove=*/false);
}
+#pragma mark Generic signature verification
+
+void GenericSignatureBuilder::verifyGenericSignature(ASTContext &context,
+ GenericSignature *sig) {
+ llvm::errs() << "Validating generic signature: ";
+ sig->print(llvm::errs());
+ llvm::errs() << "\n";
+
+ // Try removing each requirement in turn.
+ auto genericParams = sig->getGenericParams();
+ auto requirements = sig->getRequirements();
+ for (unsigned victimIndex : indices(requirements)) {
+ PrettyStackTraceGenericSignature debugStack("verifying", sig, victimIndex);
+
+ // Form a new generic signature builder.
+ GenericSignatureBuilder builder(context);
+
+ // Add the generic parameters.
+ for (auto gp : genericParams)
+ builder.addGenericParameter(gp);
+
+ // Add the requirements *except* the victim.
+ auto source = FloatingRequirementSource::forAbstract();
+ for (unsigned i : indices(requirements)) {
+ if (i != victimIndex)
+ builder.addRequirement(requirements[i], source, nullptr);
+ }
+
+ // Finalize the generic signature. If there were any errors, we formed
+ // an invalid signature, so just continue.
+ if (builder.Impl->HadAnyError) continue;
+
+ // Form a generic signature from the result.
+ auto newSig =
+ std::move(builder).computeGenericSignature(
+ SourceLoc(),
+ /*allowConcreteGenericParams=*/true,
+ /*allowBuilderToMove=*/true);
+
+ // Check whether the removed requirement
+ assert(!newSig->isRequirementSatisfied(requirements[victimIndex]) &&
+ "Generic signature is not minimal");
+
+ // Canonicalize the signature to check that it is canonical.
+ (void)newSig->getCanonicalSignature();
+ }
+}
+
+void GenericSignatureBuilder::verifyGenericSignaturesInModule(
+ ModuleDecl *module) {
+ LoadedFile *loadedFile = nullptr;
+ for (auto fileUnit : module->getFiles()) {
+ loadedFile = dyn_cast<LoadedFile>(fileUnit);
+ if (loadedFile) break;
+ }
+
+ if (!loadedFile) return;
+
+ // Check all of the (canonical) generic signatures.
+ SmallVector<GenericSignature *, 8> allGenericSignatures;
+ SmallPtrSet<CanGenericSignature, 4> knownGenericSignatures;
+ (void)loadedFile->getAllGenericSignatures(allGenericSignatures);
+ ASTContext &context = module->getASTContext();
+ for (auto genericSig : allGenericSignatures) {
+ // Check whether this is the first time we've checked this (canonical)
+ // signature.
+ auto canGenericSig = genericSig->getCanonicalSignature();
+ if (!knownGenericSignatures.insert(canGenericSig).second) continue;
+
+ verifyGenericSignature(context, canGenericSig);
+ }
+}
+
+
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index e64c8dd..f374f09 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -1176,7 +1176,8 @@
return;
auto nominal = getExtendedType()->getAnyNominal();
- if (nominal->LookupTable.getPointer()) {
+ if (nominal->LookupTable.getPointer() &&
+ nominal->LookupTable.getInt()) {
// Make sure we have the complete list of extensions.
// FIXME: This is completely unnecessary. We want to determine whether
// our own extension has already been included in the lookup table.
diff --git a/lib/AST/PrettyStackTrace.cpp b/lib/AST/PrettyStackTrace.cpp
index 26a1fb5..649baea 100644
--- a/lib/AST/PrettyStackTrace.cpp
+++ b/lib/AST/PrettyStackTrace.cpp
@@ -18,6 +18,7 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
+#include "swift/AST/GenericSignature.h"
#include "swift/AST/Module.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/Stmt.h"
@@ -214,3 +215,12 @@
out << "While " << Action << " starting at ";
printSourceLocDescription(out, Loc, Context);
}
+
+void PrettyStackTraceGenericSignature::print(llvm::raw_ostream &out) const {
+ out << "While " << Action << " generic signature ";
+ GenericSig->print(out);
+ if (Requirement) {
+ out << " in requirement #" << *Requirement;
+ }
+ out << '\n';
+}
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 5984052..1e38106 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -116,8 +116,6 @@
if (auto result = conformances(origType->getCanonicalType(),
substType,
proto->getDeclaredType())) {
- assert(result->getConditionalRequirements().empty() &&
- "unhandled conditional requirements");
return *result;
}
@@ -288,6 +286,45 @@
llvm_unreachable("Unhandled ProtocolConformanceKind in switch.");
}
+SubstitutionMap ProtocolConformance::getSubstitutions(ModuleDecl *M) const {
+ // Walk down to the base NormalProtocolConformance.
+ SubstitutionMap subMap;
+ const ProtocolConformance *parent = this;
+ while (!isa<NormalProtocolConformance>(parent)) {
+ switch (parent->getKind()) {
+ case ProtocolConformanceKind::Normal:
+ llvm_unreachable("should have exited the loop?!");
+ case ProtocolConformanceKind::Inherited:
+ parent =
+ cast<InheritedProtocolConformance>(parent)->getInheritedConformance();
+ break;
+ case ProtocolConformanceKind::Specialized: {
+ auto SC = cast<SpecializedProtocolConformance>(parent);
+ parent = SC->getGenericConformance();
+ assert(subMap.empty() && "multiple conformance specializations?!");
+ subMap = SC->getSubstitutionMap();
+ break;
+ }
+ }
+ }
+
+ // Found something; we're done!
+ if (!subMap.empty())
+ return subMap;
+
+ // If the normal conformance is for a generic type, and we didn't hit a
+ // specialized conformance, collect the substitutions from the generic type.
+ // FIXME: The AST should do this for us.
+ const NormalProtocolConformance *normalC =
+ cast<NormalProtocolConformance>(parent);
+
+ if (!normalC->getType()->isSpecialized())
+ return SubstitutionMap();
+
+ auto *DC = normalC->getDeclContext();
+ return normalC->getType()->getContextSubstitutionMap(M, DC);
+}
+
bool ProtocolConformance::isBehaviorConformance() const {
return getRootNormalConformance()->isBehaviorConformance();
}
@@ -758,10 +795,9 @@
auto *typeDecl = genericWitnessAndDecl.second;
// Form the substitution.
- auto *genericSig = GenericConformance->getGenericSignature();
- if (!genericSig) return { Type(), nullptr };
-
- auto substitutionMap = genericSig->getSubstitutionMap(GenericSubstitutions);
+ auto substitutionMap = getSubstitutionMap();
+ if (substitutionMap.empty())
+ return {Type(), nullptr};
// Apply the substitution we computed above
auto specializedType = genericWitness.subst(getSubstitutionMap(), options);
@@ -876,6 +912,10 @@
return cast<NormalProtocolConformance>(C);
}
+bool ProtocolConformance::witnessTableAccessorRequiresArguments() const {
+ return getRootNormalConformance()->getDeclContext()->isGenericContext();
+}
+
bool ProtocolConformance::isVisibleFrom(const DeclContext *dc) const {
// FIXME: Implement me!
return true;
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d1291d5..d27e118 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -18,6 +18,7 @@
#include "ForeignRepresentationInfo.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ExistentialLayout.h"
+#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/TypeVisitor.h"
#include "swift/AST/TypeWalker.h"
#include "swift/AST/Decl.h"
@@ -219,6 +220,7 @@
case TypeKind::TypeVariable:
case TypeKind::BoundGenericEnum:
case TypeKind::BoundGenericStruct:
+ case TypeKind::SILToken:
case TypeKind::UnownedStorage:
case TypeKind::UnmanagedStorage:
case TypeKind::WeakStorage:
@@ -1156,6 +1158,7 @@
case TypeKind::SILBlockStorage:
case TypeKind::SILBox:
case TypeKind::SILFunction:
+ case TypeKind::SILToken:
llvm_unreachable("SIL-only types are always canonical!");
case TypeKind::Function: {
@@ -1275,6 +1278,7 @@
case TypeKind::SILBlockStorage:
case TypeKind::SILBox:
case TypeKind::SILFunction:
+ case TypeKind::SILToken:
case TypeKind::LValue:
case TypeKind::InOut:
case TypeKind::ProtocolComposition:
@@ -1493,6 +1497,7 @@
case TypeKind::SILFunction:
case TypeKind::SILBlockStorage:
case TypeKind::SILBox:
+ case TypeKind::SILToken:
case TypeKind::GenericFunction: {
// Polymorphic function types should never be explicitly spelled.
return false;
@@ -3089,15 +3094,110 @@
getAssocType(), getName(), None);
}
+static Type substGenericFunctionType(GenericFunctionType *genericFnType,
+ TypeSubstitutionFn substitutions,
+ LookupConformanceFn lookupConformances,
+ SubstOptions options) {
+ // Substitute into the function type (without generic signature).
+ auto *bareFnType = FunctionType::get(genericFnType->getInput(),
+ genericFnType->getResult(),
+ genericFnType->getExtInfo());
+ Type result =
+ Type(bareFnType).subst(substitutions, lookupConformances, options);
+ if (!result || result->is<ErrorType>()) return result;
+
+ auto *fnType = result->castTo<FunctionType>();
+ // Substitute generic parameters.
+ bool anySemanticChanges = false;
+ SmallVector<GenericTypeParamType *, 4> genericParams;
+ for (auto param : genericFnType->getGenericParams()) {
+ Type paramTy =
+ Type(param).subst(substitutions, lookupConformances, options);
+ if (!paramTy)
+ return Type();
+
+ if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
+ if (!newParam->isEqual(param))
+ anySemanticChanges = true;
+
+ genericParams.push_back(newParam);
+ } else {
+ anySemanticChanges = true;
+ }
+ }
+
+ // If no generic parameters remain, this is a non-generic function type.
+ if (genericParams.empty())
+ return result;
+
+ // Transform requirements.
+ SmallVector<Requirement, 4> requirements;
+ for (const auto &req : genericFnType->getRequirements()) {
+ // Substitute into the requirement.
+ auto substReqt = req.subst(substitutions, lookupConformances, options);
+ if (!substReqt) {
+ anySemanticChanges = true;
+ continue;
+ }
+
+ // Did anything change?
+ if (!anySemanticChanges &&
+ (!req.getFirstType()->isEqual(substReqt->getFirstType()) ||
+ (req.getKind() != RequirementKind::Layout &&
+ !req.getSecondType()->isEqual(substReqt->getSecondType())))) {
+ anySemanticChanges = true;
+ }
+
+ // Skip any erroneous requirements.
+ if (substReqt->getFirstType()->hasError() ||
+ (substReqt->getKind() != RequirementKind::Layout &&
+ substReqt->getSecondType()->hasError()))
+ continue;
+
+ requirements.push_back(*substReqt);
+ }
+
+ GenericSignature *genericSig = nullptr;
+ if (anySemanticChanges) {
+ // If there were semantic changes, we need to build a new generic
+ // signature.
+ GenericSignatureBuilder builder(genericFnType->getASTContext());
+
+ // Add the generic parameters to the builder.
+ for (auto gp : genericParams)
+ builder.addGenericParameter(gp);
+
+ // Add the requirements to the builder.
+ auto source =
+ GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
+ for (const auto &req : requirements)
+ builder.addRequirement(req, source, /*inferForModule=*/nullptr);
+
+ // Form the generic signature.
+ genericSig = std::move(builder).computeGenericSignature(SourceLoc());
+ } else {
+ // Use the mapped generic signature.
+ genericSig = GenericSignature::get(genericParams, requirements);
+ }
+
+ // Produce the new generic function type.
+ return GenericFunctionType::get(genericSig, fnType->getInput(),
+ fnType->getResult(), fnType->getExtInfo());
+}
+
static Type substType(Type derivedType,
TypeSubstitutionFn substitutions,
LookupConformanceFn lookupConformances,
SubstOptions options) {
+ // Handle substitutions into generic function types.
+ if (auto genericFnType = derivedType->getAs<GenericFunctionType>()) {
+ return substGenericFunctionType(genericFnType, substitutions,
+ lookupConformances, options);
+ }
// FIXME: Change getTypeOfMember() to not pass GenericFunctionType here
if (!derivedType->hasArchetype() &&
- !derivedType->hasTypeParameter() &&
- !derivedType->is<GenericFunctionType>())
+ !derivedType->hasTypeParameter())
return derivedType;
return derivedType.transformRec([&](TypeBase *type) -> Optional<Type> {
@@ -3236,17 +3336,22 @@
Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
Type t(this);
+
+ if (!t->getAnyNominal()) {
+ if (auto archetype = t->getAs<ArchetypeType>()) {
+ t = archetype->getSuperclass();
+ } else if (auto dynamicSelfTy = t->getAs<DynamicSelfType>()) {
+ t = dynamicSelfTy->getSelfType();
+ } else if (auto compositionTy = t->getAs<ProtocolCompositionType>()) {
+ t = compositionTy->getExistentialLayout().superclass;
+ }
+ }
+
while (t) {
// If we have a class-constrained archetype or class-constrained
// existential, get the underlying superclass constraint.
auto *nominalDecl = t->getAnyNominal();
- if (!nominalDecl) {
- assert(t->is<ArchetypeType>() || t->isExistentialType() &&
- "expected a class, archetype or existential");
- t = t->getSuperclass();
- assert(t && "archetype or existential is not class constrained");
- continue;
- }
+ assert(nominalDecl && "expected nominal type here");
assert(isa<ClassDecl>(nominalDecl) && "expected a class here");
if (nominalDecl == baseClass)
@@ -3263,7 +3368,9 @@
assert(dc->isTypeContext());
Type baseTy(this);
- assert(!baseTy->hasLValueType() && !baseTy->is<AnyMetatypeType>());
+ assert(!baseTy->hasLValueType() &&
+ !baseTy->is<AnyMetatypeType>() &&
+ !baseTy->is<ErrorType>());
// The resulting set of substitutions. Always use this to ensure we
// don't miss out on NRVO anywhere.
@@ -3409,6 +3516,7 @@
assert(memberType);
+ // Perform the substitution.
auto substitutions = getMemberSubstitutionMap(module, member);
return memberType.subst(substitutions, SubstFlags::UseErrorType);
}
@@ -3463,6 +3571,20 @@
return false;
}
+static bool transformSILYield(
+ SILYieldInfo &yield, bool &changed,
+ llvm::function_ref<Optional<Type>(TypeBase *)> fn) {
+ Type transType = yield.getType().transformRec(fn);
+ if (!transType) return true;
+
+ CanType canTransType = transType->getCanonicalType();
+ if (canTransType != yield.getType()) {
+ changed = true;
+ yield = yield.getWithType(canTransType);
+ }
+ return false;
+}
+
static bool transformSILParameter(
SILParameterInfo ¶m, bool &changed,
llvm::function_ref<Optional<Type>(TypeBase *)> fn) {
@@ -3513,6 +3635,7 @@
case TypeKind::Unresolved:
case TypeKind::TypeVariable:
case TypeKind::GenericTypeParam:
+ case TypeKind::SILToken:
return *this;
case TypeKind::Enum:
@@ -3568,6 +3691,12 @@
transInterfaceParams.push_back(param);
}
+ SmallVector<SILYieldInfo, 8> transInterfaceYields;
+ for (SILYieldInfo yield : fnTy->getYields()) {
+ if (transformSILYield(yield, changed, fn)) return Type();
+ transInterfaceYields.push_back(yield);
+ }
+
SmallVector<SILResultInfo, 8> transInterfaceResults;
for (SILResultInfo result : fnTy->getResults()) {
if (transformSILResult(result, changed, fn)) return Type();
@@ -3583,10 +3712,15 @@
if (!changed) return *this;
- return SILFunctionType::get(fnTy->getGenericSignature(), fnTy->getExtInfo(),
+ return SILFunctionType::get(fnTy->getGenericSignature(),
+ fnTy->getExtInfo(),
+ fnTy->getCoroutineKind(),
fnTy->getCalleeConvention(),
- transInterfaceParams, transInterfaceResults,
- transErrorResult, Ptr->getASTContext(),
+ transInterfaceParams,
+ transInterfaceYields,
+ transInterfaceResults,
+ transErrorResult,
+ Ptr->getASTContext(),
fnTy->getWitnessMethodConformanceOrNone());
}
@@ -3777,6 +3911,7 @@
return DependentMemberType::get(dependentBase, dependent->getName());
}
+ case TypeKind::GenericFunction:
case TypeKind::Function: {
auto function = cast<AnyFunctionType>(base);
auto inputTy = function->getInput().transformRec(fn);
@@ -3786,131 +3921,33 @@
if (!resultTy)
return Type();
- if (inputTy.getPointer() == function->getInput().getPointer() &&
- resultTy.getPointer() == function->getResult().getPointer())
- return *this;
+ bool isUnchanged =
+ inputTy.getPointer() == function->getInput().getPointer() &&
+ resultTy.getPointer() == function->getResult().getPointer();
+
+ if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
+
+#ifndef NDEBUG
+ // Check that generic parameters won't be trasnformed.
+ // Transform generic parameters.
+ for (auto param : genericFnType->getGenericParams()) {
+ assert(Type(param).transformRec(fn).getPointer() == param &&
+ "GenericFunctionType transform() changes type parameter");
+ }
+#endif
+ if (isUnchanged) return *this;
+
+ auto genericSig = genericFnType->getGenericSignature();
+ return GenericFunctionType::get(genericSig, inputTy, resultTy,
+ function->getExtInfo());
+ }
+
+ if (isUnchanged) return *this;
return FunctionType::get(inputTy, resultTy,
function->getExtInfo());
}
- case TypeKind::GenericFunction: {
- GenericFunctionType *function = cast<GenericFunctionType>(base);
- bool anyChanges = false;
-
- // Transform generic parameters.
- SmallVector<GenericTypeParamType *, 4> genericParams;
- for (auto param : function->getGenericParams()) {
- Type paramTy = Type(param).transformRec(fn);
- if (!paramTy)
- return Type();
-
- if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
- if (newParam != param)
- anyChanges = true;
-
- genericParams.push_back(newParam);
- } else {
- anyChanges = true;
- }
- }
-
- // Transform requirements.
- SmallVector<Requirement, 4> requirements;
- for (const auto &req : function->getRequirements()) {
- auto firstType = req.getFirstType().transformRec(fn);
- if (!firstType)
- return Type();
-
- if (firstType.getPointer() != req.getFirstType().getPointer())
- anyChanges = true;
-
- if (req.getKind() == RequirementKind::Layout) {
- if (!firstType->isTypeParameter())
- continue;
-
- requirements.push_back(Requirement(req.getKind(), firstType,
- req.getLayoutConstraint()));
- continue;
- }
-
- Type secondType = req.getSecondType();
- if (secondType) {
- secondType = secondType.transformRec(fn);
- if (!secondType)
- return Type();
-
- if (secondType.getPointer() != req.getSecondType().getPointer())
- anyChanges = true;
- }
-
- if (!firstType->isTypeParameter()) {
- if (!secondType || !secondType->isTypeParameter())
- continue;
- std::swap(firstType, secondType);
- }
-
- requirements.push_back(Requirement(req.getKind(), firstType,
- secondType));
- }
-
- // Transform input type.
- auto inputTy = function->getInput().transformRec(fn);
- if (!inputTy)
- return Type();
-
- // Transform result type.
- auto resultTy = function->getResult().transformRec(fn);
- if (!resultTy)
- return Type();
-
- // Check whether anything changed.
- if (!anyChanges &&
- inputTy.getPointer() == function->getInput().getPointer() &&
- resultTy.getPointer() == function->getResult().getPointer())
- return *this;
-
- // If no generic parameters remain, this is a non-generic function type.
- if (genericParams.empty()) {
- return FunctionType::get(inputTy, resultTy, function->getExtInfo());
- }
-
- // Sort/unique the generic parameters by depth/index.
- using llvm::array_pod_sort;
- array_pod_sort(genericParams.begin(), genericParams.end(),
- [](GenericTypeParamType * const * gpp1,
- GenericTypeParamType * const * gpp2) {
- auto gp1 = *gpp1;
- auto gp2 = *gpp2;
-
- if (gp1->getDepth() < gp2->getDepth())
- return -1;
-
- if (gp1->getDepth() > gp2->getDepth())
- return 1;
-
- if (gp1->getIndex() < gp2->getIndex())
- return -1;
-
- if (gp1->getIndex() > gp2->getIndex())
- return 1;
-
- return 0;
- });
- genericParams.erase(std::unique(genericParams.begin(), genericParams.end(),
- [](GenericTypeParamType *gp1,
- GenericTypeParamType *gp2) {
- return gp1->getDepth() == gp2->getDepth()
- && gp1->getIndex() == gp2->getIndex();
- }),
- genericParams.end());
-
- // Produce the new generic function type.
- auto sig = GenericSignature::get(genericParams, requirements);
- return GenericFunctionType::get(sig, inputTy, resultTy,
- function->getExtInfo());
- }
-
case TypeKind::ArraySlice: {
auto slice = cast<ArraySliceType>(base);
auto baseTy = slice->getBaseType().transformRec(fn);
@@ -4184,6 +4221,7 @@
case TypeKind::TypeVariable:
case TypeKind::BoundGenericEnum:
case TypeKind::BoundGenericStruct:
+ case TypeKind::SILToken:
case TypeKind::UnownedStorage:
case TypeKind::UnmanagedStorage:
case TypeKind::WeakStorage:
diff --git a/lib/AST/TypeWalker.cpp b/lib/AST/TypeWalker.cpp
index 70e1061..56877a6 100644
--- a/lib/AST/TypeWalker.cpp
+++ b/lib/AST/TypeWalker.cpp
@@ -36,6 +36,7 @@
bool visitUnresolvedType(UnresolvedType *ty) { return false; }
bool visitBuiltinType(BuiltinType *ty) { return false; }
bool visitNameAliasType(NameAliasType *ty) { return false; }
+ bool visitSILTokenType(SILTokenType *ty) { return false; }
bool visitParenType(ParenType *ty) {
return doIt(ty->getUnderlyingType());
diff --git a/lib/Basic/SourceLoc.cpp b/lib/Basic/SourceLoc.cpp
index a96c4e9..f55af89 100644
--- a/lib/Basic/SourceLoc.cpp
+++ b/lib/Basic/SourceLoc.cpp
@@ -205,6 +205,13 @@
llvm_unreachable("no buffer containing location found");
}
+void SourceRange::widen(SourceRange Other) {
+ if (Other.Start.Value.getPointer() < Start.Value.getPointer())
+ Start = Other.Start;
+ if (Other.End.Value.getPointer() > End.Value.getPointer())
+ End = Other.End;
+}
+
void SourceLoc::printLineAndColumn(raw_ostream &OS,
const SourceManager &SM) const {
if (isInvalid()) {
diff --git a/lib/Basic/Statistic.cpp b/lib/Basic/Statistic.cpp
index 765e9ed..46ee77f 100644
--- a/lib/Basic/Statistic.cpp
+++ b/lib/Basic/Statistic.cpp
@@ -143,7 +143,9 @@
StringRef Directory,
SourceManager *SM,
bool TraceEvents)
- : StatsFilename(Directory),
+ : currentProcessExitStatusSet(false),
+ currentProcessExitStatus(EXIT_FAILURE),
+ StatsFilename(Directory),
TraceFilename(Directory),
StartedTime(llvm::TimeRecord::getCurrentTime()),
Timer(make_unique<NamedRegionTimer>(AuxName,
@@ -184,6 +186,13 @@
}
void
+UnifiedStatsReporter::noteCurrentProcessExitStatus(int status) {
+ assert(!currentProcessExitStatusSet);
+ currentProcessExitStatusSet = true;
+ currentProcessExitStatus = status;
+}
+
+void
UnifiedStatsReporter::publishAlwaysOnStatsToLLVM() {
if (FrontendCounters) {
auto &C = getFrontendCounters();
@@ -334,6 +343,18 @@
UnifiedStatsReporter::~UnifiedStatsReporter()
{
+ // If nobody's marked this process as successful yet,
+ // mark it as failing.
+ if (currentProcessExitStatus != EXIT_SUCCESS) {
+ if (FrontendCounters) {
+ auto &C = getFrontendCounters();
+ C.NumProcessFailures++;
+ } else {
+ auto &C = getDriverCounters();
+ C.NumProcessFailures++;
+ }
+ }
+
// NB: Timer needs to be Optional<> because it needs to be destructed early;
// LLVM will complain about double-stopping a timer if you tear down a
// NamedRegionTimer after printing all timers. The printing routines were
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 40c58a4..3982bd6 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4254,7 +4254,7 @@
result->setCheckedInheritanceClause();
result->setAddedImplicitInitializers(); // suppress all initializers
addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
- Impl.registerExternalDecl(result);
+ result->addImplicitDestructor();
return result;
};
@@ -4274,7 +4274,6 @@
auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
nsObjectDecl->getDeclContext());
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
- result->addImplicitDestructor();
return result;
}
@@ -4359,7 +4358,6 @@
markMissingSwiftDecl(result);
if (decl->getAttr<clang::ObjCRuntimeVisibleAttr>()) {
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
- result->addImplicitDestructor();
}
// If this Objective-C class has a supertype, import it.
@@ -4392,7 +4390,6 @@
if (decl->getName() == "OS_object" ||
decl->getName() == "OS_os_log") {
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
- result->addImplicitDestructor();
}
// If the superclass is runtime-only, our class is also. This only
@@ -4420,9 +4417,7 @@
#include "InferredAttributes.def"
result->setMemberLoader(&Impl, 0);
-
- // Pass the class to the type checker to create an implicit destructor.
- Impl.registerExternalDecl(result);
+ result->addImplicitDestructor();
return result;
}
diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp
index 161f1e9..845f2b7 100644
--- a/lib/ClangImporter/ImportName.cpp
+++ b/lib/ClangImporter/ImportName.cpp
@@ -839,7 +839,7 @@
if (!contextType.isNull()) {
if (auto objcPtrType = contextType->getAsObjCInterfacePointerType())
if (auto objcClassDecl = objcPtrType->getInterfaceDecl())
- allPropertyNames = nameImporter.getContext().getAllPropertyNames(
+ allPropertyNames = nameImporter.getAllPropertyNames(
objcClassDecl, isInstanceMethod);
}
@@ -1655,8 +1655,7 @@
if (auto objcPtrType = contextType->getAsObjCInterfacePointerType())
if (auto objcClassDecl = objcPtrType->getInterfaceDecl())
allPropertyNames =
- swiftCtx.getAllPropertyNames(objcClassDecl,
- /*forInstance=*/true);
+ getAllPropertyNames(objcClassDecl, /*forInstance=*/true);
}
(void)omitNeedlessWords(baseName, {}, "", propertyTypeName,
@@ -1774,3 +1773,72 @@
importNameCache[key] = res;
return res;
}
+
+const InheritedNameSet *NameImporter::getAllPropertyNames(
+ clang::ObjCInterfaceDecl *classDecl,
+ bool forInstance) {
+ classDecl = classDecl->getCanonicalDecl();
+
+ // If we already have this information, return it.
+ auto known = allProperties.find({classDecl, forInstance});
+ if (known != allProperties.end()) return known->second.get();
+
+ // Otherwise, get information from our superclass first.
+ const InheritedNameSet *parentSet = nullptr;
+ if (auto superclassDecl = classDecl->getSuperClass()) {
+ parentSet = getAllPropertyNames(superclassDecl, forInstance);
+ }
+
+ // Create the set of properties.
+ known = allProperties.insert(
+ { std::pair<const clang::ObjCInterfaceDecl *, char>(classDecl,
+ forInstance),
+ llvm::make_unique<InheritedNameSet>(parentSet) }).first;
+
+ // Local function to add properties from the given set.
+ auto addProperties = [&](clang::DeclContext::decl_range members) {
+ for (auto member : members) {
+ // Add Objective-C property names.
+ if (auto property = dyn_cast<clang::ObjCPropertyDecl>(member)) {
+ if (forInstance)
+ known->second->add(property->getName());
+ continue;
+ }
+
+ // Add no-parameter, non-void method names.
+ if (auto method = dyn_cast<clang::ObjCMethodDecl>(member)) {
+ if (method->getSelector().isUnarySelector() &&
+ !method->getReturnType()->isVoidType() &&
+ !method->hasRelatedResultType() &&
+ method->isInstanceMethod() == forInstance) {
+ known->second->add(method->getSelector().getNameForSlot(0));
+ continue;
+ }
+ }
+ }
+ };
+
+ // Dig out the class definition.
+ auto classDef = classDecl->getDefinition();
+ if (!classDef) return known->second.get();
+
+ // Collect property names from the class definition.
+ addProperties(classDef->decls());
+
+ // Dig out the module that owns the class definition.
+ auto module = classDef->getImportedOwningModule();
+ if (module) module = module->getTopLevelModule();
+
+ // Collect property names from all categories and extensions in the same
+ // module as the class.
+ for (auto category : classDef->known_categories()) {
+ auto categoryModule = category->getImportedOwningModule();
+ if (categoryModule) categoryModule = categoryModule->getTopLevelModule();
+ if (module != categoryModule) continue;
+
+ addProperties(category->decls());
+ }
+
+ return known->second.get();
+}
+
diff --git a/lib/ClangImporter/ImportName.h b/lib/ClangImporter/ImportName.h
index f993b02..b180f97 100644
--- a/lib/ClangImporter/ImportName.h
+++ b/lib/ClangImporter/ImportName.h
@@ -288,6 +288,11 @@
/// Cache for repeated calls
llvm::DenseMap<CacheKeyType, ImportedName> importNameCache;
+ /// The set of property names that show up in the defining module of
+ /// an Objective-C class.
+ llvm::DenseMap<std::pair<const clang::ObjCInterfaceDecl *, char>,
+ std::unique_ptr<InheritedNameSet>> allProperties;
+
public:
NameImporter(ASTContext &ctx, const PlatformAvailability &avail,
clang::Sema &cSema, bool inferIAM)
@@ -331,6 +336,11 @@
return getClangSema().getPreprocessor();
}
+ /// Retrieve the inherited name set for the given Objective-C class.
+ const InheritedNameSet *getAllPropertyNames(
+ clang::ObjCInterfaceDecl *classDecl,
+ bool forInstance);
+
private:
bool enableObjCInterop() const { return swiftCtx.LangOpts.EnableObjCInterop; }
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index a68dbf9..b40fe64 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -778,6 +778,9 @@
Ty = createNode(Node::Kind::BuiltinTypeName,
"Builtin.RawPointer");
break;
+ case 't':
+ Ty = createNode(Node::Kind::BuiltinTypeName, "Builtin.SILToken");
+ break;
case 'w':
Ty = createNode(Node::Kind::BuiltinTypeName,
"Builtin.Word");
@@ -1247,6 +1250,7 @@
NodePointer Demangler::demangleThunkOrSpecialization() {
switch (char c = nextChar()) {
case 'c': return createWithChild(Node::Kind::CurryThunk, popNode(isEntity));
+ case 'j': return createWithChild(Node::Kind::DispatchThunk, popNode(isEntity));
case 'o': return createNode(Node::Kind::ObjCAttribute);
case 'O': return createNode(Node::Kind::NonObjCAttribute);
case 'D': return createNode(Node::Kind::DynamicAttribute);
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index aff802b..957b2f0 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -294,6 +294,7 @@
case Node::Kind::CFunctionPointer:
case Node::Kind::Constructor:
case Node::Kind::CurryThunk:
+ case Node::Kind::DispatchThunk:
case Node::Kind::Deallocator:
case Node::Kind::DeclContext:
case Node::Kind::DefaultArgumentInitializer:
@@ -798,6 +799,10 @@
Printer << "curry thunk of ";
print(Node->getChild(0));
return nullptr;
+ case Node::Kind::DispatchThunk:
+ Printer << "dispatch thunk of ";
+ print(Node->getChild(0));
+ return nullptr;
case Node::Kind::OutlinedBridgedMethod:
Printer << "outlined bridged method (" << Node->getText() << ") of ";
return nullptr;
diff --git a/lib/Demangling/OldDemangler.cpp b/lib/Demangling/OldDemangler.cpp
index 20ce3f0..b661596 100644
--- a/lib/Demangling/OldDemangler.cpp
+++ b/lib/Demangling/OldDemangler.cpp
@@ -1848,6 +1848,9 @@
if (c == 'p')
return Factory.createNode(Node::Kind::BuiltinTypeName,
"Builtin.RawPointer");
+ if (c == 't')
+ return Factory.createNode(Node::Kind::BuiltinTypeName,
+ "Builtin.SILToken");
if (c == 'w')
return Factory.createNode(Node::Kind::BuiltinTypeName,
"Builtin.Word");
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 3666b43..73bd301 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -1668,6 +1668,10 @@
Out << "<curry-thunk>";
}
+void Remangler::mangleDispatchThunk(Node *node, EntityContext &ctx) {
+ Out << "<dispatch-thunk>";
+}
+
void Remangler::mangleEmptyList(Node *node) {
Out << "<empty>";
}
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 060cc24..146cdb5 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -579,6 +579,8 @@
Buffer << 'o';
} else if (text == "Builtin.RawPointer") {
Buffer << 'p';
+ } else if (text == "Builtin.SILToken") {
+ Buffer << 't';
} else if (text == "Builtin.Word") {
Buffer << 'w';
} else if (stripPrefix(text, "Builtin.Int")) {
@@ -1711,6 +1713,11 @@
Buffer << "Tc";
}
+void Remangler::mangleDispatchThunk(Node *node) {
+ mangleSingleChildNode(node);
+ Buffer << "Tj";
+}
+
void Remangler::mangleThrowsAnnotation(Node *node) {
Buffer << 'K';
}
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index c2a462d..50da198 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -934,7 +934,8 @@
(void)llvm::sys::fs::remove(pathPair.getKey());
}
}
-
+ if (Stats)
+ Stats->noteCurrentProcessExitStatus(result);
return result;
}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index a32e4d9..336feda 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1414,8 +1414,9 @@
}
case types::TY_SwiftModuleFile:
case types::TY_SwiftModuleDocFile:
- if (OI.ShouldGenerateModule) {
- // When generating a .swiftmodule, treat .swiftmodule files as
+ if (OI.ShouldGenerateModule && !OI.shouldLink()) {
+ // When generating a .swiftmodule as a top-level output (as opposed
+ // to, for example, linking an image), treat .swiftmodule files as
// inputs to a MergeModule action.
AllModuleInputs.push_back(Current);
break;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 8d88e15..2d1e878 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -229,44 +229,48 @@
Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
+ if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
+ Opts.VerifyGenericSignaturesInModule = A->getValue();
+ }
+
// Determine what the user has asked the frontend to do.
FrontendOptions::ActionType &Action = Opts.RequestedAction;
if (const Arg *A = Args.getLastArg(OPT_modes_Group)) {
Option Opt = A->getOption();
if (Opt.matches(OPT_emit_object)) {
- Action = FrontendOptions::EmitObject;
+ Action = FrontendOptions::ActionType::EmitObject;
} else if (Opt.matches(OPT_emit_assembly)) {
- Action = FrontendOptions::EmitAssembly;
+ Action = FrontendOptions::ActionType::EmitAssembly;
} else if (Opt.matches(OPT_emit_ir)) {
- Action = FrontendOptions::EmitIR;
+ Action = FrontendOptions::ActionType::EmitIR;
} else if (Opt.matches(OPT_emit_bc)) {
- Action = FrontendOptions::EmitBC;
+ Action = FrontendOptions::ActionType::EmitBC;
} else if (Opt.matches(OPT_emit_sil)) {
- Action = FrontendOptions::EmitSIL;
+ Action = FrontendOptions::ActionType::EmitSIL;
} else if (Opt.matches(OPT_emit_silgen)) {
- Action = FrontendOptions::EmitSILGen;
+ Action = FrontendOptions::ActionType::EmitSILGen;
} else if (Opt.matches(OPT_emit_sib)) {
- Action = FrontendOptions::EmitSIB;
+ Action = FrontendOptions::ActionType::EmitSIB;
} else if (Opt.matches(OPT_emit_sibgen)) {
- Action = FrontendOptions::EmitSIBGen;
+ Action = FrontendOptions::ActionType::EmitSIBGen;
} else if (Opt.matches(OPT_emit_pch)) {
- Action = FrontendOptions::EmitPCH;
+ Action = FrontendOptions::ActionType::EmitPCH;
} else if (Opt.matches(OPT_emit_imported_modules)) {
- Action = FrontendOptions::EmitImportedModules;
+ Action = FrontendOptions::ActionType::EmitImportedModules;
} else if (Opt.matches(OPT_parse)) {
- Action = FrontendOptions::Parse;
+ Action = FrontendOptions::ActionType::Parse;
} else if (Opt.matches(OPT_typecheck)) {
- Action = FrontendOptions::Typecheck;
+ Action = FrontendOptions::ActionType::Typecheck;
} else if (Opt.matches(OPT_dump_parse)) {
- Action = FrontendOptions::DumpParse;
+ Action = FrontendOptions::ActionType::DumpParse;
} else if (Opt.matches(OPT_dump_ast)) {
- Action = FrontendOptions::DumpAST;
+ Action = FrontendOptions::ActionType::DumpAST;
} else if (Opt.matches(OPT_emit_syntax)) {
- Action = FrontendOptions::EmitSyntax;
+ Action = FrontendOptions::ActionType::EmitSyntax;
} else if (Opt.matches(OPT_merge_modules)) {
- Action = FrontendOptions::MergeModules;
+ Action = FrontendOptions::ActionType::MergeModules;
} else if (Opt.matches(OPT_dump_scope_maps)) {
- Action = FrontendOptions::DumpScopeMaps;
+ Action = FrontendOptions::ActionType::DumpScopeMaps;
StringRef value = A->getValue();
if (value == "expanded") {
@@ -296,16 +300,16 @@
Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
}
} else if (Opt.matches(OPT_dump_type_refinement_contexts)) {
- Action = FrontendOptions::DumpTypeRefinementContexts;
+ Action = FrontendOptions::ActionType::DumpTypeRefinementContexts;
} else if (Opt.matches(OPT_dump_interface_hash)) {
- Action = FrontendOptions::DumpInterfaceHash;
+ Action = FrontendOptions::ActionType::DumpInterfaceHash;
} else if (Opt.matches(OPT_print_ast)) {
- Action = FrontendOptions::PrintAST;
+ Action = FrontendOptions::ActionType::PrintAST;
} else if (Opt.matches(OPT_repl) ||
Opt.matches(OPT_deprecated_integrated_repl)) {
- Action = FrontendOptions::REPL;
+ Action = FrontendOptions::ActionType::REPL;
} else if (Opt.matches(OPT_interpret)) {
- Action = FrontendOptions::Immediate;
+ Action = FrontendOptions::ActionType::Immediate;
} else {
llvm_unreachable("Unhandled mode option");
}
@@ -315,11 +319,11 @@
// We've been told to emit a module, but have no other mode indicators.
// As a result, put the frontend into EmitModuleOnly mode.
// (Setting up module output will be handled below.)
- Action = FrontendOptions::EmitModuleOnly;
+ Action = FrontendOptions::ActionType::EmitModuleOnly;
}
}
- if (Opts.RequestedAction == FrontendOptions::Immediate &&
+ if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
Opts.Inputs.hasPrimaryInput()) {
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
return true;
@@ -331,12 +335,13 @@
bool TreatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
if (Opts.Inputs.verifyInputs(
- Diags, TreatAsSIL, Opts.RequestedAction == FrontendOptions::REPL,
- Opts.RequestedAction == FrontendOptions::NoneAction)) {
+ Diags, TreatAsSIL,
+ Opts.RequestedAction == FrontendOptions::ActionType::REPL,
+ Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
return true;
}
- if (Opts.RequestedAction == FrontendOptions::Immediate) {
+ if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
Opts.ImmediateArgv.push_back(
Opts.Inputs.getFilenameOfFirstInput()); // argv[0]
if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
@@ -352,7 +357,7 @@
Opts.InputKind = InputFileKind::IFK_LLVM_IR;
else if (Args.hasArg(OPT_parse_as_library))
Opts.InputKind = InputFileKind::IFK_Swift_Library;
- else if (Action == FrontendOptions::REPL)
+ else if (Action == FrontendOptions::ActionType::REPL)
Opts.InputKind = InputFileKind::IFK_Swift_REPL;
else
Opts.InputKind = InputFileKind::IFK_Swift;
@@ -372,28 +377,28 @@
StringRef Suffix;
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
+ case FrontendOptions::ActionType::NoneAction:
break;
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
// Textual modes.
Opts.setOutputFilenameToStdout();
break;
- case FrontendOptions::EmitPCH:
+ case FrontendOptions::ActionType::EmitPCH:
Suffix = PCH_EXTENSION;
break;
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL: {
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL: {
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -401,23 +406,23 @@
break;
}
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
Suffix = SIB_EXTENSION;
break;
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
Suffix = SERIALIZED_MODULE_EXTENSION;
break;
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
// These modes have no frontend-generated output.
Opts.OutputFilenames.clear();
break;
- case FrontendOptions::EmitAssembly: {
+ case FrontendOptions::ActionType::EmitAssembly: {
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -425,7 +430,7 @@
break;
}
- case FrontendOptions::EmitIR: {
+ case FrontendOptions::ActionType::EmitIR: {
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -433,16 +438,16 @@
break;
}
- case FrontendOptions::EmitBC: {
+ case FrontendOptions::ActionType::EmitBC: {
Suffix = "bc";
break;
}
- case FrontendOptions::EmitObject:
+ case FrontendOptions::ActionType::EmitObject:
Suffix = "o";
break;
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::EmitImportedModules:
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -470,9 +475,9 @@
}
if (Opts.OutputFilenames.empty()) {
- if (Opts.RequestedAction != FrontendOptions::REPL &&
- Opts.RequestedAction != FrontendOptions::Immediate &&
- Opts.RequestedAction != FrontendOptions::NoneAction) {
+ if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
+ Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
+ Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
return true;
}
@@ -538,16 +543,16 @@
Opts.FixitsOutputPath = A->getValue();
}
- bool IsSIB =
- Opts.RequestedAction == FrontendOptions::EmitSIB ||
- Opts.RequestedAction == FrontendOptions::EmitSIBGen;
+ bool IsSIB = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB ||
+ Opts.RequestedAction == FrontendOptions::ActionType::EmitSIBGen;
bool canUseMainOutputForModule =
- Opts.RequestedAction == FrontendOptions::MergeModules ||
- Opts.RequestedAction == FrontendOptions::EmitModuleOnly ||
- IsSIB;
+ Opts.RequestedAction == FrontendOptions::ActionType::MergeModules ||
+ Opts.RequestedAction == FrontendOptions::ActionType::EmitModuleOnly ||
+ IsSIB;
auto ext = IsSIB ? SIB_EXTENSION : SERIALIZED_MODULE_EXTENSION;
- auto sibOpt = Opts.RequestedAction == FrontendOptions::EmitSIB ?
- OPT_emit_sib : OPT_emit_sibgen;
+ auto sibOpt = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB
+ ? OPT_emit_sib
+ : OPT_emit_sibgen;
determineOutputFilename(Opts.ModuleOutputPath,
IsSIB ? sibOpt : OPT_emit_module,
OPT_emit_module_path,
@@ -562,97 +567,97 @@
if (!Opts.DependenciesFilePath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_dependencies);
return true;
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
if (!Opts.ObjCHeaderOutputPath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
return true;
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
if (!Opts.LoadedModuleTracePath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::Parse:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
Diags.diagnose(SourceLoc(),
diag::error_mode_cannot_emit_loaded_module_trace);
return true;
- case FrontendOptions::Typecheck:
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
@@ -660,35 +665,35 @@
if (!Opts.ModuleOutputPath.empty() ||
!Opts.ModuleDocOutputPath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
if (!Opts.ModuleOutputPath.empty())
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
else
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
return true;
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
@@ -1165,8 +1170,7 @@
Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
A->getOption().getPrefixedName(), A->getValue());
}
- if (Opts.Optimization > SILOptions::SILOptMode::None
- && Opts.EnforceExclusivityDynamic) {
+ if (Opts.shouldOptimize() && Opts.EnforceExclusivityDynamic) {
Diags.diagnose(SourceLoc(),
diag::warning_argument_not_supported_with_optimization,
A->getOption().getPrefixedName() + A->getValue());
@@ -1225,40 +1229,31 @@
// Parse the optimization level.
// Default to Onone settings if no option is passed.
- IRGenOpts.Optimize = false;
- IRGenOpts.OptimizeForSize = false;
- Opts.Optimization = SILOptions::SILOptMode::None;
+ Opts.OptMode = OptimizationMode::NoOptimization;
if (const Arg *A = Args.getLastArg(OPT_O_Group)) {
if (A->getOption().matches(OPT_Onone)) {
// Already set.
} else if (A->getOption().matches(OPT_Ounchecked)) {
// Turn on optimizations and remove all runtime checks.
- IRGenOpts.Optimize = true;
- IRGenOpts.OptimizeForSize = false;
- Opts.Optimization = SILOptions::SILOptMode::OptimizeUnchecked;
+ Opts.OptMode = OptimizationMode::ForSpeed;
// Removal of cond_fail (overflow on binary operations).
Opts.RemoveRuntimeAsserts = true;
Opts.AssertConfig = SILOptions::Unchecked;
} else if (A->getOption().matches(OPT_Oplayground)) {
// For now -Oplayground is equivalent to -Onone.
- IRGenOpts.Optimize = false;
- IRGenOpts.OptimizeForSize = false;
- Opts.Optimization = SILOptions::SILOptMode::None;
+ Opts.OptMode = OptimizationMode::NoOptimization;
} else if (A->getOption().matches(OPT_Osize)) {
- IRGenOpts.Optimize = true;
- IRGenOpts.OptimizeForSize = true;
- Opts.Optimization = SILOptions::SILOptMode::OptimizeForSize;
+ Opts.OptMode = OptimizationMode::ForSize;
} else {
assert(A->getOption().matches(OPT_O));
- IRGenOpts.OptimizeForSize = false;
- IRGenOpts.Optimize = true;
- Opts.Optimization = SILOptions::SILOptMode::Optimize;
+ Opts.OptMode = OptimizationMode::ForSpeed;
}
- if (IRGenOpts.Optimize) {
+ if (Opts.shouldOptimize()) {
ClangOpts.Optimization = "-Os";
}
}
+ IRGenOpts.OptMode = Opts.OptMode;
if (Args.getLastArg(OPT_AssumeSingleThreaded)) {
Opts.AssumeSingleThreaded = true;
@@ -1288,7 +1283,7 @@
// Set the assert configuration according to the optimization level if it
// has not been set by the -Ounchecked flag.
Opts.AssertConfig =
- IRGenOpts.Optimize ? SILOptions::Release : SILOptions::Debug;
+ (IRGenOpts.shouldOptimize() ? SILOptions::Release : SILOptions::Debug);
}
// -Ounchecked might also set removal of runtime asserts (cond_fail).
@@ -1345,7 +1340,7 @@
IRGenOpts.Sanitizers = Opts.Sanitizers;
}
- if (Opts.Optimization > SILOptions::SILOptMode::None)
+ if (Opts.shouldOptimize())
Opts.EnforceExclusivityDynamic = false;
if (const Arg *A = Args.getLastArg(options::OPT_enforce_exclusivity_EQ)) {
parseExclusivityEnforcementOptions(A, Opts, Diags);
@@ -1703,3 +1698,39 @@
extendedInfo.getExtraClangImporterOptions().end());
return info.status;
}
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+CompilerInvocation::setUpInputForSILTool(
+ StringRef InputFilename, StringRef ModuleNameArg,
+ bool alwaysSetModuleToMain,
+ serialization::ExtendedValidationInfo &extendedInfo) {
+ // Load the input file.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
+ llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ if (!FileBufOrErr) {
+ return FileBufOrErr;
+ }
+
+ // If it looks like we have an AST, set the source file kind to SIL and the
+ // name of the module to the file's name.
+ addInputBuffer(FileBufOrErr.get().get());
+
+ auto result = serialization::validateSerializedAST(
+ FileBufOrErr.get()->getBuffer(), &extendedInfo);
+ bool HasSerializedAST = result.status == serialization::Status::Valid;
+
+ if (HasSerializedAST) {
+ const StringRef Stem = !ModuleNameArg.empty()
+ ? ModuleNameArg
+ : llvm::sys::path::stem(InputFilename);
+ setModuleName(Stem);
+ setInputKind(InputFileKind::IFK_Swift_Library);
+ } else {
+ const StringRef Name = (alwaysSetModuleToMain || ModuleNameArg.empty())
+ ? "main"
+ : ModuleNameArg;
+ setModuleName(Name);
+ setInputKind(InputFileKind::IFK_SIL);
+ }
+ return FileBufOrErr;
+}
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index ff1791c..344595c 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -257,14 +257,14 @@
if (Invocation.getImplicitModuleImportKind() !=
SourceFile::ImplicitModuleImportKind::Stdlib)
return false;
- SILOptions::SILOptMode optimization = Invocation.getSILOptions().Optimization;
- if (optimization <= SILOptions::SILOptMode::None &&
- shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization(
+ if (Invocation.getSILOptions().shouldOptimize())
+ return false;
+
+ if (shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization(
Invocation.getFrontendOptions().RequestedAction)) {
return true;
}
- return optimization == SILOptions::SILOptMode::None &&
- Invocation.getFrontendOptions().isCreatingSIL();
+ return Invocation.getFrontendOptions().isCreatingSIL();
}
void CompilerInstance::performSema() {
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index c9cbe96..8bdca8f 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -170,33 +170,33 @@
bool FrontendOptions::actionHasOutput() const {
switch (RequestedAction) {
- case NoneAction:
- case Parse:
- case Typecheck:
- case DumpParse:
- case DumpAST:
- case EmitSyntax:
- case DumpInterfaceHash:
- case PrintAST:
- case DumpScopeMaps:
- case DumpTypeRefinementContexts:
+ case ActionType::NoneAction:
+ case ActionType::Parse:
+ case ActionType::Typecheck:
+ case ActionType::DumpParse:
+ case ActionType::DumpAST:
+ case ActionType::EmitSyntax:
+ case ActionType::DumpInterfaceHash:
+ case ActionType::PrintAST:
+ case ActionType::DumpScopeMaps:
+ case ActionType::DumpTypeRefinementContexts:
return false;
- case EmitPCH:
- case EmitSILGen:
- case EmitSIL:
- case EmitSIBGen:
- case EmitSIB:
- case EmitModuleOnly:
- case MergeModules:
+ case ActionType::EmitPCH:
+ case ActionType::EmitSILGen:
+ case ActionType::EmitSIL:
+ case ActionType::EmitSIBGen:
+ case ActionType::EmitSIB:
+ case ActionType::EmitModuleOnly:
+ case ActionType::MergeModules:
return true;
- case Immediate:
- case REPL:
+ case ActionType::Immediate:
+ case ActionType::REPL:
return false;
- case EmitAssembly:
- case EmitIR:
- case EmitBC:
- case EmitObject:
- case EmitImportedModules:
+ case ActionType::EmitAssembly:
+ case ActionType::EmitIR:
+ case ActionType::EmitBC:
+ case ActionType::EmitObject:
+ case ActionType::EmitImportedModules:
return true;
}
llvm_unreachable("Unknown ActionType");
@@ -204,32 +204,32 @@
bool FrontendOptions::actionIsImmediate() const {
switch (RequestedAction) {
- case NoneAction:
- case Parse:
- case Typecheck:
- case DumpParse:
- case DumpAST:
- case EmitSyntax:
- case DumpInterfaceHash:
- case PrintAST:
- case DumpScopeMaps:
- case DumpTypeRefinementContexts:
- case EmitPCH:
- case EmitSILGen:
- case EmitSIL:
- case EmitSIBGen:
- case EmitSIB:
- case EmitModuleOnly:
- case MergeModules:
+ case ActionType::NoneAction:
+ case ActionType::Parse:
+ case ActionType::Typecheck:
+ case ActionType::DumpParse:
+ case ActionType::DumpAST:
+ case ActionType::EmitSyntax:
+ case ActionType::DumpInterfaceHash:
+ case ActionType::PrintAST:
+ case ActionType::DumpScopeMaps:
+ case ActionType::DumpTypeRefinementContexts:
+ case ActionType::EmitPCH:
+ case ActionType::EmitSILGen:
+ case ActionType::EmitSIL:
+ case ActionType::EmitSIBGen:
+ case ActionType::EmitSIB:
+ case ActionType::EmitModuleOnly:
+ case ActionType::MergeModules:
return false;
- case Immediate:
- case REPL:
+ case ActionType::Immediate:
+ case ActionType::REPL:
return true;
- case EmitAssembly:
- case EmitIR:
- case EmitBC:
- case EmitObject:
- case EmitImportedModules:
+ case ActionType::EmitAssembly:
+ case ActionType::EmitIR:
+ case ActionType::EmitBC:
+ case ActionType::EmitObject:
+ case ActionType::EmitImportedModules:
return false;
}
llvm_unreachable("Unknown ActionType");
@@ -237,8 +237,8 @@
void FrontendOptions::forAllOutputPaths(
std::function<void(const std::string &)> fn) const {
- if (RequestedAction != FrontendOptions::EmitModuleOnly &&
- RequestedAction != FrontendOptions::MergeModules) {
+ if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
+ RequestedAction != FrontendOptions::ActionType::MergeModules) {
for (const std::string &OutputFileName : OutputFilenames) {
fn(OutputFileName);
}
@@ -299,7 +299,7 @@
// Note: this code path will only be taken when running the frontend
// directly; the driver should always pass -module-name when invoking the
// frontend.
- if (RequestedAction == FrontendOptions::REPL) {
+ if (RequestedAction == FrontendOptions::ActionType::REPL) {
// Default to a module named "REPL" if we're in REPL mode.
return "REPL";
}
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index fba8441..d6acb03 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -30,6 +30,7 @@
#include "swift/AST/ASTScope.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/AST/DiagnosticsSema.h"
+#include "swift/AST/GenericSignatureBuilder.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/LegacyASTTransformer.h"
@@ -58,6 +59,7 @@
#include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/Syntax/Serialization/SyntaxSerialization.h"
+#include "swift/Syntax/SyntaxNodes.h"
// FIXME: We're just using CompilerInstance::createOutputFile.
// This API should be sunk down to LLVM.
@@ -255,38 +257,12 @@
assert(bufferID && "frontend should have a buffer ID "
"for the main source file");
- // Get a full token stream with associated Trivia.
- syntax::TokenPositionList tokens =
- tokenizeWithTrivia(LangOpts, SM, *bufferID);
-
- llvm::SmallVector<Decl *, 16> topLevelDecls;
- SF->getTopLevelDecls(topLevelDecls);
-
- // Convert the old ASTs to the Syntax tree and print
- // them out.
- SyntaxASTMap ASTMap;
- std::vector<RC<syntax::RawSyntax>> topLevelRaw;
- for (auto *decl : topLevelDecls) {
- if (decl->escapedFromIfConfig()) {
- continue;
- }
- auto newNode = transformAST(ASTNode(decl), ASTMap, SM, *bufferID, tokens);
- if (newNode.hasValue()) {
- topLevelRaw.push_back(newNode->getRaw());
- }
- }
-
- // Push the EOF token -- this ensures that any remaining trivia in the
- // file is serialized as the EOF's leading trivia.
- if (!tokens.empty() && tokens.back().first->getTokenKind() == tok::eof) {
- topLevelRaw.push_back(tokens.back().first);
- }
-
auto os = getFileOutputStream(OutputFilename, SF->getASTContext());
if (!os) return true;
json::Output jsonOut(*os);
- jsonOut << topLevelRaw;
+ auto Root = SF->getSyntaxRoot().getRaw();
+ jsonOut << Root;
*os << "\n";
return false;
}
@@ -343,15 +319,15 @@
/// Returns the OutputKind for the given Action.
static IRGenOutputKind getOutputKind(FrontendOptions::ActionType Action) {
switch (Action) {
- case FrontendOptions::EmitIR:
+ case FrontendOptions::ActionType::EmitIR:
return IRGenOutputKind::LLVMAssembly;
- case FrontendOptions::EmitBC:
+ case FrontendOptions::ActionType::EmitBC:
return IRGenOutputKind::LLVMBitcode;
- case FrontendOptions::EmitAssembly:
+ case FrontendOptions::ActionType::EmitAssembly:
return IRGenOutputKind::NativeAssembly;
- case FrontendOptions::EmitObject:
+ case FrontendOptions::ActionType::EmitObject:
return IRGenOutputKind::ObjectFile;
- case FrontendOptions::Immediate:
+ case FrontendOptions::ActionType::Immediate:
return IRGenOutputKind::Module;
default:
llvm_unreachable("Unknown ActionType which requires IRGen");
@@ -536,9 +512,12 @@
FrontendOptions opts = Invocation.getFrontendOptions();
FrontendOptions::ActionType Action = opts.RequestedAction;
+ if (Action == FrontendOptions::ActionType::EmitSyntax)
+ Instance.getASTContext().LangOpts.KeepSyntaxInfoInSourceFile = true;
+
// We've been asked to precompile a bridging header; we want to
// avoid touching any other inputs and just parse, emit and exit.
- if (Action == FrontendOptions::EmitPCH) {
+ if (Action == FrontendOptions::ActionType::EmitPCH) {
auto clangImporter = static_cast<ClangImporter *>(
Instance.getASTContext().getClangModuleLoader());
auto &ImporterOpts = Invocation.getClangImporterOptions();
@@ -602,16 +581,16 @@
if (shouldTrackReferences)
Instance.setReferencedNameTracker(&nameTracker);
- if (Action == FrontendOptions::Parse ||
- Action == FrontendOptions::DumpParse ||
- Action == FrontendOptions::EmitSyntax ||
- Action == FrontendOptions::DumpInterfaceHash ||
- Action == FrontendOptions::EmitImportedModules)
+ if (Action == FrontendOptions::ActionType::Parse ||
+ Action == FrontendOptions::ActionType::DumpParse ||
+ Action == FrontendOptions::ActionType::EmitSyntax ||
+ Action == FrontendOptions::ActionType::DumpInterfaceHash ||
+ Action == FrontendOptions::ActionType::EmitImportedModules)
Instance.performParseOnly();
else
Instance.performSema();
- if (Action == FrontendOptions::Parse)
+ if (Action == FrontendOptions::ActionType::Parse)
return Instance.getASTContext().hadError();
if (observer) {
@@ -630,11 +609,19 @@
ASTContext &Context = Instance.getASTContext();
+
+ auto verifyGenericSignaturesInModule =
+ Invocation.getFrontendOptions().VerifyGenericSignaturesInModule;
+ if (!verifyGenericSignaturesInModule.empty()) {
+ if (auto module = Context.getModuleByName(verifyGenericSignaturesInModule))
+ GenericSignatureBuilder::verifyGenericSignaturesInModule(module);
+ }
+
if (Invocation.getMigratorOptions().shouldRunMigrator()) {
migrator::updateCodeAndEmitRemap(&Instance, Invocation);
}
- if (Action == FrontendOptions::REPL) {
+ if (Action == FrontendOptions::ActionType::REPL) {
runREPL(Instance, ProcessCmdLine(Args.begin(), Args.end()),
Invocation.getParseStdlib());
return Context.hadError();
@@ -645,21 +632,21 @@
// We've been told to dump the AST (either after parsing or type-checking,
// which is already differentiated in CompilerInstance::performSema()),
// so dump or print the main source file and return.
- if (Action == FrontendOptions::DumpParse ||
- Action == FrontendOptions::DumpAST ||
- Action == FrontendOptions::EmitSyntax ||
- Action == FrontendOptions::PrintAST ||
- Action == FrontendOptions::DumpScopeMaps ||
- Action == FrontendOptions::DumpTypeRefinementContexts ||
- Action == FrontendOptions::DumpInterfaceHash) {
+ if (Action == FrontendOptions::ActionType::DumpParse ||
+ Action == FrontendOptions::ActionType::DumpAST ||
+ Action == FrontendOptions::ActionType::EmitSyntax ||
+ Action == FrontendOptions::ActionType::PrintAST ||
+ Action == FrontendOptions::ActionType::DumpScopeMaps ||
+ Action == FrontendOptions::ActionType::DumpTypeRefinementContexts ||
+ Action == FrontendOptions::ActionType::DumpInterfaceHash) {
SourceFile *SF = PrimarySourceFile;
if (!SF) {
SourceFileKind Kind = Invocation.getSourceFileKind();
SF = &Instance.getMainModule()->getMainSourceFile(Kind);
}
- if (Action == FrontendOptions::PrintAST)
+ if (Action == FrontendOptions::ActionType::PrintAST)
SF->print(llvm::outs(), PrintOptions::printEverything());
- else if (Action == FrontendOptions::DumpScopeMaps) {
+ else if (Action == FrontendOptions::ActionType::DumpScopeMaps) {
ASTScope &scope = SF->getScope();
if (opts.DumpScopeMapLocations.empty()) {
@@ -703,17 +690,18 @@
// Print the resulting map.
scope.print(llvm::errs());
- } else if (Action == FrontendOptions::DumpTypeRefinementContexts)
+ } else if (Action ==
+ FrontendOptions::ActionType::DumpTypeRefinementContexts)
SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr);
- else if (Action == FrontendOptions::DumpInterfaceHash)
+ else if (Action == FrontendOptions::ActionType::DumpInterfaceHash)
SF->dumpInterfaceHash(llvm::errs());
- else if (Action == FrontendOptions::EmitSyntax) {
+ else if (Action == FrontendOptions::ActionType::EmitSyntax) {
emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
opts.getSingleOutputFilename());
} else
SF->dump();
return Context.hadError();
- } else if (Action == FrontendOptions::EmitImportedModules) {
+ } else if (Action == FrontendOptions::ActionType::EmitImportedModules) {
emitImportedModules(Context, Instance.getMainModule(), opts);
return Context.hadError();
}
@@ -753,7 +741,7 @@
!Context.LangOpts.EnableAppExtensionRestrictions;
// We've just been told to perform a typecheck, so we can return now.
- if (Action == FrontendOptions::Typecheck) {
+ if (Action == FrontendOptions::ActionType::Typecheck) {
if (!opts.ObjCHeaderOutputPath.empty())
return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
opts.ImplicitObjCHeaderPath, moduleIsPublic);
@@ -776,7 +764,7 @@
return true;
}
- assert(Action >= FrontendOptions::EmitSILGen &&
+ assert(Action >= FrontendOptions::ActionType::EmitSILGen &&
"All actions not requiring SILGen must have been handled!");
std::unique_ptr<SILModule> SM = Instance.takeSILModule();
@@ -815,7 +803,7 @@
}
// We've been told to emit SIL after SILGen, so write it now.
- if (Action == FrontendOptions::EmitSILGen) {
+ if (Action == FrontendOptions::ActionType::EmitSILGen) {
// If we are asked to link all, link all.
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
performSILLinking(SM.get(), true);
@@ -823,7 +811,7 @@
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
}
- if (Action == FrontendOptions::EmitSIBGen) {
+ if (Action == FrontendOptions::ActionType::EmitSIBGen) {
// If we are asked to link all, link all.
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
performSILLinking(SM.get(), true);
@@ -849,7 +837,7 @@
std::move(OptRecordFile));
// Perform "stable" optimizations that are invariant across compiler versions.
- if (Action == FrontendOptions::MergeModules) {
+ if (Action == FrontendOptions::ActionType::MergeModules) {
// Don't run diagnostic passes at all.
} else if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses) {
if (runSILDiagnosticPasses(*SM))
@@ -921,9 +909,8 @@
// These may change across compiler versions.
{
SharedTimer timer("SIL optimization");
- if (Action != FrontendOptions::MergeModules &&
- Invocation.getSILOptions().Optimization >
- SILOptions::SILOptMode::None) {
+ if (Action != FrontendOptions::ActionType::MergeModules &&
+ Invocation.getSILOptions().shouldOptimize()) {
runSILOptPreparePasses(*SM);
@@ -969,7 +956,7 @@
opts.ImplicitObjCHeaderPath, moduleIsPublic);
}
- if (Action == FrontendOptions::EmitSIB) {
+ if (Action == FrontendOptions::ActionType::EmitSIB) {
auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
Instance.getMainModule();
if (!opts.ModuleOutputPath.empty()) {
@@ -987,8 +974,8 @@
// Serialize the SILModule if it was not serialized yet.
if (!SM.get()->isSerialized())
SM.get()->serialize();
- if (Action == FrontendOptions::MergeModules ||
- Action == FrontendOptions::EmitModuleOnly) {
+ if (Action == FrontendOptions::ActionType::MergeModules ||
+ Action == FrontendOptions::ActionType::EmitModuleOnly) {
if (shouldIndex) {
if (emitIndexData(PrimarySourceFile, Invocation, Instance))
return true;
@@ -997,18 +984,18 @@
}
}
- assert(Action >= FrontendOptions::EmitSIL &&
+ assert(Action >= FrontendOptions::ActionType::EmitSIL &&
"All actions not requiring SILPasses must have been handled!");
// We've been told to write canonical SIL, so write it now.
- if (Action == FrontendOptions::EmitSIL) {
+ if (Action == FrontendOptions::ActionType::EmitSIL) {
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
}
- assert(Action >= FrontendOptions::Immediate &&
+ assert(Action >= FrontendOptions::ActionType::Immediate &&
"All actions not requiring IRGen must have been handled!");
- assert(Action != FrontendOptions::REPL &&
+ assert(Action != FrontendOptions::ActionType::REPL &&
"REPL mode must be handled immediately after Instance->performSema()");
// Check if we had any errors; if we did, don't proceed to IRGen.
@@ -1020,7 +1007,7 @@
// TODO: remove once the frontend understands what action it should perform
IRGenOpts.OutputKind = getOutputKind(Action);
- if (Action == FrontendOptions::Immediate) {
+ if (Action == FrontendOptions::ActionType::Immediate) {
assert(!PrimarySourceFile && "-i doesn't work in -primary-file mode");
IRGenOpts.UseJIT = true;
IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal;
@@ -1122,15 +1109,13 @@
// paths as a fallback.
bool isDebugCompilation;
- switch (Invocation.getSILOptions().Optimization) {
- case SILOptions::SILOptMode::NotSet:
- case SILOptions::SILOptMode::None:
- case SILOptions::SILOptMode::Debug:
+ switch (Invocation.getSILOptions().OptMode) {
+ case OptimizationMode::NotSet:
+ case OptimizationMode::NoOptimization:
isDebugCompilation = true;
break;
- case SILOptions::SILOptMode::Optimize:
- case SILOptions::SILOptMode::OptimizeForSize:
- case SILOptions::SILOptMode::OptimizeUnchecked:
+ case OptimizationMode::ForSpeed:
+ case OptimizationMode::ForSize:
isDebugCompilation = false;
break;
}
@@ -1223,13 +1208,11 @@
}
static StringRef
-silOptModeArgStr(SILOptions::SILOptMode mode) {
+silOptModeArgStr(OptimizationMode mode) {
switch (mode) {
- case SILOptions::SILOptMode::Optimize:
+ case OptimizationMode::ForSpeed:
return "O";
- case SILOptions::SILOptMode::OptimizeUnchecked:
- return "Ounchecked";
- case SILOptions::SILOptMode::OptimizeForSize:
+ case OptimizationMode::ForSize:
return "Osize";
default:
return "Onone";
@@ -1339,7 +1322,7 @@
}
if (Invocation.getFrontendOptions().RequestedAction ==
- FrontendOptions::NoneAction) {
+ FrontendOptions::ActionType::NoneAction) {
Instance->getDiags().diagnose(SourceLoc(),
diag::error_missing_frontend_action);
return finishDiagProcessing(1);
@@ -1391,7 +1374,7 @@
auto &LangOpts = Invocation.getLangOptions();
auto &SILOpts = Invocation.getSILOptions();
StringRef InputName = FEOpts.Inputs.primaryInputFilenameIfAny();
- StringRef OptType = silOptModeArgStr(SILOpts.Optimization);
+ StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
StringRef OutFile = FEOpts.getSingleOutputFilename();
StringRef OutputType = llvm::sys::path::extension(OutFile);
std::string TripleName = LangOpts.Target.normalize();
@@ -1467,7 +1450,10 @@
}
}
- return finishDiagProcessing(HadError ? 1 : ReturnValue);
+ auto r = finishDiagProcessing(HadError ? 1 : ReturnValue);
+ if (StatsReporter)
+ StatsReporter->noteCurrentProcessExitStatus(r);
+ return r;
}
void FrontendObserver::parsedArgs(CompilerInvocation &invocation) {}
diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt
index 90ec65a..e93742f 100644
--- a/lib/IDE/CMakeLists.txt
+++ b/lib/IDE/CMakeLists.txt
@@ -12,6 +12,7 @@
Utils.cpp
IDETypeChecking.cpp
APIDigesterData.cpp
+ SourceEntityWalker.cpp
DEPENDS
swift-syntax-generated-headers
LINK_LIBRARIES
diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp
index 8a9c6e7..5b0059e 100644
--- a/lib/IDE/Formatting.cpp
+++ b/lib/IDE/Formatting.cpp
@@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTWalker.h"
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Parser.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Basic/SourceManager.h"
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index aa49de2..b61ca6d 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -819,7 +819,7 @@
// We cannot extract expressions of l-value type.
if (auto Ty = RangeInfo.getType()) {
- if (Ty->hasLValueType() || Ty->getKind() == TypeKind::InOut)
+ if (Ty->hasLValueType() || Ty->is<InOutType>())
return ExtractCheckResult();
// Disallow extracting error type expressions/statements
@@ -886,6 +886,7 @@
switch (Info.Kind) {
case RangeKind::PartOfExpression:
case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl:
case RangeKind::Invalid:
return false;
case RangeKind::SingleExpression:
@@ -940,7 +941,7 @@
static Type sanitizeType(Type Ty) {
// Transform lvalue type to inout type so that we can print it properly.
return Ty.transform([](Type Ty) {
- if (Ty->getKind() == TypeKind::LValue) {
+ if (Ty->is<LValueType>()) {
return Type(InOutType::get(Ty->getRValueType()->getCanonicalType()));
}
return Ty;
@@ -1162,7 +1163,7 @@
for (auto &RD : Parameters) {
// Inout argument needs "&".
- if (RD.Ty->getKind() == TypeKind::InOut)
+ if (RD.Ty->is<InOutType>())
OS << "&";
OS << RD.VD->getBaseName().userFacingName();
if (&RD != &Parameters.back())
@@ -1420,6 +1421,7 @@
return checkExtractConditions(Info, Diag).success();
case RangeKind::PartOfExpression:
case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl:
case RangeKind::SingleStatement:
case RangeKind::MultiStatement:
case RangeKind::Invalid:
@@ -1441,6 +1443,7 @@
success({CannotExtractReason::Literal});
case RangeKind::PartOfExpression:
case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl:
case RangeKind::SingleStatement:
case RangeKind::MultiStatement:
case RangeKind::Invalid:
@@ -1453,6 +1456,82 @@
EditConsumer).performChange();
}
+// Compute a decl context that is the parent context for all decls in
+// \c DeclaredDecls. Return \c nullptr if no such context exists.
+DeclContext *getCommonDeclContext(ArrayRef<DeclaredDecl> DeclaredDecls) {
+ if (DeclaredDecls.empty())
+ return nullptr;
+
+ DeclContext *CommonDC = DeclaredDecls.front().VD->getDeclContext();
+ for (auto DD : DeclaredDecls) {
+ auto OtherDC = DD.VD->getDeclContext();
+ CommonDC = DeclContext::getCommonParentContext(CommonDC, OtherDC);
+ }
+ return CommonDC;
+}
+
+bool RefactoringActionMoveMembersToExtension::isApplicable(
+ ResolvedRangeInfo Info, DiagnosticEngine &Diag) {
+ switch (Info.Kind) {
+ case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl: {
+ DeclContext *CommonDC = getCommonDeclContext(Info.DeclaredDecls);
+
+ // The the common decl context is not a nomial type, we cannot create an
+ // extension for it
+ if (!CommonDC || !CommonDC->getInnermostDeclarationDeclContext() ||
+ !isa<NominalTypeDecl>(CommonDC->getInnermostDeclarationDeclContext()))
+ return false;
+
+ // Members of types not declared at top file level cannot be extracted
+ // to an extension at top file level
+ if (CommonDC->getParent()->getContextKind() != DeclContextKind::FileUnit)
+ return false;
+
+ // We should not move instance variables with storage into the extension
+ // because they are not allowed to be declared there
+ for (auto DD : Info.DeclaredDecls) {
+ if (auto ASD = dyn_cast<AbstractStorageDecl>(DD.VD)) {
+ // Only disallow storages in the common decl context, allow them in
+ // any subtypes
+ if (ASD->hasStorage() && ASD->getDeclContext() == CommonDC) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ case RangeKind::SingleExpression:
+ case RangeKind::PartOfExpression:
+ case RangeKind::SingleStatement:
+ case RangeKind::MultiStatement:
+ case RangeKind::Invalid:
+ return false;
+ }
+}
+
+bool RefactoringActionMoveMembersToExtension::performChange() {
+ DeclContext *CommonDC = getCommonDeclContext(RangeInfo.DeclaredDecls);
+
+ auto CommonTypeDecl =
+ dyn_cast<NominalTypeDecl>(CommonDC->getInnermostDeclarationDeclContext());
+ assert(CommonTypeDecl && "Not applicable if common parent is no nomial type");
+
+ SmallString<64> Buffer;
+ llvm::raw_svector_ostream OS(Buffer);
+ OS << "\n\n";
+ OS << "extension " << CommonTypeDecl->getName() << " {\n";
+ OS << RangeInfo.ContentRange.str().trim();
+ OS << "\n}";
+
+ // Insert extension after the type declaration
+ EditConsumer.insertAfter(SM, CommonTypeDecl->getEndLoc(), Buffer);
+ EditConsumer.remove(SM, RangeInfo.ContentRange);
+
+ return false;
+}
+
struct CollapsibleNestedIfInfo {
IfStmt *OuterIf;
IfStmt *InnerIf;
@@ -2268,6 +2347,7 @@
return false;
}
case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl:
case RangeKind::SingleStatement:
case RangeKind::MultiStatement:
case RangeKind::Invalid:
diff --git a/lib/AST/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp
similarity index 94%
rename from lib/AST/SourceEntityWalker.cpp
rename to lib/IDE/SourceEntityWalker.cpp
index 7b04710..6622bb9 100644
--- a/lib/AST/SourceEntityWalker.cpp
+++ b/lib/IDE/SourceEntityWalker.cpp
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Lexer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
@@ -65,7 +65,9 @@
bool passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data);
bool passReference(ModuleEntity Mod, std::pair<Identifier, SourceLoc> IdLoc);
- bool passSubscriptReference(ValueDecl *D, SourceLoc Loc, bool IsOpenBracket);
+ bool passSubscriptReference(ValueDecl *D, SourceLoc Loc,
+ Optional<AccessKind> AccKind,
+ bool IsOpenBracket);
bool passCallArgNames(Expr *Fn, TupleExpr *TupleE);
@@ -297,7 +299,7 @@
SubscrD = SE->getDecl().getDecl();
if (SubscrD) {
- if (!passSubscriptReference(SubscrD, E->getLoc(), true))
+ if (!passSubscriptReference(SubscrD, E->getLoc(), OpAccess, true))
return { false, nullptr };
}
@@ -305,7 +307,7 @@
return { false, nullptr };
if (SubscrD) {
- if (!passSubscriptReference(SubscrD, E->getEndLoc(), false))
+ if (!passSubscriptReference(SubscrD, E->getEndLoc(), OpAccess, false))
return { false, nullptr };
}
@@ -434,12 +436,14 @@
}
bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) {
CharSourceRange Range = Loc.isValid()
? CharSourceRange(Loc, 1)
: CharSourceRange();
- bool Continue = SEWalker.visitSubscriptReference(D, Range, IsOpenBracket);
+ bool Continue = SEWalker.visitSubscriptReference(D, Range, AccKind,
+ IsOpenBracket);
if (!Continue)
Cancelled = true;
return Continue;
@@ -556,6 +560,17 @@
return DC->walkContext(Annotator);
}
+bool SourceEntityWalker::walk(ASTNode N) {
+ if (auto *E = N.dyn_cast<Expr*>())
+ return walk(E);
+ if (auto *S = N.dyn_cast<Stmt*>())
+ return walk(S);
+ if (auto *D = N.dyn_cast<Decl*>())
+ return walk(D);
+
+ llvm_unreachable("unsupported AST node");
+}
+
bool SourceEntityWalker::visitDeclReference(ValueDecl *D, CharSourceRange Range,
TypeDecl *CtorTyRef,
ExtensionDecl *ExtTyRef, Type T,
@@ -565,12 +580,13 @@
bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D,
CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) {
// Most of the clients treat subscript reference the same way as a
// regular reference when called on the open bracket and
// ignore the closing one.
return IsOpenBracket ? visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None)) : true;
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind)) : true;
}
bool SourceEntityWalker::visitCallArgName(Identifier Name,
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index 1848863..717e0c0 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -111,10 +111,11 @@
}
bool CursorInfoResolver::visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
- bool IsOpenBracket) {
+ Optional<AccessKind> AccKind,
+ bool IsOpenBracket) {
// We should treat both open and close brackets equally
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
ResolvedCursorInfo CursorInfoResolver::resolve(SourceLoc Loc) {
@@ -698,6 +699,7 @@
switch (Kind) {
case RangeKind::SingleExpression: OS << "SingleExpression"; break;
case RangeKind::SingleDecl: OS << "SingleDecl"; break;
+ case RangeKind::MultiTypeMemberDecl: OS << "MultiTypeMemberDecl"; break;
case RangeKind::MultiStatement: OS << "MultiStatement"; break;
case RangeKind::PartOfExpression: OS << "PartOfExpression"; break;
case RangeKind::SingleStatement: OS << "SingleStatement"; break;
@@ -824,7 +826,7 @@
return Nodes.end() != std::find_if(Nodes.begin(), Nodes.end(), [](ASTNode N) {
ThrowingEntityAnalyzer Analyzer;
- N.walk(Analyzer);
+ Analyzer.walk(N);
return Analyzer.isThrowing();
});
}
@@ -883,6 +885,17 @@
return llvm::any_of(StartMatches, IsCase) &&
llvm::any_of(EndMatches, IsCase);
}
+
+ bool isMultiTypeMemberDecl() {
+ if (StartMatches.empty() || EndMatches.empty())
+ return false;
+
+ // Multi-decls should have the same nominal type as a common parent
+ if (auto ParentDecl = Parent.dyn_cast<Decl *>())
+ return isa<NominalTypeDecl>(ParentDecl);
+
+ return false;
+ }
};
@@ -911,6 +924,7 @@
switch(Kind) {
case RangeKind::Invalid:
case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl:
case RangeKind::PartOfExpression:
llvm_unreachable("cannot get type.");
@@ -1181,7 +1195,7 @@
void postAnalysis(ASTNode EndNode) {
// Visit the content of this node thoroughly, because the walker may
// abort early.
- EndNode.walk(CompleteWalker(this));
+ CompleteWalker(this).walk(EndNode);
// Analyze whether declared decls in the range is referenced outside of it.
FurtherReferenceWalker(this).walk(getImmediateContext());
@@ -1227,7 +1241,7 @@
};
for (auto N : Nodes) {
ControlFlowStmtSelector TheWalker;
- N.walk(TheWalker);
+ TheWalker.walk(N);
for (auto Pair : TheWalker.Ranges) {
// If the entire range does not include the target's range, we find
@@ -1247,7 +1261,15 @@
Decl *D = Node.is<Decl*>() ? Node.get<Decl*>() : nullptr;
analyzeDecl(D);
auto &DCInfo = getCurrentDC();
- switch (getRangeMatchKind(Node.getSourceRange())) {
+
+ auto NodeRange = Node.getSourceRange();
+
+ // Widen the node's source range to include all attributes to get a range
+ // match if a function with its attributes has been selected.
+ if (auto D = Node.dyn_cast<Decl *>())
+ NodeRange = D->getSourceRangeIncludingAttrs();
+
+ switch (getRangeMatchKind(NodeRange)) {
case RangeMatchKind::NoneMatch: {
// PatternBindingDecl is not visited; we need to explicitly analyze here.
if (auto *VA = dyn_cast_or_null<VarDecl>(D))
@@ -1294,6 +1316,21 @@
llvm::makeArrayRef(DeclaredDecls),
llvm::makeArrayRef(ReferencedDecls)};
}
+
+ if (DCInfo.isMultiTypeMemberDecl()) {
+ postAnalysis(DCInfo.EndMatches.back());
+ Result = {RangeKind::MultiTypeMemberDecl,
+ ReturnInfo(),
+ TokensInRange,
+ getImmediateContext(),
+ /*Common Parent Expr*/ nullptr,
+ /*SinleEntry*/ true,
+ hasUnhandledError(ContainedASTNodes),
+ getOrphanKind(ContainedASTNodes),
+ llvm::makeArrayRef(ContainedASTNodes),
+ llvm::makeArrayRef(DeclaredDecls),
+ llvm::makeArrayRef(ReferencedDecls)};
+ }
}
bool shouldEnter(ASTNode Node) {
diff --git a/lib/IRGen/Fulfillment.cpp b/lib/IRGen/Fulfillment.cpp
index 739b4f5..ec1f0d2 100644
--- a/lib/IRGen/Fulfillment.cpp
+++ b/lib/IRGen/Fulfillment.cpp
@@ -18,11 +18,13 @@
#include "Fulfillment.h"
#include "IRGenModule.h"
-#include "swift/AST/Decl.h"
-#include "swift/AST/SubstitutionMap.h"
-#include "swift/SIL/TypeLowering.h"
#include "GenericRequirement.h"
#include "ProtocolInfo.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/ProtocolConformance.h"
+#include "swift/AST/SubstitutionMap.h"
+#include "swift/SIL/SILWitnessTable.h"
+#include "swift/SIL/TypeLowering.h"
using namespace swift;
using namespace irgen;
@@ -145,18 +147,38 @@
return false;
}
-/// Given that we have a source for a witness table that the given type
-/// conforms to the given protocol, check to see if it fulfills anything.
+bool FulfillmentMap::searchConformance(
+ IRGenModule &IGM, const ProtocolConformance *conformance,
+ unsigned sourceIndex, MetadataPath &&path,
+ const InterestingKeysCallback &interestingKeys) {
+ bool hadFulfillment = false;
+
+ SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ conformance, [&](unsigned index, CanType type, ProtocolDecl *protocol) {
+ MetadataPath conditionalPath = path;
+ conditionalPath.addConditionalConformanceComponent(index);
+ hadFulfillment |=
+ searchWitnessTable(IGM, type, protocol, sourceIndex,
+ std::move(conditionalPath), interestingKeys);
+
+ return /*finished?*/ false;
+ });
+
+ return hadFulfillment;
+}
+
bool FulfillmentMap::searchWitnessTable(IRGenModule &IGM,
CanType type, ProtocolDecl *protocol,
unsigned source, MetadataPath &&path,
const InterestingKeysCallback &keys) {
+ assert(Lowering::TypeConverter::protocolRequiresWitnessTable(protocol));
+
llvm::SmallPtrSet<ProtocolDecl*, 4> interestingConformancesBuffer;
- llvm::SmallPtrSetImpl<ProtocolDecl*> *interestingConformances = nullptr;
+ llvm::SmallPtrSetImpl<ProtocolDecl *> *interestingConformances = nullptr;
// If the interesting-keys set is limiting the set of interesting
// conformances, collect that filter.
- if (keys.isInterestingType(type) &&
+ if (keys.hasInterestingType(type) &&
keys.hasLimitedInterestingConformances(type)) {
// Bail out immediately if the set is empty.
// This only makes sense because we're not trying to fulfill
@@ -173,13 +195,10 @@
interestingConformances);
}
-bool FulfillmentMap::searchWitnessTable(IRGenModule &IGM,
- CanType type, ProtocolDecl *protocol,
- unsigned source, MetadataPath &&path,
- const InterestingKeysCallback &keys,
- const llvm::SmallPtrSetImpl<ProtocolDecl*> *
- interestingConformances) {
- assert(Lowering::TypeConverter::protocolRequiresWitnessTable(protocol));
+bool FulfillmentMap::searchWitnessTable(
+ IRGenModule &IGM, CanType type, ProtocolDecl *protocol, unsigned source,
+ MetadataPath &&path, const InterestingKeysCallback &keys,
+ llvm::SmallPtrSetImpl<ProtocolDecl *> *interestingConformances) {
bool hadFulfillment = false;
@@ -252,24 +271,8 @@
MetadataPath argPath = path;
argPath.addNominalTypeArgumentConformanceComponent(reqtIndex);
- llvm::SmallPtrSet<ProtocolDecl*, 4> interestingConformancesBuffer;
- llvm::SmallPtrSetImpl<ProtocolDecl*> *interestingConformances = nullptr;
-
- // If the interesting-keys set is limiting the set of interesting
- // conformances, collect that filter.
- if (keys.hasLimitedInterestingConformances(arg)) {
- // Bail out immediately if the set is empty.
- auto requiredConformances = keys.getInterestingConformances(arg);
- if (requiredConformances.empty()) return;
-
- interestingConformancesBuffer.insert(requiredConformances.begin(),
- requiredConformances.end());
- interestingConformances = &interestingConformancesBuffer;
- }
-
- hadFulfillment |=
- searchWitnessTable(IGM, arg, conf->getRequirement(), source,
- std::move(argPath), keys, interestingConformances);
+ hadFulfillment |= searchWitnessTable(IGM, arg, conf->getRequirement(),
+ source, std::move(argPath), keys);
});
return hadFulfillment;
diff --git a/lib/IRGen/Fulfillment.h b/lib/IRGen/Fulfillment.h
index 65737b6..73525d3 100644
--- a/lib/IRGen/Fulfillment.h
+++ b/lib/IRGen/Fulfillment.h
@@ -93,6 +93,11 @@
unsigned sourceIndex, MetadataPath &&path,
const InterestingKeysCallback &interestingKeys);
+ bool searchConformance(IRGenModule &IGM,
+ const ProtocolConformance *conformance,
+ unsigned sourceIndex, MetadataPath &&path,
+ const InterestingKeysCallback &interestingKeys);
+
/// Search the given witness table for useful fulfillments.
///
/// \return true if any fulfillments were added by this search.
@@ -140,12 +145,10 @@
/// Search the given witness table for useful fulfillments.
///
/// \return true if any fulfillments were added by this search.
- bool searchWitnessTable(IRGenModule &IGM, CanType type, ProtocolDecl *protocol,
- unsigned sourceIndex, MetadataPath &&path,
- const InterestingKeysCallback &interestingKeys,
- const llvm::SmallPtrSetImpl<ProtocolDecl*> *
- interestingConformances);
-
+ bool searchWitnessTable(
+ IRGenModule &IGM, CanType type, ProtocolDecl *protocol, unsigned source,
+ MetadataPath &&path, const InterestingKeysCallback &keys,
+ llvm::SmallPtrSetImpl<ProtocolDecl *> *interestingConformances);
};
}
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 5e5e9b2..0ddde22 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -73,7 +73,7 @@
bool IRGenerator::tryEnableLazyTypeMetadata(NominalTypeDecl *Nominal) {
// When compiling with -Onone keep all metadata for the debugger. Even if it
// is not used by the program itself.
- if (!Opts.Optimize)
+ if (!Opts.shouldOptimize())
return false;
switch (Nominal->getKind()) {
@@ -1329,7 +1329,7 @@
llvm::GlobalValue::VisibilityTypes,
llvm::GlobalValue::DLLStorageClassTypes>
getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
- bool isSILOnly, ForDefinition_t isDefinition,
+ ForDefinition_t isDefinition,
bool isWeakImported) {
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
std::make_tuple(llvm::GlobalValue::LINKAGE##Linkage, \
@@ -1352,19 +1352,6 @@
switch (linkage) {
case SILLinkage::Public:
- // Don't code-gen transparent functions. Internal linkage will enable llvm
- // to delete transparent functions except they are referenced from somewhere
- // (i.e. the function pointer is taken).
- //
- // In case we are generating multiple LLVM modules, we still have to use
- // ExternalLinkage so that modules can cross-reference transparent
- // functions.
- //
- // TODO: In non-whole-module-opt the generated swiftmodules are "linked" and
- // this strips all serialized transparent functions. So we have to code-gen
- // transparent functions in non-whole-module-opt.
- if (isSILOnly && !info.HasMultipleIGMs && info.IsWholeModule)
- return RESULT(Internal, Default, Default);
return std::make_tuple(llvm::GlobalValue::ExternalLinkage,
PublicDefinitionVisibility, ExportedStorage);
@@ -1389,9 +1376,6 @@
case SILLinkage::PublicExternal: {
if (isDefinition) {
- // Transparent function are not available externally.
- if (isSILOnly)
- return RESULT(LinkOnceODR, Hidden, Default);
return std::make_tuple(llvm::GlobalValue::AvailableExternallyLinkage,
llvm::GlobalValue::DefaultVisibility,
ExportedStorage);
@@ -1426,7 +1410,6 @@
UniversalLinkageInfo linkInfo(IGM);
auto linkage =
getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
- entity.isSILOnly(),
ForDefinition, entity.isWeakImported(IGM.getSwiftModule()));
global->setLinkage(std::get<0>(linkage));
global->setVisibility(std::get<1>(linkage));
@@ -1458,7 +1441,6 @@
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
getIRLinkage(linkInfo, entity.getLinkage(isDefinition),
- entity.isSILOnly(),
isDefinition, entity.isWeakImported(swiftModule));
result.ForDefinition = isDefinition;
@@ -1469,14 +1451,13 @@
LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
StringRef name,
SILLinkage linkage,
- bool isSILOnly,
ForDefinition_t isDefinition,
bool isWeakImported) {
LinkInfo result;
result.Name += name;
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
- getIRLinkage(linkInfo, linkage, isSILOnly,
+ getIRLinkage(linkInfo, linkage,
isDefinition, isWeakImported);
result.ForDefinition = isDefinition;
return result;
@@ -1490,7 +1471,8 @@
llvm::Function *irgen::createFunction(IRGenModule &IGM,
LinkInfo &linkInfo,
const Signature &signature,
- llvm::Function *insertBefore) {
+ llvm::Function *insertBefore,
+ OptimizationMode FuncOptMode) {
auto name = linkInfo.getName();
llvm::Function *existing = IGM.Module.getFunction(name);
@@ -1519,7 +1501,7 @@
}
llvm::AttrBuilder initialAttrs;
- IGM.constructInitialFnAttributes(initialAttrs);
+ IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode);
// Merge initialAttrs with attrs.
auto updatedAttrs =
signature.getAttributes().addAttributes(IGM.getLLVMContext(),
@@ -1901,7 +1883,8 @@
llvm::AttributeList::FunctionIndex,
llvm::Attribute::ReadOnly);
}
- fn = createFunction(*this, link, signature, insertBefore);
+ fn = createFunction(*this, link, signature, insertBefore,
+ f->getOptimizationMode());
// If we have an order number for this function, set it up as appropriate.
if (hasOrderNumber) {
@@ -3138,11 +3121,10 @@
metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy);
// Get a reference count of two.
- auto *strongRefCountInit = llvm::ConstantInt::get(
- Int32Ty,
- InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/)
+ auto *refCountInit = llvm::ConstantInt::get(
+ IntPtrTy,
+ InlineRefCountBits(1 /* "extra" strong ref count*/, 1 /* unowned count */)
.getBitsValue());
- auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0);
auto *count = llvm::ConstantInt::get(Int32Ty, utf8.size());
// Capacity is length plus one because of the implicitly added '\0'
@@ -3150,9 +3132,8 @@
auto *capacity = llvm::ConstantInt::get(Int32Ty, utf8.size() + 1);
auto *flags = llvm::ConstantInt::get(Int8Ty, 0);
- // FIXME: Big endian-ness.
llvm::Constant *heapObjectHeaderFields[] = {
- metaclass, strongRefCountInit, unownedRefCountInit
+ metaclass, refCountInit
};
auto *initRefCountStruct = llvm::ConstantStruct::get(
@@ -3216,11 +3197,10 @@
metaclass = llvm::ConstantExpr::getBitCast(metaclass, TypeMetadataPtrTy);
// Get a reference count of two.
- auto *strongRefCountInit = llvm::ConstantInt::get(
- Int32Ty,
- InlineRefCountBits(0 /*unowned ref count*/, 2 /*strong ref count*/)
+ auto *refCountInit = llvm::ConstantInt::get(
+ IntPtrTy,
+ InlineRefCountBits(1 /* "extra" strong ref count*/, 1 /* unowned count */)
.getBitsValue());
- auto *unownedRefCountInit = llvm::ConstantInt::get(Int32Ty, 0);
auto *count = llvm::ConstantInt::get(Int32Ty, utf16Length);
auto *capacity = llvm::ConstantInt::get(Int32Ty, utf16Length + 1);
@@ -3228,7 +3208,7 @@
auto *padding = llvm::ConstantInt::get(Int8Ty, 0);
llvm::Constant *heapObjectHeaderFields[] = {
- metaclass, strongRefCountInit, unownedRefCountInit
+ metaclass, refCountInit
};
auto *initRefCountStruct = llvm::ConstantStruct::get(
@@ -3312,11 +3292,9 @@
return entry;
}
- auto fnType = llvm::FunctionType::get(VoidTy,
- { WitnessTablePtrTy,
- TypeMetadataPtrTy,
- Int8PtrPtrTy },
- /*varargs*/ false);
+ auto fnType = llvm::FunctionType::get(
+ VoidTy, {WitnessTablePtrTy, TypeMetadataPtrTy, Int8PtrPtrTy},
+ /*varargs*/ false);
Signature signature(fnType, llvm::AttributeList(), DefaultCC);
LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
entry = createFunction(*this, link, signature);
@@ -3359,9 +3337,12 @@
}
llvm::FunctionType *fnType;
- if (conf->getDeclContext()->isGenericContext()) {
- fnType = llvm::FunctionType::get(WitnessTablePtrTy, {TypeMetadataPtrTy},
- false);
+ if (conf->witnessTableAccessorRequiresArguments()) {
+ // conditional requirements are passed indirectly, as an array of witness
+ // tables.
+ fnType = llvm::FunctionType::get(
+ WitnessTablePtrTy, {TypeMetadataPtrTy, WitnessTablePtrPtrTy, SizeTy},
+ false);
} else {
fnType = llvm::FunctionType::get(WitnessTablePtrTy, false);
}
diff --git a/lib/IRGen/GenDecl.h b/lib/IRGen/GenDecl.h
index fd233bd..c394d76 100644
--- a/lib/IRGen/GenDecl.h
+++ b/lib/IRGen/GenDecl.h
@@ -17,6 +17,7 @@
#ifndef SWIFT_IRGEN_GENDECL_H
#define SWIFT_IRGEN_GENDECL_H
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/IR/CallingConv.h"
#include "DebugTypeInfo.h"
#include "IRGen.h"
@@ -35,8 +36,9 @@
llvm::Function *createFunction(IRGenModule &IGM,
LinkInfo &linkInfo,
const Signature &signature,
- llvm::Function *insertBefore = nullptr);
-
+ llvm::Function *insertBefore = nullptr,
+ OptimizationMode FuncOptMode =
+ OptimizationMode::NotSet);
llvm::GlobalVariable *createVariable(IRGenModule &IGM,
LinkInfo &linkInfo,
diff --git a/lib/IRGen/GenExistential.cpp b/lib/IRGen/GenExistential.cpp
index 9e7b6ed..4a0cabf 100644
--- a/lib/IRGen/GenExistential.cpp
+++ b/lib/IRGen/GenExistential.cpp
@@ -2128,7 +2128,7 @@
// Size = ((sizeof(HeapObject) + align) & ~align) + size
auto *heapHeaderSize = llvm::ConstantInt::get(
- IGF.IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ IGF.IGM.SizeTy, IGM.RefCountedStructSize.getValue());
size = Builder.CreateAdd(
Builder.CreateAnd(Builder.CreateAdd(heapHeaderSize, alignmentMask),
Builder.CreateNot(alignmentMask)),
@@ -2222,7 +2222,7 @@
// StartOffset = ((sizeof(HeapObject) + align) & ~align)
auto *heapHeaderSize = llvm::ConstantInt::get(
- IGF.IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ IGF.IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset = Builder.CreateAnd(
Builder.CreateAdd(heapHeaderSize, alignmentMask),
Builder.CreateNot(alignmentMask));
diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp
index 0cfc7e8..31d2549 100644
--- a/lib/IRGen/GenHeap.cpp
+++ b/lib/IRGen/GenHeap.cpp
@@ -1294,7 +1294,7 @@
/// optimizer not to touch this value.
void IRGenFunction::emitFixLifetime(llvm::Value *value) {
// If we aren't running the LLVM ARC optimizer, we don't need to emit this.
- if (!IGM.IRGen.Opts.Optimize || IGM.IRGen.Opts.DisableLLVMARCOpts)
+ if (!IGM.IRGen.Opts.shouldOptimize() || IGM.IRGen.Opts.DisableLLVMARCOpts)
return;
if (doesNotRequireRefCounting(value)) return;
emitUnaryRefCountCall(*this, IGM.getFixLifetimeFn(), value);
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index 198f9cc..c2babaa 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -330,7 +330,6 @@
auto linkInfo = LinkInfo::get(IGM, "swift_keyPathGenericWitnessTable",
SILLinkage::PublicExternal,
- /*sil only*/ false,
NotForDefinition,
/*weak imported*/ false);
@@ -700,11 +699,6 @@
fields.add(emitMetadataGenerator(rootTy));
fields.add(emitMetadataGenerator(valueTy));
- // TODO: 32-bit heap object header still has an extra word
- if (SizeTy == Int32Ty) {
- fields.addInt32(0);
- }
-
#ifndef NDEBUG
auto endOfObjectHeader = fields.getNextOffsetFromGlobal();
unsigned expectedObjectHeaderSize;
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index bdef251..ef8f1c8 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -108,6 +108,7 @@
llvm::Value *irgen::emitObjCMetadataRefForMetadata(IRGenFunction &IGF,
llvm::Value *classPtr) {
+ assert(IGF.IGM.Context.LangOpts.EnableObjCInterop);
classPtr = IGF.Builder.CreateBitCast(classPtr, IGF.IGM.ObjCClassPtrTy);
// Fetch the metadata for that class.
@@ -704,43 +705,32 @@
"metadata ref for generic function type");
return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy);
}
-
- llvm::Value *extractAndMarkResultType(CanFunctionType type) {
- // If the function type throws, set the lower bit of the return type
- // address, so that we can carry this information over to the function
- // type metadata.
- auto metadata = IGF.emitTypeMetadataRef(type->getResult()->
- getCanonicalType());
- return metadata;
- }
- llvm::Value *extractAndMarkInOut(AnyFunctionType::CanParam param) {
- // If the type is inout, get the metadata for its inner object type
- // instead, and then set the lowest bit to help the runtime unique
- // the metadata type for this function.
+ llvm::Value *getFunctionParameterRef(AnyFunctionType::CanParam param) {
auto type = param.getType();
- if (param.getParameterFlags().isInOut()) {
- auto objectType = type->getInOutObjectType()->getCanonicalType();
- auto metadata = IGF.emitTypeMetadataRef(objectType);
- auto metadataInt = IGF.Builder.CreatePtrToInt(metadata, IGF.IGM.SizeTy);
- auto inoutFlag = llvm::ConstantInt::get(IGF.IGM.SizeTy, 1);
- auto marked = IGF.Builder.CreateOr(metadataInt, inoutFlag);
- return IGF.Builder.CreateIntToPtr(marked, IGF.IGM.Int8PtrTy);
- }
-
- auto metadata = IGF.emitTypeMetadataRef(type);
- return IGF.Builder.CreateBitCast(metadata, IGF.IGM.Int8PtrTy);
+ if (param.getParameterFlags().isInOut())
+ type = type->getInOutObjectType()->getCanonicalType();
+ return IGF.emitTypeMetadataRef(type);
}
llvm::Value *visitFunctionType(CanFunctionType type) {
if (auto metatype = tryGetLocal(type))
return metatype;
- auto resultMetadata = extractAndMarkResultType(type);
+ auto result =
+ IGF.emitTypeMetadataRef(type->getResult()->getCanonicalType());
auto params = type.getParams();
auto numParams = params.size();
+ bool hasFlags = false;
+ for (auto param : params) {
+ if (!param.getParameterFlags().isNone()) {
+ hasFlags = true;
+ break;
+ }
+ }
+
// Map the convention to a runtime metadata value.
FunctionMetadataConvention metadataConvention;
switch (type->getRepresentation()) {
@@ -759,78 +749,136 @@
}
auto flagsVal = FunctionTypeFlags()
- .withNumArguments(numParams)
+ .withNumParameters(numParams)
.withConvention(metadataConvention)
- .withThrows(type->throws());
+ .withThrows(type->throws())
+ .withParameterFlags(hasFlags);
auto flags = llvm::ConstantInt::get(IGF.IGM.SizeTy,
flagsVal.getIntValue());
- switch (numParams) {
- case 1: {
- auto arg0 = extractAndMarkInOut(params[0]);
- auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadata1Fn(),
- {flags, arg0, resultMetadata});
- call->setDoesNotThrow();
- return setLocal(CanType(type), call);
- }
+ auto collectParameters =
+ [&](llvm::function_ref<void(unsigned, llvm::Value *,
+ ParameterFlags flags)>
+ processor) {
+ for (auto index : indices(params)) {
+ auto param = params[index];
+ auto flags = param.getParameterFlags();
- case 2: {
- auto arg0 = extractAndMarkInOut(params[0]);
- auto arg1 = extractAndMarkInOut(params[1]);
- auto call = IGF.Builder.CreateCall(
- IGF.IGM.getGetFunctionMetadata2Fn(),
- {flags, arg0, arg1, resultMetadata});
- call->setDoesNotThrow();
- return setLocal(CanType(type), call);
- }
+ auto parameterFlags = ParameterFlags()
+ .withInOut(flags.isInOut())
+ .withShared(flags.isShared())
+ .withVariadic(flags.isVariadic());
- case 3: {
- auto arg0 = extractAndMarkInOut(params[0]);
- auto arg1 = extractAndMarkInOut(params[1]);
- auto arg2 = extractAndMarkInOut(params[2]);
- auto call = IGF.Builder.CreateCall(
- IGF.IGM.getGetFunctionMetadata3Fn(),
- {flags, arg0, arg1, arg2,
- resultMetadata});
- call->setDoesNotThrow();
- return setLocal(CanType(type), call);
- }
+ processor(index, getFunctionParameterRef(param), parameterFlags);
+ }
+ };
+
+ auto constructSimpleCall =
+ [&](llvm::SmallVectorImpl<llvm::Value *> &arguments)
+ -> llvm::Constant * {
+ arguments.push_back(flags);
+
+ collectParameters([&](unsigned i, llvm::Value *typeRef,
+ ParameterFlags flags) {
+ arguments.push_back(typeRef);
+ if (hasFlags)
+ arguments.push_back(
+ llvm::ConstantInt::get(IGF.IGM.Int32Ty, flags.getIntValue()));
+ });
+
+ arguments.push_back(result);
+
+ switch (params.size()) {
+ case 1:
+ return hasFlags ? IGF.IGM.getGetFunctionMetadata1WithFlagsFn()
+ : IGF.IGM.getGetFunctionMetadata1Fn();
+
+ case 2:
+ return hasFlags ? IGF.IGM.getGetFunctionMetadata2WithFlagsFn()
+ : IGF.IGM.getGetFunctionMetadata2Fn();
+
+ case 3:
+ return hasFlags ? IGF.IGM.getGetFunctionMetadata3WithFlagsFn()
+ : IGF.IGM.getGetFunctionMetadata3Fn();
default:
- auto arrayTy = llvm::ArrayType::get(IGF.IGM.Int8PtrTy, numParams + 2);
- Address buffer = IGF.createAlloca(arrayTy,
- IGF.IGM.getPointerAlignment(),
- "function-arguments");
- IGF.Builder.CreateLifetimeStart(buffer,
+ llvm_unreachable("supports only 1/2/3 parameter functions");
+ }
+ };
+
+ auto getArrayFor = [&](llvm::Type *elementType, unsigned size,
+ const llvm::Twine &name) -> Address {
+ auto arrayTy = llvm::ArrayType::get(elementType, size);
+ return IGF.createAlloca(arrayTy, IGF.IGM.getPointerAlignment(), name);
+ };
+
+ switch (numParams) {
+ case 1:
+ case 2:
+ case 3: {
+ llvm::SmallVector<llvm::Value *, 8> arguments;
+ auto *metadataFn = constructSimpleCall(arguments);
+ auto *call = IGF.Builder.CreateCall(metadataFn, arguments);
+ call->setDoesNotThrow();
+ return setLocal(CanType(type), call);
+ }
+
+ default:
+ auto *const Int32Ptr = IGF.IGM.Int32Ty->getPointerTo();
+
+ llvm::SmallVector<llvm::Value *, 8> arguments;
+ arguments.push_back(flags);
+
+ Address parameters;
+ if (!params.empty()) {
+ parameters = getArrayFor(IGF.IGM.TypeMetadataPtrTy, numParams,
+ "function-parameters");
+
+ IGF.Builder.CreateLifetimeStart(parameters,
IGF.IGM.getPointerSize() * numParams);
- Address pointerToFirstArg = IGF.Builder.CreateStructGEP(buffer, 0,
- Size(0));
- Address flagsPtr = IGF.Builder.CreateBitCast(pointerToFirstArg,
- IGF.IGM.SizeTy->getPointerTo());
- IGF.Builder.CreateStore(flags, flagsPtr);
- for (auto i : indices(params)) {
- auto argMetadata = extractAndMarkInOut(params[i]);
- Address argPtr = IGF.Builder.CreateStructGEP(buffer, i + 1,
+ ConstantInitBuilder paramFlags(IGF.IGM);
+ auto flagsArr = paramFlags.beginArray();
+ collectParameters([&](unsigned i, llvm::Value *typeRef,
+ ParameterFlags flags) {
+ auto argPtr = IGF.Builder.CreateStructGEP(parameters, i,
IGF.IGM.getPointerSize());
- IGF.Builder.CreateStore(argMetadata, argPtr);
+ IGF.Builder.CreateStore(typeRef, argPtr);
+ if (hasFlags)
+ flagsArr.addInt32(flags.getIntValue());
+ });
+
+ auto parametersPtr =
+ IGF.Builder.CreateStructGEP(parameters, 0, Size(0));
+ arguments.push_back(parametersPtr.getAddress());
+
+ if (hasFlags) {
+ auto *flagsVar = flagsArr.finishAndCreateGlobal(
+ "parameter-flags", IGF.IGM.getPointerAlignment(),
+ /* constant */ true);
+ arguments.push_back(IGF.Builder.CreateBitCast(flagsVar, Int32Ptr));
+ } else {
+ flagsArr.abandon();
+ arguments.push_back(llvm::ConstantPointerNull::get(Int32Ptr));
}
+ } else {
+ arguments.push_back(llvm::ConstantPointerNull::get(
+ IGF.IGM.TypeMetadataPtrTy->getPointerTo()));
+ arguments.push_back(llvm::ConstantPointerNull::get(Int32Ptr));
+ }
- Address resultPtr = IGF.Builder.CreateStructGEP(
- buffer, numParams + 1, IGF.IGM.getPointerSize());
- resultPtr = IGF.Builder.CreateBitCast(resultPtr,
- IGF.IGM.TypeMetadataPtrTy->getPointerTo());
- IGF.Builder.CreateStore(resultMetadata, resultPtr);
+ arguments.push_back(result);
- auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(),
- pointerToFirstArg.getAddress());
- call->setDoesNotThrow();
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetFunctionMetadataFn(),
+ arguments);
+ call->setDoesNotThrow();
- IGF.Builder.CreateLifetimeEnd(buffer,
+ if (parameters.isValid())
+ IGF.Builder.CreateLifetimeEnd(parameters,
IGF.IGM.getPointerSize() * numParams);
- return setLocal(type, call);
+ return setLocal(type, call);
}
}
@@ -933,6 +981,9 @@
llvm_unreachable("should not be asking for metadata of a lowered SIL "
"function type--SILGen should have used the AST type");
}
+ llvm::Value *visitSILTokenType(CanSILTokenType type) {
+ llvm_unreachable("should not be asking for metadata of a SILToken type");
+ }
llvm::Value *visitArchetypeType(CanArchetypeType type) {
return emitArchetypeTypeMetadataRef(IGF, type);
@@ -1337,7 +1388,7 @@
cacheVariable = cast<llvm::GlobalVariable>(
IGM.getAddrOfTypeMetadataLazyCacheVariable(type, ForDefinition));
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
}
@@ -1381,7 +1432,7 @@
if (!shouldDefine || !accessor->empty())
return accessor;
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
emitLazyCacheAccessFunction(IGM, accessor, /*cacheVariable=*/nullptr,
@@ -4204,46 +4255,16 @@
if (hasKnownSwiftMetadata(IGF.IGM, type))
return metatype;
- // Otherwise, we inline a little operation here.
-
- // Load the metatype kind.
- auto metatypeKindAddr =
- Address(IGF.Builder.CreateStructGEP(/*Ty=*/nullptr, metatype, 0),
- IGF.IGM.getPointerAlignment());
- auto metatypeKind =
- IGF.Builder.CreateLoad(metatypeKindAddr, metatype->getName() + ".kind");
-
- // Compare it with the class wrapper kind.
- auto classWrapperKind =
- llvm::ConstantInt::get(IGF.IGM.MetadataKindTy,
- unsigned(MetadataKind::ObjCClassWrapper));
- auto isObjCClassWrapper =
- IGF.Builder.CreateICmpEQ(metatypeKind, classWrapperKind,
- "isObjCClassWrapper");
-
- // Branch based on that.
- llvm::BasicBlock *contBB = IGF.createBasicBlock("metadataForClass.cont");
- llvm::BasicBlock *wrapBB = IGF.createBasicBlock("isWrapper");
- IGF.Builder.CreateCondBr(isObjCClassWrapper, wrapBB, contBB);
- llvm::BasicBlock *origBB = IGF.Builder.GetInsertBlock();
-
- // If it's a wrapper, load from the 'Class' field, which is at index 1.
- // TODO: if we guaranteed that this load couldn't crash, we could use
- // a select here instead, which might be profitable.
- IGF.Builder.emitBlock(wrapBB);
- auto classFromWrapper =
- emitInvariantLoadFromMetadataAtIndex(IGF, metatype, 1,
- IGF.IGM.TypeMetadataPtrTy);
- IGF.Builder.CreateBr(contBB);
-
- // Continuation block.
- IGF.Builder.emitBlock(contBB);
- auto phi = IGF.Builder.CreatePHI(IGF.IGM.TypeMetadataPtrTy, 2,
- metatype->getName() + ".class");
- phi->addIncoming(metatype, origBB);
- phi->addIncoming(classFromWrapper, wrapBB);
-
- return phi;
+ // Otherwise, we may have to unwrap an ObjC class wrapper.
+ assert(IGF.IGM.Context.LangOpts.EnableObjCInterop);
+ metatype = IGF.Builder.CreateBitCast(metatype, IGF.IGM.TypeMetadataPtrTy);
+
+ // Fetch the metadata for that class.
+ auto call = IGF.Builder.CreateCall(IGF.IGM.getGetObjCClassFromMetadataFn(),
+ metatype);
+ call->setDoesNotThrow();
+ call->setDoesNotAccessMemory();
+ return call;
}
/// Load the correct virtual function for the given class method.
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index 2a6c1c5..10d28c2 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -143,7 +143,7 @@
// If we're emitting optimized code, record the string in the module
// and let the late ARC pass insert it, but don't generate any calls
// right now.
- if (IRGen.Opts.Optimize) {
+ if (IRGen.Opts.shouldOptimize()) {
llvm::NamedMDNode *metadata =
Module.getOrInsertNamedMetadata(
"clang.arc.retainAutoreleasedReturnValueMarker");
@@ -908,7 +908,8 @@
subIGF.emitObjCAutoreleaseCall(self);
}
// Release the context.
- subIGF.emitNativeStrongRelease(context, subIGF.getDefaultAtomicity());
+ if (!resultType->isCalleeGuaranteed())
+ subIGF.emitNativeStrongRelease(context, subIGF.getDefaultAtomicity());
};
// Emit the call and produce the return value.
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index e784a90..3338f58 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -735,7 +735,7 @@
SILType T,
llvm::Value *numEmptyCases,
Address destObject) {
- if (!IGF.IGM.getOptions().OptimizeForSize) {
+ if (!IGF.optimizeForSize()) {
llvm::Value *metadata;
auto fn = IGF.emitValueWitnessFunctionRef(
T, metadata, ValueWitness::GetEnumTagSinglePayload);
@@ -755,7 +755,7 @@
llvm::Value *irgen::emitStoreEnumTagSinglePayloadCall(
IRGenFunction &IGF, SILType T, llvm::Value *whichCase,
llvm::Value *numEmptyCases, Address destObject) {
- if (!IGF.IGM.getOptions().OptimizeForSize) {
+ if (!IGF.optimizeForSize()) {
llvm::Value *metadata;
auto fn = IGF.emitValueWitnessFunctionRef(
T, metadata, ValueWitness::StoreEnumTagSinglePayload);
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 4797745..d9bb28c 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -74,6 +74,10 @@
using namespace swift;
using namespace irgen;
+// Return the offset one should do on a witness table pointer to retrieve the
+// `index`th piece of private data.
+static int privateIndexToTableOffset(unsigned index) { return -1 - (int)index; }
+
namespace {
/// A class for computing how to pass arguments to a polymorphic
@@ -138,9 +142,32 @@
bool isSelfParameter);
void addSelfMetadataFulfillment(CanType arg);
- void addSelfWitnessTableFulfillment(CanType arg, ProtocolDecl *proto);
+ void addSelfWitnessTableFulfillment(CanType arg,
+ ProtocolConformanceRef conformance);
void addPseudogenericFulfillments();
+
+ struct FulfillmentMapCallback : FulfillmentMap::InterestingKeysCallback {
+ PolymorphicConvention &Self;
+ FulfillmentMapCallback(PolymorphicConvention &self) : Self(self) {}
+
+ bool isInterestingType(CanType type) const override {
+ return type->isTypeParameter();
+ }
+ bool hasInterestingType(CanType type) const override {
+ return type->hasTypeParameter();
+ }
+ bool hasLimitedInterestingConformances(CanType type) const override {
+ return true;
+ }
+ GenericSignature::ConformsToArray
+ getInterestingConformances(CanType type) const override {
+ return Self.getConformsTo(type);
+ }
+ CanType getSuperclassBound(CanType type) const override {
+ return Self.getSuperclassBound(type);
+ }
+ };
};
} // end anonymous namespace
@@ -163,9 +190,9 @@
}
if (rep == SILFunctionTypeRepresentation::WitnessMethod) {
- // Protocol witnesses always derive all polymorphic parameter
- // information from the Self argument. We also *cannot* consider other
- // arguments; doing so would potentially make the signature
+ // Protocol witnesses always derive all polymorphic parameter information
+ // from the Self and Self witness table arguments. We also *cannot* consider
+ // other arguments; doing so would potentially make the signature
// incompatible with other witnesses for the same method.
considerWitnessSelf(fnType);
} else if (rep == SILFunctionTypeRepresentation::ObjCMethod) {
@@ -280,27 +307,7 @@
bool PolymorphicConvention::considerType(CanType type, IsExact_t isExact,
unsigned sourceIndex,
MetadataPath &&path) {
- struct Callback : FulfillmentMap::InterestingKeysCallback {
- PolymorphicConvention &Self;
- Callback(PolymorphicConvention &self) : Self(self) {}
-
- bool isInterestingType(CanType type) const override {
- return type->isTypeParameter();
- }
- bool hasInterestingType(CanType type) const override {
- return type->hasTypeParameter();
- }
- bool hasLimitedInterestingConformances(CanType type) const override {
- return true;
- }
- GenericSignature::ConformsToArray
- getInterestingConformances(CanType type) const override {
- return Self.getConformsTo(type);
- }
- CanType getSuperclassBound(CanType type) const override {
- return Self.getSuperclassBound(type);
- }
- } callbacks(*this);
+ FulfillmentMapCallback callbacks(*this);
return Fulfillments.searchTypeMetadata(IGM, type, isExact, sourceIndex,
std::move(path), callbacks);
}
@@ -308,29 +315,17 @@
void PolymorphicConvention::considerWitnessSelf(CanSILFunctionType fnType) {
CanType selfTy = fnType->getSelfInstanceType();
auto conformance = fnType->getWitnessMethodConformance();
- auto protocol = conformance.getRequirement();
// First, bind type metadata for Self.
Sources.emplace_back(MetadataSource::Kind::SelfMetadata,
MetadataSource::InvalidSourceIndex,
selfTy);
- if (auto *proto = fnType->getDefaultWitnessMethodProtocol()) {
+ if (fnType->getDefaultWitnessMethodProtocol() ||
+ fnType->getWitnessMethodClass(M)) {
// The Self type is abstract, so we can fulfill its metadata from
// the Self metadata parameter.
addSelfMetadataFulfillment(selfTy);
-
- // The witness table for the Self : P conformance can be
- // fulfilled from the Self witness table parameter.
- Sources.emplace_back(MetadataSource::Kind::SelfWitnessTable,
- MetadataSource::InvalidSourceIndex,
- selfTy);
- addSelfWitnessTableFulfillment(selfTy, proto);
- } else if (auto *classDecl = fnType->getWitnessMethodClass(M)) {
- // The Self type is abstract, so we can fulfill its metadata from
- // the Self metadata parameter.
- addSelfMetadataFulfillment(selfTy);
- addSelfWitnessTableFulfillment(selfTy, protocol);
} else {
// If the Self type is concrete, we have a witness thunk with a
// fully substituted Self type. The witness table parameter is not
@@ -342,9 +337,13 @@
//
// For now, just fulfill the generic arguments of 'Self'.
considerType(selfTy, IsInexact, Sources.size() - 1, MetadataPath());
-
- addSelfWitnessTableFulfillment(selfTy, protocol);
}
+
+ // The witness table for the Self : P conformance can be
+ // fulfilled from the Self witness table parameter.
+ Sources.emplace_back(MetadataSource::Kind::SelfWitnessTable,
+ MetadataSource::InvalidSourceIndex, selfTy);
+ addSelfWitnessTableFulfillment(selfTy, conformance);
}
void PolymorphicConvention::considerObjCGenericSelf(CanSILFunctionType fnType) {
@@ -429,9 +428,17 @@
Fulfillments.addFulfillment({arg, nullptr}, source, MetadataPath());
}
-void PolymorphicConvention::addSelfWitnessTableFulfillment(CanType arg, ProtocolDecl *proto) {
+void PolymorphicConvention::addSelfWitnessTableFulfillment(
+ CanType arg, ProtocolConformanceRef conformance) {
+ auto proto = conformance.getRequirement();
unsigned source = Sources.size() - 1;
Fulfillments.addFulfillment({arg, proto}, source, MetadataPath());
+
+ if (conformance.isConcrete()) {
+ FulfillmentMapCallback callbacks(*this);
+ Fulfillments.searchConformance(IGM, conformance.getConcrete(), source,
+ MetadataPath(), callbacks);
+ }
}
const Fulfillment *
@@ -549,20 +556,48 @@
case MetadataSource::Kind::SelfWitnessTable: {
assert(witnessMetadata && "no metadata for witness method");
- llvm::Value *wtable = witnessMetadata->SelfWitnessTable;
- assert(wtable && "no Self witness table for witness method");
+ llvm::Value *selfTable = witnessMetadata->SelfWitnessTable;
+ assert(selfTable && "no Self witness table for witness method");
// Mark this as the cached witness table for Self.
+ auto conformance = FnType->getWitnessMethodConformance();
+ auto selfProto = conformance.getRequirement();
- if (auto *proto = FnType->getDefaultWitnessMethodProtocol()) {
- auto selfTy = FnType->getSelfInstanceType();
- CanType argTy = getTypeInContext(selfTy);
- auto archetype = cast<ArchetypeType>(argTy);
+ auto selfTy = FnType->getSelfInstanceType();
+ CanType argTy = getTypeInContext(selfTy);
+ if (auto archetype = dyn_cast<ArchetypeType>(argTy)) {
+ setProtocolWitnessTableName(IGF.IGM, selfTable, argTy, selfProto);
+ IGF.setUnscopedLocalTypeData(
+ archetype,
+ LocalTypeDataKind::forAbstractProtocolWitnessTable(selfProto),
+ selfTable);
+ }
- setProtocolWitnessTableName(IGF.IGM, wtable, argTy, proto);
- IGF.setUnscopedLocalTypeData(archetype,
- LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
- wtable);
+ if (conformance.isConcrete()) {
+ // Now bind all the conditional witness tables that can be pulled out of
+ // the self witness table.
+ SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ conformance.getConcrete(),
+ [&](unsigned index, CanType type, ProtocolDecl *proto) {
+ auto archetype = getTypeInContext(type);
+ if (isa<ArchetypeType>(archetype)) {
+ WitnessIndex wIndex(privateIndexToTableOffset(index),
+ /*prefix*/ false);
+
+ auto table =
+ emitInvariantLoadOfOpaqueWitness(IGF, selfTable, wIndex);
+ table =
+ IGF.Builder.CreateBitCast(table, IGF.IGM.WitnessTablePtrTy);
+ setProtocolWitnessTableName(IGF.IGM, table, archetype, proto);
+
+ IGF.setUnscopedLocalTypeData(
+ archetype,
+ LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
+ table);
+ }
+
+ return /*finished?*/ false;
+ });
}
return;
}
@@ -960,7 +995,10 @@
return true;
}
- return false;
+ // Check if there are any conditional conformances. Other forms of conditional
+ // requirements don't exist in the witness table.
+ return SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ conformance, [](unsigned, CanType, ProtocolDecl *) { return true; });
}
/// Detail about how an object conforms to a protocol.
@@ -977,23 +1015,73 @@
CanType conformingType) const = 0;
};
-static llvm::Value *
-emitWitnessTableAccessorCall(IRGenFunction &IGF,
- const NormalProtocolConformance *conformance,
- CanType conformingType,
- llvm::Value **srcMetadataCache) {
- auto accessor =
- IGF.IGM.getAddrOfWitnessTableAccessFunction(conformance, NotForDefinition);
+static std::pair<llvm::Value *, llvm::Value *>
+emitConditionalConformancesBuffer(IRGenFunction &IGF,
+ const ProtocolConformance *conformance) {
+ // Pointers to the witness tables, in the right order, which will be included
+ // in the buffer that gets passed to the witness table accessor.
+ llvm::SmallVector<llvm::Value *, 4> tables;
- // If the conformance is generic, the accessor takes the metatype
- // as an argument.
+ auto subMap = conformance->getSubstitutions(IGF.IGM.getSwiftModule());
+ auto rootConformance = conformance->getRootNormalConformance();
+
+ SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ rootConformance, [&](unsigned, CanType type, ProtocolDecl *proto) {
+ auto substType = type.subst(subMap)->getCanonicalType();
+ auto reqConformance = subMap.lookupConformance(type, proto);
+ assert(reqConformance && "conditional conformance must exist");
+
+ tables.push_back(emitWitnessTableRef(IGF, substType, *reqConformance));
+ return /*finished?*/ false;
+ });
+
+ // No conditional requirements means no need for a buffer, and size == 0 means
+ // no reading of the pointer.
+ // FIXME(cond. conf. assert): once the dynamic assertion is removed from the
+ // instantiation function, we can have size as undef too.
+ if (tables.empty()) {
+ return {llvm::UndefValue::get(IGF.IGM.WitnessTablePtrPtrTy),
+ llvm::ConstantInt::get(IGF.IGM.SizeTy, 0)};
+ }
+
+ auto buffer = IGF.createAlloca(
+ llvm::ArrayType::get(IGF.IGM.WitnessTablePtrTy, tables.size()),
+ IGF.IGM.getPointerAlignment(), "conditional.requirement.buffer");
+ buffer = IGF.Builder.CreateStructGEP(buffer, 0, Size(0));
+
+ // Write each of the conditional witness tables into the buffer.
+ for (auto idx : indices(tables)) {
+ auto slot =
+ IGF.Builder.CreateConstArrayGEP(buffer, idx, IGF.IGM.getPointerSize());
+ IGF.Builder.CreateStore(tables[idx], slot);
+ }
+
+ auto count = llvm::ConstantInt::get(IGF.IGM.SizeTy, tables.size());
+ return {buffer.getAddress(), count};
+}
+
+static llvm::Value *emitWitnessTableAccessorCall(
+ IRGenFunction &IGF, const ProtocolConformance *conformance,
+ CanType conformingType, llvm::Value **srcMetadataCache) {
+ auto accessor = IGF.IGM.getAddrOfWitnessTableAccessFunction(
+ conformance->getRootNormalConformance(), NotForDefinition);
+
+ // If the conformance is generic, the accessor takes the metatype plus
+ // possible conditional conformances arguments.
llvm::CallInst *call;
- if (conformance->getDeclContext()->isGenericContext()) {
+ if (conformance->witnessTableAccessorRequiresArguments()) {
// Emit the source metadata if we haven't yet.
if (!*srcMetadataCache) {
*srcMetadataCache = IGF.emitTypeMetadataRef(conformingType);
}
- call = IGF.Builder.CreateCall(accessor, {*srcMetadataCache});
+
+ llvm::Value *conditionalTables, *numConditionalTables;
+ std::tie(conditionalTables, numConditionalTables) =
+ emitConditionalConformancesBuffer(IGF, conformance);
+
+ call = IGF.Builder.CreateCall(
+ accessor, {*srcMetadataCache, conditionalTables, numConditionalTables});
+
} else {
call = IGF.Builder.CreateCall(accessor, {});
}
@@ -1009,25 +1097,25 @@
/// given type.
static llvm::Function *
getWitnessTableLazyAccessFunction(IRGenModule &IGM,
- const NormalProtocolConformance *conformance,
+ const ProtocolConformance *conformance,
CanType conformingType) {
assert(!conformingType->hasArchetype());
- llvm::Function *accessor =
- IGM.getAddrOfWitnessTableLazyAccessFunction(conformance, conformingType,
- ForDefinition);
+ auto rootConformance = conformance->getRootNormalConformance();
+ llvm::Function *accessor = IGM.getAddrOfWitnessTableLazyAccessFunction(
+ rootConformance, conformingType, ForDefinition);
// If we're not supposed to define the accessor, or if we already
// have defined it, just return the pointer.
if (!accessor->empty())
return accessor;
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
// Okay, define the accessor.
- auto cacheVariable = cast<llvm::GlobalVariable>(
- IGM.getAddrOfWitnessTableLazyCacheVariable(conformance, conformingType,
- ForDefinition));
+ auto cacheVariable =
+ cast<llvm::GlobalVariable>(IGM.getAddrOfWitnessTableLazyCacheVariable(
+ rootConformance, conformingType, ForDefinition));
emitLazyCacheAccessFunction(IGM, accessor, cacheVariable,
[&](IRGenFunction &IGF) -> llvm::Value* {
llvm::Value *conformingMetadataCache = nullptr;
@@ -1046,8 +1134,8 @@
const NormalProtocolConformance *RootConformance;
public:
- DirectConformanceInfo(const NormalProtocolConformance *C)
- : RootConformance(C) {}
+ DirectConformanceInfo(const ProtocolConformance *C)
+ : RootConformance(C->getRootNormalConformance()) {}
llvm::Value *getTable(IRGenFunction &IGF, CanType conformingType,
llvm::Value **conformingMetadataCache) const override {
@@ -1064,10 +1152,10 @@
class AccessorConformanceInfo : public ConformanceInfo {
friend ProtocolInfo;
- const NormalProtocolConformance *Conformance;
+ const ProtocolConformance *Conformance;
+
public:
- AccessorConformanceInfo(const NormalProtocolConformance *C)
- : Conformance(C) {}
+ AccessorConformanceInfo(const ProtocolConformance *C) : Conformance(C) {}
llvm::Value *getTable(IRGenFunction &IGF, CanType type,
llvm::Value **typeMetadataCache) const override {
@@ -1102,27 +1190,29 @@
CanType ConcreteType;
const NormalProtocolConformance &Conformance;
ArrayRef<SILWitnessTable::Entry> SILEntries;
+ ArrayRef<SILWitnessTable::ConditionalConformance>
+ SILConditionalConformances;
const ProtocolInfo &PI;
Optional<FulfillmentMap> Fulfillments;
SmallVector<std::pair<size_t, const ConformanceInfo *>, 4>
SpecializedBaseConformances;
- // Metadata caches are stored at negative offsets.
- unsigned NextCacheIndex = 0;
+
+ SmallVector<size_t, 4> ConditionalRequirementPrivateDataIndices;
+
+ // Conditional conformances and metadata caches are stored at negative
+ // offsets, with conditional conformances closest to 0.
+ unsigned NextPrivateDataIndex = 0;
bool RequiresSpecialization = false;
public:
- WitnessTableBuilder(IRGenModule &IGM,
- ConstantArrayBuilder &table,
+ WitnessTableBuilder(IRGenModule &IGM, ConstantArrayBuilder &table,
SILWitnessTable *SILWT)
- : IGM(IGM), Table(table),
- ConcreteType(SILWT->getConformance()->getType()->getCanonicalType()),
- Conformance(*SILWT->getConformance()),
- SILEntries(SILWT->getEntries()),
- PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol()))
- {
- // TODO: in conditional conformances, allocate space for the assumed
- // conformances here.
-
+ : IGM(IGM), Table(table),
+ ConcreteType(SILWT->getConformance()->getType()->getCanonicalType()),
+ Conformance(*SILWT->getConformance()),
+ SILEntries(SILWT->getEntries()),
+ SILConditionalConformances(SILWT->getConditionalConformances()),
+ PI(IGM.getProtocolInfo(SILWT->getConformance()->getProtocol())) {
// If the conformance is resilient, we require runtime instantiation.
if (isResilientConformance(&Conformance))
RequiresSpecialization = true;
@@ -1144,8 +1234,8 @@
assert(entry.getBaseProtocolWitness().Requirement == baseProto
&& "sil witness table does not match protocol");
auto piIndex = PI.getBaseIndex(baseProto);
- assert(piIndex.getValue() == Table.size()
- && "offset doesn't match ProtocolInfo layout");
+ assert((size_t)piIndex.getValue() == Table.size() &&
+ "offset doesn't match ProtocolInfo layout");
#endif
SILEntries = SILEntries.slice(1);
@@ -1189,8 +1279,8 @@
&& "sil witness table does not match protocol");
auto piIndex =
PI.getFunctionIndex(cast<AbstractFunctionDecl>(requirement.getDecl()));
- assert(piIndex.getValue() == Table.size()
- && "offset doesn't match ProtocolInfo layout");
+ assert((size_t)piIndex.getValue() == Table.size() &&
+ "offset doesn't match ProtocolInfo layout");
#endif
SILFunction *Func = entry.getMethodWitness().Witness;
@@ -1220,8 +1310,8 @@
== requirement.getAssociation()
&& "sil witness table does not match protocol");
auto piIndex = PI.getAssociatedTypeIndex(requirement);
- assert(piIndex.getValue() == Table.size()
- && "offset doesn't match ProtocolInfo layout");
+ assert((size_t)piIndex.getValue() == Table.size() &&
+ "offset doesn't match ProtocolInfo layout");
#endif
SILEntries = SILEntries.slice(1);
@@ -1263,13 +1353,13 @@
requirement.getAssociatedRequirement()
&& "sil witness table does not match protocol");
auto piIndex = PI.getAssociatedConformanceIndex(requirement);
- assert(piIndex.getValue() == Table.size()
- && "offset doesn't match ProtocolInfo layout");
+ assert((size_t)piIndex.getValue() == Table.size() &&
+ "offset doesn't match ProtocolInfo layout");
#endif
SILEntries = SILEntries.slice(1);
- llvm::Constant *wtableAccessFunction =
+ llvm::Constant *wtableAccessFunction =
getAssociatedTypeWitnessTableAccessFunction(requirement,
associate,
associatedConformance);
@@ -1277,6 +1367,17 @@
}
private:
+ void addConditionalConformances() {
+ for (auto conditional : SILConditionalConformances) {
+ // We don't actually need to know anything about the specific
+ // conformances here, just make sure we get right private data slots.
+ (void)conditional;
+
+ auto reqtIndex = getNextPrivateDataIndex();
+ ConditionalRequirementPrivateDataIndices.push_back(reqtIndex);
+ }
+ }
+
llvm::Constant *buildInstantiationFunction();
llvm::Constant *
@@ -1295,9 +1396,16 @@
llvm::function_ref<llvm::Value*()> body);
/// Allocate another word of private data storage in the conformance table.
- unsigned getNextCacheIndex() {
+ unsigned getNextPrivateDataIndex() {
RequiresSpecialization = true;
- return NextCacheIndex++;
+ return NextPrivateDataIndex++;
+ }
+
+ Address getAddressOfPrivateDataSlot(IRGenFunction &IGF, Address table,
+ unsigned index) {
+ assert(index < NextPrivateDataIndex);
+ return IGF.Builder.CreateConstArrayGEP(
+ table, privateIndexToTableOffset(index), IGF.IGM.getPointerSize());
}
const FulfillmentMap &getFulfillmentMap() {
@@ -1336,6 +1444,7 @@
/// Build the witness table.
void WitnessTableBuilder::build() {
+ addConditionalConformances();
visitProtocolDecl(Conformance.getProtocol());
TableSize = Table.size();
}
@@ -1355,7 +1464,7 @@
llvm::Function *accessor =
IGM.getAddrOfAssociatedTypeMetadataAccessFunction(&Conformance,
requirement);
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
IRGenFunction IGF(IGM, accessor);
@@ -1421,15 +1530,11 @@
// and won't let us re-use the cache with other non-dependent uses in
// the module. Therefore, in this case, we use the address of the lazy-cache
// function.
- //
- // FIXME: we will need to pass additional parameters if the target
- // conformance is conditional.
auto rootConformance = conformance->getRootNormalConformance();
- if (rootConformance->getDeclContext()->isGenericContext()) {
+ if (rootConformance->witnessTableAccessorRequiresArguments()) {
return getWitnessTableLazyAccessFunction(IGM, rootConformance, type);
} else {
- return IGM.getAddrOfWitnessTableAccessFunction(
- conformance->getRootNormalConformance(),
+ return IGM.getAddrOfWitnessTableAccessFunction(rootConformance,
NotForDefinition);
}
}
@@ -1465,7 +1570,7 @@
if (IGM.DebugInfo)
IGM.DebugInfo->emitArtificialFunction(IGF, accessor);
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
Explosion parameters = IGF.collectParameters();
@@ -1554,9 +1659,8 @@
llvm::Value *selfMetadata,
llvm::function_ref<llvm::Value*()> body) {
// Allocate a new cache slot and drill down to it.
- int cacheIndex = -1 - getNextCacheIndex();
- Address cache = IGF.Builder.CreateConstArrayGEP(destTable, cacheIndex,
- IGM.getPointerSize());
+ auto cache =
+ getAddressOfPrivateDataSlot(IGF, destTable, getNextPrivateDataIndex());
llvm::Type *expectedTy = IGF.CurFn->getReturnType();
cache = IGF.Builder.CreateBitCast(cache, expectedTy->getPointerTo());
@@ -1620,11 +1724,18 @@
Explosion params = IGF.collectParameters();
llvm::Value *metadata;
+ llvm::Value *conditionalReqtWtables;
+ llvm::Value *numConditionalReqtWtables;
- if (Conformance.getDeclContext()->isGenericContext())
+ if (Conformance.witnessTableAccessorRequiresArguments()) {
metadata = params.claimNext();
- else
+ conditionalReqtWtables = params.claimNext();
+ numConditionalReqtWtables = params.claimNext();
+ } else {
metadata = llvm::ConstantPointerNull::get(IGF.IGM.TypeMetadataPtrTy);
+ conditionalReqtWtables = nullptr;
+ numConditionalReqtWtables = llvm::ConstantInt::get(IGF.IGM.SizeTy, 0);
+ }
// Okay, we need a cache. Build the cache structure.
// struct GenericWitnessTable {
@@ -1641,7 +1752,8 @@
// RelativeDirectPointer<WitnessTable> WitnessTable;
//
// /// The instantiation function, which is called after the template is copied.
- // RelativeDirectPointer<void(WitnessTable *, const Metadata *)> Instantiator;
+ // RelativeDirectPointer<void(WitnessTable *, const Metadata *, void * const *)>
+ // Instantiator;
//
// void *PrivateData[swift::NumGenericMetadataPrivateDataWords];
// };
@@ -1655,7 +1767,8 @@
// is non-dependent.
// TODO: the conformance might be conditional.
llvm::Constant *instantiationFn;
- if (SpecializedBaseConformances.empty()) {
+ if (SpecializedBaseConformances.empty() &&
+ ConditionalRequirementPrivateDataIndices.empty()) {
instantiationFn = nullptr;
} else {
instantiationFn = buildInstantiationFunction();
@@ -1672,7 +1785,7 @@
// WitnessTableSizeInWords
cacheData.addInt(IGM.Int16Ty, TableSize);
// WitnessTablePrivateSizeInWords
- cacheData.addInt(IGM.Int16Ty, NextCacheIndex);
+ cacheData.addInt(IGM.Int16Ty, NextPrivateDataIndex);
// RelativeIndirectablePointer<ProtocolDescriptor>
cacheData.addRelativeAddress(descriptorRef);
// RelativePointer<WitnessTable>
@@ -1694,10 +1807,31 @@
cacheData.finishAndSetAsInitializer(cache);
cache->setConstant(true);
- llvm::Value *instantiationArgs =
- llvm::ConstantPointerNull::get(IGM.Int8PtrPtrTy);
- auto call = IGF.Builder.CreateCall(IGM.getGetGenericWitnessTableFn(),
- { cache, metadata, instantiationArgs });
+ // Create the slice structure for the conditional conformances, which is
+ // passed as the last argument to the instantiation function.
+ // FIXME(cond. conf. assert): Elide this local/replace it with `undef` once
+ // the size assertion in the instantiation function is gone.
+ auto conditionalSlice =
+ IGF.createAlloca(IGF.IGM.WitnessTableSliceTy,
+ IGF.IGM.getPointerAlignment(), "conditional.tables");
+
+ // Only store a pointer if it will be read. If not (i.e. size == 0/this
+ // conformance is unconditional), we can leave it as undef.
+ if (conditionalReqtWtables) {
+ auto tableSlot = IGF.Builder.CreateStructGEP(conditionalSlice, 0, Size(0));
+ IGF.Builder.CreateStore(conditionalReqtWtables, tableSlot);
+ }
+
+ auto sizeSlot = IGF.Builder.CreateStructGEP(conditionalSlice, 1,
+ Size(IGF.IGM.getPointerSize()));
+ IGF.Builder.CreateStore(numConditionalReqtWtables, sizeSlot);
+
+ auto instantiationArgs =
+ IGF.Builder.CreateBitCast(conditionalSlice, IGM.Int8PtrPtrTy);
+
+ auto call =
+ IGF.Builder.CreateCall(IGM.getGetGenericWitnessTableFn(),
+ {cache, metadata, instantiationArgs.getAddress()});
call->setDoesNotThrow();
IGF.Builder.CreateRet(call);
@@ -1710,32 +1844,82 @@
if (IGM.DebugInfo)
IGM.DebugInfo->emitArtificialFunction(IGF, fn);
+ auto PointerAlignment = IGM.getPointerAlignment();
+ auto PointerSize = IGM.getPointerSize();
+
// Break out the parameters.
Explosion params = IGF.collectParameters();
- Address wtable(params.claimNext(), IGM.getPointerAlignment());
+ Address wtable(params.claimNext(), PointerAlignment);
llvm::Value *metadata = params.claimNext();
- llvm::Value *instantiationArgs = params.claimNext();
- (void) instantiationArgs; // unused for now
+ Address instantiationArgs(params.claimNext(), PointerAlignment);
- // TODO: store any required conditional-conformance information
- // in the private data.
+ // The details of any conditional conformances are in the last argument, as a
+ // pointer/size pair.
+ auto conditionalTablesSlice = IGF.Builder.CreateElementBitCast(
+ instantiationArgs, IGF.IGM.WitnessTableSliceTy);
+
+ auto conditionalTablesPtr =
+ IGF.Builder.CreateStructGEP(conditionalTablesSlice, 0, Size(0));
+ Address conditionalTables(IGF.Builder.CreateLoad(conditionalTablesPtr),
+ PointerAlignment);
+
+ auto numConditionalTablesPtr =
+ IGF.Builder.CreateStructGEP(conditionalTablesSlice, 1, Size(PointerSize));
+ auto numConditionalTables = IGF.Builder.CreateLoad(numConditionalTablesPtr);
+
+ // Assert that the number of witness tables passed in is the number required
+ // for the conditional conformances of this witness table.
+
+ // FIXME(cond. conf. assert): remove this once we're confident in conditional
+ // conformances and especially dynamic casting. (Look for the other
+ // 'cond. conf. assert' FIXMEs too.)
+ auto failBB = IGF.createBasicBlock("bad_witness_table_count");
+ auto contBB = IGF.createBasicBlock("cont");
+
+ auto cmp = IGF.Builder.CreateICmpEQ(
+ numConditionalTables,
+ llvm::ConstantInt::get(IGM.SizeTy,
+ ConditionalRequirementPrivateDataIndices.size()));
+ IGF.Builder.CreateCondBr(cmp, contBB, failBB);
+
+ // All good: now we can actually fill in the witness table.
+ IGF.Builder.emitBlock(contBB);
// Initialize all the specialized base conformances.
for (auto &base : SpecializedBaseConformances) {
// Ask the ConformanceInfo to emit the wtable.
- // TODO: we may need to bind extra information in the IGF in order
- // to make conditional conformances work.
llvm::Value *baseWTable =
base.second->getTable(IGF, ConcreteType, &metadata);
baseWTable = IGF.Builder.CreateBitCast(baseWTable, IGM.Int8PtrTy);
// Store that to the appropriate slot in the new witness table.
- Address slot = IGF.Builder.CreateConstArrayGEP(wtable, base.first,
- IGM.getPointerSize());
+ Address slot =
+ IGF.Builder.CreateConstArrayGEP(wtable, base.first, PointerSize);
IGF.Builder.CreateStore(baseWTable, slot);
}
+ /// Run through the conditional conformance witness tables, pulling them out
+ /// of the slice and putting them into the private data of the witness table.
+ for (auto idx : indices(ConditionalRequirementPrivateDataIndices)) {
+ Address conditionalTablePtr =
+ IGF.Builder.CreateConstArrayGEP(conditionalTables, idx, PointerSize);
+ Address slot = getAddressOfPrivateDataSlot(
+ IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
+ auto conditionalTable = IGF.Builder.CreateLoad(conditionalTablePtr);
+ auto coercedSlot =
+ IGF.Builder.CreateElementBitCast(slot, conditionalTable->getType());
+ IGF.Builder.CreateStore(conditionalTable, coercedSlot);
+ }
+
IGF.Builder.CreateRetVoid();
+
+ // The counts didn't match; abort.
+ IGF.Builder.emitBlock(failBB);
+ llvm::Function *trapIntrinsic =
+ llvm::Intrinsic::getDeclaration(&IGM.Module, llvm::Intrinsic::ID::trap);
+ IGF.Builder.CreateCall(trapIntrinsic, {});
+ IGF.Builder.CreateUnreachable();
+
return fn;
}
@@ -1787,28 +1971,40 @@
assert(conformance->getProtocol() == protocol &&
"conformance is for wrong protocol");
- // Drill down to the root normal conformance.
+ auto checkCache =
+ [&](const ProtocolConformance *conf) -> Optional<ConformanceInfo *> {
+ // Check whether we've already cached this.
+ auto it = Conformances.find(conformance);
+ if (it != Conformances.end())
+ return it->second;
+
+ return None;
+ };
+
+ if (auto found = checkCache(conformance))
+ return **found;
+
+ // Drill down to the root normal
auto normalConformance = conformance->getRootNormalConformance();
- // Check whether we've already cached this.
- auto it = Conformances.find(normalConformance);
- if (it != Conformances.end()) return *it->second;
-
ConformanceInfo *info;
-
// If the conformance is dependent in any way, we need to unique it.
// TODO: maybe this should apply whenever it's out of the module?
// TODO: actually enable this
if (isDependentConformance(IGM, normalConformance,
ResilienceExpansion::Maximal)) {
- info = new AccessorConformanceInfo(normalConformance);
-
- // Otherwise, we can use a direct-referencing conformance.
+ info = new AccessorConformanceInfo(conformance);
+ Conformances.insert({conformance, info});
} else {
+ // Otherwise, we can use a direct-referencing conformance, which can get
+ // away with the non-specialized conformance.
+ if (auto found = checkCache(normalConformance))
+ return **found;
+
info = new DirectConformanceInfo(normalConformance);
+ Conformances.insert({normalConformance, info});
}
- Conformances.insert({normalConformance, info});
return *info;
}
@@ -2177,6 +2373,41 @@
return source;
}
+ case Component::Kind::ConditionalConformance: {
+ auto sourceConformance = sourceKey.Kind.getProtocolConformance();
+
+ auto reqtIndex = component.getPrimaryIndex();
+
+ ProtocolDecl *conformingProto;
+ auto found = SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ sourceConformance.getConcrete(),
+ [&](unsigned index, CanType type, ProtocolDecl *proto) {
+ if (reqtIndex == index) {
+ conformingProto = proto;
+ sourceKey.Type = type;
+ // done!
+ return true;
+ }
+ return /*finished?*/ false;
+ });
+ assert(found && "too many conditional conformances");
+
+ sourceKey.Kind =
+ LocalTypeDataKind::forAbstractProtocolWitnessTable(conformingProto);
+
+ if (source) {
+ WitnessIndex index(privateIndexToTableOffset(reqtIndex),
+ /*prefix*/ false);
+
+ source = emitInvariantLoadOfOpaqueWitness(IGF, source, index);
+ source = IGF.Builder.CreateBitCast(source, IGF.IGM.WitnessTablePtrTy);
+ setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type,
+ conformingProto);
+ }
+
+ return source;
+ }
+
case Component::Kind::Impossible:
llvm_unreachable("following an impossible path!");
@@ -2207,6 +2438,9 @@
out << "nominal_type_argument_conformance["
<< component.getPrimaryIndex() << "]";
break;
+ case Component::Kind::ConditionalConformance:
+ out << "conditional_conformance[" << component.getPrimaryIndex() << "]";
+ break;
case Component::Kind::Impossible:
out << "impossible";
break;
@@ -2594,8 +2828,10 @@
auto generics = ncGenerics->getCanonicalSignature();
CanSILFunctionType fnType = [&]() -> CanSILFunctionType {
return SILFunctionType::get(generics, SILFunctionType::ExtInfo(),
+ SILCoroutineKind::None,
/*callee*/ ParameterConvention::Direct_Unowned,
- /*params*/ {}, /*results*/ {}, /*error*/ None,
+ /*params*/ {}, /*yields*/ {},
+ /*results*/ {}, /*error*/ None,
IGM.Context);
}();
diff --git a/lib/IRGen/GenType.cpp b/lib/IRGen/GenType.cpp
index 50f37d2..cfc0e81 100644
--- a/lib/IRGen/GenType.cpp
+++ b/lib/IRGen/GenType.cpp
@@ -1636,6 +1636,8 @@
return convertBlockStorageType(cast<SILBlockStorageType>(ty));
case TypeKind::SILBox:
return convertBoxType(cast<SILBoxType>(ty));
+ case TypeKind::SILToken:
+ llvm_unreachable("should not be asking for representation of a SILToken");
}
}
llvm_unreachable("bad type kind");
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index 348ceb8..fe7ac34 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -242,8 +242,8 @@
buffer.getAlignment());
auto *boxStart = IGF.Builder.CreateLoad(boxAddress);
auto *alignmentMask = type.getAlignmentMask(IGF, T);
- auto *heapHeaderSize =
- llvm::ConstantInt::get(IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ auto *heapHeaderSize = llvm::ConstantInt::get(
+ IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset =
Builder.CreateAnd(Builder.CreateAdd(heapHeaderSize, alignmentMask),
Builder.CreateNot(alignmentMask));
@@ -820,7 +820,7 @@
IGF.Builder.CreateStore(ptr, dest);
auto *alignmentMask = fixedTI.getStaticAlignmentMask(IGM);
auto *heapHeaderSize = llvm::ConstantInt::get(
- IGM.SizeTy, getHeapHeaderSize(IGM).getValue());
+ IGM.SizeTy, IGM.RefCountedStructSize.getValue());
auto *startOffset = IGF.Builder.CreateAnd(
IGF.Builder.CreateAdd(heapHeaderSize, alignmentMask),
IGF.Builder.CreateNot(alignmentMask));
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 6861c81..ec76528 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -158,7 +158,7 @@
// Set up a pipeline.
PassManagerBuilderWrapper PMBuilder(Opts);
- if (Opts.Optimize && !Opts.DisableLLVMOptzns) {
+ if (Opts.shouldOptimize() && !Opts.DisableLLVMOptzns) {
PMBuilder.OptLevel = 2; // -Os
PMBuilder.SizeLevel = 1; // -Os
PMBuilder.Inliner = llvm::createFunctionInliningPass(200);
@@ -455,7 +455,7 @@
// rely on any other LLVM ARC transformations, but we do need ARC
// contraction to add the objc_retainAutoreleasedReturnValue
// assembly markers and remove clang.arc.used.
- if (Opts.Optimize && !DisableObjCARCContract)
+ if (Opts.shouldOptimize() && !DisableObjCARCContract)
EmitPasses.add(createObjCARCContractPass());
// Set up the final emission passes.
@@ -524,8 +524,9 @@
return nullptr;
}
- CodeGenOpt::Level OptLevel = Opts.Optimize ? CodeGenOpt::Default // -Os
- : CodeGenOpt::None;
+ CodeGenOpt::Level OptLevel = (Opts.shouldOptimize() ?
+ CodeGenOpt::Default // -Os
+ : CodeGenOpt::None);
// Set up TargetOptions and create the target features string.
TargetOptions TargetOpts;
@@ -684,7 +685,7 @@
/// IRGenModule.
static void runIRGenPreparePasses(SILModule &Module,
irgen::IRGenModule &IRModule) {
- SILPassManager PM(&Module, &IRModule);
+ SILPassManager PM(&Module, &IRModule, "irgen", /*isMandatoryPipeline=*/ true);
bool largeLoadable = Module.getOptions().EnableLargeLoadableTypes;
#define PASS(ID, Tag, Name)
#define IRGEN_PASS(ID, Tag, Name) \
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index 9907fd4..1f35073 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -45,6 +45,7 @@
#include "llvm/Config/config.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -275,31 +276,6 @@
return false;
}
- /// Determine whether this location is some kind of closure.
- static bool isAbstractClosure(const SILLocation &Loc) {
- if (Expr *E = Loc.getAsASTNode<Expr>())
- if (isa<AbstractClosureExpr>(E))
- return true;
- return false;
- }
-
- /// Both the code that is used to set up a closure object and the
- /// (beginning of) the closure itself has the AbstractClosureExpr as
- /// location. We are only interested in the latter case and want to
- /// ignore the setup code.
- ///
- /// callWithClosure(
- /// { // <-- a breakpoint here should only stop inside of the closure.
- /// foo();
- /// })
- ///
- /// The actual closure has a closure expression as scope.
- static bool shouldIgnoreAbstractClosure(Optional<SILLocation> Loc,
- const SILDebugScope *DS) {
- return Loc && isAbstractClosure(*Loc) && DS &&
- !isAbstractClosure(DS->Loc) && !Loc->is<ImplicitReturnLocation>();
- }
-
llvm::MDNode *createInlinedAt(const SILDebugScope *DS) {
auto *CS = DS->InlinedCallSite;
if (!CS)
@@ -1358,6 +1334,7 @@
case TypeKind::Module:
case TypeKind::SILBlockStorage:
case TypeKind::SILBox:
+ case TypeKind::SILToken:
case TypeKind::BuiltinUnsafeValueBuffer:
DEBUG(llvm::errs() << "Unhandled type: "; DbgTy.getType()->dump();
@@ -1502,7 +1479,6 @@
unsigned Lang = llvm::dwarf::DW_LANG_Swift;
std::string Producer = version::getSwiftFullVersion(
IGM.Context.LangOpts.EffectiveLanguageVersion);
- bool IsOptimized = Opts.Optimize;
StringRef Flags = Opts.DWARFDebugFlags;
unsigned Major, Minor;
std::tie(Major, Minor) = version::getSwiftNumericVersion();
@@ -1514,7 +1490,7 @@
// Clang is doing the same thing here.
TheCU = DBuilder.createCompileUnit(
Lang, DBuilder.createFile(AbsMainFile, Opts.DebugCompilationDir),
- Producer, IsOptimized, Flags, MajorRuntimeVersion, SplitName,
+ Producer, Opts.shouldOptimize(), Flags, MajorRuntimeVersion, SplitName,
Opts.DebugInfoKind > IRGenDebugInfoKind::LineTables
? llvm::DICompileUnit::FullDebug
: llvm::DICompileUnit::LineTablesOnly);
@@ -1597,7 +1573,7 @@
SILFunction *Fn = DS->getInlinedFunction();
SILLocation::DebugLoc L;
- if (shouldIgnoreAbstractClosure(Loc, DS) || (Fn && Fn->isThunk())) {
+ if ((Loc && Loc->isAutoGenerated()) || (Fn && Fn->isThunk())) {
// Reuse the last source location if we are still in the same
// scope to get a more contiguous line table.
// Otherwise use a line 0 artificial location.
@@ -1827,7 +1803,6 @@
// Various flags.
bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
bool IsDefinition = true;
- bool IsOptimized = Opts.Optimize;
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
// Mark everything that is not visible from the source code (i.e.,
@@ -1862,7 +1837,7 @@
// Construct the DISubprogram.
llvm::DISubprogram *SP = DBuilder.createFunction(
Scope, Name, LinkageName, File, Line, DIFnTy, IsLocalToUnit, IsDefinition,
- ScopeLine, Flags, IsOptimized, TemplateParameters, Decl, Error);
+ ScopeLine, Flags, Opts.shouldOptimize(), TemplateParameters, Decl, Error);
if (Fn && !Fn->isDeclaration())
Fn->setSubprogram(SP);
@@ -2002,7 +1977,7 @@
auto *BB = Builder.GetInsertBlock();
// An alloca may only be described by exactly one dbg.declare.
- if (isa<llvm::AllocaInst>(Storage) && llvm::FindAllocaDbgDeclare(Storage))
+ if (isa<llvm::AllocaInst>(Storage) && !llvm::FindDbgAddrUses(Storage).empty())
return;
// A dbg.declare is only meaningful if there is a single alloca for
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index 3dd914d..d9e5e78 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -32,10 +32,12 @@
using namespace irgen;
IRGenFunction::IRGenFunction(IRGenModule &IGM, llvm::Function *Fn,
+ OptimizationMode OptMode,
const SILDebugScope *DbgScope,
Optional<SILLocation> DbgLoc)
: IGM(IGM), Builder(IGM.getLLVMContext(),
IGM.DebugInfo && !IGM.Context.LangOpts.DebuggerSupport),
+ OptMode(OptMode),
CurFn(Fn), DbgScope(DbgScope), inOutlinedFunction(false) {
// Make sure the instructions in this function are attached its debug scope.
@@ -60,6 +62,13 @@
if (LocalTypeData) destroyLocalTypeData();
}
+OptimizationMode IRGenFunction::getEffectiveOptimizationMode() const {
+ if (OptMode != OptimizationMode::NotSet)
+ return OptMode;
+
+ return IGM.getOptions().OptMode;
+}
+
ModuleDecl *IRGenFunction::getSwiftModule() const {
return IGM.getSwiftModule();
}
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index 507cddb..8d46cbf 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -66,6 +66,10 @@
IRGenModule &IGM;
IRBuilder Builder;
+ /// If != OptimizationMode::NotSet, the optimization mode specified with an
+ /// function attribute.
+ OptimizationMode OptMode;
+
llvm::Function *CurFn;
ModuleDecl *getSwiftModule() const;
SILModule &getSILModule() const;
@@ -73,6 +77,7 @@
const IRGenOptions &getOptions() const;
IRGenFunction(IRGenModule &IGM, llvm::Function *fn,
+ OptimizationMode Mode = OptimizationMode::NotSet,
const SILDebugScope *DbgScope = nullptr,
Optional<SILLocation> DbgLoc = None);
~IRGenFunction();
@@ -111,6 +116,16 @@
//--- Helper methods -----------------------------------------------------------
public:
+
+ /// Returns the optimization mode for the function. If no mode is set for the
+ /// function, returns the global mode, i.e. the mode in IRGenOptions.
+ OptimizationMode getEffectiveOptimizationMode() const;
+
+ /// Returns true if this function should be optimized for size.
+ bool optimizeForSize() const {
+ return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
+ }
+
Address createAlloca(llvm::Type *ty, Alignment align,
const llvm::Twine &name);
Address createAlloca(llvm::Type *ty, llvm::Value *ArraySize, Alignment align,
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index b931047..e973c4f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -88,7 +88,7 @@
auto &ClangContext = Importer->getClangASTContext();
auto &CGO = Importer->getClangCodeGenOpts();
- CGO.OptimizationLevel = Opts.Optimize ? 3 : 0;
+ CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0;
CGO.DisableFPElim = Opts.DisableFPElim;
CGO.DiscardValueNames = !Opts.shouldProvideValueNames();
switch (Opts.DebugInfoKind) {
@@ -264,8 +264,11 @@
});
FullBoxMetadataPtrTy = FullBoxMetadataStructTy->getPointerTo(DefaultAS);
- llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, Int32Ty, Int32Ty};
+ // This must match struct HeapObject in the runtime.
+ llvm::Type *refCountedElts[] = {TypeMetadataPtrTy, IntPtrTy};
RefCountedStructTy->setBody(refCountedElts);
+ RefCountedStructSize =
+ Size(DataLayout.getStructLayout(RefCountedStructTy)->getSizeInBytes());
PtrSize = Size(DataLayout.getPointerSize(DefaultAS));
@@ -365,6 +368,10 @@
/*packed*/ false);
OpenedErrorTriplePtrTy = OpenedErrorTripleTy->getPointerTo(DefaultAS);
+ WitnessTablePtrPtrTy = WitnessTablePtrTy->getPointerTo(DefaultAS);
+ WitnessTableSliceTy = createStructType(*this, "swift.witness_table_slice",
+ {WitnessTablePtrPtrTy, SizeTy});
+
InvariantMetadataID = LLVMContext.getMDKindID("invariant.load");
InvariantNode = llvm::MDNode::get(LLVMContext, {});
DereferenceableID = LLVMContext.getMDKindID("dereferenceable");
@@ -811,7 +818,8 @@
}
/// Construct initial function attributes from options.
-void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs) {
+void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
+ OptimizationMode FuncOptMode) {
// Add DisableFPElim.
if (!IRGen.Opts.DisableFPElim) {
Attrs.addAttribute("no-frame-pointer-elim", "false");
@@ -844,7 +852,9 @@
});
Attrs.addAttribute("target-features", allFeatures);
}
- if (IRGen.Opts.OptimizeForSize)
+ if (FuncOptMode == OptimizationMode::NotSet)
+ FuncOptMode = IRGen.Opts.OptMode;
+ if (FuncOptMode == OptimizationMode::ForSize)
Attrs.addAttribute(llvm::Attribute::MinSize);
}
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index b242a31..6471f3e 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -24,6 +24,7 @@
#include "swift/Basic/LLVM.h"
#include "swift/Basic/ClusteredBitVector.h"
#include "swift/Basic/SuccessorMap.h"
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
@@ -446,6 +447,7 @@
llvm::PointerType *WitnessTablePtrTy;
};
llvm::StructType *RefCountedStructTy;/// %swift.refcounted = type { ... }
+ Size RefCountedStructSize; /// sizeof(%swift.refcounted)
llvm::PointerType *RefCountedPtrTy; /// %swift.refcounted*
llvm::PointerType *WeakReferencePtrTy;/// %swift.weak_reference*
llvm::PointerType *UnownedReferencePtrTy;/// %swift.unowned_reference*
@@ -491,6 +493,8 @@
llvm::PointerType *ErrorPtrTy; /// %swift.error*
llvm::StructType *OpenedErrorTripleTy; /// { %swift.opaque*, %swift.type*, i8** }
llvm::PointerType *OpenedErrorTriplePtrTy; /// { %swift.opaque*, %swift.type*, i8** }*
+ llvm::PointerType *WitnessTablePtrPtrTy; /// i8***
+ llvm::StructType *WitnessTableSliceTy; /// { witness_table**, i64 }
/// Used to create unique names for class layout types with tail allocated
/// elements.
@@ -954,7 +958,9 @@
/// invalid.
bool finalize();
- void constructInitialFnAttributes(llvm::AttrBuilder &Attrs);
+ void constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
+ OptimizationMode FuncOptMode =
+ OptimizationMode::NotSet);
llvm::AttributeList constructInitialAttributes();
void emitProtocolDecl(ProtocolDecl *D);
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 6656db0..8d12c00 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -593,7 +593,7 @@
/// expression depending on the value in the blocks dominated by the
/// value.
void emitDebugVariableRangeExtension(const SILBasicBlock *CurBB) {
- if (IGM.IRGen.Opts.Optimize)
+ if (IGM.IRGen.Opts.shouldOptimize())
return;
for (auto &Variable : ValueDomPoints) {
auto VarDominancePoint = Variable.second;
@@ -671,7 +671,7 @@
Alignment Align = Alignment(0)) {
auto Ty = Storage->getType();
// Never emit shadow copies when optimizing, or if already on the stack.
- if (IGM.IRGen.Opts.Optimize ||
+ if (IGM.IRGen.Opts.shouldOptimize() ||
isa<llvm::AllocaInst>(Storage) ||
isa<llvm::UndefValue>(Storage) ||
Ty == IGM.RefCountedPtrTy) // No debug info is emitted for refcounts.
@@ -710,7 +710,7 @@
StringRef Name, unsigned ArgNo,
llvm::SmallVectorImpl<llvm::Value *> ©) {
// Only do this at -O0.
- if (IGM.IRGen.Opts.Optimize) {
+ if (IGM.IRGen.Opts.shouldOptimize()) {
copy.append(vals.begin(), vals.end());
return;
}
@@ -776,7 +776,7 @@
auto runtimeTy = getRuntimeReifiedType(IGM,
Ty.getType()->getCanonicalType());
- if (!IGM.IRGen.Opts.Optimize && runtimeTy->hasArchetype())
+ if (!IGM.IRGen.Opts.shouldOptimize() && runtimeTy->hasArchetype())
runtimeTy.visit([&](CanType t) {
if (auto archetype = dyn_cast<ArchetypeType>(t))
emitTypeMetadataRef(archetype);
@@ -1018,12 +1018,18 @@
void visitIndexAddrInst(IndexAddrInst *i);
void visitTailAddrInst(TailAddrInst *i);
void visitIndexRawPointerInst(IndexRawPointerInst *i);
+
+ void visitBeginApplyInst(BeginApplyInst *i);
+ void visitEndApplyInst(EndApplyInst *i);
+ void visitAbortApplyInst(AbortApplyInst *i);
void visitUnreachableInst(UnreachableInst *i);
void visitBranchInst(BranchInst *i);
void visitCondBranchInst(CondBranchInst *i);
void visitReturnInst(ReturnInst *i);
void visitThrowInst(ThrowInst *i);
+ void visitUnwindInst(UnwindInst *i);
+ void visitYieldInst(YieldInst *i);
void visitSwitchValueInst(SwitchValueInst *i);
void visitSwitchEnumInst(SwitchEnumInst *i);
void visitSwitchEnumAddrInst(SwitchEnumAddrInst *i);
@@ -1103,6 +1109,7 @@
IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM,
SILFunction *f)
: IRGenFunction(IGM, IGM.getAddrOfSILFunction(f, ForDefinition),
+ f->getOptimizationMode(),
f->getDebugScope(), f->getLocation()),
CurSILFn(f) {
// Apply sanitizer attributes to the function.
@@ -2470,6 +2477,47 @@
}
}
+void IRGenSILFunction::visitUnwindInst(swift::UnwindInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "unwind instruction");
+ Builder.CreateUnreachable();
+ Builder.emitBlock(createBasicBlock("unwind"));
+}
+
+void IRGenSILFunction::visitYieldInst(swift::YieldInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "yield instruction");
+ Builder.CreateUnreachable();
+ Builder.emitBlock(createBasicBlock("yield"));
+}
+
+void IRGenSILFunction::visitBeginApplyInst(BeginApplyInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "begin_apply instruction");
+
+ // Set undef lowered values for all the results.
+ for (auto result : i->getYieldedValues()) {
+ auto &resultTI = getTypeInfo(result->getType());
+ if (result->getType().isAddress()) {
+ setLoweredAddress(result, resultTI.getUndefAddress());
+ } else {
+ Explosion undef;
+ emitFakeExplosion(resultTI, undef);
+ setLoweredExplosion(result, undef);
+ }
+ }
+}
+
+void IRGenSILFunction::visitEndApplyInst(EndApplyInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "end_apply instruction");
+}
+
+void IRGenSILFunction::visitAbortApplyInst(AbortApplyInst *i) {
+ IGM.unimplemented(i->getLoc().getSourceLoc(),
+ "abort_apply instruction");
+}
+
static llvm::BasicBlock *emitBBMapForSwitchValue(
IRGenSILFunction &IGF,
SmallVectorImpl<std::pair<SILValue, llvm::BasicBlock*>> &dests,
@@ -5060,7 +5108,7 @@
Builder.CreateCondBr(cond, failBB, contBB);
Builder.emitBlock(failBB);
- if (IGM.IRGen.Opts.Optimize) {
+ if (IGM.IRGen.Opts.shouldOptimize()) {
// Emit unique side-effecting inline asm calls in order to eliminate
// the possibility that an LLVM optimization or code generation pass
// will merge these blocks back together again. We emit an empty asm
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 31069ff..80c2e9b 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -73,47 +73,60 @@
return true;
}
-static bool modResultType(GenericEnvironment *genEnv,
- CanSILFunctionType loweredTy,
- irgen::IRGenModule &Mod);
+static bool shouldTransformResults(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
-static bool containsLargeLoadable(GenericEnvironment *GenericEnv,
- ArrayRef<SILParameterInfo> params,
- irgen::IRGenModule &Mod) {
- for (SILParameterInfo param : params) {
- SILType storageType = param.getSILStorageType();
- CanType currCanType = storageType.getSwiftRValueType();
- if (SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer())) {
- if (containsLargeLoadable(GenericEnv,
- currSILFunctionType->getParameters(), Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
- return true;
- }
- } else {
- switch (param.getConvention()) {
- case ParameterConvention::Indirect_In_Guaranteed:
- case ParameterConvention::Indirect_Inout:
- case ParameterConvention::Indirect_InoutAliasable:
- case ParameterConvention::Indirect_In: {
- continue;
- }
- default:
- break;
- }
- if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
- return true;
- }
- }
+static bool shouldTransformFunctionType(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
+
+static bool shouldTransformParameter(GenericEnvironment *env,
+ SILParameterInfo param,
+ irgen::IRGenModule &IGM) {
+ SILType storageType = param.getSILStorageType();
+
+ // FIXME: only function types and not recursively-transformable types?
+ if (auto fnType = storageType.getAs<SILFunctionType>())
+ return shouldTransformFunctionType(env, fnType, IGM);
+
+ switch (param.getConvention()) {
+ case ParameterConvention::Indirect_In_Guaranteed:
+ case ParameterConvention::Indirect_Inout:
+ case ParameterConvention::Indirect_InoutAliasable:
+ case ParameterConvention::Indirect_In:
+ return false;
+ default:
+ return isLargeLoadableType(env, storageType, IGM);
}
+}
+
+static bool shouldTransformFunctionType(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ if (shouldTransformResults(env, fnType, IGM))
+ return true;
+
+ for (auto param : fnType->getParameters()) {
+ if (shouldTransformParameter(env, param, IGM))
+ return true;
+ }
+
+ for (auto yield : fnType->getYields()) {
+ if (shouldTransformParameter(env, yield, IGM))
+ return true;
+ }
+
return false;
}
// Forward declarations - functions depend on each other
static SmallVector<SILParameterInfo, 4>
-getNewArgTys(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod);
+getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
+static SmallVector<SILYieldInfo, 2>
+getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM);
static SILType getNewSILType(GenericEnvironment *GenericEnv,
SILType storageType, irgen::IRGenModule &Mod);
@@ -135,11 +148,11 @@
static SmallVector<SILResultInfo, 2>
getNewResults(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod) {
+ CanSILFunctionType fnType, irgen::IRGenModule &Mod) {
// Get new SIL Function results - same as old results UNLESS:
// 1) Function type results might have a different signature
// 2) Large loadables are replaced by @out version
- auto origResults = currSILFunctionType->getResults();
+ auto origResults = fnType->getResults();
SmallVector<SILResultInfo, 2> newResults;
for (auto result : origResults) {
SILType currResultTy = result.getSILStorageType();
@@ -152,8 +165,7 @@
result.getConvention());
newResults.push_back(newResult);
} else if ((newSILType != currResultTy) &&
- modResultType(GenericEnv,
- CanSILFunctionType(currSILFunctionType), Mod)) {
+ shouldTransformResults(GenericEnv, fnType, Mod)) {
// Case (2) Above
SILResultInfo newSILResultInfo(newSILType.getSwiftRValueType(),
ResultConvention::Indirect);
@@ -165,39 +177,28 @@
return newResults;
}
-static SILFunctionType *
-getNewSILFunctionTypePtr(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType,
- irgen::IRGenModule &Mod) {
- if (!modifiableFunction(CanSILFunctionType(currSILFunctionType))) {
- return currSILFunctionType;
+static CanSILFunctionType
+getNewSILFunctionType(GenericEnvironment *env,
+ CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ if (!modifiableFunction(fnType)) {
+ return fnType;
}
- SmallVector<SILParameterInfo, 4> newArgTys =
- getNewArgTys(GenericEnv, currSILFunctionType, Mod);
- SILFunctionType *newSILFunctionType = SILFunctionType::get(
- currSILFunctionType->getGenericSignature(),
- currSILFunctionType->getExtInfo(),
- currSILFunctionType->getCalleeConvention(), newArgTys,
- getNewResults(GenericEnv, currSILFunctionType, Mod),
- currSILFunctionType->getOptionalErrorResult(),
- currSILFunctionType->getASTContext(),
- currSILFunctionType->getWitnessMethodConformanceOrNone());
- return newSILFunctionType;
-}
-
-static SILType getNewSILFunctionType(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType,
- irgen::IRGenModule &Mod) {
- if (!modifiableFunction(CanSILFunctionType(currSILFunctionType))) {
- SILType newSILType = SILType::getPrimitiveObjectType(
- currSILFunctionType->getCanonicalType());
- return newSILType;
- }
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(GenericEnv, currSILFunctionType, Mod);
- SILType newSILType =
- SILType::getPrimitiveObjectType(newSILFunctionType->getCanonicalType());
- return newSILType;
+ auto newParams = getNewParameters(env, fnType, IGM);
+ auto newYields = getNewYields(env, fnType, IGM);
+ auto newResults = getNewResults(env, fnType, IGM);
+ auto newFnType = SILFunctionType::get(
+ fnType->getGenericSignature(),
+ fnType->getExtInfo(),
+ fnType->getCoroutineKind(),
+ fnType->getCalleeConvention(),
+ newParams,
+ newYields,
+ newResults,
+ fnType->getOptionalErrorResult(),
+ fnType->getASTContext(),
+ fnType->getWitnessMethodConformanceOrNone());
+ return newFnType;
}
// Get the function type or the optional function type
@@ -223,35 +224,22 @@
SILType storageType,
irgen::IRGenModule &Mod) {
SILType newSILType = storageType;
- CanType currCanType = storageType.getSwiftRValueType();
- OptionalTypeKind optKind;
- if (auto optionalType = currCanType.getAnyOptionalObjectType(optKind)) {
- assert(optKind != OptionalTypeKind::OTK_None &&
- "Expected Real Optional Type");
- if (auto *currSILFunctionType =
- dyn_cast<SILFunctionType>(optionalType.getPointer())) {
- if (containsLargeLoadable(GenericEnv,
- currSILFunctionType->getParameters(), Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
+ if (auto objectType = storageType.getAnyOptionalObjectType()) {
+ if (auto fnType = objectType.getAs<SILFunctionType>()) {
+ if (shouldTransformFunctionType(GenericEnv, fnType, Mod)) {
+ auto newFnType = getNewSILFunctionType(GenericEnv, fnType, Mod);
newSILType =
- getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
- currCanType = newSILType.getSwiftRValueType();
- auto newType = OptionalType::get(optKind, currCanType);
- CanType newCanType = newType->getCanonicalType();
- newSILType = SILType::getPrimitiveObjectType(newCanType);
- if (storageType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
+ SILType::getPrimitiveType(newFnType, storageType.getCategory());
+ newSILType = SILType::getOptionalType(newSILType);
}
}
}
return newSILType;
}
-static bool modResultType(GenericEnvironment *genEnv,
- CanSILFunctionType loweredTy,
- irgen::IRGenModule &Mod) {
+static bool shouldTransformResults(GenericEnvironment *genEnv,
+ CanSILFunctionType loweredTy,
+ irgen::IRGenModule &Mod) {
if (!modifiableFunction(loweredTy)) {
return false;
}
@@ -274,53 +262,55 @@
genEnv = getGenericEnvironment(F->getModule(), loweredTy);
}
- return modResultType(genEnv, loweredTy, Mod);
+ return shouldTransformResults(genEnv, loweredTy, Mod);
+}
+
+static SILParameterInfo
+getNewParameter(GenericEnvironment *env, SILParameterInfo param,
+ irgen::IRGenModule &IGM) {
+ SILType storageType = param.getSILStorageType();
+ SILType newOptFuncType =
+ getNewOptionalFunctionType(env, storageType, IGM);
+ if (newOptFuncType != storageType) {
+ return param.getWithType(newOptFuncType.getSwiftRValueType());
+ }
+
+ if (auto paramFnType = storageType.getAs<SILFunctionType>()) {
+ if (shouldTransformFunctionType(env, paramFnType, IGM)) {
+ auto newFnType = getNewSILFunctionType(env, paramFnType, IGM);
+ return param.getWithType(newFnType);
+ } else {
+ return param;
+ }
+ } else if (isLargeLoadableType(env, storageType, IGM)) {
+ return SILParameterInfo(storageType.getSwiftRValueType(),
+ ParameterConvention::Indirect_In_Constant);
+ } else {
+ return param;
+ }
}
static SmallVector<SILParameterInfo, 4>
-getNewArgTys(GenericEnvironment *GenericEnv,
- SILFunctionType *currSILFunctionType, irgen::IRGenModule &Mod) {
- ArrayRef<SILParameterInfo> params = currSILFunctionType->getParameters();
- SmallVector<SILParameterInfo, 4> newArgTys;
- for (SILParameterInfo param : params) {
- SILType storageType = param.getSILStorageType();
- SILType newOptFuncType =
- getNewOptionalFunctionType(GenericEnv, storageType, Mod);
- if (newOptFuncType != storageType) {
- auto newParam = SILParameterInfo(newOptFuncType.getSwiftRValueType(),
- param.getConvention());
- newArgTys.push_back(newParam);
- continue;
- }
- CanType currCanType = storageType.getSwiftRValueType();
- if (SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer())) {
- if (containsLargeLoadable(GenericEnv,
- currSILFunctionType->getParameters(), Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
- SILType newSILType =
- getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
- if (storageType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
- auto newParam = SILParameterInfo(newSILType.getSwiftRValueType(),
- param.getConvention());
- newArgTys.push_back(newParam);
- } else {
- newArgTys.push_back(param);
- }
- } else if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
- SILType addrType = storageType.getAddressType();
- auto newParam =
- SILParameterInfo(addrType.getSwiftRValueType(),
- ParameterConvention::Indirect_In_Constant);
- newArgTys.push_back(newParam);
- } else {
- newArgTys.push_back(param);
- }
+getNewParameters(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ SmallVector<SILParameterInfo, 4> newParams;
+ for (SILParameterInfo param : fnType->getParameters()) {
+ auto newParam = getNewParameter(env, param, IGM);
+ newParams.push_back(newParam);
}
- return newArgTys;
+ return newParams;
+}
+
+static SmallVector<SILYieldInfo, 2>
+getNewYields(GenericEnvironment *env, CanSILFunctionType fnType,
+ irgen::IRGenModule &IGM) {
+ SmallVector<SILYieldInfo, 2> newYields;
+ for (auto oldYield : fnType->getYields()) {
+ auto newYieldAsParam = getNewParameter(env, oldYield, IGM);
+ newYields.push_back(SILYieldInfo(newYieldAsParam.getType(),
+ newYieldAsParam.getConvention()));
+ }
+ return newYields;
}
static SILType getNewSILType(GenericEnvironment *GenericEnv,
@@ -329,17 +319,11 @@
if (newSILType != storageType) {
return newSILType;
}
- CanType currCanType = storageType.getSwiftRValueType();
- if (SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer())) {
- if (containsLargeLoadable(GenericEnv, currSILFunctionType->getParameters(),
- Mod) ||
- modResultType(GenericEnv, CanSILFunctionType(currSILFunctionType),
- Mod)) {
- newSILType = getNewSILFunctionType(GenericEnv, currSILFunctionType, Mod);
- if (storageType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
+ if (auto fnType = storageType.getAs<SILFunctionType>()) {
+ if (shouldTransformFunctionType(GenericEnv, fnType, Mod)) {
+ auto newFnType = getNewSILFunctionType(GenericEnv, fnType, Mod);
+ newSILType = SILType::getPrimitiveType(newFnType,
+ storageType.getCategory());
}
} else if (isLargeLoadableType(GenericEnv, storageType, Mod)) {
newSILType = storageType.getAddressType();
@@ -584,14 +568,14 @@
return;
}
// Check callee - need new generic env:
- SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
+ CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
GenericEnvironment *genEnvCallee = nullptr;
if (origSILFunctionType->isPolymorphic()) {
genEnvCallee = getGenericEnvironment(
applySite.getModule(), CanSILFunctionType(origSILFunctionType));
}
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(genEnvCallee, origSILFunctionType, pass.Mod);
+ auto newSILFunctionType =
+ getNewSILFunctionType(genEnvCallee, origSILFunctionType, pass.Mod);
if (origSILFunctionType != newSILFunctionType) {
pass.applies.push_back(applySite.getInstruction());
}
@@ -617,27 +601,19 @@
return;
}
SILType currSILType = instr->getType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer());
- if (!currSILFunctionType) {
- llvm_unreachable("unsupported type");
- }
+ auto fnType = currSILType.castTo<SILFunctionType>();
+
GenericEnvironment *genEnv = nullptr;
- if (currSILFunctionType->isPolymorphic()) {
- genEnv = getGenericEnvironment(instr->getModule(),
- CanSILFunctionType(currSILFunctionType));
+ if (fnType->isPolymorphic()) {
+ genEnv = getGenericEnvironment(instr->getModule(), fnType);
}
Lowering::GenericContextScope GenericScope(
- instr->getModule().Types, currSILFunctionType->getGenericSignature());
- if (containsLargeLoadable(genEnv, currSILFunctionType->getParameters(),
- pass.Mod) ||
- modResultType(genEnv, CanSILFunctionType(currSILFunctionType),
- pass.Mod)) {
+ instr->getModule().Types, fnType->getGenericSignature());
+ if (shouldTransformFunctionType(genEnv, fnType, pass.Mod)) {
pass.methodInstsToMod.push_back(instr);
return;
}
- if (newResultsDiffer(genEnv, currSILFunctionType->getResults(), pass.Mod)) {
+ if (newResultsDiffer(genEnv, fnType->getResults(), pass.Mod)) {
pass.methodInstsToMod.push_back(instr);
}
}
@@ -763,8 +739,8 @@
if (!genEnv && canFuncType->isPolymorphic()) {
genEnv = getGenericEnvironment(instr->getModule(), canFuncType);
}
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(genEnv, funcType, pass.Mod);
+ auto newSILFunctionType =
+ getNewSILFunctionType(genEnv, funcType, pass.Mod);
if (funcType != newSILFunctionType) {
pass.tupleInstsToMod.push_back(instr);
}
@@ -1255,23 +1231,22 @@
if (!modifiableApply(applySite, pass.Mod)) {
continue;
}
- SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
- auto canSILFunctionType = CanSILFunctionType(origSILFunctionType);
+ CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
Lowering::GenericContextScope GenericScope(
- silModue.Types, canSILFunctionType->getGenericSignature());
+ silModue.Types, origSILFunctionType->getGenericSignature());
GenericEnvironment *genEnv = nullptr;
if (origSILFunctionType->isPolymorphic()) {
- genEnv = getGenericEnvironment(silModue, canSILFunctionType);
+ genEnv = getGenericEnvironment(silModue, origSILFunctionType);
}
- if (!modResultType(genEnv, canSILFunctionType, pass.Mod)) {
+ if (!shouldTransformResults(genEnv, origSILFunctionType, pass.Mod)) {
continue;
}
- auto singleResult = canSILFunctionType->getSingleResult();
+ auto singleResult = origSILFunctionType->getSingleResult();
auto resultStorageType = singleResult.getSILStorageType();
if (!isLargeLoadableType(genEnv, resultStorageType, pass.Mod)) {
// Make sure it is a function type
auto canType = resultStorageType.getSwiftRValueType();
- if (!dyn_cast<SILFunctionType>(canType.getPointer())) {
+ if (!isa<SILFunctionType>(canType)) {
// Check if it is an optional funciton type
OptionalTypeKind optKind;
auto optionalType = canType.getAnyOptionalObjectType(optKind);
@@ -1607,19 +1582,16 @@
}
static void castTupleInstr(SingleValueInstruction *instr, IRGenModule &Mod) {
- SILType currSILType = instr->getType().getObjectType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
- assert(funcType && "Expected SILFunctionType as tuple's return");
- CanSILFunctionType canFuncType = CanSILFunctionType(funcType);
+ SILType currSILType = instr->getType();
+ auto funcType = currSILType.castTo<SILFunctionType>();
GenericEnvironment *genEnv = instr->getFunction()->getGenericEnvironment();
- if (!genEnv && canFuncType->isPolymorphic()) {
- genEnv = getGenericEnvironment(instr->getModule(), canFuncType);
+ if (!genEnv && funcType->isPolymorphic()) {
+ genEnv = getGenericEnvironment(instr->getModule(), funcType);
}
- SILType newSILType = getNewSILFunctionType(genEnv, funcType, Mod);
- if (currSILType.isAddress()) {
- newSILType = newSILType.getAddressType();
- }
+ auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
+ SILType newSILType =
+ SILType::getPrimitiveType(newFnType, currSILType.getCategory());
+
auto II = instr->getIterator();
++II;
SILBuilder castBuilder(II);
@@ -1993,16 +1965,14 @@
for (MethodInst *instr : pass.methodInstsToMod) {
SILType currSILType = instr->getType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer());
+ auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
GenericEnvironment *genEnvForMethod = nullptr;
if (currSILFunctionType->isPolymorphic()) {
genEnvForMethod = getGenericEnvironment(
instr->getModule(), CanSILFunctionType(currSILFunctionType));
}
- SILType newSILType =
- getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod);
+ SILType newSILType = SILType::getPrimitiveObjectType(
+ getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod));
auto member = instr->getMember();
auto loc = instr->getLoc();
SILBuilder methodBuilder(instr);
@@ -2104,7 +2074,9 @@
origResultInfo.getConvention());
auto NewTy = SILFunctionType::get(
loweredTy->getGenericSignature(), loweredTy->getExtInfo(),
+ loweredTy->getCoroutineKind(),
loweredTy->getCalleeConvention(), loweredTy->getParameters(),
+ loweredTy->getYields(),
newSILResultInfo, loweredTy->getOptionalErrorResult(),
F->getModule().getASTContext(),
loweredTy->getWitnessMethodConformanceOrNone());
@@ -2131,10 +2103,8 @@
if (!genEnv && loweredTy->isPolymorphic()) {
genEnv = getGenericEnvironment(F->getModule(), loweredTy);
}
- if (containsLargeLoadable(
- genEnv, F->getLoweredFunctionType()->getParameters(), *currIRMod) ||
- modResultType(genEnv, CanSILFunctionType(F->getLoweredFunctionType()),
- *currIRMod)) {
+ if (shouldTransformFunctionType(genEnv, F->getLoweredFunctionType(),
+ *currIRMod)) {
modFuncs.insert(F);
}
return;
@@ -2178,16 +2148,15 @@
getOperandTypeWithCastIfNecessary(SILInstruction *containingInstr, SILValue op,
IRGenModule &Mod, SILBuilder &builder) {
SILType currSILType = op->getType();
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *funcType = dyn_cast<SILFunctionType>(currCanType);
- if (funcType) {
+ if (auto funcType = currSILType.getAs<SILFunctionType>()) {
CanSILFunctionType canFuncType = CanSILFunctionType(funcType);
GenericEnvironment *genEnv =
containingInstr->getFunction()->getGenericEnvironment();
if (!genEnv && canFuncType->isPolymorphic()) {
genEnv = getGenericEnvironment(containingInstr->getModule(), canFuncType);
}
- SILType newSILType = getNewSILFunctionType(genEnv, funcType, Mod);
+ auto newFnType = getNewSILFunctionType(genEnv, funcType, Mod);
+ SILType newSILType = SILType::getPrimitiveObjectType(newFnType);
if (currSILType.isAddress()) {
newSILType = newSILType.getAddressType(); // we need address for loads
if (newSILType != currSILType) {
@@ -2242,7 +2211,7 @@
callee = applySite.getCallee();
}
}
- SILFunctionType *origSILFunctionType = applySite.getSubstCalleeType();
+ CanSILFunctionType origSILFunctionType = applySite.getSubstCalleeType();
auto origCanType = CanSILFunctionType(origSILFunctionType);
Lowering::GenericContextScope GenericScope(
getModule()->Types, origCanType->getGenericSignature());
@@ -2251,8 +2220,8 @@
genEnv = getGenericEnvironment(applyInst->getModule(),
CanSILFunctionType(origSILFunctionType));
}
- SILFunctionType *newSILFunctionType =
- getNewSILFunctionTypePtr(genEnv, origSILFunctionType, *currIRMod);
+ CanSILFunctionType newSILFunctionType =
+ getNewSILFunctionType(genEnv, origSILFunctionType, *currIRMod);
CanSILFunctionType newCanSILFuncType(newSILFunctionType);
SILFunctionConventions newSILFunctionConventions(newCanSILFuncType,
*getModule());
@@ -2432,23 +2401,19 @@
if (auto *thinToPointer = dyn_cast<ThinFunctionToPointerInst>(convInstr)) {
currSILType = thinToPointer->getOperand()->getType();
}
- CanType currCanType = currSILType.getSwiftRValueType();
- SILFunctionType *currSILFunctionType =
- dyn_cast<SILFunctionType>(currCanType.getPointer());
+ auto currSILFunctionType = currSILType.castTo<SILFunctionType>();
Lowering::GenericContextScope GenericScope(
getModule()->Types,
- CanSILFunctionType(currSILFunctionType)->getGenericSignature());
- if (!currSILFunctionType) {
- llvm_unreachable("unsupported type");
- }
+ currSILFunctionType->getGenericSignature());
GenericEnvironment *genEnv =
convInstr->getFunction()->getGenericEnvironment();
auto loweredTy = convInstr->getFunction()->getLoweredFunctionType();
if (!genEnv && loweredTy->isPolymorphic()) {
genEnv = getGenericEnvironment(convInstr->getModule(), loweredTy);
}
- SILType newType =
+ CanSILFunctionType newFnType =
getNewSILFunctionType(genEnv, currSILFunctionType, *currIRMod);
+ SILType newType = SILType::getPrimitiveObjectType(newFnType);
SILBuilder convBuilder(convInstr);
SingleValueInstruction *newInstr = nullptr;
switch (convInstr->getKind()) {
@@ -2511,7 +2476,6 @@
void LoadableByAddress::updateLoweredTypes(SILFunction *F) {
IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
CanSILFunctionType funcType = F->getLoweredFunctionType();
- auto *currSILFunctionType = dyn_cast<SILFunctionType>(funcType.getPointer());
Lowering::GenericContextScope GenericScope(getModule()->Types,
funcType->getGenericSignature());
GenericEnvironment *genEnv = F->getGenericEnvironment();
@@ -2519,10 +2483,8 @@
if (!genEnv && loweredTy->isPolymorphic()) {
genEnv = getGenericEnvironment(F->getModule(), loweredTy);
}
- auto *newFuncTy =
- getNewSILFunctionTypePtr(genEnv, currSILFunctionType, *currIRMod);
-
- F->rewriteLoweredTypeUnsafe(CanSILFunctionType(newFuncTy));
+ auto newFuncTy = getNewSILFunctionType(genEnv, funcType, *currIRMod);
+ F->rewriteLoweredTypeUnsafe(newFuncTy);
}
/// The entry point to this function transformation.
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
index fe2fc05..7b3aa73 100644
--- a/lib/IRGen/LocalTypeData.cpp
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -194,7 +194,7 @@
// At -O0, create an alloca to keep the type alive.
auto name = type->getFullName();
- if (!IGF.IGM.IRGen.Opts.Optimize) {
+ if (!IGF.IGM.IRGen.Opts.shouldOptimize()) {
auto temp = IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(),
name);
IGF.Builder.CreateStore(data, temp);
diff --git a/lib/IRGen/MetadataPath.h b/lib/IRGen/MetadataPath.h
index 0dd1566..f72d034 100644
--- a/lib/IRGen/MetadataPath.h
+++ b/lib/IRGen/MetadataPath.h
@@ -57,7 +57,11 @@
/// Type metadata at requirement index P of a generic nominal type.
NominalTypeArgument,
- LastWithPrimaryIndex = NominalTypeArgument,
+
+ /// Conditional conformance at index P (i.e. the P'th element) of a
+ /// conformance.
+ ConditionalConformance,
+ LastWithPrimaryIndex = ConditionalConformance,
// Everything past this point has no index.
@@ -99,6 +103,7 @@
case Kind::OutOfLineBaseProtocol:
case Kind::NominalTypeArgumentConformance:
case Kind::NominalTypeArgument:
+ case Kind::ConditionalConformance:
return OperationCost::Load;
case Kind::AssociatedConformance:
@@ -169,6 +174,10 @@
index.getValue()));
}
+ void addConditionalConformanceComponent(unsigned index) {
+ Path.push_back(Component(Component::Kind::ConditionalConformance, index));
+ }
+
/// Return an abstract measurement of the cost of this path.
OperationCost cost() const {
auto cost = OperationCost::Free;
diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp
index e27403f..003caf3 100644
--- a/lib/IRGen/StructLayout.cpp
+++ b/lib/IRGen/StructLayout.cpp
@@ -38,11 +38,6 @@
llvm_unreachable("bad layout kind!");
}
-/// Return the size of the standard heap header.
-Size irgen::getHeapHeaderSize(IRGenModule &IGM) {
- return IGM.getPointerSize() + Size(8);
-}
-
/// Perform structure layout on the given types.
StructLayout::StructLayout(IRGenModule &IGM, CanType astTy,
LayoutKind layoutKind,
@@ -184,7 +179,7 @@
void StructLayoutBuilder::addHeapHeader() {
assert(StructFields.empty() && "adding heap header at a non-zero offset");
- CurSize = getHeapHeaderSize(IGM);
+ CurSize = IGM.RefCountedStructSize;
CurAlignment = IGM.getPointerAlignment();
StructFields.push_back(IGM.RefCountedStructTy);
}
diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h
index 70c1531..84128b8 100644
--- a/lib/IRGen/StructLayout.h
+++ b/lib/IRGen/StructLayout.h
@@ -395,8 +395,6 @@
const llvm::Twine &name = "") const;
};
-Size getHeapHeaderSize(IRGenModule &IGM);
-
/// Different policies for accessing a physical field.
enum class FieldAccess : uint8_t {
/// Instance variable offsets are constant.
diff --git a/lib/IRGen/WitnessIndex.h b/lib/IRGen/WitnessIndex.h
index fa11a7e..64d006e 100644
--- a/lib/IRGen/WitnessIndex.h
+++ b/lib/IRGen/WitnessIndex.h
@@ -25,15 +25,17 @@
/// A class which encapsulates an index into a witness table.
class WitnessIndex {
- unsigned Value : 31;
+ // Negative values are indexing into the private area of a protocol witness
+ // table.
+ int Value : 31;
unsigned IsPrefix : 1;
public:
WitnessIndex() = default;
- WitnessIndex(ValueWitness index) : Value(unsigned(index)) {}
- explicit WitnessIndex(unsigned index, bool isPrefix)
- : Value(index), IsPrefix(isPrefix) {}
+ WitnessIndex(ValueWitness index) : Value(int(index)) {}
+ explicit WitnessIndex(int index, bool isPrefix)
+ : Value(index), IsPrefix(isPrefix) {}
- unsigned getValue() const { return Value; }
+ int getValue() const { return Value; }
bool isPrefix() const { return IsPrefix; }
};
diff --git a/lib/Immediate/Immediate.cpp b/lib/Immediate/Immediate.cpp
index 967a64e..9d50334 100644
--- a/lib/Immediate/Immediate.cpp
+++ b/lib/Immediate/Immediate.cpp
@@ -195,12 +195,11 @@
/*, llvm::Linker::LinkerMode LinkerMode */)
{
llvm::LLVMContext &Ctx = SubModule->getContext();
- auto OldHandler = Ctx.getDiagnosticHandler();
+ auto OldHandler = Ctx.getDiagnosticHandlerCallBack();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
- Ctx.setDiagnosticHandler(linkerDiagnosticHandler, nullptr);
+ Ctx.setDiagnosticHandlerCallBack(linkerDiagnosticHandler, nullptr);
bool Failed = llvm::Linker::linkModules(*Module, std::move(SubModule));
- Ctx.setDiagnosticHandler(OldHandler, OldDiagnosticContext);
-
+ Ctx.setDiagnosticHandlerCallBack(OldHandler, OldDiagnosticContext);
return !Failed;
}
diff --git a/lib/Immediate/REPL.cpp b/lib/Immediate/REPL.cpp
index 31cc858..f2f1329 100644
--- a/lib/Immediate/REPL.cpp
+++ b/lib/Immediate/REPL.cpp
@@ -966,7 +966,7 @@
EE = builder.create();
IRGenOpts.OutputFilenames.clear();
- IRGenOpts.Optimize = false;
+ IRGenOpts.OptMode = OptimizationMode::NoOptimization;
IRGenOpts.OutputKind = IRGenOutputKind::Module;
IRGenOpts.UseJIT = true;
IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::None;
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 29ea715..5c6bd6b 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -19,11 +19,11 @@
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/Types.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/StringExtras.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Markup/Markup.h"
#include "swift/Sema/IDETypeChecking.h"
#include "llvm/ADT/APInt.h"
@@ -352,9 +352,9 @@
IndexSymbol Info;
if (CtorTyRef)
- if (!reportRef(CtorTyRef, Loc, Info))
+ if (!reportRef(CtorTyRef, Loc, Info, Data.AccKind))
return false;
- if (!reportRef(D, Loc, Info))
+ if (!reportRef(D, Loc, Info, Data.AccKind))
return false;
return true;
@@ -397,7 +397,8 @@
bool report(ValueDecl *D);
bool reportExtension(ExtensionDecl *D);
- bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
+ bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
+ Optional<AccessKind> AccKind);
bool startEntity(Decl *D, IndexSymbol &Info);
bool startEntityDecl(ValueDecl *D);
@@ -435,7 +436,7 @@
bool initFuncDeclIndexSymbol(FuncDecl *D, IndexSymbol &Info);
bool initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
- IndexSymbol &Info);
+ IndexSymbol &Info, Optional<AccessKind> AccKind);
bool indexComment(const Decl *D);
@@ -690,7 +691,7 @@
// don't report this ref again when visitDeclReference reports it
repressRefAtLoc(Loc);
- if (!reportRef(D, Loc, Info)) {
+ if (!reportRef(D, Loc, Info, None)) {
Cancelled = true;
return false;
}
@@ -716,7 +717,7 @@
if (auto *VD = Comps.back()->getBoundDecl()) {
if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
IndexSymbol Info;
- if (!reportRef(TAD, IdLoc, Info))
+ if (!reportRef(TAD, IdLoc, Info, None))
return false;
if (auto Ty = TAD->getUnderlyingTypeLoc().getType()) {
NTD = Ty->getAnyNominal();
@@ -934,7 +935,8 @@
}
bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
- IndexSymbol &Info) {
+ IndexSymbol &Info,
+ Optional<AccessKind> AccKind) {
if (!shouldIndex(D, /*IsRef=*/true))
return true; // keep walking
@@ -942,7 +944,7 @@
if (initFuncRefIndexSymbol(D, Loc, Info))
return true;
} else if (isa<AbstractStorageDecl>(D)) {
- if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info))
+ if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info, AccKind))
return true;
} else {
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
@@ -1146,7 +1148,9 @@
return false;
}
-bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc, IndexSymbol &Info) {
+bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D,
+ SourceLoc Loc, IndexSymbol &Info,
+ Optional<AccessKind> AccKind) {
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
return true;
@@ -1154,7 +1158,7 @@
if (!CurrentE)
return false;
- AccessKind Kind = CurrentE->hasLValueAccessKind() ? CurrentE->getLValueAccessKind() : AccessKind::Read;
+ AccessKind Kind = AccKind.hasValue() ? *AccKind : AccessKind::Read;
switch (Kind) {
case swift::AccessKind::Read:
Info.roles |= (unsigned)SymbolRole::Read;
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 360cbe4..717c120 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -15,6 +15,7 @@
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Migrator/ASTMigratorPass.h"
#include "swift/Parse/Lexer.h"
diff --git a/lib/Migrator/TypeOfMigratorPass.cpp b/lib/Migrator/TypeOfMigratorPass.cpp
index b7cb259..3697b9c 100644
--- a/lib/Migrator/TypeOfMigratorPass.cpp
+++ b/lib/Migrator/TypeOfMigratorPass.cpp
@@ -16,6 +16,7 @@
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Migrator/ASTMigratorPass.h"
#include "swift/Parse/Lexer.h"
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cbc064f..5595983 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -613,7 +613,8 @@
}
if (Tok.isNot(tok::identifier)) {
- diagnose(Loc, diag::inline_attribute_expect_option, AttrName);
+ diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
+ "none");
return false;
}
@@ -623,7 +624,7 @@
else if (Tok.getText() == "__always")
kind = InlineKind::Always;
else {
- diagnose(Loc, diag::inline_attribute_unknown_option,
+ diagnose(Loc, diag::optimization_attribute_unknown_option,
Tok.getText(), AttrName);
return false;
}
@@ -642,6 +643,46 @@
break;
}
+ case DAK_Optimize: {
+ if (!consumeIf(tok::l_paren)) {
+ diagnose(Loc, diag::attr_expected_lparen, AttrName,
+ DeclAttribute::isDeclModifier(DK));
+ return false;
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
+ "speed");
+ return false;
+ }
+
+ OptimizationMode optMode = OptimizationMode::NotSet;
+ if (Tok.getText() == "none")
+ optMode = OptimizationMode::NoOptimization;
+ else if (Tok.getText() == "speed")
+ optMode = OptimizationMode::ForSpeed;
+ else if (Tok.getText() == "size")
+ optMode = OptimizationMode::ForSize;
+ else {
+ diagnose(Loc, diag::optimization_attribute_unknown_option,
+ Tok.getText(), AttrName);
+ return false;
+ }
+ consumeToken(tok::identifier);
+ AttrRange = SourceRange(Loc, Tok.getRange().getStart());
+
+ if (!consumeIf(tok::r_paren)) {
+ diagnose(Loc, diag::attr_expected_rparen, AttrName,
+ DeclAttribute::isDeclModifier(DK));
+ return false;
+ }
+
+ if (!DiscardAttribute)
+ Attributes.add(new (Context) OptimizeAttr(AtLoc, AttrRange, optMode));
+
+ break;
+ }
+
case DAK_Ownership: {
// Handle weak/unowned/unowned(unsafe).
Ownership Kind = AttrName == "weak" ? Ownership::Weak : Ownership::Unowned;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index d3a64cc..46bfa7d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -165,9 +165,12 @@
ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
bool isExprBasic,
bool isForConditionalDirective) {
+ SyntaxParsingContextChild ExprSequnceContext(SyntaxContext,
+ SyntaxContextKind::Expr);
SmallVector<Expr*, 8> SequencedExprs;
SourceLoc startLoc = Tok.getLoc();
bool HasCodeCompletion = false;
+ bool PendingTernary = false;
while (true) {
if (isForConditionalDirective && Tok.isAtStartOfLine())
@@ -189,6 +192,12 @@
}
SequencedExprs.push_back(Primary.get());
+ // We know we can make a syntax node for ternary expression.
+ if (PendingTernary) {
+ SyntaxContext->makeNode(SyntaxKind::TernaryExpr, Tok.getLoc());
+ PendingTernary = false;
+ }
+
if (isForConditionalDirective && Tok.isAtStartOfLine())
break;
@@ -245,6 +254,10 @@
colonLoc);
SequencedExprs.push_back(unresolvedIf);
Message = diag::expected_expr_after_if_colon;
+
+ // Wait for the next expression to make a syntax node for ternary
+ // expression.
+ PendingTernary = true;
break;
}
@@ -368,6 +381,8 @@
/// sequence, but this isn't enforced until sequence-folding.
ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
bool isExprBasic) {
+ SyntaxParsingContextChild ElementContext(SyntaxContext,
+ SyntaxContextKind::Expr);
SourceLoc tryLoc;
bool hadTry = consumeIf(tok::kw_try, tryLoc);
Optional<Token> trySuffix;
@@ -473,7 +488,6 @@
Tok.setKind(tok::oper_prefix);
LLVM_FALLTHROUGH;
case tok::oper_prefix:
- SyntaxContext->addTokenSyntax(Tok.getLoc());
Operator = parseExprOperator();
break;
case tok::oper_binary_spaced:
@@ -867,7 +881,8 @@
lSquareLoc, indexArgs, indexArgLabels,
indexArgLabelLocs,
rSquareLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::Unknown);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
if (status.isError())
@@ -1216,7 +1231,8 @@
ParserStatus status = parseExprList(
tok::l_square, tok::r_square,
/*isPostfix=*/true, isExprBasic, lSquareLoc, indexArgs,
- indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure);
+ indexArgLabels, indexArgLabelLocs, rSquareLoc, trailingClosure,
+ SyntaxKind::Unknown);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
if (status.isError() || Result.isNull())
@@ -1389,8 +1405,7 @@
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
- SyntaxContext->addTokenSyntax(Loc);
- SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr);
+ SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Tok.getLoc());
Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
break;
@@ -1398,8 +1413,7 @@
case tok::floating_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
SourceLoc Loc = consumeToken(tok::floating_literal);
- SyntaxContext->addTokenSyntax(Loc);
- SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr);
+ SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Tok.getLoc());
Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
/*Implicit=*/false));
break;
@@ -1420,13 +1434,17 @@
Result = parseExprStringLiteral();
break;
- case tok::kw_nil:
+ case tok::kw_nil: {
+ SyntaxParsingContextChild NilContext(SyntaxContext, SyntaxKind::NilLiteralExpr);
Result = makeParserResult(
new (Context) NilLiteralExpr(consumeToken(tok::kw_nil)));
break;
+ }
case tok::kw_true:
case tok::kw_false: {
+ SyntaxParsingContextChild BoolContext(SyntaxContext,
+ SyntaxKind::BooleanLiteralExpr);
bool isTrue = Tok.is(tok::kw_true);
Result = makeParserResult(
new (Context) BooleanLiteralExpr(isTrue, consumeToken()));
@@ -1519,10 +1537,13 @@
break;
// If the next token is '_', parse a discard expression.
- case tok::kw__:
+ case tok::kw__: {
+ SyntaxParsingContextChild DAContext(SyntaxContext,
+ SyntaxKind::DiscardAssignmentExpr);
Result = makeParserResult(
new (Context) DiscardAssignmentExpr(consumeToken(), /*Implicit=*/false));
break;
+ }
case tok::pound_selector: // expr-selector
Result = parseExprSelector();
@@ -1608,7 +1629,8 @@
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::FunctionCallArgumentList);
if (status.isError())
return nullptr;
@@ -1657,7 +1679,8 @@
}
case tok::l_paren:
- Result = parseExprList(tok::l_paren, tok::r_paren);
+ Result = parseExprList(tok::l_paren, tok::r_paren,
+ SyntaxKind::FunctionCallArgumentList);
break;
case tok::l_square:
@@ -1805,13 +1828,10 @@
Token EntireTok = Tok;
// Create a syntax node for string literal.
- SyntaxContext->addTokenSyntax(Tok.getLoc());
- SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr);
- SyntaxParsingContextChild LocalContext(SyntaxContext,
- SyntaxContextKind::Expr);
+ SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, peekToken().getLoc());
// FIXME: Avoid creating syntax nodes for string interpolation.
- LocalContext.disable();
+ SyntaxParsingContextChild LocalContext(SyntaxContext, /*disabled*/true);
// The start location of the entire string literal.
SourceLoc Loc = Tok.getLoc();
@@ -1883,7 +1903,8 @@
assert(Tok.is(tok::l_paren));
TokReceiver->registerTokenKindChange(Tok.getLoc(),
tok::string_interpolation_anchor);
- ParserResult<Expr> E = parseExprList(tok::l_paren, tok::r_paren);
+ ParserResult<Expr> E = parseExprList(tok::l_paren, tok::r_paren,
+ SyntaxKind::Unknown);
Status |= E;
if (E.isNonNull()) {
Exprs.push_back(E.get());
@@ -1995,6 +2016,10 @@
SourceLoc lparenLoc = consumeToken(tok::l_paren);
SourceLoc rparenLoc;
while (true) {
+ // The following code may backtrack; so we disable the syntax tree creation
+ // in this scope.
+ SyntaxParsingContextChild DisabledContext(SyntaxContext, /*disabled*/true);
+
// Terminate at ')'.
if (Tok.is(tok::r_paren)) {
rparenLoc = consumeToken(tok::r_paren);
@@ -2054,6 +2079,8 @@
/// unqualified-decl-name generic-args?
Expr *Parser::parseExprIdentifier() {
assert(Tok.isAny(tok::identifier, tok::kw_self, tok::kw_Self));
+ SyntaxParsingContextChild IDSyntaxContext(SyntaxContext,
+ SyntaxKind::IdentifierExpr);
Token IdentTok = Tok;
// Parse the unqualified-decl-name.
@@ -2143,6 +2170,7 @@
Expr *Parser::parseExprEditorPlaceholder(Token PlaceholderTok,
Identifier PlaceholderId) {
+ SyntaxParsingContextChild DisableContext(SyntaxContext, /*disabled*/true);
assert(PlaceholderTok.is(tok::identifier));
assert(PlaceholderId.isEditorPlaceholder());
@@ -2752,7 +2780,8 @@
/// expr-paren-element:
/// (identifier ':')? expr
///
-ParserResult<Expr> Parser::parseExprList(tok leftTok, tok rightTok) {
+ParserResult<Expr>
+Parser::parseExprList(tok leftTok, tok rightTok, SyntaxKind Kind) {
SmallVector<Expr*, 8> subExprs;
SmallVector<Identifier, 8> subExprNames;
SmallVector<SourceLoc, 8> subExprNameLocs;
@@ -2766,7 +2795,8 @@
subExprNames,
subExprNameLocs,
rightLoc,
- trailingClosure);
+ trailingClosure,
+ Kind);
// A tuple with a single, unlabeled element is just parentheses.
if (subExprs.size() == 1 &&
@@ -2801,7 +2831,8 @@
SmallVectorImpl<Identifier> &exprLabels,
SmallVectorImpl<SourceLoc> &exprLabelLocs,
SourceLoc &rightLoc,
- Expr *&trailingClosure) {
+ Expr *&trailingClosure,
+ SyntaxKind Kind) {
trailingClosure = nullptr;
StructureMarkerRAII ParsingExprList(*this, Tok);
@@ -2812,6 +2843,7 @@
rightTok == tok::r_paren
? diag::expected_rparen_expr_list
: diag::expected_rsquare_expr_list,
+ Kind,
[&] () -> ParserStatus {
Identifier FieldName;
SourceLoc FieldNameLoc;
@@ -2823,6 +2855,8 @@
ParserStatus Status;
Expr *SubExpr = nullptr;
if (Tok.isBinaryOperator() && peekToken().isAny(rightTok, tok::comma)) {
+ SyntaxParsingContextChild operatorContext(SyntaxContext,
+ SyntaxContextKind::Expr);
SourceLoc Loc;
Identifier OperName;
if (parseAnyIdentifier(OperName, Loc, diag::expected_operator_ref)) {
@@ -2963,7 +2997,8 @@
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::FunctionCallArgumentList);
if (status.hasCodeCompletion())
return makeParserCodeCompletionResult<Expr>();
if (status.isError())
@@ -3055,7 +3090,8 @@
lParenLoc, args, argLabels,
argLabelLocs,
rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::FunctionCallArgumentList);
// Form the call.
auto Result = makeParserResult(status | fn,
@@ -3081,6 +3117,8 @@
/// expr-dictionary
// lsquare-starting ']'
ParserResult<Expr> Parser::parseExprCollection(SourceLoc LSquareLoc) {
+ SyntaxParsingContextChild ArrayOrDictContext(SyntaxContext);
+
// If the caller didn't already consume the '[', do so now.
if (LSquareLoc.isInvalid())
LSquareLoc = consumeToken(tok::l_square);
@@ -3091,6 +3129,8 @@
// [] is always an array.
if (Tok.is(tok::r_square)) {
+ // FIXME: Handle empty array syntax node.
+ ArrayOrDictContext.setSyntaxKind(SyntaxKind::ArrayExpr);
SourceLoc RSquareLoc = consumeToken(tok::r_square);
return makeParserResult(
ArrayExpr::create(Context, LSquareLoc, {}, {}, RSquareLoc));
@@ -3098,29 +3138,43 @@
// [:] is always an empty dictionary.
if (Tok.is(tok::colon) && peekToken().is(tok::r_square)) {
+ // FIXME: Handle empty dictionary syntax node.
+ ArrayOrDictContext.setSyntaxKind(SyntaxKind::DictionaryExpr);
consumeToken(tok::colon);
SourceLoc RSquareLoc = consumeToken(tok::r_square);
return makeParserResult(
DictionaryExpr::create(Context, LSquareLoc, {}, RSquareLoc));
}
- // Parse the first expression.
- ParserResult<Expr> FirstExpr
- = parseExpr(diag::expected_expr_in_collection_literal);
- if (FirstExpr.isNull()) {
- skipUntil(tok::r_square);
- if (Tok.is(tok::r_square))
- consumeToken();
- return FirstExpr;
+ bool ParseDict;
+ {
+ BacktrackingScope Scope(*this);
+ // Disable the syntax tree creation in the context.
+ SyntaxParsingContextChild DisabledContext(SyntaxContext, /*disabled*/true);
+ auto HasDelayedDecl = State->hasDelayedDecl();
+ // Parse the first expression.
+ ParserResult<Expr> FirstExpr
+ = parseExpr(diag::expected_expr_in_collection_literal);
+ if (FirstExpr.isNull() || Tok.is(tok::eof)) {
+ skipUntil(tok::r_square);
+ if (Tok.is(tok::r_square))
+ consumeToken();
+ Scope.cancelBacktrack();
+ ArrayOrDictContext.setContextKind(SyntaxContextKind::Expr);
+ return FirstExpr;
+ }
+ if (!HasDelayedDecl)
+ State->takeDelayedDeclState();
+ // If we have a ':', this is a dictionary literal.
+ ParseDict = Tok.is(tok::colon);
}
-
- // If we have a ':', this is a dictionary literal.
- if (Tok.is(tok::colon)) {
- return parseExprDictionary(LSquareLoc, FirstExpr);
+ if (ParseDict) {
+ ArrayOrDictContext.setSyntaxKind(SyntaxKind::DictionaryExpr);
+ return parseExprDictionary(LSquareLoc);
+ } else {
+ ArrayOrDictContext.setSyntaxKind(SyntaxKind::ArrayExpr);
+ return parseExprArray(LSquareLoc);
}
-
- // Otherwise, we have an array literal.
- return parseExprArray(LSquareLoc, FirstExpr);
}
/// parseExprArray - Parse an array literal expression.
@@ -3131,26 +3185,18 @@
/// expr-array:
/// '[' expr (',' expr)* ','? ']'
/// '[' ']'
-ParserResult<Expr> Parser::parseExprArray(SourceLoc LSquareLoc,
- ParserResult<Expr> FirstExpr) {
+ParserResult<Expr> Parser::parseExprArray(SourceLoc LSquareLoc) {
SmallVector<Expr *, 8> SubExprs;
SmallVector<SourceLoc, 8> CommaLocs;
- SubExprs.push_back(FirstExpr.get());
- SourceLoc CommaLoc, RSquareLoc;
- ParserStatus Status(FirstExpr);
-
- if (Tok.isNot(tok::r_square) && !consumeIf(tok::comma, CommaLoc)) {
- diagnose(Tok, diag::expected_separator, ",")
- .fixItInsertAfter(PreviousLoc, ",");
- Status.setIsParseError();
- }
-
- CommaLocs.push_back(CommaLoc);
-
+ SourceLoc RSquareLoc;
+ ParserStatus Status;
+ bool First = true;
+ bool HasError = false;
Status |= parseList(tok::r_square, LSquareLoc, RSquareLoc,
/*AllowSepAfterLast=*/true,
diag::expected_rsquare_array_expr,
+ SyntaxKind::ArrayElementList,
[&] () -> ParserStatus
{
ParserResult<Expr> Element
@@ -3158,11 +3204,21 @@
if (Element.isNonNull())
SubExprs.push_back(Element.get());
+ if (First) {
+ if (Tok.isNot(tok::r_square) && Tok.isNot(tok::comma)) {
+ diagnose(Tok, diag::expected_separator, ",").
+ fixItInsertAfter(PreviousLoc, ",");
+ HasError = true;
+ }
+ First = false;
+ }
+
if (Tok.is(tok::comma))
CommaLocs.push_back(Tok.getLoc());
-
return Element;
});
+ if (HasError)
+ Status.setIsParseError();
assert(SubExprs.size() >= 1);
return makeParserResult(Status,
@@ -3178,10 +3234,7 @@
/// expr-dictionary:
/// '[' expr ':' expr (',' expr ':' expr)* ','? ']'
/// '[' ':' ']'
-ParserResult<Expr> Parser::parseExprDictionary(SourceLoc LSquareLoc,
- ParserResult<Expr> FirstKey) {
- assert(Tok.is(tok::colon));
-
+ParserResult<Expr> Parser::parseExprDictionary(SourceLoc LSquareLoc) {
// Each subexpression is a (key, value) tuple.
// FIXME: We're not tracking the colon locations in the AST.
SmallVector<Expr *, 8> SubExprs;
@@ -3193,23 +3246,19 @@
SubExprs.push_back(TupleExpr::createImplicit(Context, Exprs, { }));
};
- bool FirstPair = true;
-
- ParserStatus Status(FirstKey);
+ ParserStatus Status;
Status |=
parseList(tok::r_square, LSquareLoc, RSquareLoc,
/*AllowSepAfterLast=*/true,
- diag::expected_rsquare_array_expr, [&]() -> ParserStatus {
+ diag::expected_rsquare_array_expr,
+ SyntaxKind::DictionaryElementList,
+ [&]() -> ParserStatus {
// Parse the next key.
ParserResult<Expr> Key;
- if (FirstPair) {
- Key = makeParserResult(FirstKey.get());
- FirstPair = false;
- } else {
- Key = parseExpr(diag::expected_key_in_dictionary_literal);
- if (Key.isNull())
- return Key;
- }
+
+ Key = parseExpr(diag::expected_key_in_dictionary_literal);
+ if (Key.isNull())
+ return Key;
// Parse the ':'.
if (Tok.isNot(tok::colon)) {
diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp
index 09c2496..352e927 100644
--- a/lib/Parse/ParsePattern.cpp
+++ b/lib/Parse/ParsePattern.cpp
@@ -19,10 +19,15 @@
#include "swift/AST/ASTWalker.h"
#include "swift/AST/Initializer.h"
#include "swift/Basic/StringExtras.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/SaveAndRestore.h"
+
using namespace swift;
+using namespace swift::syntax;
/// \brief Determine the kind of a default argument given a parsed
/// expression that has not yet been type-checked.
@@ -162,6 +167,7 @@
return parseList(tok::r_paren, leftParenLoc, rightParenLoc,
/*AllowSepAfterLast=*/false,
diag::expected_rparen_parameter,
+ SyntaxKind::Unknown,
[&]() -> ParserStatus {
ParsedParameter param;
ParserStatus status;
@@ -795,7 +801,8 @@
/*isExprBasic=*/false,
lParenLoc, args, argLabels,
argLabelLocs, rParenLoc,
- trailingClosure);
+ trailingClosure,
+ SyntaxKind::Unknown);
if (status.isSuccess()) {
backtrack.cancelBacktrack();
@@ -947,6 +954,7 @@
parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
diag::expected_rparen_tuple_pattern_list,
+ SyntaxKind::Unknown,
[&] () -> ParserStatus {
// Parse the pattern tuple element.
ParserStatus EltStatus;
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index aa7059c..5a91fae 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -592,17 +592,14 @@
}
SyntaxParsingContextChild LocalContext(SyntaxContext, SyntaxKind::CodeBlock);
SourceLoc LBLoc = consumeToken(tok::l_brace);
- LocalContext.addTokenSyntax(LBLoc);
SmallVector<ASTNode, 16> Entries;
SourceLoc RBLoc;
ParserStatus Status = parseBraceItems(Entries, BraceItemListKind::Brace,
BraceItemListKind::Brace);
- if (!parseMatchingToken(tok::r_brace, RBLoc,
- diag::expected_rbrace_in_brace_stmt, LBLoc)) {
- LocalContext.addTokenSyntax(RBLoc);
- }
+ parseMatchingToken(tok::r_brace, RBLoc,
+ diag::expected_rbrace_in_brace_stmt, LBLoc);
return makeParserResult(Status,
BraceStmt::create(Context, LBLoc, Entries, RBLoc));
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index bf66864..9721141 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -15,10 +15,14 @@
//===----------------------------------------------------------------------===//
#include "swift/Parse/Parser.h"
+#include "swift/AST/ASTWalker.h"
#include "swift/AST/Attr.h"
#include "swift/AST/TypeLoc.h"
#include "swift/Parse/Lexer.h"
#include "swift/Parse/CodeCompletionCallbacks.h"
+#include "swift/Syntax/SyntaxFactory.h"
+#include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
@@ -26,6 +30,7 @@
#include "llvm/Support/SaveAndRestore.h"
using namespace swift;
+using namespace swift::syntax;
TypeRepr *Parser::applyAttributeToType(TypeRepr *ty,
const TypeAttributes &attrs,
@@ -794,6 +799,7 @@
ParserStatus Status = parseList(tok::r_paren, LPLoc, RPLoc,
/*AllowSepAfterLast=*/false,
diag::expected_rparen_tuple_type_list,
+ SyntaxKind::Unknown,
[&] () -> ParserStatus {
TupleTypeReprElement element;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index a5d5c6d..b90d5f8 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -35,6 +35,7 @@
#include "llvm/ADT/Twine.h"
using namespace swift;
+using namespace swift::syntax;
void DelayedParsingCallbacks::anchor() { }
void SILParserTUStateBase::anchor() { }
@@ -127,6 +128,14 @@
}
} // unnamed namespace
+
+swift::Parser::BacktrackingScope::~BacktrackingScope() {
+ if (Backtrack) {
+ P.backtrackToPosition(PP);
+ DT.abort();
+ }
+}
+
void swift::performDelayedParsing(
DeclContext *DC, PersistentParserState &PersistentState,
CodeCompletionCallbacksFactory *CodeCompletionFactory) {
@@ -438,8 +447,8 @@
TokReceiver(SF.shouldKeepSyntaxInfo() ?
new TokenRecorder(SF) :
new ConsumeTokenReceiver()),
- SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(), Tok)) {
-
+ SyntaxContext(new syntax::SyntaxParsingContextRoot(SF, L->getBufferID(),
+ Tok)) {
State = PersistentState;
if (!State) {
OwnedState.reset(new PersistentParserState());
@@ -817,12 +826,33 @@
return false;
}
+static Optional<SyntaxKind> getListElementKind(SyntaxKind ListKind) {
+ switch (ListKind) {
+ case SyntaxKind::FunctionCallArgumentList:
+ return SyntaxKind::FunctionCallArgument;
+ case SyntaxKind::ArrayElementList:
+ return SyntaxKind::ArrayElement;
+ case SyntaxKind::DictionaryElementList:
+ return SyntaxKind::DictionaryElement;
+ default:
+ return None;
+ }
+}
+
ParserStatus
Parser::parseList(tok RightK, SourceLoc LeftLoc, SourceLoc &RightLoc,
- bool AllowSepAfterLast, Diag<> ErrorDiag,
+ bool AllowSepAfterLast, Diag<> ErrorDiag, SyntaxKind Kind,
std::function<ParserStatus()> callback) {
+ SyntaxParsingContextChild ListContext(SyntaxContext);
+ Optional<SyntaxKind> ElementKind = getListElementKind(Kind);
+ if (ElementKind)
+ ListContext.setSyntaxKind(Kind);
+ else
+ // FIXME: we shouldn't need this when all cases are handled.
+ ListContext.disable();
if (Tok.is(RightK)) {
+ ListContext.finalize();
RightLoc = consumeToken(RightK);
return makeParserSuccess();
}
@@ -835,6 +865,12 @@
consumeToken();
}
SourceLoc StartLoc = Tok.getLoc();
+ SyntaxParsingContextChild ElementContext(SyntaxContext);
+ if (ElementKind) {
+ ElementContext.setSyntaxKind(*ElementKind);
+ } else {
+ ElementContext.disable();
+ }
Status |= callback();
if (Tok.is(RightK))
break;
@@ -878,6 +914,7 @@
Status.setIsParseError();
}
+ ListContext.finalize();
if (Status.isError()) {
// If we've already got errors, don't emit missing RightK diagnostics.
RightLoc = Tok.is(RightK) ? consumeToken() : PreviousLoc;
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index cc7166e..675615d 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -28,10 +28,13 @@
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILUndef.h"
#include "swift/SIL/TypeLowering.h"
+#include "swift/Syntax/SyntaxKind.h"
#include "swift/Subsystems.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/SaveAndRestore.h"
+
using namespace swift;
+using namespace swift::syntax;
//===----------------------------------------------------------------------===//
// SILParserState implementation
@@ -875,7 +878,9 @@
static bool parseDeclSILOptional(bool *isTransparent,
IsSerialized_t *isSerialized,
IsThunk_t *isThunk, bool *isGlobalInit,
- Inline_t *inlineStrategy, bool *isLet,
+ Inline_t *inlineStrategy,
+ OptimizationMode *optimizationMode,
+ bool *isLet,
SmallVectorImpl<std::string> *Semantics,
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
ValueDecl **ClangDecl,
@@ -904,6 +909,12 @@
*isGlobalInit = true;
else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
*inlineStrategy = NoInline;
+ else if (optimizationMode && SP.P.Tok.getText() == "Onone")
+ *optimizationMode = OptimizationMode::NoOptimization;
+ else if (optimizationMode && SP.P.Tok.getText() == "Ospeed")
+ *optimizationMode = OptimizationMode::ForSpeed;
+ else if (optimizationMode && SP.P.Tok.getText() == "Osize")
+ *optimizationMode = OptimizationMode::ForSize;
else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
*inlineStrategy = AlwaysInline;
else if (MRK && SP.P.Tok.getText() == "readnone")
@@ -1236,7 +1247,7 @@
if (!P.consumeIf(tok::sil_exclamation)) {
// Construct SILDeclRef.
Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
- if (uncurryLevel < Result.getUncurryLevel())
+ if (uncurryLevel < Result.getParameterListCount() - 1)
Result = Result.asCurried();
return false;
}
@@ -1327,7 +1338,7 @@
// Construct SILDeclRef.
Result = SILDeclRef(VD, Kind, expansion, /*isCurried=*/false, IsObjC);
- if (uncurryLevel < Result.getUncurryLevel())
+ if (uncurryLevel < Result.getParameterListCount() - 1)
Result = Result.asCurried();
return false;
}
@@ -1462,6 +1473,7 @@
if (P.parseList(tok::r_paren, LParenLoc, RParenLoc,
/*AllowSepAfterLast=*/false,
diag::sil_basicblock_arg_rparen,
+ SyntaxKind::Unknown,
[&]() -> ParserStatus {
SILValue Arg;
SourceLoc ArgLoc;
@@ -1938,11 +1950,30 @@
break;
}
case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::BeginApplyInst:
case SILInstructionKind::PartialApplyInst:
case SILInstructionKind::TryApplyInst:
if (parseCallInstruction(InstLoc, Opcode, B, ResultVal))
return true;
break;
+ case SILInstructionKind::AbortApplyInst:
+ case SILInstructionKind::EndApplyInst: {
+ UnresolvedValueName argName;
+ if (parseValueName(argName)) return true;
+
+ if (parseSILDebugLocation(InstLoc, B))
+ return true;
+
+ SILType expectedTy = SILType::getSILTokenType(P.Context);
+ SILValue op = getLocalValue(argName, expectedTy, InstLoc, B);
+
+ if (Opcode == SILInstructionKind::AbortApplyInst) {
+ ResultVal = B.createAbortApply(InstLoc, op);
+ } else {
+ ResultVal = B.createEndApply(InstLoc, op);
+ }
+ break;
+ }
case SILInstructionKind::IntegerLiteralInst: {
SILType Ty;
if (parseSILType(Ty) ||
@@ -3735,6 +3766,51 @@
ResultVal = B.createThrow(InstLoc, Val);
break;
}
+ case SILInstructionKind::UnwindInst: {
+ if (parseSILDebugLocation(InstLoc, B))
+ return true;
+ ResultVal = B.createUnwind(InstLoc);
+ break;
+ }
+ case SILInstructionKind::YieldInst: {
+ SmallVector<SILValue, 6> values;
+
+ // Parse a parenthesized (unless length-1), comma-separated list
+ // of yielded values.
+ if (P.consumeIf(tok::l_paren)) {
+ do {
+ if (parseTypedValueRef(Val, B))
+ return true;
+ values.push_back(Val);
+ } while (P.consumeIf(tok::comma));
+
+ if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
+ return true;
+
+ } else {
+ if (parseTypedValueRef(Val, B))
+ return true;
+ values.push_back(Val);
+ }
+
+ Identifier resumeName, unwindName;
+ SourceLoc resumeLoc, unwindLoc;
+ if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
+ parseVerbatim("resume") ||
+ parseSILIdentifier(resumeName, resumeLoc,
+ diag::expected_sil_block_name) ||
+ P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
+ parseVerbatim("unwind") ||
+ parseSILIdentifier(unwindName, unwindLoc,
+ diag::expected_sil_block_name) ||
+ parseSILDebugLocation(InstLoc, B))
+ return true;
+
+ auto resumeBB = getBBForReference(resumeName, resumeLoc);
+ auto unwindBB = getBBForReference(unwindName, unwindLoc);
+ ResultVal = B.createYield(InstLoc, values, resumeBB, unwindBB);
+ break;
+ }
case SILInstructionKind::BranchInst: {
Identifier BBName;
SourceLoc NameLoc;
@@ -4677,17 +4753,39 @@
}
SILFunctionConventions substConv(substFTI, B.getModule());
+ // Validate the operand count.
+ if (substConv.getNumSILArguments() != ArgNames.size() &&
+ Opcode != SILInstructionKind::PartialApplyInst) {
+ P.diagnose(TypeLoc, diag::expected_sil_type_kind,
+ "to have the same number of arg names as arg types");
+ return true;
+ }
+
+ // Validate the coroutine kind.
+ if (Opcode == SILInstructionKind::ApplyInst ||
+ Opcode == SILInstructionKind::TryApplyInst) {
+ if (FTI->getCoroutineKind() != SILCoroutineKind::None) {
+ P.diagnose(TypeLoc, diag::expected_sil_type_kind,
+ "to not be a coroutine");
+ return true;
+ }
+ } else if (Opcode == SILInstructionKind::BeginApplyInst) {
+ if (FTI->getCoroutineKind() != SILCoroutineKind::YieldOnce) {
+ P.diagnose(TypeLoc, diag::expected_sil_type_kind,
+ "to be a yield_once coroutine");
+ return true;
+ }
+ } else {
+ assert(Opcode == SILInstructionKind::PartialApplyInst);
+ // partial_apply accepts all kinds of function
+ }
+
switch (Opcode) {
default: llvm_unreachable("Unexpected case");
case SILInstructionKind::ApplyInst : {
if (parseSILDebugLocation(InstLoc, B))
return true;
- if (substConv.getNumSILArguments() != ArgNames.size()) {
- P.diagnose(TypeLoc, diag::expected_sil_type_kind,
- "to have the same number of arg names as arg types");
- return true;
- }
-
+
unsigned ArgNo = 0;
SmallVector<SILValue, 4> Args;
for (auto &ArgName : ArgNames) {
@@ -4698,14 +4796,25 @@
ResultVal = B.createApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
break;
}
+ case SILInstructionKind::BeginApplyInst: {
+ if (parseSILDebugLocation(InstLoc, B))
+ return true;
+
+ unsigned ArgNo = 0;
+ SmallVector<SILValue, 4> Args;
+ for (auto &ArgName : ArgNames) {
+ SILType expectedTy = substConv.getSILArgumentType(ArgNo++);
+ Args.push_back(getLocalValue(ArgName, expectedTy, InstLoc, B));
+ }
+
+ ResultVal =
+ B.createBeginApply(InstLoc, FnVal, subs, Args, IsNonThrowingApply);
+ ResultVal->dump();
+ break;
+ }
case SILInstructionKind::PartialApplyInst: {
if (parseSILDebugLocation(InstLoc, B))
return true;
- if (substFTI->getParameters().size() < ArgNames.size()) {
- P.diagnose(TypeLoc, diag::expected_sil_type_kind,
- "have the right argument types");
- return true;
- }
// Compute the result type of the partial_apply, based on which arguments
// are getting applied.
@@ -4735,12 +4844,6 @@
parseSILDebugLocation(InstLoc, B))
return true;
- if (substConv.getNumSILArguments() != ArgNames.size()) {
- P.diagnose(TypeLoc, diag::expected_sil_type_kind,
- "to have the same number of arg names as arg types");
- return true;
- }
-
unsigned argNo = 0;
SmallVector<SILValue, 4> args;
for (auto &argName : ArgNames) {
@@ -4917,13 +5020,15 @@
IsThunk_t isThunk = IsNotThunk;
bool isGlobalInit = false;
Inline_t inlineStrategy = InlineDefault;
+ OptimizationMode optimizationMode = OptimizationMode::NotSet;
SmallVector<std::string, 1> Semantics;
SmallVector<ParsedSpecAttr, 4> SpecAttrs;
ValueDecl *ClangDecl = nullptr;
EffectsKind MRK = EffectsKind::Unspecified;
if (parseSILLinkage(FnLinkage, P) ||
parseDeclSILOptional(&isTransparent, &isSerialized, &isThunk, &isGlobalInit,
- &inlineStrategy, nullptr, &Semantics, &SpecAttrs,
+ &inlineStrategy, &optimizationMode, nullptr,
+ &Semantics, &SpecAttrs,
&ClangDecl, &MRK, FunctionState) ||
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -4950,6 +5055,7 @@
FunctionState.F->setThunk(IsThunk_t(isThunk));
FunctionState.F->setGlobalInit(isGlobalInit);
FunctionState.F->setInlineStrategy(inlineStrategy);
+ FunctionState.F->setOptimizationMode(optimizationMode);
FunctionState.F->setEffectsKind(MRK);
if (ClangDecl)
FunctionState.F->setClangNodeOwner(ClangDecl);
@@ -5078,7 +5184,7 @@
SILParser State(P);
if (parseSILLinkage(GlobalLinkage, P) ||
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
- nullptr, &isLet, nullptr, nullptr, nullptr,
+ nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
nullptr, State) ||
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
@@ -5121,7 +5227,7 @@
IsSerialized_t Serialized = IsNotSerialized;
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, VTableState))
return true;
@@ -5470,7 +5576,7 @@
IsSerialized_t isSerialized = IsNotSerialized;
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, WitnessState))
return true;
@@ -5522,6 +5628,8 @@
Lexer::SILBodyRAII Tmp(*P.L);
// Parse the entry list.
std::vector<SILWitnessTable::Entry> witnessEntries;
+ std::vector<SILWitnessTable::ConditionalConformance> conditionalConformances;
+
if (P.Tok.isNot(tok::r_brace)) {
do {
Identifier EntryKeyword;
@@ -5547,7 +5655,8 @@
continue;
}
- if (EntryKeyword.str() == "associated_type_protocol") {
+ if (EntryKeyword.str() == "associated_type_protocol" ||
+ EntryKeyword.str() == "conditional_conformance") {
if (P.parseToken(tok::l_paren, diag::expected_sil_witness_lparen))
return true;
CanType assoc = parseAssociatedTypePath(P, WitnessState, proto);
@@ -5572,9 +5681,14 @@
P.consumeToken();
}
- witnessEntries.push_back(SILWitnessTable::AssociatedTypeProtocolWitness{
- assoc, proto, conformance
- });
+ if (EntryKeyword.str() == "associated_type_protocol")
+ witnessEntries.push_back(
+ SILWitnessTable::AssociatedTypeProtocolWitness{assoc, proto,
+ conformance});
+ else
+ conditionalConformances.push_back(
+ SILWitnessTable::ConditionalConformance{assoc, conformance});
+
continue;
}
@@ -5647,7 +5761,8 @@
if (!wt)
wt = SILWitnessTable::create(M, *Linkage, theConformance);
- wt->convertToDefinition(witnessEntries, isSerialized);
+ wt->convertToDefinition(witnessEntries, conditionalConformances,
+ isSerialized);
BodyScope.reset();
return false;
}
diff --git a/lib/RemoteAST/RemoteAST.cpp b/lib/RemoteAST/RemoteAST.cpp
index 064af07..5dcf23e 100644
--- a/lib/RemoteAST/RemoteAST.cpp
+++ b/lib/RemoteAST/RemoteAST.cpp
@@ -334,7 +334,12 @@
auto label = Ctx.getIdentifier(param.getLabel());
auto flags = param.getFlags();
- funcParams.push_back(AnyFunctionType::Param(type, label, flags));
+ auto parameterFlags = ParameterTypeFlags()
+ .withInOut(flags.isInOut())
+ .withShared(flags.isShared())
+ .withVariadic(flags.isVariadic());
+
+ funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));
}
return FunctionType::get(funcParams, output, einfo);
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index 669c0d3..48e6546 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -151,6 +151,11 @@
return DynamicCastFeasibility::WillFail;
}
+ // AnyHashable is a special case: although it's a struct, there maybe another
+ // type conforming to it and to the TargetProtocol at the same time.
+ if (SourceNominalTy == SourceNominalTy->getASTContext().getAnyHashableDecl())
+ return DynamicCastFeasibility::MaySucceed;
+
// If we are in a whole-module compilation and
// if the source type is internal or target protocol is internal,
// then conformances cannot be changed at run-time, because only this
diff --git a/lib/SIL/OptimizationRemark.cpp b/lib/SIL/OptimizationRemark.cpp
index 87f8b26..c62a5fc 100644
--- a/lib/SIL/OptimizationRemark.cpp
+++ b/lib/SIL/OptimizationRemark.cpp
@@ -19,6 +19,7 @@
#include "swift/SIL/OptimizationRemark.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsSIL.h"
+#include "swift/Demangling/Demangler.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
@@ -43,7 +44,13 @@
: Key(Key), Val(llvm::utostr(N)) {}
Argument::Argument(StringRef Key, SILFunction *F)
- : Key(Key), Val(F->getName()) {
+ : Key(Key),
+ Val((Twine("\"") +
+ Demangle::demangleSymbolAsString(
+ F->getName(),
+ Demangle::DemangleOptions::SimplifiedUIDemangleOptions()) +
+ "\"")
+ .str()) {
if (F->hasLocation())
Loc = F->getLocation().getSourceLoc();
}
@@ -70,6 +77,8 @@
template <typename RemarkT, typename... ArgTypes>
static void emitRemark(SILModule &Module, const Remark<RemarkT> &R,
Diag<ArgTypes...> ID, bool DiagEnabled) {
+ if (R.getLocation().isInvalid())
+ return;
if (auto *Out = Module.getOptRecordStream())
// YAMLTraits takes a non-const reference even when outputting.
*Out << const_cast<Remark<RemarkT> &>(R);
@@ -110,7 +119,9 @@
if (!io.outputting() || Loc.isValid())
io.mapOptional("DebugLoc", Loc);
- StringRef FN = R.getFunction()->getName();
+ std::string FN = Demangle::demangleSymbolAsString(
+ R.getFunction()->getName(),
+ Demangle::DemangleOptions::SimplifiedUIDemangleOptions());
io.mapRequired("Function", FN);
io.mapOptional("Args", R.getArgs());
}
diff --git a/lib/SIL/SILArgument.cpp b/lib/SIL/SILArgument.cpp
index dfd1686..87ed4af 100644
--- a/lib/SIL/SILArgument.cpp
+++ b/lib/SIL/SILArgument.cpp
@@ -73,12 +73,14 @@
case TermKind::UnreachableInst:
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
llvm_unreachable("Have terminator that implies no successors?!");
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
case TermKind::SwitchEnumAddrInst:
case TermKind::CheckedCastAddrBranchInst:
case TermKind::DynamicMethodBranchInst:
+ case TermKind::YieldInst:
return SILValue();
case TermKind::BranchInst:
return cast<const BranchInst>(TI)->getArg(Index);
diff --git a/lib/SIL/SILBuilder.cpp b/lib/SIL/SILBuilder.cpp
index 06d7bff..aa65f47 100644
--- a/lib/SIL/SILBuilder.cpp
+++ b/lib/SIL/SILBuilder.cpp
@@ -79,8 +79,10 @@
}
auto appliedFnType = SILFunctionType::get(nullptr, extInfo,
+ FTI->getCoroutineKind(),
calleeConvention,
newParams,
+ FTI->getYields(),
results,
FTI->getOptionalErrorResult(),
M.getASTContext());
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 1acb152..e7ac325 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -227,29 +227,6 @@
return false;
}
-static unsigned getFuncNaturalUncurryLevel(AnyFunctionRef AFR) {
- assert(AFR.getParameterLists().size() >= 1 && "no arguments for func?!");
- return AFR.getParameterLists().size() - 1;
-}
-
-unsigned swift::getNaturalUncurryLevel(ValueDecl *vd) {
- if (auto *func = dyn_cast<FuncDecl>(vd)) {
- return getFuncNaturalUncurryLevel(func);
- } else if (isa<ConstructorDecl>(vd)) {
- return 1;
- } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
- return ed->hasAssociatedValues() ? 1 : 0;
- } else if (isa<DestructorDecl>(vd)) {
- return 0;
- } else if (isa<ClassDecl>(vd)) {
- return 1;
- } else if (isa<VarDecl>(vd)) {
- return 0;
- } else {
- llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
- }
-}
-
SILDeclRef::SILDeclRef(ValueDecl *vd, SILDeclRef::Kind kind,
ResilienceExpansion expansion,
bool isCurried, bool isForeign)
@@ -709,6 +686,10 @@
case SILDeclRef::ManglingKind::DynamicThunk:
SKind = ASTMangler::SymbolKind::DynamicThunk;
break;
+ case SILDeclRef::ManglingKind::SwiftDispatchThunk:
+ assert(!isForeign && !isDirectReference && !isCurried);
+ SKind = ASTMangler::SymbolKind::SwiftDispatchThunk;
+ break;
}
switch (kind) {
@@ -795,6 +776,22 @@
llvm_unreachable("bad entity kind!");
}
+bool SILDeclRef::requiresNewVTableEntry() const {
+ if (cast<AbstractFunctionDecl>(getDecl())->needsNewVTableEntry())
+ return true;
+ if (kind == SILDeclRef::Kind::Allocator) {
+ auto *cd = cast<ConstructorDecl>(getDecl());
+ if (cd->isRequired()) {
+ auto *baseCD = cd->getOverriddenDecl();
+ if(!baseCD ||
+ !baseCD->isRequired() ||
+ baseCD->hasClangNode())
+ return true;
+ }
+ }
+ return false;
+}
+
SILDeclRef SILDeclRef::getOverridden() const {
if (!hasDecl())
return SILDeclRef();
@@ -888,12 +885,23 @@
llvm_unreachable("Unhandled access level in switch.");
}
-unsigned SILDeclRef::getUncurryLevel() const {
- if (isCurried)
- return 0;
- if (!hasDecl())
- return getFuncNaturalUncurryLevel(*getAnyFunctionRef());
- if (kind == Kind::DefaultArgGenerator)
- return 0;
- return getNaturalUncurryLevel(getDecl());
+unsigned SILDeclRef::getParameterListCount() const {
+ if (isCurried || !hasDecl() || kind == Kind::DefaultArgGenerator)
+ return 1;
+
+ auto *vd = getDecl();
+
+ if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
+ return func->getParameterLists().size();
+ } else if (auto *ed = dyn_cast<EnumElementDecl>(vd)) {
+ return ed->hasAssociatedValues() ? 2 : 1;
+ } else if (isa<DestructorDecl>(vd)) {
+ return 1;
+ } else if (isa<ClassDecl>(vd)) {
+ return 2;
+ } else if (isa<VarDecl>(vd)) {
+ return 1;
+ } else {
+ llvm_unreachable("Unhandled ValueDecl for SILDeclRef");
+ }
}
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index ec909fd..4212375 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -18,6 +18,7 @@
#include "swift/SIL/CFG.h"
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/AST/GenericEnvironment.h"
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/GraphWriter.h"
@@ -96,7 +97,8 @@
Serialized(isSerialized), Thunk(isThunk),
ClassSubclassScope(unsigned(classSubclassScope)), GlobalInitFlag(false),
InlineStrategy(inlineStrategy), Linkage(unsigned(Linkage)),
- HasCReferences(false), KeepAsPublic(false), EffectsKindAttr(E),
+ HasCReferences(false), KeepAsPublic(false),
+ OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
EntryCount(entryCount) {
if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this);
@@ -168,10 +170,16 @@
return getModule().getASTContext();
}
+OptimizationMode SILFunction::getEffectiveOptimizationMode() const {
+ if (OptMode != OptimizationMode::NotSet)
+ return OptMode;
+
+ return getModule().getOptions().OptMode;
+}
+
bool SILFunction::shouldOptimize() const {
- if (Module.getStage() == SILStage::Raw)
- return true;
- return !hasSemanticsAttr("optimize.sil.never");
+ return !hasSemanticsAttr("optimize.sil.never") &&
+ getEffectiveOptimizationMode() != OptimizationMode::NoOptimization;
}
Type SILFunction::mapTypeIntoContext(Type type) const {
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 29c2e2e..b55264e 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -196,10 +196,13 @@
type->getWitnessMethodConformanceOrNone() == witnessMethodConformance)
return type;
- return SILFunctionType::get(type->getGenericSignature(), extInfo, callee,
- type->getParameters(), type->getResults(),
+ return SILFunctionType::get(type->getGenericSignature(),
+ extInfo, type->getCoroutineKind(), callee,
+ type->getParameters(), type->getYields(),
+ type->getResults(),
type->getOptionalErrorResult(),
- type->getASTContext(), witnessMethodConformance);
+ type->getASTContext(),
+ witnessMethodConformance);
}
namespace {
@@ -960,7 +963,8 @@
.withIsPseudogeneric(pseudogeneric)
.withNoEscape(extInfo.isNoEscape());
- return SILFunctionType::get(genericSig, silExtInfo, calleeConvention, inputs,
+ return SILFunctionType::get(genericSig, silExtInfo, SILCoroutineKind::None,
+ calleeConvention, inputs, /*yields*/ {},
results, errorResult, M.getASTContext(),
witnessMethodConformance);
}
@@ -1777,7 +1781,7 @@
return false;
// Must be a type member.
- if (constant.getUncurryLevel() != 1)
+ if (constant.getParameterListCount() != 2)
return false;
// Must be imported from a function.
@@ -2005,20 +2009,6 @@
return ty->getParameters().back();
}
-static bool requiresNewVTableEntry(SILDeclRef method) {
- if (cast<AbstractFunctionDecl>(method.getDecl())->needsNewVTableEntry())
- return true;
- if (method.kind == SILDeclRef::Kind::Allocator) {
- auto *ctor = cast<ConstructorDecl>(method.getDecl());
- if (ctor->isRequired()) {
- if (!ctor->getOverriddenDecl()->isRequired()
- || ctor->getOverriddenDecl()->hasClangNode())
- return true;
- }
- }
- return false;
-}
-
// This check duplicates TypeConverter::checkForABIDifferences(),
// but on AST types. The issue is we only want to introduce a new
// vtable thunk if the AST type changes, but an abstraction change
@@ -2034,7 +2024,7 @@
SILDeclRef cur = method, next = method;
do {
cur = next;
- if (requiresNewVTableEntry(cur))
+ if (cur.requiresNewVTableEntry())
return cur;
next = cur.getNextOverriddenVTableEntry();
} while (next);
@@ -2112,7 +2102,7 @@
if (found != ConstantOverrideTypes.end())
return *found->second;
- assert(requiresNewVTableEntry(base) && "base must not be an override");
+ assert(base.requiresNewVTableEntry() && "base must not be an override");
auto baseInfo = getConstantInfo(base);
auto derivedInfo = getConstantInfo(derived);
@@ -2235,6 +2225,12 @@
substParams.push_back(subst(origParam));
}
+ SmallVector<SILYieldInfo, 8> substYields;
+ substYields.reserve(origType->getYields().size());
+ for (auto &origYield : origType->getYields()) {
+ substYields.push_back(subst(origYield));
+ }
+
Optional<ProtocolConformanceRef> witnessMethodConformance;
if (auto conformance = origType->getWitnessMethodConformanceOrNone()) {
assert(origType->getExtInfo().hasSelfParam());
@@ -2253,8 +2249,9 @@
}
return SILFunctionType::get(nullptr, origType->getExtInfo(),
+ origType->getCoroutineKind(),
origType->getCalleeConvention(), substParams,
- substResults, substErrorResult,
+ substYields, substResults, substErrorResult,
getASTContext(), witnessMethodConformance);
}
@@ -2267,6 +2264,10 @@
return SILResultInfo(visit(orig.getType()), orig.getConvention());
}
+ SILYieldInfo subst(SILYieldInfo orig) {
+ return SILYieldInfo(visit(orig.getType()), orig.getConvention());
+ }
+
SILParameterInfo subst(SILParameterInfo orig) {
return SILParameterInfo(visit(orig.getType()), orig.getConvention());
}
@@ -2486,7 +2487,7 @@
TypeConverter::LoweredFormalTypes
TypeConverter::getLoweredFormalTypes(SILDeclRef constant,
CanAnyFunctionType fnType) {
- unsigned uncurryLevel = constant.getUncurryLevel();
+ unsigned uncurryLevel = constant.getParameterListCount() - 1;
auto extInfo = fnType->getExtInfo();
// Form an abstraction pattern for bridging purposes.
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index 589b5c1..2e247bf 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -1335,10 +1335,25 @@
return iterator(*this, getEndOffset());
}
+SILInstructionResultArray::reverse_iterator
+SILInstructionResultArray::rbegin() const {
+ return llvm::make_reverse_iterator(end());
+}
+
+SILInstructionResultArray::reverse_iterator
+SILInstructionResultArray::rend() const {
+ return llvm::make_reverse_iterator(begin());
+}
+
SILInstructionResultArray::range SILInstructionResultArray::getValues() const {
return {begin(), end()};
}
+SILInstructionResultArray::reverse_range
+SILInstructionResultArray::getReversedValues() const {
+ return {rbegin(), rend()};
+}
+
const ValueBase *SILInstructionResultArray::front() const {
assert(size() && "Can not access front of an empty result array");
return *begin();
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 2af36c2..6f1f581 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -33,6 +33,14 @@
using namespace swift;
using namespace Lowering;
+/// Allocate an instruction that inherits from llvm::TrailingObjects<>.
+template <class Inst, class... TrailingTypes, class... CountTypes>
+static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
+ return F.getModule().allocateInst(
+ Inst::template totalSizeToAlloc<TrailingTypes...>(counts...),
+ alignof(Inst));
+}
+
// Collect used open archetypes from a given type into the \p openedArchetypes.
// \p openedArchetypes is being used as a set. We don't use a real set type here
// for performance reasons.
@@ -403,6 +411,7 @@
: InstructionBase(Loc, Callee, SubstCalleeTy, Subs, Args,
TypeDependentOperands, SpecializationInfo, Result) {
setNonThrowing(isNonThrowing);
+ assert(!SubstCalleeTy.castTo<SILFunctionType>()->isCoroutine());
}
ApplyInst *
@@ -423,13 +432,77 @@
SmallVector<SILValue, 32> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
SubstCalleeSILTy.getSwiftRValueType(), Subs);
- void *Buffer = allocate(F, Subs, TypeDependentOperands, Args);
+ void *Buffer =
+ allocateTrailingInst<ApplyInst, Operand, Substitution>(
+ F, getNumAllOperands(Args, TypeDependentOperands), Subs.size());
return ::new(Buffer) ApplyInst(Loc, Callee, SubstCalleeSILTy,
Result, Subs, Args,
TypeDependentOperands, isNonThrowing,
SpecializationInfo);
}
+BeginApplyInst::BeginApplyInst(SILDebugLocation loc, SILValue callee,
+ SILType substCalleeTy,
+ ArrayRef<SILType> allResultTypes,
+ ArrayRef<ValueOwnershipKind> allResultOwnerships,
+ SubstitutionList subs,
+ ArrayRef<SILValue> args,
+ ArrayRef<SILValue> typeDependentOperands,
+ bool isNonThrowing,
+ const GenericSpecializationInformation *specializationInfo)
+ : InstructionBase(loc, callee, substCalleeTy, subs, args,
+ typeDependentOperands, specializationInfo),
+ MultipleValueInstructionTrailingObjects(this, allResultTypes,
+ allResultOwnerships) {
+ setNonThrowing(isNonThrowing);
+ assert(substCalleeTy.castTo<SILFunctionType>()->isCoroutine());
+}
+
+BeginApplyInst *
+BeginApplyInst::create(SILDebugLocation loc, SILValue callee,
+ SubstitutionList subs, ArrayRef<SILValue> args,
+ bool isNonThrowing,
+ Optional<SILModuleConventions> moduleConventions,
+ SILFunction &F,
+ SILOpenedArchetypesState &openedArchetypes,
+ const GenericSpecializationInformation *specializationInfo) {
+ SILType substCalleeSILType =
+ callee->getType().substGenericArgs(F.getModule(), subs);
+ auto substCalleeType = substCalleeSILType.castTo<SILFunctionType>();
+
+ SILFunctionConventions conv(substCalleeType,
+ moduleConventions.hasValue()
+ ? moduleConventions.getValue()
+ : SILModuleConventions(F.getModule()));
+
+ SmallVector<SILType, 8> resultTypes;
+ SmallVector<ValueOwnershipKind, 8> resultOwnerships;
+
+ for (auto &yield : substCalleeType->getYields()) {
+ auto yieldType = conv.getSILType(yield);
+ auto convention = SILArgumentConvention(yield.getConvention());
+ resultTypes.push_back(yieldType);
+ resultOwnerships.push_back(
+ ValueOwnershipKind(F.getModule(), yieldType, convention));
+ }
+
+ resultTypes.push_back(SILType::getSILTokenType(F.getASTContext()));
+ resultOwnerships.push_back(ValueOwnershipKind::Trivial);
+
+ SmallVector<SILValue, 32> typeDependentOperands;
+ collectTypeDependentOperands(typeDependentOperands, openedArchetypes, F,
+ substCalleeType, subs);
+ void *buffer =
+ allocateTrailingInst<BeginApplyInst, Operand, Substitution,
+ MultipleValueInstruction*, BeginApplyResult>(
+ F, getNumAllOperands(args, typeDependentOperands), subs.size(),
+ 1, resultTypes.size());
+ return ::new(buffer) BeginApplyInst(loc, callee, substCalleeSILType,
+ resultTypes, resultOwnerships, subs,
+ args, typeDependentOperands,
+ isNonThrowing, specializationInfo);
+}
+
bool swift::doesApplyCalleeHaveSemantics(SILValue callee, StringRef semantics) {
if (auto *FRI = dyn_cast<FunctionRefInst>(callee))
if (auto *F = FRI->getReferencedFunction())
@@ -437,10 +510,6 @@
return false;
}
-void *swift::allocateApplyInst(SILFunction &F, size_t size, size_t alignment) {
- return F.getModule().allocateInst(size, alignment);
-}
-
PartialApplyInst::PartialApplyInst(
SILDebugLocation Loc, SILValue Callee, SILType SubstCalleeTy,
SubstitutionList Subs, ArrayRef<SILValue> Args,
@@ -467,7 +536,9 @@
SmallVector<SILValue, 32> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
SubstCalleeTy.getSwiftRValueType(), Subs);
- void *Buffer = allocate(F, Subs, TypeDependentOperands, Args);
+ void *Buffer =
+ allocateTrailingInst<PartialApplyInst, Operand, Substitution>(
+ F, getNumAllOperands(Args, TypeDependentOperands), Subs.size());
return ::new(Buffer) PartialApplyInst(Loc, Callee, SubstCalleeTy,
Subs, Args,
TypeDependentOperands, ClosureType,
@@ -491,20 +562,22 @@
errorBB) {}
TryApplyInst *TryApplyInst::create(
- SILDebugLocation Loc, SILValue callee, SubstitutionList subs,
+ SILDebugLocation loc, SILValue callee, SubstitutionList subs,
ArrayRef<SILValue> args, SILBasicBlock *normalBB, SILBasicBlock *errorBB,
- SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes,
- const GenericSpecializationInformation *SpecializationInfo) {
+ SILFunction &F, SILOpenedArchetypesState &openedArchetypes,
+ const GenericSpecializationInformation *specializationInfo) {
SILType substCalleeTy =
callee->getType().substGenericArgs(F.getModule(), subs);
- SmallVector<SILValue, 32> TypeDependentOperands;
- collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
+ SmallVector<SILValue, 32> typeDependentOperands;
+ collectTypeDependentOperands(typeDependentOperands, openedArchetypes, F,
substCalleeTy.getSwiftRValueType(), subs);
- void *buffer = allocate(F, subs, TypeDependentOperands, args);
- return ::new (buffer) TryApplyInst(Loc, callee, substCalleeTy, subs, args,
- TypeDependentOperands,
- normalBB, errorBB, SpecializationInfo);
+ void *buffer =
+ allocateTrailingInst<TryApplyInst, Operand, Substitution>(
+ F, getNumAllOperands(args, typeDependentOperands), subs.size());
+ return ::new (buffer) TryApplyInst(loc, callee, substCalleeTy, subs, args,
+ typeDependentOperands,
+ normalBB, errorBB, specializationInfo);
}
FunctionRefInst::FunctionRefInst(SILDebugLocation Loc, SILFunction *F)
@@ -1056,15 +1129,33 @@
case TermKind::CheckedCastAddrBranchInst:
case TermKind::UnreachableInst:
case TermKind::TryApplyInst:
+ case TermKind::YieldInst:
return false;
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
return true;
}
llvm_unreachable("Unhandled TermKind in switch.");
}
+YieldInst::YieldInst(SILDebugLocation loc, ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB)
+ : InstructionBase(loc),
+ DestBBs{{this, normalBB}, {this, unwindBB}},
+ Operands(this, yieldedValues) {}
+
+YieldInst *YieldInst::create(SILDebugLocation loc,
+ ArrayRef<SILValue> yieldedValues,
+ SILBasicBlock *normalBB, SILBasicBlock *unwindBB,
+ SILFunction &F) {
+ void *buffer = F.getModule().allocateInst(sizeof(YieldInst) +
+ decltype(Operands)::getExtraSize(yieldedValues.size()),
+ alignof(YieldInst));
+ return ::new (buffer) YieldInst(loc, yieldedValues, normalBB, unwindBB);
+}
+
BranchInst::BranchInst(SILDebugLocation Loc, SILBasicBlock *DestBB,
ArrayRef<SILValue> Args)
: InstructionBase(Loc), DestBB(this, DestBB),
diff --git a/lib/SIL/SILLocation.cpp b/lib/SIL/SILLocation.cpp
index 1024b27..ac09dde5 100644
--- a/lib/SIL/SILLocation.cpp
+++ b/lib/SIL/SILLocation.cpp
@@ -64,12 +64,7 @@
if (isSILFile())
return Loc.SILFileLoc;
- if (isAutoGenerated())
- return SourceLoc();
-
if (auto *expr = Loc.ASTNode.Primary.dyn_cast<Expr*>()) {
- if (isa<CallExpr>(expr))
- return expr->getEndLoc();
// Code that has an autoclosure as location should not show up in
// the line table (rdar://problem/14627460). Note also that the
// closure function still has a valid DW_AT_decl_line. Depending
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index aac1ced..2b41a69 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -240,8 +240,8 @@
assert(!type->isNoEscape() && "Function decls always have escaping types.");
if (auto fn = lookUpFunction(name)) {
assert(fn->getLoweredFunctionType() == type);
- assert(fn->getLinkage() == linkage ||
- stripExternalFromLinkage(fn->getLinkage()) == linkage);
+ assert(stripExternalFromLinkage(fn->getLinkage()) ==
+ stripExternalFromLinkage(linkage));
return fn;
}
@@ -280,6 +280,32 @@
PInfo.isGuaranteed() || PInfo.isIndirectMutating();
}
+static void addFunctionAttributes(SILFunction *F, DeclAttributes &Attrs,
+ SILModule &M) {
+ for (auto *A : Attrs.getAttributes<SemanticsAttr>())
+ F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
+
+ // Propagate @_specialize.
+ for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
+ auto *SA = cast<SpecializeAttr>(A);
+ auto kind = SA->getSpecializationKind() ==
+ SpecializeAttr::SpecializationKind::Full
+ ? SILSpecializeAttr::SpecializationKind::Full
+ : SILSpecializeAttr::SpecializationKind::Partial;
+ F->addSpecializeAttr(SILSpecializeAttr::create(
+ M, SA->getRequirements(), SA->isExported(), kind));
+ }
+
+ if (auto *OA = Attrs.getAttribute<OptimizeAttr>()) {
+ F->setOptimizationMode(OA->getMode());
+ }
+
+ // @_silgen_name and @_cdecl functions may be called from C code somewhere.
+ if (Attrs.hasAttribute<SILGenNameAttr>() ||
+ Attrs.hasAttribute<CDeclAttr>())
+ F->setHasCReferences(true);
+}
+
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
SILDeclRef constant,
ForDefinition_t forDefinition,
@@ -334,26 +360,12 @@
if (constant.isForeign && decl->hasClangNode())
F->setClangNodeOwner(decl);
- // Propagate @_semantics.
- auto Attrs = decl->getAttrs();
- for (auto *A : Attrs.getAttributes<SemanticsAttr>())
- F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
-
- // Propagate @_specialize.
- for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
- auto *SA = cast<SpecializeAttr>(A);
- auto kind = SA->getSpecializationKind() ==
- SpecializeAttr::SpecializationKind::Full
- ? SILSpecializeAttr::SpecializationKind::Full
- : SILSpecializeAttr::SpecializationKind::Partial;
- F->addSpecializeAttr(SILSpecializeAttr::create(
- *this, SA->getRequirements(), SA->isExported(), kind));
+ if (auto *FDecl = dyn_cast<FuncDecl>(decl)) {
+ if (auto *StorageDecl = FDecl->getAccessorStorageDecl())
+ // Add attributes for e.g. computed properties.
+ addFunctionAttributes(F, StorageDecl->getAttrs(), *this);
}
-
- // @_silgen_name and @_cdecl functions may be called from C code somewhere.
- if (Attrs.hasAttribute<SILGenNameAttr>() ||
- Attrs.hasAttribute<CDeclAttr>())
- F->setHasCReferences(true);
+ addFunctionAttributes(F, decl->getAttrs(), *this);
}
// If this function has a self parameter, make sure that it has a +0 calling
@@ -513,8 +525,7 @@
// compilation, simply convert it into an external declaration,
// so that a compiled version from the shared library is used.
if (F->isDefinition() &&
- F->getModule().getOptions().Optimization <
- SILOptions::SILOptMode::Optimize) {
+ !F->getModule().getOptions().shouldOptimize()) {
F->convertToDeclaration();
}
if (F->isExternalDeclaration())
@@ -769,8 +780,7 @@
/// Returns true if it is the optimized OnoneSupport module.
bool SILModule::isOptimizedOnoneSupportModule() const {
- return getOptions().Optimization >= SILOptions::SILOptMode::Optimize &&
- isOnoneSupportModule();
+ return getOptions().shouldOptimize() && isOnoneSupportModule();
}
void SILModule::setSerializeSILAction(SILModule::ActionCallback Action) {
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index 8372dce..cde8e70 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -448,6 +448,7 @@
NO_OPERAND_INST(StrongRetainUnowned)
NO_OPERAND_INST(UnownedRetain)
NO_OPERAND_INST(Unreachable)
+NO_OPERAND_INST(Unwind)
#undef NO_OPERAND_INST
/// Instructions whose arguments are always compatible with one convention.
@@ -478,6 +479,7 @@
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, UnownedRelease)
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, InitExistentialRef)
CONSTANT_OWNERSHIP_INST(Owned, MustBeInvalidated, EndLifetime)
+CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, AbortApply)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, AddressToPointer)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, BeginAccess)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, BeginUnpairedAccess)
@@ -490,6 +492,7 @@
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, DeinitExistentialAddr)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, DestroyAddr)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, EndAccess)
+CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, EndApply)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, EndUnpairedAccess)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, IndexAddr)
CONSTANT_OWNERSHIP_INST(Trivial, MustBeLive, IndexRawPointer)
@@ -1088,6 +1091,11 @@
}
OwnershipUseCheckerResult
+OwnershipCompatibilityUseChecker::visitBeginApplyInst(BeginApplyInst *I) {
+ return visitFullApply(I);
+}
+
+OwnershipUseCheckerResult
OwnershipCompatibilityUseChecker::visitApplyInst(ApplyInst *I) {
return visitFullApply(I);
}
@@ -1109,6 +1117,35 @@
}
OwnershipUseCheckerResult
+OwnershipCompatibilityUseChecker::visitYieldInst(YieldInst *I) {
+ // Indirect return arguments are address types.
+ if (isAddressOrTrivialType())
+ return {compatibleWithOwnership(ValueOwnershipKind::Trivial),
+ UseLifetimeConstraint::MustBeLive};
+
+ auto fnType = I->getFunction()->getLoweredFunctionType();
+ auto yieldInfo = fnType->getYields()[getOperandIndex()];
+ switch (yieldInfo.getConvention()) {
+ case ParameterConvention::Indirect_In:
+ case ParameterConvention::Direct_Owned:
+ return visitApplyParameter(ValueOwnershipKind::Owned,
+ UseLifetimeConstraint::MustBeInvalidated);
+ case ParameterConvention::Indirect_In_Constant:
+ case ParameterConvention::Direct_Unowned:
+ // We accept unowned, owned, and guaranteed in unowned positions.
+ return {true, UseLifetimeConstraint::MustBeLive};
+ case ParameterConvention::Indirect_In_Guaranteed:
+ case ParameterConvention::Direct_Guaranteed:
+ return visitApplyParameter(ValueOwnershipKind::Guaranteed,
+ UseLifetimeConstraint::MustBeLive);
+ // The following conventions should take address types.
+ case ParameterConvention::Indirect_Inout:
+ case ParameterConvention::Indirect_InoutAliasable:
+ llvm_unreachable("Unexpected non-trivial parameter convention.");
+ }
+}
+
+OwnershipUseCheckerResult
OwnershipCompatibilityUseChecker::visitAssignInst(AssignInst *I) {
if (getValue() == I->getSrc()) {
if (isAddressOrTrivialType()) {
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index a4dacb1..8a25896 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -351,7 +351,7 @@
break;
}
- auto uncurryLevel = getUncurryLevel();
+ auto uncurryLevel = getParameterListCount() - 1;
if (uncurryLevel != 0)
OS << (isDot ? '.' : '!') << uncurryLevel;
@@ -1073,9 +1073,8 @@
*this << '>';
}
- void visitApplyInst(ApplyInst *AI) {
- if (AI->isNonThrowing())
- *this << "[nothrow] ";
+ template <class Inst>
+ void visitApplyInstBase(Inst *AI) {
*this << Ctx.getID(AI->getCallee());
printSubstitutions(AI->getSubstitutions());
*this << '(';
@@ -1085,14 +1084,20 @@
*this << ") : " << AI->getCallee()->getType();
}
+ void visitApplyInst(ApplyInst *AI) {
+ if (AI->isNonThrowing())
+ *this << "[nothrow] ";
+ visitApplyInstBase(AI);
+ }
+
+ void visitBeginApplyInst(BeginApplyInst *AI) {
+ if (AI->isNonThrowing())
+ *this << "[nothrow] ";
+ visitApplyInstBase(AI);
+ }
+
void visitTryApplyInst(TryApplyInst *AI) {
- *this << Ctx.getID(AI->getCallee());
- printSubstitutions(AI->getSubstitutions());
- *this << '(';
- interleave(AI->getArguments(),
- [&](const SILValue &arg) { *this << Ctx.getID(arg); },
- [&] { *this << ", "; });
- *this << ") : " << AI->getCallee()->getType();
+ visitApplyInstBase(AI);
*this << ", normal " << Ctx.getID(AI->getNormalBB());
*this << ", error " << Ctx.getID(AI->getErrorBB());
}
@@ -1115,13 +1120,15 @@
case ParameterConvention::Indirect_InoutAliasable:
llvm_unreachable("unexpected callee convention!");
}
- *this << Ctx.getID(CI->getCallee());
- printSubstitutions(CI->getSubstitutions());
- *this << '(';
- interleave(CI->getArguments(),
- [&](const SILValue &arg) { *this << Ctx.getID(arg); },
- [&] { *this << ", "; });
- *this << ") : " << CI->getCallee()->getType();
+ visitApplyInstBase(CI);
+ }
+
+ void visitAbortApplyInst(AbortApplyInst *AI) {
+ *this << Ctx.getID(AI->getOperand());
+ }
+
+ void visitEndApplyInst(EndApplyInst *AI) {
+ *this << Ctx.getID(AI->getOperand());
}
void visitFunctionRefInst(FunctionRefInst *FRI) {
@@ -1854,6 +1861,21 @@
*this << getIDAndType(TI->getOperand());
}
+ void visitUnwindInst(UnwindInst *UI) {
+ // no operands
+ }
+
+ void visitYieldInst(YieldInst *YI) {
+ auto values = YI->getYieldedValues();
+ if (values.size() != 1) *this << '(';
+ interleave(values,
+ [&](SILValue value) { *this << getIDAndType(value); },
+ [&] { *this << ", "; });
+ if (values.size() != 1) *this << ')';
+ *this << ", resume " << Ctx.getID(YI->getResumeBB())
+ << ", unwind " << Ctx.getID(YI->getUnwindBB());
+ }
+
void visitSwitchValueInst(SwitchValueInst *SII) {
*this << getIDAndType(SII->getOperand());
for (unsigned i = 0, e = SII->getNumCases(); i < e; ++i) {
@@ -2230,6 +2252,13 @@
case InlineDefault: break;
}
+ switch (getOptimizationMode()) {
+ case OptimizationMode::NoOptimization: OS << "[Onone] "; break;
+ case OptimizationMode::ForSpeed: OS << "[Ospeed] "; break;
+ case OptimizationMode::ForSize: OS << "[Osize] "; break;
+ default: break;
+ }
+
if (getEffectsKind() == EffectsKind::ReadOnly)
OS << "[readonly] ";
else if (getEffectsKind() == EffectsKind::ReadNone)
@@ -2731,7 +2760,22 @@
}
OS << '\n';
}
-
+
+ for (auto conditionalConformance : getConditionalConformances()) {
+ // conditional_conformance (TypeName: Protocol):
+ // <conformance>
+ OS << " conditional_conformance (";
+ conditionalConformance.Requirement.print(OS, Options);
+ OS << ": " << conditionalConformance.Conformance.getRequirement()->getName()
+ << "): ";
+ if (conditionalConformance.Conformance.isConcrete())
+ conditionalConformance.Conformance.getConcrete()->printName(OS, Options);
+ else
+ OS << "dependent";
+
+ OS << '\n';
+ }
+
OS << "}\n\n";
}
diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp
index 87ad018..c99d242 100644
--- a/lib/SIL/SILType.cpp
+++ b/lib/SIL/SILType.cpp
@@ -71,6 +71,10 @@
return getPrimitiveType(CanType(optType), type.getCategory());
}
+SILType SILType::getSILTokenType(const ASTContext &C) {
+ return getPrimitiveObjectType(C.TheSILTokenType);
+}
+
bool SILType::isTrivial(SILModule &M) const {
return M.getTypeLowering(*this).isTrivial();
}
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 7252575..15afdf3 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -671,9 +671,24 @@
/// Check that the types of this value producer are all legal in the function
/// context in which it exists.
void checkLegalType(SILFunction *F, ValueBase *value, SILInstruction *I) {
- if (SILType type = value->getType()) {
- checkLegalType(F, type, I);
+ SILType type = value->getType();
+ if (type.is<SILTokenType>()) {
+ require(isLegalSILTokenProducer(value),
+ "SIL tokens can only be produced as the results of specific "
+ "instructions");
+ return;
}
+
+ checkLegalType(F, type, I);
+ }
+
+ static bool isLegalSILTokenProducer(SILValue value) {
+ if (auto beginApply = dyn_cast<BeginApplyResult>(value))
+ return beginApply->isTokenResult();
+
+ // Add more token cases here as they arise.
+
+ return false;
}
/// Check that the given type is a legal SIL value type.
@@ -918,9 +933,9 @@
// Check that the arguments and result match.
SILFunctionConventions substConv(substTy, F.getModule());
//require(site.getArguments().size() == substTy->getNumSILArguments(),
- require(site.getNumCallArguments() == substConv.getNumSILArguments(),
+ require(site.getNumArguments() == substConv.getNumSILArguments(),
"apply doesn't have right number of arguments for function");
- for (size_t i = 0, size = site.getNumCallArguments(); i < size; ++i) {
+ for (size_t i = 0, size = site.getNumArguments(); i < size; ++i) {
requireSameType(site.getArguments()[i]->getType(),
substConv.getSILArgumentType(i),
"operand of 'apply' doesn't match function input type");
@@ -941,6 +956,9 @@
"apply instruction cannot call function with error result");
}
+ require(!calleeConv.funcTy->isCoroutine(),
+ "cannot call coroutine with normal apply");
+
// Check that if the apply is of a noreturn callee, make sure that an
// unreachable is the next instruction.
if (AI->getModule().getStage() == SILStage::Raw ||
@@ -955,6 +973,9 @@
SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
+ require(!calleeConv.funcTy->isCoroutine(),
+ "cannot call coroutine with normal apply");
+
auto normalBB = AI->getNormalBB();
require(normalBB->args_size() == 1,
"normal destination of try_apply must take one argument");
@@ -974,6 +995,43 @@
"of error result type");
}
+ void checkBeginApplyInst(BeginApplyInst *AI) {
+ checkFullApplySite(AI);
+
+ SILFunctionConventions calleeConv(AI->getSubstCalleeType(), F.getModule());
+ auto yieldResults = AI->getYieldedValues();
+ auto yields = calleeConv.getYields();
+ require(yields.size() == yieldResults.size(),
+ "length mismatch in callee yields vs. begin_apply results");
+ for (auto i : indices(yields)) {
+ require(yieldResults[i]->getType() == calleeConv.getSILType(yields[i]),
+ "callee yield type does not match begin_apply result type");
+ }
+
+ if (AI->isNonThrowing()) {
+ require(calleeConv.funcTy->hasErrorResult(),
+ "nothrow flag used for callee without error result");
+ } else {
+ require(!calleeConv.funcTy->hasErrorResult(),
+ "begin_apply instruction cannot call function with error result");
+ }
+
+ require(calleeConv.funcTy->getCoroutineKind() == SILCoroutineKind::YieldOnce,
+ "must call yield_once coroutine with begin_apply");
+ }
+
+ void checkAbortApplyInst(AbortApplyInst *AI) {
+ require(isa<BeginApplyResult>(AI->getOperand()) &&
+ cast<BeginApplyResult>(AI->getOperand())->isTokenResult(),
+ "operand of abort_apply must be a begin_apply");
+ }
+
+ void checkEndApplyInst(EndApplyInst *AI) {
+ require(isa<BeginApplyResult>(AI->getOperand()) &&
+ cast<BeginApplyResult>(AI->getOperand())->isTokenResult(),
+ "operand of end_apply must be a begin_apply");
+ }
+
void verifyLLVMIntrinsic(BuiltinInst *BI, llvm::Intrinsic::ID ID) {
// Certain llvm intrinsic require constant values as their operands.
// Consequently, these must not be phi nodes (aka. basic block arguments).
@@ -2164,6 +2222,8 @@
auto constantInfo = F.getModule().Types.getConstantInfo(method);
auto methodTy = constantInfo.SILFnType;
+ assert(!methodTy->isCoroutine());
+
// Map interface types to archetypes.
if (auto *env = constantInfo.GenericEnv) {
auto subs = env->getForwardingSubstitutions();
@@ -2196,8 +2256,10 @@
auto fnTy = SILFunctionType::get(nullptr,
methodTy->getExtInfo(),
+ methodTy->getCoroutineKind(),
methodTy->getCalleeConvention(),
dynParams,
+ methodTy->getYields(),
dynResults,
methodTy->getOptionalErrorResult(),
F.getASTContext());
@@ -3309,6 +3371,35 @@
"throw operand type does not match error result type of function");
}
+ void checkUnwindInst(UnwindInst *UI) {
+ require(F.getLoweredFunctionType()->isCoroutine(),
+ "unwind in non-coroutine function");
+ }
+
+ void checkYieldInst(YieldInst *YI) {
+ CanSILFunctionType fnType = F.getLoweredFunctionType();
+ require(fnType->isCoroutine(),
+ "yield in non-coroutine function");
+
+ auto yieldedValues = YI->getYieldedValues();
+ auto yieldInfos = fnType->getYields();
+ require(yieldedValues.size() == yieldInfos.size(),
+ "wrong number of yielded values for function");
+ for (auto i : indices(yieldedValues)) {
+ SILType yieldType =
+ F.mapTypeIntoContext(fnConv.getSILType(yieldInfos[i]));
+ require(yieldedValues[i]->getType() == yieldType,
+ "yielded value does not match yield type of coroutine");
+ }
+
+ // We require the resume and unwind destinations to be unique in order
+ // to prevent either edge from becoming critical.
+ require(YI->getResumeBB()->getSinglePredecessorBlock(),
+ "resume dest of 'yield' must be uniquely used");
+ require(YI->getUnwindBB()->getSinglePredecessorBlock(),
+ "unwind dest of 'yield' must be uniquely used");
+ }
+
void checkSelectEnumCases(SelectEnumInstBase *I) {
EnumDecl *eDecl = I->getEnumOperand()->getType().getEnumOrBoundGenericEnum();
require(eDecl, "select_enum operand must be an enum");
@@ -4147,9 +4238,21 @@
/// - accesses must be uniquely ended
/// - flow-sensitive states must be equivalent on all paths into a block
void verifyFlowSensitiveRules(SILFunction *F) {
+ enum CFGState {
+ /// No special rules are in play.
+ Normal,
+ /// We've followed the resume edge of a yield in a yield_once coroutine.
+ YieldOnceResume,
+ /// We've followed the unwind edge of a yield.
+ YieldUnwind
+ };
struct BBState {
std::vector<SingleValueInstruction*> Stack;
- std::set<BeginAccessInst*> Accesses;
+
+ /// Contents: BeginAccessInst*, BeginApplyInst*.
+ std::set<SILInstruction*> ActiveOps;
+
+ CFGState CFG = Normal;
};
// Do a breath-first search through the basic blocks.
@@ -4176,25 +4279,47 @@
"stack dealloc does not match most recent stack alloc");
state.Stack.pop_back();
- } else if (auto access = dyn_cast<BeginAccessInst>(&i)) {
- bool notAlreadyPresent = state.Accesses.insert(access).second;
+ } else if (isa<BeginAccessInst>(i) || isa<BeginApplyInst>(i)) {
+ bool notAlreadyPresent = state.ActiveOps.insert(&i).second;
require(notAlreadyPresent,
- "access was not ended before re-beginning it");
+ "operation was not ended before re-beginning it");
- } else if (auto endAccess = dyn_cast<EndAccessInst>(&i)) {
- // We don't call getBeginAccess() because this isn't the right
- // place to assert on malformed SIL.
- if (auto access = dyn_cast<BeginAccessInst>(endAccess->getOperand())){
- bool present = state.Accesses.erase(access);
- require(present, "access has already been ended");
+ } else if (isa<EndAccessInst>(i) || isa<AbortApplyInst>(i) ||
+ isa<EndApplyInst>(i)) {
+ if (auto beginOp = i.getOperand(0)->getDefiningInstruction()) {
+ bool present = state.ActiveOps.erase(beginOp);
+ require(present, "operation has already been ended");
}
} else if (auto term = dyn_cast<TermInst>(&i)) {
if (term->isFunctionExiting()) {
require(state.Stack.empty(),
"return with stack allocs that haven't been deallocated");
- require(state.Accesses.empty(),
- "return with accesses that haven't been ended");
+ require(state.ActiveOps.empty(),
+ "return with operations still active");
+
+ if (isa<UnwindInst>(term)) {
+ require(state.CFG == YieldUnwind,
+ "encountered 'unwind' when not on unwind path");
+ } else {
+ require(state.CFG != YieldUnwind,
+ "encountered 'return' or 'throw' when on unwind path");
+ if (isa<ReturnInst>(term) &&
+ F->getLoweredFunctionType()->getCoroutineKind() ==
+ SILCoroutineKind::YieldOnce &&
+ F->getModule().getStage() != SILStage::Raw) {
+ require(state.CFG == YieldOnceResume,
+ "encountered 'return' before yielding a value in "
+ "yield_once coroutine");
+ }
+ }
+ }
+
+ if (isa<YieldInst>(term)) {
+ require(state.CFG != YieldOnceResume,
+ "encountered multiple 'yield's along single path");
+ require(state.CFG == Normal,
+ "encountered 'yield' on abnormal CFG path");
}
auto successors = term->getSuccessors();
@@ -4215,9 +4340,30 @@
// worklist and continue.
if (insertResult.second) {
Worklist.push_back(succBB);
+
+ // If we're following a 'yield', update the CFG state:
+ if (isa<YieldInst>(term)) {
+ // Enforce that the unwind logic is segregated in all stages.
+ if (i == 1) {
+ insertResult.first->second.CFG = YieldUnwind;
+
+ // We check the yield_once rule in the mandatory analyses,
+ // so we can't assert it yet in the raw stage.
+ } else if (F->getLoweredFunctionType()->getCoroutineKind()
+ == SILCoroutineKind::YieldOnce &&
+ F->getModule().getStage() != SILStage::Raw) {
+ insertResult.first->second.CFG = YieldOnceResume;
+ }
+ }
+
continue;
}
+ // This rule is checked elsewhere, but we'd want to assert it
+ // here anyway.
+ require(!isa<YieldInst>(term),
+ "successor of 'yield' should not be encountered twice");
+
// Check that the stack height is consistent coming from all entry
// points into this BB. We only care about consistency if there is
// a possible return from this function along the path starting at
@@ -4231,8 +4377,10 @@
const auto &foundState = insertResult.first->second;
require(state.Stack == foundState.Stack || isUnreachable(),
"inconsistent stack heights entering basic block");
- require(state.Accesses == foundState.Accesses || isUnreachable(),
- "inconsistent access sets entering basic block");
+ require(state.ActiveOps == foundState.ActiveOps || isUnreachable(),
+ "inconsistent active-operations sets entering basic block");
+ require(state.CFG == foundState.CFG,
+ "inconsistent coroutine states entering basic block");
}
}
}
diff --git a/lib/SIL/SILWitnessTable.cpp b/lib/SIL/SILWitnessTable.cpp
index 4e0728e..a6f31d4 100644
--- a/lib/SIL/SILWitnessTable.cpp
+++ b/lib/SIL/SILWitnessTable.cpp
@@ -43,11 +43,11 @@
Mod.witnessTables.push_back(this);
}
-SILWitnessTable *
-SILWitnessTable::create(SILModule &M, SILLinkage Linkage,
- IsSerialized_t Serialized,
- NormalProtocolConformance *Conformance,
- ArrayRef<SILWitnessTable::Entry> entries) {
+SILWitnessTable *SILWitnessTable::create(
+ SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized,
+ NormalProtocolConformance *Conformance,
+ ArrayRef<SILWitnessTable::Entry> entries,
+ ArrayRef<ConditionalConformance> conditionalConformances) {
assert(Conformance && "Cannot create a witness table for a null "
"conformance.");
@@ -56,8 +56,9 @@
// Allocate the witness table and initialize it.
void *buf = M.allocate(sizeof(SILWitnessTable), alignof(SILWitnessTable));
- SILWitnessTable *wt = ::new (buf) SILWitnessTable(M, Linkage, Serialized,
- Name.str(), Conformance, entries);
+ SILWitnessTable *wt = ::new (buf)
+ SILWitnessTable(M, Linkage, Serialized, Name.str(), Conformance, entries,
+ conditionalConformances);
wt->addWitnessTable();
@@ -86,20 +87,19 @@
return wt;
}
-SILWitnessTable::SILWitnessTable(SILModule &M, SILLinkage Linkage,
- IsSerialized_t Serialized, StringRef N,
- NormalProtocolConformance *Conformance,
- ArrayRef<Entry> entries)
- : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
- IsDeclaration(true), Serialized(false) {
- convertToDefinition(entries, Serialized);
+SILWitnessTable::SILWitnessTable(
+ SILModule &M, SILLinkage Linkage, IsSerialized_t Serialized, StringRef N,
+ NormalProtocolConformance *Conformance, ArrayRef<Entry> entries,
+ ArrayRef<ConditionalConformance> conditionalConformances)
+ : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
+ ConditionalConformances(), IsDeclaration(true), Serialized(false) {
+ convertToDefinition(entries, conditionalConformances, Serialized);
}
SILWitnessTable::SILWitnessTable(SILModule &M, SILLinkage Linkage, StringRef N,
NormalProtocolConformance *Conformance)
- : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
- IsDeclaration(true), Serialized(false)
-{}
+ : Mod(M), Name(N), Linkage(Linkage), Conformance(Conformance), Entries(),
+ ConditionalConformances(), IsDeclaration(true), Serialized(false) {}
SILWitnessTable::~SILWitnessTable() {
if (isDeclaration())
@@ -127,14 +127,17 @@
return Serialized ? IsSerialized : IsNotSerialized;
}
-void SILWitnessTable::convertToDefinition(ArrayRef<Entry> entries,
- IsSerialized_t isSerialized) {
+void SILWitnessTable::convertToDefinition(
+ ArrayRef<Entry> entries,
+ ArrayRef<ConditionalConformance> conditionalConformances,
+ IsSerialized_t isSerialized) {
assert(isDeclaration() && "Definitions should never call this method.");
IsDeclaration = false;
assert(isSerialized != IsSerializable);
Serialized = (isSerialized == IsSerialized);
Entries = Mod.allocateCopy(entries);
+ ConditionalConformances = Mod.allocateCopy(conditionalConformances);
// Bump the reference count of witness functions referenced by this table.
for (auto entry : getEntries()) {
@@ -174,3 +177,23 @@
auto typeIsPublic = nominal->getEffectiveAccess() >= AccessLevel::Public;
return nominal->hasFixedLayout() && protocolIsPublic && typeIsPublic;
}
+
+bool SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ const ProtocolConformance *conformance,
+ llvm::function_ref<bool(unsigned, CanType, ProtocolDecl *)> fn) {
+ unsigned conformanceIndex = 0;
+ for (auto req : conformance->getConditionalRequirements()) {
+ if (req.getKind() != RequirementKind::Conformance)
+ continue;
+
+ auto proto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
+
+ if (Lowering::TypeConverter::protocolRequiresWitnessTable(proto)) {
+ if (fn(conformanceIndex, req.getFirstType()->getCanonicalType(), proto))
+ return true;
+
+ conformanceIndex++;
+ }
+ }
+ return false;
+}
diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp
index da1b89c..83c83f2 100644
--- a/lib/SIL/TypeLowering.cpp
+++ b/lib/SIL/TypeLowering.cpp
@@ -211,6 +211,7 @@
IMPL(BuiltinUnknownObject, Reference)
IMPL(BuiltinUnsafeValueBuffer, AddressOnly)
IMPL(BuiltinVector, Trivial)
+ IMPL(SILToken, Trivial)
IMPL(Class, Reference)
IMPL(BoundGenericClass, Reference)
IMPL(AnyMetatype, Trivial)
@@ -2107,9 +2108,9 @@
if (genericSig && genericSig->areAllParamsConcrete())
genericSig = nullptr;
- return SILFunctionType::get(genericSig, extInfo,
+ return SILFunctionType::get(genericSig, extInfo, SILCoroutineKind::None,
/*callee*/ ParameterConvention::Direct_Unowned,
- params, results, None, ctx,
+ params, {}, results, None, ctx,
witnessMethodConformance);
}
diff --git a/lib/SIL/ValueOwnershipKindClassifier.cpp b/lib/SIL/ValueOwnershipKindClassifier.cpp
index 0d56fc9..b6e7982 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.cpp
+++ b/lib/SIL/ValueOwnershipKindClassifier.cpp
@@ -262,6 +262,11 @@
return Result->getOwnershipKind();
}
+ValueOwnershipKind ValueOwnershipKindClassifier::visitBeginApplyResult(
+ BeginApplyResult *Result) {
+ return Result->getOwnershipKind();
+}
+
ValueOwnershipKind ValueOwnershipKindClassifier::visitSILFunctionArgument(
SILFunctionArgument *Arg) {
return Arg->getOwnershipKind();
diff --git a/lib/SILGen/ArgumentSource.cpp b/lib/SILGen/ArgumentSource.cpp
index 5661f17..7226ee8 100644
--- a/lib/SILGen/ArgumentSource.cpp
+++ b/lib/SILGen/ArgumentSource.cpp
@@ -21,25 +21,6 @@
using namespace swift;
using namespace Lowering;
-RValue &ArgumentSource::forceAndPeekRValue(SILGenFunction &SGF) & {
- if (isRValue()) {
- return peekRValue();
- }
-
- // Extract an r-value.
- SILLocation loc = getLocation();
- RValue value = std::move(*this).getAsRValue(SGF);
-
- // Destroy the current state.
- Storage.destruct(StoredKind);
-
- // Emplace the r-value back into the source.
- StoredKind = Kind::RValue;
- Storage.emplaceAggregate<RValueStorage>(StoredKind, std::move(value), loc);
-
- return peekRValue();
-}
-
RValue &ArgumentSource::peekRValue() & {
assert(isRValue() && "Undefined behavior to call this method without the "
"ArgumentSource actually being an RValue");
@@ -55,7 +36,6 @@
case Kind::Tuple:
llvm_unreachable("cannot rewrite type of tuple");
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
Storage.get<RValueStorage>(StoredKind).Value.rewriteType(newType);
return;
case Kind::Expr:
@@ -89,7 +69,6 @@
case Kind::Invalid:
llvm_unreachable("argument source is invalid");
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
case Kind::LValue:
return false;
case Kind::Expr:
@@ -138,9 +117,6 @@
llvm_unreachable("argument source is invalid");
case Kind::LValue:
llvm_unreachable("cannot get l-value as r-value");
- case Kind::DelayedBorrowedRValue:
- return std::move(*this).asKnownRValue(SGF).borrow(SGF,
- getKnownRValueLocation());
case Kind::RValue:
return std::move(*this).asKnownRValue(SGF);
case Kind::Expr:
@@ -195,15 +171,6 @@
return SGF.emitAddressOfLValue(loc, std::move(*this).asKnownLValue(),
AccessKind::ReadWrite);
}
- case Kind::DelayedBorrowedRValue: {
- assert(!C.getEmitInto() &&
- "Can not put a delayed borrowed rvalue into an initialization");
- auto loc = getKnownRValueLocation();
- return std::move(*this)
- .asKnownRValue(SGF)
- .getAsSingleValue(SGF, loc)
- .borrow(SGF, loc);
- }
case Kind::RValue: {
auto loc = getKnownRValueLocation();
if (auto init = C.getEmitInto()) {
@@ -250,9 +217,6 @@
llvm_unreachable("argument source is invalid");
case Kind::LValue:
llvm_unreachable("cannot get converted l-value");
- case Kind::DelayedBorrowedRValue:
- // TODO: We probably can, but we would need to introduce a copy.
- llvm_unreachable("cannot get converted borrowed r-value");
case Kind::RValue:
case Kind::Expr:
case Kind::Tuple:
@@ -270,8 +234,6 @@
llvm_unreachable("argument source is invalid");
case Kind::LValue:
llvm_unreachable("cannot forward an l-value");
- case Kind::DelayedBorrowedRValue:
- llvm_unreachable("cannot forward a delayed borrowed r-value");
case Kind::RValue: {
auto loc = getKnownRValueLocation();
std::move(*this).asKnownRValue(SGF).forwardInto(SGF, loc, dest);
@@ -299,26 +261,12 @@
Storage.emplaceAggregate<RValueStorage>(StoredKind, std::move(rv), loc);
}
-ArgumentSource ArgumentSource::delayedBorrow(SILGenFunction &SGF) const & {
- assert(isRValue() && "Can only perform a delayed borrow on an rvalue");
- // We are doing something evil here since we know that we are going to perform
- // a borrow.
- //
- // Once uncurrying is removed from the compiler, we will no longer need to
- // perform delayed borrows and this evilness can be expunged.
- const RValue &rv = asKnownRValue();
- return ArgumentSource(getKnownRValueLocation(),
- RValue(&SGF, rv.values, rv.type),
- Kind::DelayedBorrowedRValue);
-}
-
ArgumentSource ArgumentSource::borrow(SILGenFunction &SGF) const & {
switch (StoredKind) {
case Kind::Invalid:
llvm_unreachable("argument source is invalid");
case Kind::LValue:
llvm_unreachable("cannot borrow an l-value");
- case Kind::DelayedBorrowedRValue:
case Kind::RValue: {
auto loc = getKnownRValueLocation();
return ArgumentSource(loc, asKnownRValue().borrow(SGF, loc));
@@ -449,7 +397,6 @@
return;
}
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
out << "RValue\n";
Storage.get<RValueStorage>(StoredKind).Value.dump(out, indent + 2);
return;
diff --git a/lib/SILGen/ArgumentSource.h b/lib/SILGen/ArgumentSource.h
index 63f4417..036a46e 100644
--- a/lib/SILGen/ArgumentSource.h
+++ b/lib/SILGen/ArgumentSource.h
@@ -52,8 +52,6 @@
enum class Kind : unsigned char {
Invalid,
RValue,
- // An RValue that will be borrowed when emitted.
- DelayedBorrowedRValue,
LValue,
Expr,
Tuple,
@@ -91,7 +89,6 @@
switch (kind) {
case Kind::Invalid: return StorageMembers::indexOf<void>();
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
return StorageMembers::indexOf<RValueStorage>();
case Kind::LValue: return StorageMembers::indexOf<LValueStorage>();
case Kind::Expr: return StorageMembers::indexOf<Expr*>();
@@ -147,7 +144,6 @@
case Kind::Invalid:
return false;
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
return !asKnownRValue().isNull();
case Kind::LValue:
return asKnownLValue().isValid();
@@ -164,7 +160,6 @@
case Kind::Invalid:
llvm_unreachable("argument source is invalid");
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
return asKnownRValue().getType();
case Kind::LValue:
return CanInOutType::get(asKnownLValue().getSubstFormalType());
@@ -183,7 +178,6 @@
case Kind::Invalid:
llvm_unreachable("argument source is invalid");
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
return asKnownRValue().getType();
case Kind::LValue:
return asKnownLValue().getSubstFormalType();
@@ -201,7 +195,6 @@
switch (StoredKind) {
case Kind::Invalid: llvm_unreachable("argument source is invalid");
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
return false;
case Kind::LValue: return true;
case Kind::Expr: return asKnownExpr()->isSemanticallyInOutExpr();
@@ -215,7 +208,6 @@
case Kind::Invalid:
llvm_unreachable("argument source is invalid");
case Kind::RValue:
- case Kind::DelayedBorrowedRValue:
return getKnownRValueLocation();
case Kind::LValue:
return getKnownLValueLocation();
@@ -228,21 +220,13 @@
}
bool isExpr() const & { return StoredKind == Kind::Expr; }
- bool isRValue() const & {
- return StoredKind == Kind::RValue ||
- StoredKind == Kind::DelayedBorrowedRValue;
- }
+ bool isRValue() const & { return StoredKind == Kind::RValue; }
bool isLValue() const & { return StoredKind == Kind::LValue; }
bool isTuple() const & { return StoredKind == Kind::Tuple; }
/// Given that this source is storing an RValue, extract and clear
/// that value.
RValue &&asKnownRValue(SILGenFunction &SGF) && {
- if (isDelayedBorrowedRValue()) {
- std::move(Storage.get<RValueStorage>(StoredKind).Value)
- .borrow(SGF, getKnownRValueLocation());
- }
-
return std::move(Storage.get<RValueStorage>(StoredKind).Value);
}
@@ -287,10 +271,6 @@
return result;
}
- /// Force this source to become an r-value, then return an unmoved
- /// handle to that r-value.
- RValue &forceAndPeekRValue(SILGenFunction &SGF) &;
-
/// Return an unowned handle to the r-value stored in this source. Undefined
/// if this ArgumentSource is not an rvalue.
RValue &peekRValue() &;
@@ -313,15 +293,6 @@
/// return the ArgumentSource. Otherwise, assert.
ArgumentSource borrow(SILGenFunction &SGF) const &;
- /// If we have an rvalue, return an Argument Source that when the RValue is
- /// retrieved, the RValue is always borrowed first.
- ///
- /// This allows us to specify when creating callees that a value must be
- /// borrowed, but emit the actual borrow once the callee is evaluated later in
- /// SILGenApply. Ideally, the callee would always eagerly borrow, but since we
- /// still have uncurrying, we can not do that.
- ArgumentSource delayedBorrow(SILGenFunction &SGF) const &;
-
ManagedValue materialize(SILGenFunction &SGF) &&;
/// Emit this value to memory so that it follows the abstraction
@@ -346,14 +317,6 @@
/// Private helper constructor for delayed borrowed rvalues.
ArgumentSource(SILLocation loc, RValue &&rv, Kind kind);
- /// Returns true if this ArgumentSource stores a delayed borrowed RValue.
- ///
- /// This is private since we do not want users to be able to determine if the
- /// given ArgumentSource is a normal RValue or a delayed borrow rvalue.
- bool isDelayedBorrowedRValue() const & {
- return StoredKind == Kind::DelayedBorrowedRValue;
- }
-
// Make the non-move accessors private to make it more difficult
// to accidentally re-emit values.
const RValue &asKnownRValue() const & {
diff --git a/lib/SILGen/Cleanup.cpp b/lib/SILGen/Cleanup.cpp
index 567e95a..bdaf095 100644
--- a/lib/SILGen/Cleanup.cpp
+++ b/lib/SILGen/Cleanup.cpp
@@ -138,7 +138,7 @@
// Otherwise, create and emit a new block.
auto *newBlock = SGF.createBasicBlock();
- SavedInsertionPoint IPRAII(SGF, newBlock);
+ SILGenSavedInsertionPoint IPRAII(SGF, newBlock);
emitBranchAndCleanups(dest, branchLoc, args);
return newBlock;
}
diff --git a/lib/SILGen/RValue.h b/lib/SILGen/RValue.h
index d7191d1..68fd72a 100644
--- a/lib/SILGen/RValue.h
+++ b/lib/SILGen/RValue.h
@@ -225,22 +225,6 @@
/// Get the rvalue as a single unmanaged value, imploding tuples if necessary.
/// The values must not require any cleanups.
SILValue getUnmanagedSingleValue(SILGenFunction &SGF, SILLocation l) const &;
-
- /// Peek at the single scalar value backing this rvalue without consuming it.
- /// The rvalue must not be of a tuple type.
- SILValue peekScalarValue() const & {
- assert(!isa<TupleType>(type) && "peekScalarValue of a tuple rvalue");
- assert(values.size() == 1 && "exploded scalar value?!");
- return values[0].getValue();
- }
-
- /// Peek at the single ManagedValue backing this rvalue without consuming it
- /// and return true if the value is not at +1.
- bool peekIsPlusZeroRValueOrTrivial() const & {
- assert(!isa<TupleType>(type) && "peekScalarValue of a tuple rvalue");
- assert(values.size() == 1 && "exploded scalar value?!");
- return values[0].isPlusZeroRValueOrTrivial();
- }
ManagedValue getScalarValue() && {
assert(!isa<TupleType>(type) && "getScalarValue of a tuple rvalue");
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index bb4e271..abc9989 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -432,8 +432,9 @@
};
CanSILFunctionType topLevelType = SILFunctionType::get(nullptr, extInfo,
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params,
+ params, /*yields*/ {},
SILResultInfo(Int32Ty,
ResultConvention::Unowned),
None,
@@ -1323,8 +1324,8 @@
SGF.B.emitBlock(returnBB);
// Emit the rethrow block.
- SavedInsertionPoint savedIP(SGF, rethrowBB,
- FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint savedIP(SGF, rethrowBB,
+ FunctionSection::Postmatter);
// Log the error.
SILValue error = rethrowBB->getArgument(0);
diff --git a/lib/SILGen/SILGen.h b/lib/SILGen/SILGen.h
index 0c42dad..b64c803 100644
--- a/lib/SILGen/SILGen.h
+++ b/lib/SILGen/SILGen.h
@@ -181,11 +181,19 @@
/// Get the function for a SILDeclRef, creating it if necessary.
SILFunction *getFunction(SILDeclRef constant,
ForDefinition_t forDefinition);
-
+
+ /// Get the function for a dispatch thunk, creating it if necessary.
+ SILFunction *getDispatchThunk(SILDeclRef constant,
+ ForDefinition_t forDefinition);
+
+ /// Emit a native Swift class or protocol method dispatch thunk, used for
+ /// resilient method dispatch.
+ SILFunction *emitDispatchThunk(SILDeclRef constant);
+
/// Get the dynamic dispatch thunk for a SILDeclRef.
SILFunction *getDynamicThunk(SILDeclRef constant,
CanSILFunctionType constantTy);
-
+
/// Emit a vtable thunk for a derived method if its natural abstraction level
/// diverges from the overridden base method. If no thunking is needed,
/// returns a static reference to the derived method.
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 71395d6..445abfb 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -64,16 +64,6 @@
llvm_unreachable("bad representation");
}
-static CanType getDynamicMethodSelfType(SILGenFunction &SGF,
- const ArgumentSource &proto,
- ValueDecl *member) {
- if (member->isInstanceMember()) {
- return SGF.getASTContext().getAnyObjectType();
- } else {
- return proto.getSILSubstType(SGF).getSwiftRValueType();
- }
-}
-
/// Return the formal type for the partial-apply result type of a
/// dynamic method invocation.
static CanFunctionType
@@ -113,55 +103,16 @@
return fnType;
}
-/// Replace the 'self' parameter in the given type.
-static CanSILFunctionType
-replaceSelfTypeForDynamicLookup(ASTContext &ctx,
- CanSILFunctionType fnType,
- CanType newSelfType,
- SILDeclRef methodName) {
- auto oldParams = fnType->getParameters();
- SmallVector<SILParameterInfo, 4> newParams;
- newParams.append(oldParams.begin(), oldParams.end() - 1);
- newParams.push_back({newSelfType, oldParams.back().getConvention()});
-
- // If the method returns Self, substitute AnyObject for the result type.
- SmallVector<SILResultInfo, 4> newResults;
- newResults.append(fnType->getResults().begin(), fnType->getResults().end());
- if (auto fnDecl = dyn_cast<FuncDecl>(methodName.getDecl())) {
- if (fnDecl->hasDynamicSelf()) {
- auto anyObjectTy = ctx.getAnyObjectType();
- for (auto &result : newResults) {
- auto newResultTy
- = result.getType()->replaceCovariantResultType(anyObjectTy, 0);
- result = result.getWithType(newResultTy->getCanonicalType());
- }
- }
- }
-
- return SILFunctionType::get(nullptr, fnType->getExtInfo(),
- fnType->getCalleeConvention(), newParams,
- newResults, fnType->getOptionalErrorResult(), ctx,
- fnType->getWitnessMethodConformanceOrNone());
-}
-
/// Retrieve the type to use for a method found via dynamic lookup.
-static CanSILFunctionType
-getDynamicMethodLoweredType(SILGenFunction &SGF, SILValue v,
- SILDeclRef methodName,
+static SILType
+getDynamicMethodLoweredType(SILModule &M,
+ SILDeclRef constant,
CanAnyFunctionType substMemberTy) {
- auto &ctx = SGF.getASTContext();
- CanType selfTy = v->getType().getSwiftRValueType();
- assert((!methodName.getDecl()->isInstanceMember() ||
- selfTy->is<ArchetypeType>()) &&
- "Dynamic lookup needs an archetype");
-
- // Replace the 'self' parameter type in the method type with it.
+ assert(constant.isForeign);
auto objcFormalTy = substMemberTy.withExtInfo(substMemberTy->getExtInfo()
.withSILRepresentation(SILFunctionTypeRepresentation::ObjCMethod));
-
- auto methodTy = SGF.SGM.M.Types
- .getUncachedSILFunctionTypeForConstant(methodName, objcFormalTy);
- return replaceSelfTypeForDynamicLookup(ctx, methodTy, selfTy, methodName);
+ return SILType::getPrimitiveObjectType(
+ M.Types.getUncachedSILFunctionTypeForConstant(constant, objcFormalTy));
}
/// Check if we can perform a dynamic dispatch on a super method call.
@@ -198,6 +149,9 @@
}
static SILValue getOriginalSelfValue(SILValue selfValue) {
+ if (auto *TTOI = dyn_cast<ThickToObjCMetatypeInst>(selfValue))
+ selfValue = TTOI->getOperand();
+
if (auto *BBI = dyn_cast<BeginBorrowInst>(selfValue))
selfValue = BBI->getOperand();
@@ -283,10 +237,6 @@
/// *NOTE* This should never be non-null if IndirectValue is non-null.
SILDeclRef Constant;
- /// This field is set if we are calling to a SuperMethod or ClassMethod and
- /// thus need to pass self to get the correct implementation.
- Optional<ArgumentSource> SelfValue;
-
/// The abstraction pattern of the callee.
AbstractionPattern OrigFormalInterfaceType;
@@ -339,11 +289,10 @@
{
}
- Callee(Kind methodKind, SILGenFunction &SGF,
- Optional<ArgumentSource> &&selfValue, SILDeclRef methodName,
+ Callee(Kind methodKind, SILGenFunction &SGF, SILDeclRef methodName,
AbstractionPattern origFormalType, CanAnyFunctionType substFormalType,
SubstitutionList subs, SILLocation l)
- : kind(methodKind), Constant(methodName), SelfValue(std::move(selfValue)),
+ : kind(methodKind), Constant(methodName),
OrigFormalInterfaceType(origFormalType),
SubstFormalInterfaceType(
getSubstFormalInterfaceType(substFormalType, subs)),
@@ -368,23 +317,23 @@
SILLocation l) {
assert(isa<EnumElementDecl>(c.getDecl()));
auto &ci = SGF.getConstantInfo(c);
- return Callee(Kind::EnumElement, SGF, None, c, ci.FormalPattern,
+ return Callee(Kind::EnumElement, SGF, c, ci.FormalPattern,
ci.FormalType, subs, l);
}
- static Callee forClassMethod(SILGenFunction &SGF, ArgumentSource &&selfValue,
+ static Callee forClassMethod(SILGenFunction &SGF,
SILDeclRef c, SubstitutionList subs,
SILLocation l) {
auto base = SGF.SGM.Types.getOverriddenVTableEntry(c);
auto &baseCI = SGF.getConstantInfo(base);
auto &derivedCI = SGF.getConstantInfo(c);
- return Callee(Kind::ClassMethod, SGF, std::move(selfValue), c,
+ return Callee(Kind::ClassMethod, SGF, c,
baseCI.FormalPattern, derivedCI.FormalType, subs, l);
}
- static Callee forSuperMethod(SILGenFunction &SGF, ArgumentSource &&selfValue,
+ static Callee forSuperMethod(SILGenFunction &SGF,
SILDeclRef c, SubstitutionList subs,
SILLocation l) {
auto &ci = SGF.getConstantInfo(c);
- return Callee(Kind::SuperMethod, SGF, std::move(selfValue), c,
+ return Callee(Kind::SuperMethod, SGF, c,
ci.FormalPattern, ci.FormalType, subs, l);
}
static Callee forWitnessMethod(SILGenFunction &SGF,
@@ -393,18 +342,16 @@
SubstitutionList subs,
SILLocation l) {
auto &ci = SGF.getConstantInfo(c);
- return Callee(Kind::WitnessMethod, SGF, None, c, ci.FormalPattern,
+ return Callee(Kind::WitnessMethod, SGF, c, ci.FormalPattern,
ci.FormalType, subs, l);
}
- static Callee forDynamic(SILGenFunction &SGF, ArgumentSource &&arg,
+ static Callee forDynamic(SILGenFunction &SGF,
SILDeclRef c, const SubstitutionList &constantSubs,
- CanAnyFunctionType partialSubstFormalType,
+ CanAnyFunctionType substFormalType,
SubstitutionList subs, SILLocation l) {
auto &ci = SGF.getConstantInfo(c);
AbstractionPattern origFormalType = ci.FormalPattern;
- auto selfType = getDynamicMethodSelfType(SGF, arg, c.getDecl());
-
// Replace the original self type with the partially-applied subst type.
auto origFormalFnType = cast<AnyFunctionType>(origFormalType.getType());
if (auto genericFnType = dyn_cast<GenericFunctionType>(origFormalFnType)) {
@@ -418,17 +365,9 @@
cast<FunctionType>(genericFnType->substGenericArgs(constantSubs)
->getCanonicalType());
}
- origFormalFnType = CanFunctionType::get(selfType,
- origFormalFnType.getResult(),
- origFormalFnType->getExtInfo());
origFormalType.rewriteType(CanGenericSignature(), origFormalFnType);
- // Add the self type clause to the partially-applied subst type.
- auto substFormalType = CanFunctionType::get(selfType,
- partialSubstFormalType,
- origFormalFnType->getExtInfo());
-
- return Callee(Kind::DynamicMethod, SGF, std::move(arg), c, origFormalType,
+ return Callee(Kind::DynamicMethod, SGF, c, origFormalType,
substFormalType, subs, l);
}
@@ -457,10 +396,10 @@
return SubstFormalInterfaceType;
}
- unsigned getNaturalUncurryLevel() const {
+ unsigned getParameterListCount() const {
switch (kind) {
case Kind::IndirectValue:
- return 0;
+ return 1;
case Kind::StandaloneFunction:
case Kind::EnumElement:
@@ -468,7 +407,23 @@
case Kind::SuperMethod:
case Kind::WitnessMethod:
case Kind::DynamicMethod:
- return Constant.getUncurryLevel();
+ return Constant.getParameterListCount();
+ }
+
+ llvm_unreachable("Unhandled Kind in switch.");
+ }
+
+ bool requiresSelfValueForDispatch() const {
+ switch (kind) {
+ case Kind::IndirectValue:
+ case Kind::StandaloneFunction:
+ case Kind::EnumElement:
+ case Kind::WitnessMethod:
+ return false;
+ case Kind::ClassMethod:
+ case Kind::SuperMethod:
+ case Kind::DynamicMethod:
+ return true;
}
llvm_unreachable("Unhandled Kind in switch.");
@@ -498,21 +453,40 @@
return result;
}
- ManagedValue getFnValueAtUncurryLevel(SILGenFunction &SGF,
- unsigned level) const & {
+ SILDeclRef getCurriedConstant(bool isCurried) const {
+ if (isCurried) {
+ auto constant = Constant.asCurried();
+
+ // If we're currying a direct reference to a class-dispatched method,
+ // make sure we emit the right set of thunks.
+ if (kind == Kind::StandaloneFunction) {
+ if (auto func = Constant.getAbstractFunctionDecl()) {
+ if (getMethodDispatch(func) == MethodDispatch::Class) {
+ return constant.asDirectReference(true);
+ }
+ }
+ }
+
+ return constant;
+ }
+
+ return Constant;
+ }
+
+ ManagedValue getFnValue(SILGenFunction &SGF, bool isCurried,
+ Optional<ManagedValue> borrowedSelf) const & {
Optional<SILDeclRef> constant = None;
if (!Constant) {
- assert(level == 0 && "can't curry indirect function");
+ assert(!isCurried && "can't curry indirect function");
} else {
- unsigned uncurryLevel = Constant.getUncurryLevel();
- assert(level <= uncurryLevel &&
- "uncurrying past natural uncurry level of standalone function");
- if (level < uncurryLevel) {
- assert(level == 0);
- constant = Constant.asCurried();
- } else {
- constant = Constant;
+ constant = getCurriedConstant(isCurried);
+
+ // If the call is curried, emit a direct call to the curry thunk.
+ if (constant->isCurried) {
+ auto constantInfo = SGF.getConstantInfo(*constant);
+ SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
+ return ManagedValue::forUnmanaged(ref);
}
}
@@ -522,51 +496,25 @@
return IndirectValue;
case Kind::StandaloneFunction: {
- // If we're currying a direct reference to a class-dispatched method,
- // make sure we emit the right set of thunks.
- if (constant->isCurried && Constant.hasDecl())
- if (auto func = Constant.getAbstractFunctionDecl())
- if (getMethodDispatch(func) == MethodDispatch::Class)
- constant = constant->asDirectReference(true);
-
auto constantInfo = SGF.getConstantInfo(*constant);
SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
return ManagedValue::forUnmanaged(ref);
}
- case Kind::EnumElement: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // We should not end up here if the enum constructor call is fully
- // applied.
- assert(constant->isCurried);
-
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
+ case Kind::EnumElement:
+ llvm_unreachable("Should have been curried");
case Kind::ClassMethod: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
-
auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant);
// Otherwise, do the dynamic dispatch inline.
Scope S(SGF, Loc);
- ManagedValue borrowedSelf =
- SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
SILValue methodVal;
if (!constant->isForeign) {
- methodVal = SGF.B.createClassMethod(
- Loc, borrowedSelf.getValue(), *constant,
- SILType::getPrimitiveObjectType(methodTy));
+ methodVal = SGF.emitClassMethodRef(
+ Loc, borrowedSelf->getValue(), *constant, methodTy);
} else {
methodVal = SGF.B.createObjCMethod(
- Loc, borrowedSelf.getValue(), *constant,
+ Loc, borrowedSelf->getValue(), *constant,
SILType::getPrimitiveObjectType(methodTy));
}
return ManagedValue::forUnmanaged(methodVal);
@@ -575,9 +523,8 @@
assert(!constant->isCurried);
Scope S(SGF, Loc);
- ManagedValue self =
- SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
- ManagedValue castValue = borrowedCastToOriginalSelfType(SGF, Loc, self);
+ ManagedValue castValue = borrowedCastToOriginalSelfType(
+ SGF, Loc, *borrowedSelf);
auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
auto constantInfo =
@@ -594,15 +541,8 @@
case Kind::WitnessMethod: {
auto constantInfo = SGF.getConstantInfo(*constant);
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
- return ManagedValue::forUnmanaged(ref);
- }
-
- auto proto = Constant.getDecl()
- ->getDeclContext()
- ->getAsProtocolOrProtocolExtensionContext();
+ auto proto = cast<ProtocolDecl>(
+ Constant.getDecl()->getDeclContext());
auto lookupType = getSubstFormalType()
.getInput()
->getRValueInstanceType()
@@ -612,52 +552,32 @@
Loc, lookupType, ProtocolConformanceRef(proto), *constant,
constantInfo.getSILType(), constant->isForeign);
return ManagedValue::forUnmanaged(fn);
- ;
}
case Kind::DynamicMethod: {
- assert(!constant->isCurried);
- assert(constant->isForeign);
-
- // Lower the substituted type from the AST, which should have any generic
- // parameters in the original signature erased to their upper bounds.
- auto substFormalType = getSubstFormalType();
- auto objcFormalType = substFormalType.withExtInfo(
- substFormalType->getExtInfo().withSILRepresentation(
- SILFunctionTypeRepresentation::ObjCMethod));
- auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
- *constant, objcFormalType);
-
- auto closureType = replaceSelfTypeForDynamicLookup(
- SGF.getASTContext(), fnType,
- SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
- Constant);
+ auto closureType = getDynamicMethodLoweredType(
+ SGF.SGM.M, *constant, getSubstFormalType());
Scope S(SGF, Loc);
- ManagedValue self =
- SelfValue.getValue().borrow(SGF).getAsSingleValue(SGF);
SILValue fn = SGF.B.createObjCMethod(
- Loc, self.getValue(), *constant,
- SILType::getPrimitiveObjectType(closureType));
+ Loc, borrowedSelf->getValue(), *constant,
+ closureType);
return ManagedValue::forUnmanaged(fn);
}
}
}
- CalleeTypeInfo getTypeInfoAtUncurryLevel(SILGenFunction &SGF,
- unsigned level) const & {
+ CalleeTypeInfo getTypeInfo(SILGenFunction &SGF, bool isCurried) const & {
Optional<SILDeclRef> constant = None;
if (!Constant) {
- assert(level == 0 && "can't curry indirect function");
+ assert(!isCurried && "can't curry indirect function");
} else {
- unsigned uncurryLevel = Constant.getUncurryLevel();
- assert(level <= uncurryLevel &&
- "uncurrying past natural uncurry level of standalone function");
- if (level < uncurryLevel) {
- assert(level == 0);
- constant = Constant.asCurried();
- } else {
- constant = Constant;
+ constant = getCurriedConstant(isCurried);
+
+ // If the call is curried, emit a direct call to the curry thunk.
+ if (constant->isCurried) {
+ auto constantInfo = SGF.getConstantInfo(*constant);
+ return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
}
@@ -667,38 +587,16 @@
return createCalleeTypeInfo(SGF, constant, IndirectValue.getType());
case Kind::StandaloneFunction: {
- // If we're currying a direct reference to a class-dispatched method,
- // make sure we emit the right set of thunks.
- if (constant->isCurried && Constant.hasDecl())
- if (auto func = Constant.getAbstractFunctionDecl())
- if (getMethodDispatch(func) == MethodDispatch::Class)
- constant = constant->asDirectReference(true);
-
auto constantInfo = SGF.getConstantInfo(*constant);
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- ;
}
- case Kind::EnumElement: {
- auto constantInfo = SGF.getConstantInfo(*constant);
-
- // We should not end up here if the enum constructor call is fully
- // applied.
- assert(constant->isCurried);
- return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- }
+ case Kind::EnumElement:
+ llvm_unreachable("Should have been curried");
case Kind::ClassMethod: {
- // If the call is curried, emit a direct call to the curry thunk.
- if (constant->isCurried) {
- auto constantInfo = SGF.getConstantInfo(*constant);
- return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
- }
-
- // Otherwise, grab the override info.
auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant);
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
case Kind::SuperMethod: {
- assert(!constant->isCurried);
auto base = SGF.SGM.Types.getOverriddenVTableEntry(*constant);
auto constantInfo =
SGF.SGM.Types.getConstantOverrideInfo(*constant, base);
@@ -709,23 +607,8 @@
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
}
case Kind::DynamicMethod: {
- assert(!constant->isCurried);
-
- // Lower the substituted type from the AST, which should have any generic
- // parameters in the original signature erased to their upper bounds.
- auto substFormalType = getSubstFormalType();
- auto objcFormalType = substFormalType.withExtInfo(
- substFormalType->getExtInfo().withSILRepresentation(
- SILFunctionTypeRepresentation::ObjCMethod));
- auto fnType = SGF.SGM.M.Types.getUncachedSILFunctionTypeForConstant(
- *constant, objcFormalType);
-
- auto closureType = replaceSelfTypeForDynamicLookup(
- SGF.getASTContext(), fnType,
- SelfValue.getValue().getSILSubstType(SGF).getSwiftRValueType(),
- Constant);
-
- SILType formalType = SILType::getPrimitiveObjectType(closureType);
+ auto formalType = getDynamicMethodLoweredType(
+ SGF.SGM.M, *constant, getSubstFormalType());
return createCalleeTypeInfo(SGF, constant, formalType);
}
}
@@ -743,11 +626,7 @@
/// lowering, such as a builtin, or return null if there is no specialized
/// emitter.
Optional<SpecializedEmitter>
- getSpecializedEmitter(SILGenModule &SGM, unsigned uncurryLevel) const {
- // Currently we have no curried known functions.
- if (uncurryLevel != 0)
- return None;
-
+ getSpecializedEmitter(SILGenModule &SGM) const {
switch (kind) {
case Kind::StandaloneFunction: {
return SpecializedEmitter::forDecl(SGM, Constant);
@@ -805,17 +684,10 @@
/// The lvalue or rvalue representing the argument source of self.
ArgumentSource selfParam;
- Expr *selfApplyExpr = nullptr;
Type selfType;
std::vector<ApplyExpr*> callSites;
Expr *sideEffect = nullptr;
- /// When visiting expressions, sometimes we need to emit self before we know
- /// what the actual callee is. In such cases, we assume that we are passing
- /// self at +0 and then after we know what the callee is, we check if the
- /// self is passed at +1. If so, we add an extra retain.
- bool assumedPlusZeroSelf = false;
-
SILGenApply(SILGenFunction &SGF)
: SGF(SGF)
{}
@@ -833,17 +705,9 @@
void setSelfParam(ArgumentSource &&theSelfParam, Expr *theSelfApplyExpr) {
assert(!selfParam && "already set this!");
selfParam = std::move(theSelfParam);
- selfApplyExpr = theSelfApplyExpr;
selfType = theSelfApplyExpr->getType();
}
- void setSelfParam(ArgumentSource &&theSelfParam, Type selfType) {
- assert(!selfParam && "already set this!");
- selfParam = std::move(theSelfParam);
- selfApplyExpr = nullptr;
- selfType = selfType;
- }
-
void decompose(Expr *e) {
visit(e);
}
@@ -918,8 +782,8 @@
/*objc=*/true, {}, {});
}
- void processProtocolDecl(DeclRefExpr *e, AbstractFunctionDecl *afd,
- ProtocolDecl *proto) {
+ void processProtocolMethod(DeclRefExpr *e, AbstractFunctionDecl *afd,
+ ProtocolDecl *proto) {
assert(!callSites.empty());
ApplyExpr *thisCallSite = callSites.back();
callSites.pop_back();
@@ -952,139 +816,87 @@
SILDeclRef constant(afd, kind);
constant = constant.asForeign(afd->isObjC());
- // Prepare the callee. This can modify both selfValue and subs.
+ // Prepare the callee.
Callee theCallee = Callee::forWitnessMethod(
SGF, selfValue.getSubstRValueType(),
constant, subs, e);
- assumedPlusZeroSelf =
- selfValue.isRValue() &&
- selfValue.forceAndPeekRValue(SGF).peekIsPlusZeroRValueOrTrivial();
setSelfParam(std::move(selfValue), thisCallSite);
setCallee(std::move(theCallee));
}
- bool processAbstractFunctionDecl(DeclRefExpr *e, AbstractFunctionDecl *afd) {
- // We have four cases to deal with here:
- //
- // 1) for a "static" / "type" method, the base is a metatype.
- // 2) for a classbound protocol, the base is a class-bound protocol
- // rvalue,
- // which is loadable.
- // 3) for a mutating method, the base has inout type.
- // 4) for a nonmutating method, the base is a general archetype
- // rvalue, which is address-only. The base is passed at +0, so it
- // isn't
- // consumed.
- //
- // In the last case, the AST has this call typed as being applied
- // to an rvalue, but the witness is actually expecting a pointer
- // to the +0 value in memory. We just pass in the address since
- // archetypes are address-only.
-
- if (auto *proto = dyn_cast<ProtocolDecl>(afd->getDeclContext())) {
- processProtocolDecl(e, afd, proto);
- return true;
- }
-
- Optional<SILDeclRef::Kind> kind;
- bool isDynamicallyDispatched;
- bool requiresAllocRefDynamic = false;
-
- // Determine whether the method is dynamically dispatched.
- if (e->getAccessSemantics() != AccessSemantics::Ordinary) {
- isDynamicallyDispatched = false;
- } else {
- switch (getMethodDispatch(afd)) {
- case MethodDispatch::Class:
- isDynamicallyDispatched = true;
- break;
- case MethodDispatch::Static:
- isDynamicallyDispatched = false;
- break;
- }
- }
-
- if (isa<FuncDecl>(afd) && isDynamicallyDispatched) {
- kind = SILDeclRef::Kind::Func;
- } else if (auto ctor = dyn_cast<ConstructorDecl>(afd)) {
- ApplyExpr *thisCallSite = callSites.back();
- // Required constructors are dynamically dispatched when the 'self'
- // value is not statically derived.
- if (ctor->isRequired() &&
- thisCallSite->getArg()->getType()->is<AnyMetatypeType>() &&
- !thisCallSite->getArg()->isStaticallyDerivedMetatype()) {
- if (requiresForeignEntryPoint(afd)) {
- // When we're performing Objective-C dispatch, we don't have an
- // allocating constructor to call. So, perform an alloc_ref_dynamic
- // and pass that along to the initializer.
- requiresAllocRefDynamic = true;
- kind = SILDeclRef::Kind::Initializer;
- } else {
- kind = SILDeclRef::Kind::Allocator;
- }
- } else {
- isDynamicallyDispatched = false;
- }
- }
-
- if (!isDynamicallyDispatched)
+ bool isClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
+ if (e->getAccessSemantics() != AccessSemantics::Ordinary)
return false;
- // At this point, we know for sure that we are actually dynamically
- // dispatched.
+ if (getMethodDispatch(afd) == MethodDispatch::Static)
+ return false;
+
+ if (auto ctor = dyn_cast<ConstructorDecl>(afd)) {
+ // Non-required initializers are statically dispatched.
+ if (!ctor->isRequired())
+ return false;
+
+ // Required constructors are statically dispatched when the 'self'
+ // value is statically derived.
+ ApplyExpr *thisCallSite = callSites.back();
+ assert(thisCallSite->getArg()->getType()->is<AnyMetatypeType>());
+ if (thisCallSite->getArg()->isStaticallyDerivedMetatype())
+ return false;
+ }
+
+ // Ok, we're dynamically dispatched.
+ return true;
+ }
+
+ void processClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
+ SILDeclRef::Kind kind;
+ bool requiresAllocRefDynamic = false;
+
+ if (isa<FuncDecl>(afd)) {
+ kind = SILDeclRef::Kind::Func;
+ } else {
+ if (requiresForeignEntryPoint(afd)) {
+ // When we're performing Objective-C dispatch, we don't have an
+ // allocating constructor to call. So, perform an alloc_ref_dynamic
+ // and pass that along to the initializer.
+ requiresAllocRefDynamic = true;
+ kind = SILDeclRef::Kind::Initializer;
+ } else {
+ kind = SILDeclRef::Kind::Allocator;
+ }
+ }
+
ApplyExpr *thisCallSite = callSites.back();
callSites.pop_back();
- // Emit the rvalue for self, allowing for guaranteed plus zero if we
- // have a func.
- bool AllowPlusZero = kind && *kind == SILDeclRef::Kind::Func;
- RValue self = SGF.emitRValue(
- thisCallSite->getArg(),
- AllowPlusZero ? SGFContext::AllowGuaranteedPlusZero : SGFContext());
-
- // If we allowed for PlusZero and we *did* get the value back at +0,
- // then we assumed that self could be passed at +0. We will check later
- // if the actual callee passes self at +1 later when we know its actual
- // type.
- assumedPlusZeroSelf =
- AllowPlusZero && self.peekIsPlusZeroRValueOrTrivial();
-
// If we require a dynamic allocation of the object here, do so now.
if (requiresAllocRefDynamic) {
SILLocation loc = thisCallSite->getArg();
+ RValue selfMetatype = SGF.emitRValue(thisCallSite->getArg());
auto selfValue =
- allocateObjCObject(std::move(self).getAsSingleValue(SGF, loc), loc);
- self = RValue(SGF, loc, selfValue.getType().getSwiftRValueType(),
- selfValue);
+ allocateObjCObject(std::move(selfMetatype).getAsSingleValue(SGF, loc), loc);
+ RValue self = RValue(SGF, loc, selfValue.getType().getSwiftRValueType(),
+ selfValue);
+ ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
+ setSelfParam(std::move(selfArgSource), thisCallSite);
+ } else {
+ ArgumentSource selfArgSource(thisCallSite->getArg());
+ setSelfParam(std::move(selfArgSource), thisCallSite);
}
- auto constant = SILDeclRef(afd, kind.getValue())
+ auto constant = SILDeclRef(afd, kind)
.asForeign(requiresForeignEntryPoint(afd));
- ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
auto subs = e->getDeclRef().getSubstitutions();
- SILLocation loc(thisCallSite->getArg());
- setCallee(Callee::forClassMethod(SGF, selfArgSource.delayedBorrow(SGF),
- constant, subs, e));
-
- setSelfParam(std::move(selfArgSource), thisCallSite);
- return true;
+ setCallee(Callee::forClassMethod(SGF, constant, subs, e));
}
//
// Known callees.
//
void visitDeclRefExpr(DeclRefExpr *e) {
- // If we need to perform dynamic dispatch for the given function,
- // emit class_method to do so.
- if (auto *afd = dyn_cast<AbstractFunctionDecl>(e->getDecl())) {
- // If after processing the abstract function decl, we do not have any more
- // work, just return.
- if (processAbstractFunctionDecl(e, afd)) {
- return;
- }
- }
+ SubstitutionList subs = e->getDeclRef().getSubstitutions();
// If this is a direct reference to a vardecl, just emit its value directly.
// Recursive references to callable declarations are allowed.
@@ -1093,38 +905,45 @@
return;
}
+ // Enum case constructor references are open-coded.
+ if (auto *eed = dyn_cast<EnumElementDecl>(e->getDecl())) {
+ setCallee(Callee::forEnumElement(SGF, SILDeclRef(e->getDecl()), subs, e));
+ return;
+ }
+
+ // Ok, we have a constructor or a function.
+ auto *afd = cast<AbstractFunctionDecl>(e->getDecl());
+
+ // Witness method or @objc protocol dispatch.
+ if (auto *proto = dyn_cast<ProtocolDecl>(afd->getDeclContext())) {
+ processProtocolMethod(e, afd, proto);
+ return;
+ }
+
+ // VTable class method or @objc class method dispatch.
+ if (isClassMethod(e, afd)) {
+ processClassMethod(e, afd);
+ return;
+ }
+
+ // Otherwise, we have a statically-dispatched call.
auto constant = SILDeclRef(e->getDecl())
.asForeign(!isConstructorWithGeneratedAllocatorThunk(e->getDecl())
&& requiresForeignEntryPoint(e->getDecl()));
- auto afd = dyn_cast<AbstractFunctionDecl>(e->getDecl());
+ auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(afd);
+ if (afd->getDeclContext()->isLocalContext() &&
+ !captureInfo.hasGenericParamCaptures())
+ subs = SubstitutionList();
- CaptureInfo captureInfo;
-
- // Otherwise, we have a statically-dispatched call.
- SubstitutionList subs = e->getDeclRef().getSubstitutions();
-
- if (afd) {
- captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(afd);
- if (afd->getDeclContext()->isLocalContext() &&
- !captureInfo.hasGenericParamCaptures())
- subs = SubstitutionList();
- }
-
- // Enum case constructor references are open-coded.
- if (isa<EnumElementDecl>(e->getDecl()))
- setCallee(Callee::forEnumElement(SGF, constant, subs, e));
- else
- setCallee(Callee::forDirect(SGF, constant, subs, e));
+ setCallee(Callee::forDirect(SGF, constant, subs, e));
// If the decl ref requires captures, emit the capture params.
- if (afd) {
- if (!captureInfo.getCaptures().empty()) {
- SmallVector<ManagedValue, 4> captures;
- SGF.emitCaptures(e, afd, CaptureEmission::ImmediateApplication,
- captures);
- applyCallee->setCaptures(std::move(captures));
- }
+ if (!captureInfo.getCaptures().empty()) {
+ SmallVector<ManagedValue, 4> captures;
+ SGF.emitCaptures(e, afd, CaptureEmission::ImmediateApplication,
+ captures);
+ applyCallee->setCaptures(std::move(captures));
}
}
@@ -1168,6 +987,7 @@
setCallee(Callee::forDirect(SGF,
SILDeclRef(e->getDecl(), SILDeclRef::Kind::Initializer), subs, e));
}
+
void visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e) {
setSideEffect(e->getLHS());
visit(e->getRHS());
@@ -1249,8 +1069,7 @@
ArgumentSource superArgSource(arg, std::move(super));
if (!canUseStaticDispatch(SGF, constant)) {
// ObjC super calls require dynamic dispatch.
- setCallee(Callee::forSuperMethod(SGF, superArgSource.delayedBorrow(SGF),
- constant, substitutions, fn));
+ setCallee(Callee::forSuperMethod(SGF, constant, substitutions, fn));
} else {
// Native Swift super calls to final methods are direct.
setCallee(Callee::forDirect(SGF, constant, substitutions, fn));
@@ -1419,8 +1238,7 @@
// Dynamic dispatch to the initializer.
Scope S(SGF, expr);
setCallee(Callee::forClassMethod(
- SGF, selfArgSource.delayedBorrow(SGF),
- constant, subs, fn));
+ SGF, constant, subs, fn));
} else {
// Directly call the peer constructor.
setCallee(
@@ -1515,8 +1333,11 @@
auto substFormalType =
cast<FunctionType>(dynamicMemberRef->getType()->getCanonicalType()
.getAnyOptionalObjectType());
- setCallee(Callee::forDynamic(SGF, baseArgSource.delayedBorrow(SGF),
- member, memberRef.getSubstitutions(),
+ substFormalType = CanFunctionType::get(
+ dynamicMemberRef->getBase()->getType()->getCanonicalType(),
+ substFormalType, AnyFunctionType::ExtInfo());
+
+ setCallee(Callee::forDynamic(SGF, member, memberRef.getSubstitutions(),
substFormalType, {}, e));
setSelfParam(std::move(baseArgSource), dynamicMemberRef);
};
@@ -1846,6 +1667,7 @@
}
// Emit the raw application.
+ loc.decodeDebugLoc(SGM.M.getASTContext().SourceMgr);
SILValue rawDirectResult = emitRawApply(*this, loc, fn, subs, args,
substFnType, options,
indirectResultAddrs);
@@ -3892,50 +3714,6 @@
ArgumentSource &&forward() && {
return std::move(ArgValue);
}
-
- /// Returns true if the argument of this value is a single valued RValue
- /// that is passed either at plus zero or is trivial.
- bool isArgPlusZeroOrTrivialRValue() {
- if (!ArgValue.isRValue())
- return false;
- return ArgValue.peekRValue().peekIsPlusZeroRValueOrTrivial();
- }
-
- /// If callsite has an argument that is a plus zero or trivial rvalue, emit
- /// a retain so that the argument is at PlusOne.
- void convertToPlusOneFromPlusZero(SILGenFunction &SGF) {
- assert(isArgPlusZeroOrTrivialRValue() && "Must have a plus zero or "
- "trivial rvalue as an argument.");
- SILValue ArgSILValue = ArgValue.peekRValue().peekScalarValue();
- SILType ArgTy = ArgSILValue->getType();
-
- // If we are trivial, there is no difference in between +1 and +0 since
- // a trivial object is not reference counted.
- if (ArgTy.isTrivial(SGF.SGM.M))
- return;
-
- // Grab the SILLocation and the new managed value.
- SILLocation ArgLoc = ArgValue.getKnownRValueLocation();
- ManagedValue ArgManagedValue;
- if (ArgSILValue->getType().isAddress()) {
- auto result = SGF.emitTemporaryAllocation(ArgLoc,
- ArgSILValue->getType());
- SGF.B.createCopyAddr(ArgLoc, ArgSILValue, result,
- IsNotTake, IsInitialization);
- ArgManagedValue = SGF.emitManagedBufferWithCleanup(result);
- } else {
- ArgManagedValue = SGF.emitManagedRetain(ArgLoc, ArgSILValue);
- }
-
- // Ok now we make our transformation. First set ArgValue to a used albeit
- // invalid, empty ArgumentSource.
- ArgValue = ArgumentSource();
-
- // Reassign ArgValue.
- RValue NewRValue = RValue(SGF, ArgLoc, ArgTy.getSwiftRValueType(),
- ArgManagedValue);
- ArgValue = ArgumentSource(ArgLoc, std::move(NewRValue));
- }
};
/// Once the Callee and CallSites have been prepared by SILGenApply,
@@ -3957,28 +3735,21 @@
std::vector<CallSite> extraSites;
Callee callee;
FormalEvaluationScope initialWritebackScope;
- unsigned uncurries;
- bool applied;
- bool assumedPlusZeroSelf;
+ unsigned expectedSiteCount;
public:
/// Create an emission for a call of the given callee.
CallEmission(SILGenFunction &SGF, Callee &&callee,
- FormalEvaluationScope &&writebackScope,
- bool assumedPlusZeroSelf = false)
+ FormalEvaluationScope &&writebackScope)
: SGF(SGF), callee(std::move(callee)),
initialWritebackScope(std::move(writebackScope)),
- uncurries(callee.getNaturalUncurryLevel() + 1), applied(false),
- assumedPlusZeroSelf(assumedPlusZeroSelf) {}
+ expectedSiteCount(callee.getParameterListCount()) {}
/// Add a level of function application by passing in its possibly
/// unevaluated arguments and their formal type.
void addCallSite(CallSite &&site) {
- assert(!applied && "already applied!");
-
// Append to the main argument list if we have uncurry levels remaining.
- if (uncurries > 0) {
- --uncurries;
+ if (uncurriedSites.size() < expectedSiteCount) {
uncurriedSites.push_back(std::move(site));
return;
}
@@ -3994,45 +3765,23 @@
addCallSite(CallSite{std::forward<T>(args)...});
}
- /// If we assumed that self was being passed at +0 before we knew what the
- /// final uncurried level of the callee was, but given the final uncurried
- /// level of the callee, we are actually passing self at +1, add in a retain
- /// of self.
- void convertSelfToPlusOneFromPlusZero() {
- // Self is always the first callsite.
- if (!uncurriedSites[0].isArgPlusZeroOrTrivialRValue())
- return;
-
- // Insert an invalid ArgumentSource into uncurriedSites[0] so it is.
- uncurriedSites[0].convertToPlusOneFromPlusZero(SGF);
- }
-
/// Is this a fully-applied enum element constructor call?
bool isEnumElementConstructor() {
- return (callee.kind == Callee::Kind::EnumElement && uncurries == 0);
+ return (callee.kind == Callee::Kind::EnumElement &&
+ uncurriedSites.size() == expectedSiteCount);
}
/// True if this is a completely unapplied super method call
- bool isPartiallyAppliedSuperMethod(unsigned uncurryLevel) {
+ bool isPartiallyAppliedSuperMethod() {
return (callee.kind == Callee::Kind::SuperMethod &&
- uncurryLevel == 0);
+ uncurriedSites.size() == 1);
}
RValue apply(SGFContext C = SGFContext()) {
initialWritebackScope.verify();
- assert(!applied && "already applied!");
-
- applied = true;
-
- // Get the callee value at the needed uncurry level, uncurrying as
- // much as possible. If the number of calls is less than the natural
- // uncurry level, the callee emission might create a curry thunk.
- unsigned uncurryLevel = callee.getNaturalUncurryLevel() - uncurries;
-
// Emit the first level of call.
- FirstLevelApplicationResult firstLevelResult =
- applyFirstLevelCallee(uncurryLevel, C);
+ auto firstLevelResult = applyFirstLevelCallee(C);
// End of the initial writeback scope.
initialWritebackScope.verify();
@@ -4061,17 +3810,8 @@
firstLevelResult.foreignSelf, C, formalTypeThrows);
}
- ~CallEmission() { assert(applied && "never applied!"); }
-
// Movable, but not copyable.
- CallEmission(CallEmission &&e)
- : SGF(e.SGF), uncurriedSites(std::move(e.uncurriedSites)),
- extraSites(std::move(e.extraSites)), callee(std::move(e.callee)),
- initialWritebackScope(std::move(e.initialWritebackScope)),
- uncurries(e.uncurries), applied(e.applied),
- assumedPlusZeroSelf(e.assumedPlusZeroSelf) {
- e.applied = true;
- }
+ CallEmission(CallEmission &&e) = default;
private:
CallEmission(const CallEmission &) = delete;
@@ -4130,19 +3870,17 @@
FirstLevelApplicationResult
applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
- unsigned uncurryLevel, SGFContext C);
+ SGFContext C);
FirstLevelApplicationResult
- applyPartiallyAppliedSuperMethod(unsigned uncurryLevel, SGFContext C);
+ applyPartiallyAppliedSuperMethod(SGFContext C);
FirstLevelApplicationResult
- applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C);
+ applyEnumElementConstructor(SGFContext C);
- FirstLevelApplicationResult applyNormalCall(unsigned uncurryLevel,
- SGFContext C);
+ FirstLevelApplicationResult applyNormalCall(SGFContext C);
- FirstLevelApplicationResult applyFirstLevelCallee(unsigned uncurryLevel,
- SGFContext C);
+ FirstLevelApplicationResult applyFirstLevelCallee(SGFContext C);
RValue applyRemainingCallSites(RValue &&result,
AbstractionPattern origFormalType,
@@ -4165,25 +3903,27 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyFirstLevelCallee(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyFirstLevelCallee(SGFContext C) {
// Check for a specialized emitter.
- if (auto emitter = callee.getSpecializedEmitter(SGF.SGM, uncurryLevel)) {
- return applySpecializedEmitter(emitter.getValue(), uncurryLevel, C);
+ if (uncurriedSites.size() == expectedSiteCount) {
+ if (auto emitter = callee.getSpecializedEmitter(SGF.SGM)) {
+ return applySpecializedEmitter(emitter.getValue(), C);
+ }
}
- if (isPartiallyAppliedSuperMethod(uncurryLevel)) {
- return applyPartiallyAppliedSuperMethod(uncurryLevel, C);
+ if (isPartiallyAppliedSuperMethod()) {
+ return applyPartiallyAppliedSuperMethod(C);
}
if (isEnumElementConstructor()) {
- return applyEnumElementConstructor(uncurryLevel, C);
+ return applyEnumElementConstructor(C);
}
- return applyNormalCall(uncurryLevel, C);
+ return applyNormalCall(C);
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyNormalCall(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyNormalCall(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
// We use the context emit-into initialization only for the
@@ -4193,16 +3933,15 @@
firstLevelResult.formalType = callee.getSubstFormalType();
auto origFormalType = callee.getOrigFormalType();
+ bool isCurried = (uncurriedSites.size() < callee.getParameterListCount());
+
// Get the callee type information.
- CalleeTypeInfo calleeTypeInfo =
- callee.getTypeInfoAtUncurryLevel(SGF, uncurryLevel);
- ManagedValue mv = callee.getFnValueAtUncurryLevel(SGF, uncurryLevel);
+ auto calleeTypeInfo = callee.getTypeInfo(SGF, isCurried);
// In C language modes, substitute the type of the AbstractionPattern
// so that we won't see type parameters down when we try to form bridging
// conversions.
- CanSILFunctionType calleeFnTy = mv.getType().castTo<SILFunctionType>();
- if (calleeFnTy->getLanguage() == SILFunctionLanguage::C) {
+ if (calleeTypeInfo.substFnType->getLanguage() == SILFunctionLanguage::C) {
if (auto genericFnType =
dyn_cast<GenericFunctionType>(origFormalType.getType())) {
auto fnType = genericFnType->substGenericArgs(callee.getSubstitutions());
@@ -4220,20 +3959,6 @@
SGF, calleeTypeInfo, uncurriedSites.back().Loc, uncurriedContext);
ArgumentScope argScope(SGF, uncurriedSites.back().Loc);
- // Now that we know the substFnType, check if we assumed that we were
- // passing self at +0. If we did and self is not actually passed at +0,
- // retain Self.
- if (assumedPlusZeroSelf) {
- // If the final emitted function does not have a self param or it does
- // have a self param that is consumed, convert what we think is self
- // to
- // be plus zero.
- if (!calleeTypeInfo.substFnType->hasSelfParam() ||
- calleeTypeInfo.substFnType->getSelfParameter().isConsumed()) {
- convertSelfToPlusOneFromPlusZero();
- }
- }
-
// Emit the arguments.
SmallVector<ManagedValue, 4> uncurriedArgs;
Optional<SILLocation> uncurriedLoc;
@@ -4245,6 +3970,15 @@
firstLevelResult.formalType, origFormalType, calleeTypeInfo.substFnType,
calleeTypeInfo.foreignError, calleeTypeInfo.foreignSelf, uncurriedArgs,
uncurriedLoc, formalApplyType);
+
+ // Now evaluate the callee.
+ Optional<ManagedValue> borrowedSelf;
+ if (callee.requiresSelfValueForDispatch()) {
+ borrowedSelf = uncurriedArgs.back();
+ }
+
+ auto mv = callee.getFnValue(SGF, isCurried, borrowedSelf);
+
// Emit the uncurried call.
firstLevelResult.value =
SGF.emitApply(std::move(resultPlan), std::move(argScope),
@@ -4255,14 +3989,10 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyEnumElementConstructor(unsigned uncurryLevel, SGFContext C) {
+CallEmission::applyEnumElementConstructor(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
- assert(!assumedPlusZeroSelf);
SGFContext uncurriedContext = (extraSites.empty() ? C : SGFContext());
- // The uncurry level in an enum element constructor is weird, so
- // it's quite fortunate that we can completely ignore it.
-
// Get the callee type information.
//
// Enum payloads are always stored at the abstraction level of the
@@ -4310,10 +4040,8 @@
}
CallEmission::FirstLevelApplicationResult
-CallEmission::applyPartiallyAppliedSuperMethod(unsigned uncurryLevel,
- SGFContext C) {
+CallEmission::applyPartiallyAppliedSuperMethod(SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
- assert(uncurryLevel == 0);
// We want to emit the arguments as fully-substituted values
// because that's what the partially applied super method expects;
@@ -4322,20 +4050,6 @@
auto substFnType =
SGF.getSILFunctionType(origFormalType, firstLevelResult.formalType);
- // Now that we know the substFnType, check if we assumed that we were
- // passing self at +0. If we did and self is not actually passed at +0,
- // retain Self.
- if (assumedPlusZeroSelf) {
- // If the final emitted function does not have a self param or it does
- // have a self param that is consumed, convert what we think is self
- // to
- // be plus zero.
- if (!substFnType->hasSelfParam() ||
- substFnType->getSelfParameter().isConsumed()) {
- convertSelfToPlusOneFromPlusZero();
- }
- }
-
// Emit the arguments.
SmallVector<ManagedValue, 4> uncurriedArgs;
Optional<SILLocation> uncurriedLoc;
@@ -4393,7 +4107,7 @@
CallEmission::FirstLevelApplicationResult
CallEmission::applySpecializedEmitter(SpecializedEmitter &specializedEmitter,
- unsigned uncurryLevel, SGFContext C) {
+ SGFContext C) {
FirstLevelApplicationResult firstLevelResult;
// We use the context emit-into initialization only for the
@@ -4402,8 +4116,6 @@
ManagedValue mv;
- assert(uncurryLevel == 0);
-
// Get the callee type information. We want to emit the arguments as
// fully-substituted values because that's what the specialized emitters
// expect.
@@ -4412,19 +4124,6 @@
auto substFnType =
SGF.getSILFunctionType(origFormalType, firstLevelResult.formalType);
- // Now that we know the substFnType, check if we assumed that we were
- // passing self at +0. If we did and self is not actually passed at +0,
- // retain Self.
- if (assumedPlusZeroSelf) {
- // If the final emitted function does not have a self param or it does
- // have a self param that is consumed, convert what we think is self to
- // be plus zero.
- if (!substFnType->hasSelfParam() ||
- substFnType->getSelfParameter().isConsumed()) {
- convertSelfToPlusOneFromPlusZero();
- }
- }
-
// If we have an early emitter, just let it take over for the
// uncurried call site.
if (specializedEmitter.isEarlyEmitter()) {
@@ -4638,8 +4337,7 @@
// Build the call.
// Pass the writeback scope on to CallEmission so it can thread scopes through
// nested calls.
- CallEmission emission(SGF, apply.getCallee(), std::move(writebacks),
- apply.assumedPlusZeroSelf);
+ CallEmission emission(SGF, apply.getCallee(), std::move(writebacks));
// Apply 'self' if provided.
if (apply.selfParam) {
@@ -4686,8 +4384,13 @@
auto origFormalType = callee.getOrigFormalType();
auto substFormalType = callee.getSubstFormalType();
- CalleeTypeInfo calleeTypeInfo = callee.getTypeInfoAtUncurryLevel(*this, 0);
- ManagedValue mv = callee.getFnValueAtUncurryLevel(*this, 0);
+ auto calleeTypeInfo = callee.getTypeInfo(*this, /*isCurried=*/false);
+
+ Optional<ManagedValue> borrowedSelf;
+ if (callee.requiresSelfValueForDispatch())
+ borrowedSelf = args.back();
+ auto mv = callee.getFnValue(*this, /*isCurried=*/false,
+ borrowedSelf);
assert(!calleeTypeInfo.foreignError);
assert(!calleeTypeInfo.foreignSelf.isImportAsMember());
@@ -5016,14 +4719,12 @@
// Otherwise, if we have a non-final class dispatch to a normal method,
// perform a dynamic dispatch.
if (!isSuper)
- return Callee::forClassMethod(SGF, selfValue.delayedBorrow(SGF), constant,
- subs, loc);
+ return Callee::forClassMethod(SGF, constant, subs, loc);
// If this is a "super." dispatch, we do a dynamic dispatch for objc methods
// or non-final native Swift methods.
if (!canUseStaticDispatch(SGF, constant))
- return Callee::forSuperMethod(SGF, selfValue.delayedBorrow(SGF), constant,
- subs, loc);
+ return Callee::forSuperMethod(SGF, constant, subs, loc);
return Callee::forDirect(SGF, constant, subs, loc);
}
@@ -5676,17 +5377,17 @@
operand->getType().getSwiftRValueType(),
memberMethodTy->getCanonicalType());
- auto dynamicMethodTy = getDynamicMethodLoweredType(*this, operand, member,
+ auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member,
memberFnTy);
- auto loweredMethodTy = SILType::getPrimitiveObjectType(dynamicMethodTy);
SILValue memberArg = hasMemberBB->createPHIArgument(
loweredMethodTy, ValueOwnershipKind::Owned);
// Create the result value.
+ Scope applyScope(Cleanups, CleanupLocation(e));
ManagedValue result =
emitDynamicPartialApply(*this, e, memberArg, operand,
foreignMethodTy, methodTy);
- Scope applyScope(Cleanups, CleanupLocation(e));
+
RValue resultRV;
if (isa<VarDecl>(e->getMember().getDecl())) {
resultRV = emitMonomorphicApply(e, result, {},
@@ -5772,19 +5473,18 @@
auto functionTy = CanFunctionType::get(base->getType().getSwiftRValueType(),
methodTy);
- auto dynamicMethodTy = getDynamicMethodLoweredType(*this, base, member,
+ auto loweredMethodTy = getDynamicMethodLoweredType(SGM.M, member,
functionTy);
- auto loweredMethodTy = SILType::getPrimitiveObjectType(dynamicMethodTy);
SILValue memberArg = hasMemberBB->createPHIArgument(
loweredMethodTy, ValueOwnershipKind::Owned);
// Emit the application of 'self'.
+ Scope applyScope(Cleanups, CleanupLocation(e));
ManagedValue result = emitDynamicPartialApply(*this, e, memberArg, base,
foreignMethodTy, methodTy);
// Emit the index.
llvm::SmallVector<ManagedValue, 2> indexArgs;
std::move(index).getAll(indexArgs);
- Scope applyScope(Cleanups, CleanupLocation(e));
auto resultRV = emitMonomorphicApply(e, result, indexArgs,
foreignMethodTy.getResult(), valueTy,
ApplyOptions::DoesNotThrow,
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index f3a4cc2..ae0d272 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -127,6 +127,16 @@
// Substitute into the witness function type.
witnessFnTy = witnessFnTy.substGenericArgs(SGF.SGM.M, typeSubMap);
+ // We might have to re-abstract the 'self' value if it is an
+ // Optional.
+ AbstractionPattern origSelfType(witness->getInterfaceType());
+ origSelfType = origSelfType.getFunctionInputType();
+
+ swiftValue = SGF.emitSubstToOrigValue(loc, swiftValue,
+ origSelfType,
+ swiftValueType,
+ SGFContext());
+
// The witness may be more abstract than the concrete value we're bridging,
// for instance, if the value is a concrete instantiation of a generic type.
//
@@ -345,6 +355,12 @@
return results;
}
+static CanAnyFunctionType getBridgedBlockType(SILGenModule &SGM,
+ CanAnyFunctionType blockType) {
+ return SGM.Types.getBridgedFunctionType(AbstractionPattern(blockType),
+ blockType, blockType->getExtInfo());
+}
+
static void buildFuncToBlockInvokeBody(SILGenFunction &SGF,
SILLocation loc,
CanAnyFunctionType formalFuncType,
@@ -358,10 +374,7 @@
SILFunctionConventions funcConv(funcTy, SGF.SGM.M);
// Make sure we lower the component types of the formal block type.
- formalBlockType =
- SGF.SGM.Types.getBridgedFunctionType(AbstractionPattern(formalBlockType),
- formalBlockType,
- formalBlockType->getExtInfo());
+ formalBlockType = getBridgedBlockType(SGF.SGM, formalBlockType);
// Set up the indirect result.
SILType blockResultTy = blockTy->getAllResultsType();
@@ -498,6 +511,8 @@
auto blockInterfaceTy = cast<SILFunctionType>(
F.mapTypeOutOfContext(loweredBlockTy)->getCanonicalType());
+ assert(!blockInterfaceTy->isCoroutine());
+
auto storageTy = SILBlockStorageType::get(loweredFuncTy);
auto storageInterfaceTy = SILBlockStorageType::get(fnInterfaceTy);
@@ -535,8 +550,9 @@
}
auto invokeTy = SILFunctionType::get(
- genericSig, extInfo, ParameterConvention::Direct_Unowned, params,
- blockInterfaceTy->getResults(),
+ genericSig, extInfo, SILCoroutineKind::None,
+ ParameterConvention::Direct_Unowned, params,
+ /*yields*/ {}, blockInterfaceTy->getResults(),
blockInterfaceTy->getOptionalErrorResult(), getASTContext());
// Create the invoke function. Borrow the mangling scheme from reabstraction
@@ -751,6 +767,9 @@
// Collect the native arguments, which should all be +1.
Scope scope(SGF.Cleanups, CleanupLocation::get(loc));
+ // Make sure we lower the component types of the formal block type.
+ formalBlockTy = getBridgedBlockType(SGF.SGM, formalBlockTy);
+
assert(blockTy->getNumParameters() == funcTy->getNumParameters()
&& "block and function types don't match");
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index f782af6..c6f9aa8 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -229,7 +229,8 @@
// On failure, we'll clean up everything (except self, which should have
// been cleaned up before jumping here) and return nil instead.
- SavedInsertionPoint savedIP(*this, failureBB, FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint savedIP(*this, failureBB,
+ FunctionSection::Postmatter);
failureExitBB = createBasicBlock();
Cleanups.emitCleanupsForReturn(ctor);
// Return nil.
@@ -275,7 +276,7 @@
// SIL representation.
SILValue selfValue;
{
- SavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
+ SILGenSavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
assert(B.getInsertionBB()->empty() && "Epilog already set up?");
auto cleanupLoc = CleanupLocation::get(ctor);
@@ -621,7 +622,8 @@
loc.markAutoGenerated();
// On failure, we'll clean up everything and return nil instead.
- SavedInsertionPoint savedIP(*this, failureBB, FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint savedIP(*this, failureBB,
+ FunctionSection::Postmatter);
failureExitBB = createBasicBlock();
failureExitArg = failureExitBB->createPHIArgument(
@@ -674,7 +676,7 @@
ReturnDest.getDepth()) &&
"emitting epilog in wrong scope");
- SavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
+ SILGenSavedInsertionPoint savedIP(*this, ReturnDest.getBlock());
assert(B.getInsertionBB()->empty() && "Epilog already set up?");
auto cleanupLoc = CleanupLocation(ctor);
@@ -857,8 +859,10 @@
initConstantTy = SILFunctionType::get(initConstantTy->getGenericSignature(),
initConstantTy->getExtInfo(),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
param,
+ /*yields*/ {},
result,
// TODO: throwing initializer?
None,
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index 4009cc0..11b1f41 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -396,7 +396,7 @@
finalResult = emitManagedBufferWithCleanup(
emitTemporaryAllocation(loc, resultTy), resultTL);
} else {
- SavedInsertionPoint IP(*this, contBB);
+ SILGenSavedInsertionPoint IP(*this, contBB);
finalResult = B.createOwnedPHIArgument(resultTL.getLoweredType());
}
diff --git a/lib/SILGen/SILGenDecl.cpp b/lib/SILGen/SILGenDecl.cpp
index ffe41f8..b969f52 100644
--- a/lib/SILGen/SILGenDecl.cpp
+++ b/lib/SILGen/SILGenDecl.cpp
@@ -1125,7 +1125,7 @@
// the initialization. Otherwise, mark it uninitialized for DI to resolve.
if (auto *Init = entry.getInit()) {
FullExpr Scope(Cleanups, CleanupLocation(Init));
- emitExprInto(Init, initialization.get());
+ emitExprInto(Init, initialization.get(), SILLocation(PBD));
} else {
initialization->finishUninitialized(*this);
}
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 0528044..2252d6c 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -361,7 +361,8 @@
return ManagedValue(v, enterDestroyCleanup(v));
}
-void SILGenFunction::emitExprInto(Expr *E, Initialization *I) {
+void SILGenFunction::emitExprInto(Expr *E, Initialization *I,
+ Optional<SILLocation> L) {
// Handle the special case of copying an lvalue.
if (auto load = dyn_cast<LoadExpr>(E)) {
FormalEvaluationScope writeback(*this);
@@ -372,7 +373,7 @@
RValue result = emitRValue(E, SGFContext(I));
if (!result.isInContext())
- std::move(result).forwardInto(*this, E, I);
+ std::move(result).forwardInto(*this, L ? *L : E, I);
}
namespace {
@@ -1042,8 +1043,11 @@
// If the referenced decl isn't a VarDecl, it should be a constant of some
// sort.
SILDeclRef silDeclRef(decl);
- if (silDeclRef.getUncurryLevel() > 0)
+ if (silDeclRef.getParameterListCount() == 2) {
+ // Unqualified reference to an instance method from a static context,
+ // without applying 'self'.
silDeclRef = silDeclRef.asCurried();
+ }
ManagedValue result = emitClosureValue(loc, silDeclRef, refType,
declRef.getSubstitutions());
@@ -1414,7 +1418,7 @@
SGF.eraseBasicBlock(catchBB);
} else {
// Otherwise, we need to emit it.
- SavedInsertionPoint scope(SGF, catchBB, FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint scope(SGF, catchBB, FunctionSection::Postmatter);
ASTContext &ctx = SGF.getASTContext();
auto error = catchBB->createPHIArgument(SILType::getExceptionType(ctx),
@@ -1887,9 +1891,11 @@
case AnyFunctionType::Representation::Swift: {
switch (sourceTy->getRepresentation()) {
case SILFunctionType::Representation::Thin: {
- auto v = SGF.B.createThinToThickFunction(loc, source.getValue(),
- SILType::getPrimitiveObjectType(
- adjustFunctionType(sourceTy, SILFunctionType::Representation::Thick)));
+ auto v = SGF.B.createThinToThickFunction(
+ loc, source.getValue(),
+ SILType::getPrimitiveObjectType(adjustFunctionType(
+ sourceTy, SILFunctionType::Representation::Thick,
+ SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)));
// FIXME: what if other reabstraction is required?
return ManagedValue(v, source.getCleanup());
}
@@ -1913,9 +1919,11 @@
switch (sourceTy->getRepresentation()) {
case SILFunctionType::Representation::Thin: {
// Make thick first.
- auto v = SGF.B.createThinToThickFunction(loc, source.getValue(),
- SILType::getPrimitiveObjectType(
- adjustFunctionType(sourceTy, SILFunctionType::Representation::Thick)));
+ auto v = SGF.B.createThinToThickFunction(
+ loc, source.getValue(),
+ SILType::getPrimitiveObjectType(adjustFunctionType(
+ sourceTy, SILFunctionType::Representation::Thick,
+ SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)));
source = ManagedValue(v, source.getCleanup());
LLVM_FALLTHROUGH;
}
@@ -2845,7 +2853,9 @@
// Generate the closure value (if any) for the closure expr's function
// reference.
auto refType = e->getType()->getCanonicalType();
- ManagedValue result = SGF.emitClosureValue(e, SILDeclRef(e),
+ SILLocation L = e;
+ L.markAutoGenerated();
+ ManagedValue result = SGF.emitClosureValue(L, SILDeclRef(e),
refType, subs);
return RValue(SGF, e, refType, result);
}
@@ -3029,8 +3039,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, result, None, SGF.getASTContext());
+ params, {}, result, None, SGF.getASTContext());
// Find the function and see if we already created it.
SmallVector<CanType, 2> interfaceSubs;
@@ -3149,8 +3160,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, {}, None, SGF.getASTContext());
+ params, {}, {}, None, SGF.getASTContext());
// Mangle the name of the thunk to see if we already created it.
SmallString<64> nameBuf;
@@ -3317,8 +3329,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, results, None, C);
+ params, /*yields*/ {}, results, None, C);
// Mangle the name of the thunk to see if we already created it.
SmallString<64> nameBuf;
@@ -3483,8 +3496,9 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false,
/*noescape*/ false),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
- params, results, None, C);
+ params, /*yields*/ {}, results, None, C);
// Mangle the name of the thunk to see if we already created it.
SmallString<64> nameBuf;
@@ -5066,37 +5080,25 @@
llvm::function_ref<void(Expr *)> emitSubExpr) {
Optional<FormalEvaluationScope> writebackScope;
- Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
-
// Emit the existential value.
- SILGenFunction::OpaqueValueState state;
-
- AccessKind accessKind;
if (E->getExistentialValue()->getType()->is<LValueType>()) {
- // Create a writeback scope for the access to the existential lvalue.
- writebackScope.emplace(*this);
+ bool inserted = OpaqueValueExprs.insert({E->getOpaqueValue(), E}).second;
+ (void)inserted;
+ assert(inserted && "already have this opened existential?");
- Type formalRValueType =
- E->getOpaqueValue()->getType()->getWithoutSpecifierType();
+ emitSubExpr(E->getSubExpr());
+ return;
+ }
- accessKind = E->getExistentialValue()->getLValueAccessKind();
- auto lv = emitLValue(E->getExistentialValue(), accessKind);
- lv = emitOpenExistentialLValue(E, std::move(lv),
- CanArchetypeType(E->getOpenedArchetype()),
- formalRValueType->getCanonicalType(),
- accessKind);
- auto addr = emitAddressOfLValue(E, std::move(lv), accessKind);
- state = {addr, false, false};
- } else {
- accessKind = AccessKind::Read;
- auto existentialValue = emitRValueAsSingleValue(
+ auto existentialValue = emitRValueAsSingleValue(
E->getExistentialValue(),
SGFContext::AllowGuaranteedPlusZero);
-
- state = emitOpenExistential(
+
+ Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
+ auto state = emitOpenExistential(
E, existentialValue, E->getOpenedArchetype(),
- getLoweredType(opaqueValueType), accessKind);
- }
+ getLoweredType(opaqueValueType),
+ AccessKind::Read);
// Register the opaque value for the projected existential.
SILGenFunction::OpaqueValueRAII opaqueValueRAII(
diff --git a/lib/SILGen/SILGenForeignError.cpp b/lib/SILGen/SILGenForeignError.cpp
index 7f39f0a..63dcf62 100644
--- a/lib/SILGen/SILGenForeignError.cpp
+++ b/lib/SILGen/SILGenForeignError.cpp
@@ -253,7 +253,8 @@
void SILGenFunction::emitForeignErrorBlock(SILLocation loc,
SILBasicBlock *errorBB,
Optional<ManagedValue> errorSlot) {
- SavedInsertionPoint savedIP(*this, errorBB, FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint savedIP(*this, errorBB,
+ FunctionSection::Postmatter);
// Load the error (taking responsibility for it). In theory, this
// is happening within conditional code, so we need to be only
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 8844bc6..f579dcc 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -475,9 +475,11 @@
SILFunctionType::ExtInfo()
.withRepresentation(SILFunctionType::Representation::
CFunctionPointer),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
SILParameterInfo(anyObjectMetaTy,
ParameterConvention::Direct_Unowned),
+ /*yields*/ {},
SILResultInfo(OptNSStringTy,
ResultConvention::Autoreleased),
/*error result*/ None,
@@ -577,8 +579,10 @@
// Should be C calling convention, but NSApplicationMain
// has an overlay to fix the type of argv.
.withRepresentation(SILFunctionType::Representation::Thin),
+ SILCoroutineKind::None,
ParameterConvention::Direct_Unowned,
argTypes,
+ /*yields*/ {},
SILResultInfo(argc->getType().getSwiftRValueType(),
ResultConvention::Unowned),
/*error result*/ None,
diff --git a/lib/SILGen/SILGenFunction.h b/lib/SILGen/SILGenFunction.h
index 85603c9..978debb 100644
--- a/lib/SILGen/SILGenFunction.h
+++ b/lib/SILGen/SILGenFunction.h
@@ -518,6 +518,8 @@
void emitForeignToNativeThunk(SILDeclRef thunk);
/// Generates a thunk from a native function to the conventions.
void emitNativeToForeignThunk(SILDeclRef thunk);
+ /// Generates a resilient method dispatch thunk.
+ void emitDispatchThunk(SILDeclRef constant);
/// Generate a nullary function that returns the given value.
void emitGeneratorFunction(SILDeclRef function, Expr *value);
@@ -952,7 +954,8 @@
/// Generate SIL for the given expression, storing the final result into the
/// specified Initialization buffer(s). This avoids an allocation and copy if
/// the result would be allocated into temporary memory normally.
- void emitExprInto(Expr *E, Initialization *I);
+ /// The location defaults to \c E.
+ void emitExprInto(Expr *E, Initialization *I, Optional<SILLocation> L = None);
/// Emit the given expression as an r-value.
RValue emitRValue(Expr *E, SGFContext C = SGFContext());
@@ -1044,6 +1047,11 @@
SILValue emitDynamicMethodRef(SILLocation loc, SILDeclRef constant,
CanSILFunctionType constantTy);
+ /// Returns a reference to a vtable-dispatched method.
+ SILValue emitClassMethodRef(SILLocation loc, SILValue selfPtr,
+ SILDeclRef constant,
+ CanSILFunctionType constantTy);
+
/// Emit the specified VarDecl as an LValue if possible, otherwise return
/// null.
ManagedValue emitLValueForDecl(SILLocation loc, VarDecl *var,
@@ -1810,15 +1818,15 @@
/// A utility class for saving and restoring the insertion point.
-class SavedInsertionPoint {
+class SILGenSavedInsertionPoint {
SILGenFunction &SGF;
SILBasicBlock *SavedIP;
FunctionSection SavedSection;
public:
- SavedInsertionPoint(SILGenFunction &SGF, SILBasicBlock *newIP,
- Optional<FunctionSection> optSection = None)
- : SGF(SGF), SavedIP(SGF.B.getInsertionBB()),
- SavedSection(SGF.CurFunctionSection) {
+ SILGenSavedInsertionPoint(SILGenFunction &SGF, SILBasicBlock *newIP,
+ Optional<FunctionSection> optSection = None)
+ : SGF(SGF), SavedIP(SGF.B.getInsertionBB()),
+ SavedSection(SGF.CurFunctionSection) {
FunctionSection section = (optSection ? *optSection : SavedSection);
assert((section != FunctionSection::Postmatter ||
SGF.StartOfPostmatter != SGF.F.end()) &&
@@ -1829,10 +1837,11 @@
SGF.CurFunctionSection = section;
}
- SavedInsertionPoint(const SavedInsertionPoint &) = delete;
- SavedInsertionPoint &operator=(const SavedInsertionPoint &) = delete;
+ SILGenSavedInsertionPoint(const SILGenSavedInsertionPoint &) = delete;
+ SILGenSavedInsertionPoint &
+ operator=(const SILGenSavedInsertionPoint &) = delete;
- ~SavedInsertionPoint() {
+ ~SILGenSavedInsertionPoint() {
if (SavedIP) {
SGF.B.setInsertionPoint(SavedIP);
} else {
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index b0ccd080..859abba 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -1146,10 +1146,8 @@
// If the declaration is in a different resilience domain, we have
// to use materializeForSet.
- //
- // FIXME: Use correct ResilienceExpansion if SGF is @transparent
if (!decl->hasFixedLayout(SGF.SGM.M.getSwiftModule(),
- ResilienceExpansion::Maximal))
+ SGF.F.getResilienceExpansion()))
return true;
// If the declaration is dynamically dispatched through a class,
diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp
index 8c3e142..27910a1 100644
--- a/lib/SILGen/SILGenPattern.cpp
+++ b/lib/SILGen/SILGenPattern.cpp
@@ -1988,9 +1988,8 @@
enumDecl = SGF.getASTContext().getOptionalDecl();
}
- // FIXME: Get expansion from SILFunction
if (enumDecl->hasFixedLayout(SGF.SGM.M.getSwiftModule(),
- ResilienceExpansion::Maximal)) {
+ SGF.F.getResilienceExpansion())) {
exhaustive = true;
for (auto elt : enumDecl->getAllElements()) {
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index 4cd88e0..3a7fe53 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -60,8 +60,11 @@
// Witness thunks
// ==============
//
-// Currently protocol witness methods are called with an additional generic
-// parameter bound to the Self type, and thus always require a thunk.
+// Protocol witness methods are called with an additional generic parameter
+// bound to the Self type, and thus always require a thunk. Thunks are also
+// required for conditional conformances, since the extra requirements aren't
+// part of the protocol and so any witness tables need to be loaded from the
+// original protocol's witness table and passed into the real witness method.
//
// Thunks for class method witnesses dispatch through the vtable allowing
// inherited witnesses to be overridden in subclasses. Hence a witness thunk
@@ -2817,12 +2820,15 @@
extInfo = extInfo.withIsPseudogeneric();
// Add the function type as the parameter.
+ auto contextConvention = SGM.M.getOptions().EnableGuaranteedClosureContexts
+ ? ParameterConvention::Direct_Guaranteed
+ : DefaultThickCalleeConvention;
SmallVector<SILParameterInfo, 4> params;
params.append(expectedType->getParameters().begin(),
expectedType->getParameters().end());
params.push_back({sourceType,
sourceType->getExtInfo().hasContext()
- ? DefaultThickCalleeConvention
+ ? contextConvention
: ParameterConvention::Direct_Unowned});
// Map the parameter and expected types out of context to get the interface
@@ -2837,6 +2843,15 @@
param.getConvention()));
}
+ SmallVector<SILYieldInfo, 4> interfaceYields;
+ for (auto &yield : expectedType->getYields()) {
+ auto yieldIfaceTy = GenericEnvironment::mapTypeOutOfContext(
+ genericEnv, yield.getType());
+ auto interfaceYield =
+ yield.getWithType(yieldIfaceTy->getCanonicalType(genericSig));
+ interfaceYields.push_back(interfaceYield);
+ }
+
SmallVector<SILResultInfo, 4> interfaceResults;
for (auto &result : expectedType->getResults()) {
auto resultIfaceTy = GenericEnvironment::mapTypeOutOfContext(
@@ -2858,9 +2873,10 @@
// The type of the thunk function.
return SILFunctionType::get(genericSig, extInfo,
+ expectedType->getCoroutineKind(),
ParameterConvention::Direct_Unowned,
- interfaceParams, interfaceResults,
- interfaceErrorResult,
+ interfaceParams, interfaceYields,
+ interfaceResults, interfaceErrorResult,
getASTContext());
}
@@ -2974,9 +2990,8 @@
// Apply any ABI-compatible conversions before doing thin-to-thick.
if (fnType != newFnType) {
SILType resTy = SILType::getPrimitiveObjectType(newFnType);
- fn = ManagedValue(
- SGF.B.createConvertFunction(Loc, fn.getValue(), resTy),
- fn.getCleanup());
+ fn = SGF.emitManagedRValueWithCleanup(
+ SGF.B.createConvertFunction(Loc, fn.forward(SGF), resTy));
}
// Now do thin-to-thick if necessary.
@@ -3274,9 +3289,7 @@
return SGF.emitDynamicMethodRef(loc, witness, witnessFTy);
case WitnessDispatchKind::Class: {
SILValue selfPtr = witnessParams.back().getValue();
- assert(!witness.isForeign);
- return SGF.B.createClassMethod(loc, selfPtr, witness,
- SILType::getPrimitiveObjectType(witnessFTy));
+ return SGF.emitClassMethodRef(loc, selfPtr, witness, witnessFTy);
}
}
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index 87d6e2c..025443a 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -390,14 +390,20 @@
SILType ty = lowering.getLoweredType();
SILValue val = SGF.F.begin()->createFunctionArgument(ty, VD);
+ bool NeedToDestroyValueAtExit =
+ !SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts;
+
// If the original variable was settable, then Sema will have treated the
// VarDecl as an lvalue, even in the closure's use. As such, we need to
// allow formation of the address for this captured value. Create a
// temporary within the closure to provide this address.
if (VD->isSettable(VD->getDeclContext())) {
auto addr = SGF.emitTemporaryAllocation(VD, ty);
- if (SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)
+ if (SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts) {
+ // We have created a copy that needs to be destroyed.
val = SGF.B.createCopyValue(Loc, val);
+ NeedToDestroyValueAtExit = true;
+ }
lowering.emitStore(SGF.B, VD, val, addr, StoreOwnershipQualifier::Init);
val = addr;
}
@@ -409,8 +415,7 @@
SGF.B.createDebugValue(Loc, val, {/*Constant*/true, ArgNo});
// TODO: Closure contexts should always be guaranteed.
- if (!SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts
- && !lowering.isTrivial())
+ if (NeedToDestroyValueAtExit && !lowering.isTrivial())
SGF.enterDestroyCleanup(val);
break;
}
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index fd1e468..82953ae 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -550,7 +550,7 @@
// Move the insertion point to the 'body' block temporarily and emit it.
// Note that we don't push break/continue locations since they aren't valid
// in this statement.
- SavedInsertionPoint savedIP(SGF, bodyBB.getBlock());
+ SILGenSavedInsertionPoint savedIP(SGF, bodyBB.getBlock());
SGF.emitProfilerIncrement(S->getBody());
SGF.emitStmt(S->getBody());
@@ -691,7 +691,7 @@
// has no predecessors, and SGF.ThrowDest may not be valid either.
if (auto *BB = getOrEraseBlock(SGF, throwDest)) {
// Move the insertion point to the throw destination.
- SavedInsertionPoint savedIP(SGF, BB, FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint savedIP(SGF, BB, FunctionSection::Postmatter);
// The exception cleanup should be getting forwarded around
// correctly anyway, but push a scope to ensure it gets popped.
@@ -976,7 +976,7 @@
ValueOwnershipKind::Owned);
assert(B.hasValidInsertionPoint() && B.insertingAtEndOfBlock());
- SavedInsertionPoint savedIP(*this, destBB, FunctionSection::Postmatter);
+ SILGenSavedInsertionPoint savedIP(*this, destBB, FunctionSection::Postmatter);
// If we're suppressing error paths, just wrap it up as unreachable
// and return.
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index 6c56589..9429e09 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -33,11 +33,116 @@
using namespace swift;
using namespace Lowering;
+SILFunction *SILGenModule::getDispatchThunk(SILDeclRef constant,
+ ForDefinition_t forDefinition) {
+ // Mangle the constant with a Tv suffix.
+ auto name = constant.mangle(SILDeclRef::ManglingKind::SwiftDispatchThunk);
+ auto constantTy = M.Types.getConstantOverrideType(constant);
+
+ auto linkage = (forDefinition
+ ? SILLinkage::Public
+ : SILLinkage::PublicExternal);
+
+ // N.B.: Right now, we don't serialize vtables in resilient modules,
+ // so there's nothing to gain from marking these as serialized.
+ return M.getOrCreateFunction(constant.getDecl(), name, linkage,
+ constantTy, IsBare, IsNotTransparent,
+ IsNotSerialized, ProfileCounter(), IsThunk);
+}
+
+SILFunction *SILGenModule::emitDispatchThunk(SILDeclRef constant) {
+ auto *F = getDispatchThunk(constant, ForDefinition);
+
+ if (F->empty()) {
+ auto *afd = cast<AbstractFunctionDecl>(constant.getDecl());
+
+ preEmitFunction(constant, afd, F, afd);
+ SILGenFunction SGF(*this, *F);
+ SGF.emitDispatchThunk(constant);
+ postEmitFunction(constant, F);
+ }
+
+ return F;
+}
+
+void SILGenFunction::emitDispatchThunk(SILDeclRef constant) {
+ auto *afd = cast<AbstractFunctionDecl>(constant.getDecl());
+
+ SILLocation loc(afd);
+ loc.markAutoGenerated();
+
+ auto subs = F.getForwardingSubstitutions();
+
+ SmallVector<SILValue, 8> args;
+
+ // Add the indirect results.
+ for (auto resultTy : F.getConventions().getIndirectSILResultTypes()) {
+ auto paramTy = F.mapTypeIntoContext(resultTy);
+ args.push_back(F.begin()->createFunctionArgument(paramTy));
+ }
+
+ // Add the parameters.
+ auto paramTypes = F.getLoweredFunctionType()->getParameters();
+ for (auto param : paramTypes) {
+ auto paramTy = F.mapTypeIntoContext(F.getConventions().getSILType(param));
+ args.push_back(F.begin()->createFunctionArgument(paramTy));
+ }
+
+ auto constantTy = F.getLoweredFunctionType();
+
+ auto selfPtr = args.back();
+ auto fnValue =
+ B.createClassMethod(loc, selfPtr, constant,
+ SILType::getPrimitiveObjectType(constantTy));
+ auto substFnType = fnValue->getType().substGenericArgs(SGM.M, subs);
+ auto result =
+ emitApplyWithRethrow(loc, fnValue, substFnType, subs, args);
+
+ B.createReturn(loc, result);
+}
+
+static bool shouldUseDispatchThunk(SILDeclRef constant,
+ SILFunction *F,
+ SILModule &M) {
+ auto *afd = cast<AbstractFunctionDecl>(constant.getDecl());
+ auto *classDecl = cast<ClassDecl>(afd->getDeclContext());
+
+ // Resilient classes in other resilience domains use dispatch thunks.
+ return !classDecl->hasFixedLayout(M.getSwiftModule(),
+ F->getResilienceExpansion());
+}
+
+SILValue SILGenFunction::emitClassMethodRef(SILLocation loc,
+ SILValue selfPtr,
+ SILDeclRef constant,
+ CanSILFunctionType constantTy) {
+ assert(!constant.isForeign);
+
+ // Not every override gets a dispatch thunk; find the least derived one
+ // that does.
+ auto base = SGM.M.Types.getOverriddenVTableEntry(constant);
+
+ if (shouldUseDispatchThunk(base, &F, SGM.M)) {
+ auto *thunkFn = SGM.getDispatchThunk(base, NotForDefinition);
+
+ SILValue ref = B.createFunctionRef(loc, thunkFn);
+ if (thunkFn->getLoweredFunctionType() != constantTy) {
+ auto resultTy = SILType::getPrimitiveObjectType(constantTy);
+ ref = B.createConvertFunction(loc, ref, resultTy);
+ }
+
+ return ref;
+ }
+
+ return B.createClassMethod(loc, selfPtr, constant,
+ SILType::getPrimitiveObjectType(constantTy));
+}
+
SILFunction *SILGenModule::getDynamicThunk(SILDeclRef constant,
CanSILFunctionType constantTy) {
assert(constant.kind != SILDeclRef::Kind::Allocator &&
"allocating entry point for constructor is never dynamic");
- // Mangle the constant with a _TTD header.
+ // Mangle the constant with a TD suffix.
auto name = constant.mangle(SILDeclRef::ManglingKind::DynamicThunk);
auto F = M.getOrCreateFunction(constant.getDecl(), name, SILLinkage::Shared,
@@ -98,16 +203,11 @@
if (auto *func = dyn_cast<AbstractFunctionDecl>(vd)) {
if (getMethodDispatch(func) == MethodDispatch::Class) {
// Use the dynamic thunk if dynamic.
- if (vd->isDynamic()) {
- auto dynamicThunk = SGF.SGM.getDynamicThunk(next,
- constantInfo.SILFnType);
- return SGF.B.createFunctionRef(loc, dynamicThunk);
- }
+ if (vd->isDynamic())
+ return SGF.emitDynamicMethodRef(loc, next, constantInfo.SILFnType);
auto methodTy = SGF.SGM.Types.getConstantOverrideType(next);
- assert(!next.isForeign);
- return SGF.B.createClassMethod(loc, selfArg, next,
- SILType::getPrimitiveObjectType(methodTy));
+ return SGF.emitClassMethodRef(loc, selfArg, next, methodTy);
}
// If the fully-uncurried reference is to a generic method, look up the
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index 61bdb663..dbd8e4a 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -170,6 +170,7 @@
public:
SILGenModule &SGM;
ClassDecl *theClass;
+ bool hasFixedLayout;
// Map a base SILDeclRef to the corresponding element in vtableMethods.
llvm::DenseMap<SILDeclRef, unsigned> baseToIndexMap;
@@ -178,8 +179,9 @@
SmallVector<std::pair<SILDeclRef, SILDeclRef>, 8> vtableMethods;
SILGenVTable(SILGenModule &SGM, ClassDecl *theClass)
- : SILVTableVisitor(SGM.Types), SGM(SGM), theClass(theClass)
- { }
+ : SILVTableVisitor(SGM.Types), SGM(SGM), theClass(theClass) {
+ hasFixedLayout = theClass->hasFixedLayout();
+ }
void emitVTable() {
// Imported types don't have vtables right now.
@@ -260,9 +262,21 @@
auto result = baseToIndexMap.insert(std::make_pair(member, index));
assert(result.second);
(void) result;
+
+ // Emit a method dispatch thunk if the method is public and the
+ // class is resilient.
+ auto *func = cast<AbstractFunctionDecl>(member.getDecl());
+ if (func->getDeclContext() == theClass) {
+ if (!hasFixedLayout &&
+ func->getEffectiveAccess() >= AccessLevel::Public) {
+ SGM.emitDispatchThunk(member);
+ }
+ }
}
- void addPlaceholder(MissingMemberDecl *) {}
+ void addPlaceholder(MissingMemberDecl *) {
+ llvm_unreachable("Should not be emitting class with missing members");
+ }
};
} // end anonymous namespace
@@ -367,6 +381,7 @@
SILGenModule &SGM;
NormalProtocolConformance *Conformance;
std::vector<SILWitnessTable::Entry> Entries;
+ std::vector<SILWitnessTable::ConditionalConformance> ConditionalConformances;
SILLinkage Linkage;
IsSerialized_t Serialized;
@@ -398,6 +413,8 @@
auto *proto = Conformance->getProtocol();
visitProtocolDecl(proto);
+ addConditionalRequirements();
+
// Check if we already have a declaration or definition for this witness
// table.
if (auto *wt = SGM.M.lookUpWitnessTable(Conformance, false)) {
@@ -410,7 +427,7 @@
// If we have a declaration, convert the witness table to a definition.
if (wt->isDeclaration()) {
- wt->convertToDefinition(Entries, Serialized);
+ wt->convertToDefinition(Entries, ConditionalConformances, Serialized);
// Since we had a declaration before, its linkage should be external,
// ensure that we have a compatible linkage for sanity. *NOTE* we are ok
@@ -427,8 +444,8 @@
}
// Otherwise if we have no witness table yet, create it.
- return SILWitnessTable::create(SGM.M, Linkage, Serialized,
- Conformance, Entries);
+ return SILWitnessTable::create(SGM.M, Linkage, Serialized, Conformance,
+ Entries, ConditionalConformances);
}
void addOutOfLineBaseProtocol(ProtocolDecl *baseProtocol) {
@@ -518,6 +535,22 @@
req.getAssociation(), req.getAssociatedRequirement(),
assocConformance});
}
+
+ void addConditionalRequirements() {
+ SILWitnessTable::enumerateWitnessTableConditionalConformances(
+ Conformance, [&](unsigned, CanType type, ProtocolDecl *protocol) {
+ auto conformance =
+ Conformance->getGenericSignature()->lookupConformance(type,
+ protocol);
+ assert(conformance &&
+ "unable to find conformance that should be known");
+
+ ConditionalConformances.push_back(
+ SILWitnessTable::ConditionalConformance{type, *conformance});
+
+ return /*finished?*/ false;
+ });
+ }
};
} // end anonymous namespace
diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp
index e4c2eed..f776571 100644
--- a/lib/SILOptimizer/ARC/ARCRegionState.cpp
+++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp
@@ -170,6 +170,8 @@
// against the operand or can use the value in some way.
case TermKind::ThrowInst:
case TermKind::ReturnInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
case TermKind::SwitchEnumInst:
diff --git a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
index bf3d1ae..50ae744 100644
--- a/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
+++ b/lib/SILOptimizer/ARC/GlobalARCSequenceDataflow.cpp
@@ -211,6 +211,8 @@
// against the operand or can use the value in some way.
case TermKind::ThrowInst:
case TermKind::ReturnInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
case TermKind::SwitchEnumInst:
diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
index 24cc25a..518cec2 100644
--- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp
+++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
@@ -84,16 +84,9 @@
auto *AllocBufferAI = dyn_cast<ApplyInst>(Arg0);
if (!AllocBufferAI)
return false;
-
auto *AllocFn = AllocBufferAI->getReferencedFunction();
- if (!AllocFn)
- return false;
-
- StringRef AllocFuncName = AllocFn->getName();
- if (AllocFuncName != "swift_bufferAllocate")
- return false;
-
- if (!hasOneNonDebugUse(AllocBufferAI))
+ if (!AllocFn || AllocFn->getName() != "swift_bufferAllocate" ||
+ !hasOneNonDebugUse(AllocBufferAI))
return false;
}
return true;
diff --git a/lib/SILOptimizer/Analysis/CFG.cpp b/lib/SILOptimizer/Analysis/CFG.cpp
index ef1b825..e0e84de 100644
--- a/lib/SILOptimizer/Analysis/CFG.cpp
+++ b/lib/SILOptimizer/Analysis/CFG.cpp
@@ -34,6 +34,11 @@
case TermKind::UnreachableInst:
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
+ return false;
+ // yield and try_apply are special because they can do arbitrary,
+ // potentially-process-terminating things.
+ case TermKind::YieldInst:
case TermKind::TryApplyInst:
return false;
}
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index 49b1c64..ddaacb2 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -416,7 +416,8 @@
// Create the thin function type for the cloned closure.
auto ClonedTy = SILFunctionType::get(
OrigFTI->getGenericSignature(), OrigFTI->getExtInfo(),
- OrigFTI->getCalleeConvention(), ClonedInterfaceArgTys,
+ OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(),
+ ClonedInterfaceArgTys, OrigFTI->getYields(),
OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone());
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index 5a0496e..ac5d62e 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -251,8 +251,9 @@
// expressed as literals. So its callee signature will be the same as its
// return signature.
auto NewFTy = getPartialApplyInterfaceResultType(PAI);
- NewFTy = Lowering::adjustFunctionType(NewFTy,
- SILFunctionType::Representation::Thin);
+ NewFTy = Lowering::adjustFunctionType(
+ NewFTy, SILFunctionType::Representation::Thin,
+ OrigF->getModule().getOptions().EnableGuaranteedClosureContexts);
GenericEnvironment *GenericEnv = nullptr;
if (NewFTy->getGenericSignature())
@@ -404,6 +405,9 @@
if (PAI->hasSubstitutions()) {
if (Specialized->isExternalDeclaration())
return nullptr;
+ if (!Orig->shouldOptimize())
+ return nullptr;
+
// Perform a generic specialization of the Specialized function.
ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
/* ConvertIndirectToDirect */ false);
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index 73c0ff0..c21f9c9 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -614,8 +614,9 @@
auto ClonedTy = SILFunctionType::get(
ClosureUserFunTy->getGenericSignature(), ExtInfo,
+ ClosureUserFunTy->getCoroutineKind(),
ClosureUserFunTy->getCalleeConvention(), NewParameterInfoList,
- ClosureUserFunTy->getResults(),
+ ClosureUserFunTy->getYields(), ClosureUserFunTy->getResults(),
ClosureUserFunTy->getOptionalErrorResult(), M.getASTContext());
// We make this function bare so we don't have to worry about decls in the
diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index 51445c8..b12697f 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -208,6 +208,10 @@
}
}
+ for (const auto &conf : WT->getConditionalConformances()) {
+ if (conf.Conformance.isConcrete())
+ ensureAliveConformance(conf.Conformance.getConcrete());
+ }
}
/// Marks the declarations referenced by a key path pattern as alive if they
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 7de21a7..4d3581c 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -260,7 +260,8 @@
SILFunctionType::ExtInfo EInfo;
EInfo = EInfo.withRepresentation(SILFunctionType::Representation::Thin);
auto LoweredType = SILFunctionType::get(nullptr, EInfo,
- ParameterConvention::Direct_Owned, { }, Results, None,
+ SILCoroutineKind::None, ParameterConvention::Direct_Owned,
+ /*params*/ {}, /*yields*/ {}, Results, None,
Store->getModule().getASTContext());
auto *GetterF = Store->getModule().getOrCreateFunction(
Store->getLoc(),
@@ -514,7 +515,8 @@
SILFunctionType::ExtInfo EInfo;
EInfo = EInfo.withRepresentation(SILFunctionType::Representation::Thin);
auto LoweredType = SILFunctionType::get(nullptr, EInfo,
- ParameterConvention::Direct_Owned, { }, Results, None,
+ SILCoroutineKind::None, ParameterConvention::Direct_Owned,
+ /*params*/ {}, /*yields*/ {}, Results, None,
InitF->getASTContext());
auto *GetterF = InitF->getModule().getOrCreateFunction(
InitF->getLocation(),
diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
index b7267e7..70fd6da 100644
--- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
+++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
@@ -2316,8 +2316,7 @@
auto *Fn = getFunction();
// Don't hoist array property calls at Osize.
- auto OptMode = Fn->getModule().getOptions().Optimization;
- if (OptMode == SILOptions::SILOptMode::OptimizeForSize)
+ if (Fn->optimizeForSize())
return;
DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
diff --git a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
index 10e581c..f92c682 100644
--- a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
@@ -442,33 +442,56 @@
}
void SelectEnforcement::updateCapture(AddressCapture capture) {
+ auto captureIfEscaped = [&](SILInstruction *user) {
+ if (hasPotentiallyEscapedAt(user))
+ dynamicCaptures.recordCapture(capture);
+ };
llvm::SmallSetVector<SingleValueInstruction *, 8> worklist;
auto visitUse = [&](Operand *oper) {
auto *user = oper->getUser();
if (FullApplySite::isa(user)) {
// A call is considered a closure access regardless of whether it calls
// the closure or accepts the closure as an argument.
- if (hasPotentiallyEscapedAt(user)) {
- dynamicCaptures.recordCapture(capture);
- }
+ captureIfEscaped(user);
return;
}
- if (auto *CFI = dyn_cast<ConvertFunctionInst>(user)) {
- worklist.insert(CFI);
+ switch (user->getKind()) {
+ case SILInstructionKind::ConvertFunctionInst:
+ case SILInstructionKind::BeginBorrowInst:
+ case SILInstructionKind::CopyValueInst:
+ case SILInstructionKind::EnumInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::PartialApplyInst:
+ // Propagate the closure.
+ worklist.insert(cast<SingleValueInstruction>(user));
return;
- }
- if (auto *PAI = dyn_cast<PartialApplyInst>(user)) {
- assert(oper->get() != PAI->getCallee() && "cannot re-partially apply");
- // The closure is capture by another closure. Transitively consider any
- // calls to the parent closure as an access.
- worklist.insert(PAI);
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DestroyValueInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::EndBorrowInst:
+ // Benign use.
return;
+ case SILInstructionKind::TupleExtractInst:
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::AssignInst:
+ case SILInstructionKind::BranchInst:
+ case SILInstructionKind::CondBranchInst:
+ case SILInstructionKind::ReturnInst:
+ case SILInstructionKind::StoreInst:
+ // These are all valid partial_apply users, however we don't expect them
+ // to occur with non-escaping closures. Handle them conservatively just in
+ // case they occur.
+ LLVM_FALLTHROUGH;
+ default:
+ DEBUG(llvm::dbgs() << " Unrecognized partial_apply user: " << *user);
+
+ // Handle unknown uses conservatively by assuming a capture.
+ captureIfEscaped(user);
}
- DEBUG(llvm::dbgs() << " Unrecognized partial_apply user: " << *user);
- // If this user has no results, then we can safely assume it doesn't pass
- // the closure to a call site. If it has results, then it might propagate
- // the closure, in which case it needs to be handled above.
- assert(user->getResults().empty());
};
SingleValueInstruction *PAIUser = dyn_cast<PartialApplyInst>(capture.site);
while (true) {
diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
index ff94b7e..7933b93 100644
--- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
+++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
@@ -890,11 +890,13 @@
continue;
unsigned OperandNumber = OEAUse->getOperandNumber();
- if (OperandNumber < 1 || OperandNumber > AI->getNumCallArguments())
+ auto OptArgumentNumber =
+ AI->getArgumentIndexForOperandIndex(OperandNumber);
+ if (!OptArgumentNumber)
// Not used as a call argument
continue;
- unsigned ArgumentNumber = OperandNumber - 1;
+ unsigned ArgumentNumber = *OptArgumentNumber;
CanSILFunctionType calleeType = AI->getSubstCalleeType();
SILParameterInfo parameterInfo = calleeType->getParameters()[ArgumentNumber];
diff --git a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
index dd776f8..e24b67b 100644
--- a/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
+++ b/lib/SILOptimizer/Mandatory/DiagnoseStaticExclusivity.cpp
@@ -988,7 +988,7 @@
// Check the closure's captures, which are a suffix of the closure's
// parameters.
unsigned StartIndex =
- Closure->getArguments().size() - PAI->getNumCallArguments();
+ Closure->getArguments().size() - PAI->getNumArguments();
checkForViolationWithCall(Accesses, Closure, StartIndex,
PAI->getArguments(), ASA, ConflictingAccesses);
}
diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
index 29aa4fe..1805c17 100644
--- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
+++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
@@ -12,11 +12,12 @@
#define DEBUG_TYPE "predictable-memopt"
-#include "swift/SILOptimizer/PassManager/Passes.h"
#include "DIMemoryUseCollector.h"
#include "swift/SIL/SILBuilder.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/PassManager/Passes.h"
#include "swift/SILOptimizer/PassManager/Transforms.h"
+#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/SILSSAUpdater.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Compiler.h"
@@ -29,7 +30,7 @@
STATISTIC(NumAllocRemoved, "Number of allocations completely removed");
//===----------------------------------------------------------------------===//
-// Subelement Analysis Implementation
+// Subelement Analysis
//===----------------------------------------------------------------------===//
// We can only analyze components of structs whose storage is fully accessible
@@ -89,17 +90,16 @@
/// This will return a subelement number of 2.
///
/// If this pointer is to within an existential projection, it returns ~0U.
-///
static unsigned computeSubelement(SILValue Pointer,
SingleValueInstruction *RootInst) {
- unsigned SubEltNumber = 0;
+ unsigned SubElementNumber = 0;
SILModule &M = RootInst->getModule();
while (1) {
// If we got to the root, we're done.
if (RootInst == Pointer)
- return SubEltNumber;
-
+ return SubElementNumber;
+
if (auto *PBI = dyn_cast<ProjectBoxInst>(Pointer)) {
Pointer = PBI->getOperand();
continue;
@@ -115,7 +115,7 @@
// Keep track of what subelement is being referenced.
for (unsigned i = 0, e = TEAI->getFieldNo(); i != e; ++i) {
- SubEltNumber += getNumSubElements(TT.getTupleElementType(i), M);
+ SubElementNumber += getNumSubElements(TT.getTupleElementType(i), M);
}
Pointer = TEAI->getOperand();
continue;
@@ -128,7 +128,7 @@
StructDecl *SD = SEAI->getStructDecl();
for (auto *D : SD->getStoredProperties()) {
if (D == SEAI->getField()) break;
- SubEltNumber += getNumSubElements(ST.getFieldType(D, M), M);
+ SubElementNumber += getNumSubElements(ST.getFieldType(D, M), M);
}
Pointer = SEAI->getOperand();
@@ -143,14 +143,152 @@
}
}
+//===----------------------------------------------------------------------===//
+// Available Value
+//===----------------------------------------------------------------------===//
+namespace {
-/// Given an aggregate value and an access path, extract the value indicated by
-/// the path.
-static SILValue extractSubElement(SILValue Val, unsigned SubElementNumber,
- SILBuilder &B, SILLocation Loc) {
- SILType ValTy = Val->getType();
-
+class AvailableValueAggregator;
+
+struct AvailableValue {
+ friend class AvailableValueAggregator;
+
+ /// If this gets too expensive in terms of copying, we can use an arena and a
+ /// FrozenPtrSet like we do in ARC.
+ using SetVector = llvm::SmallSetVector<SILInstruction *, 1>;
+
+ SILValue Value;
+ unsigned SubElementNumber;
+ SetVector InsertionPoints;
+
+ /// Just for updating.
+ SmallVectorImpl<DIMemoryUse> *Uses;
+
+public:
+ AvailableValue() = default;
+
+ /// Main initializer for available values.
+ ///
+ /// *NOTE* We assume that all available values start with a singular insertion
+ /// point and insertion points are added by merging.
+ AvailableValue(SILValue Value, unsigned SubElementNumber,
+ SILInstruction *InsertPoint)
+ : Value(Value), SubElementNumber(SubElementNumber), InsertionPoints() {
+ InsertionPoints.insert(InsertPoint);
+ }
+
+ /// Deleted copy constructor. This is a move only type.
+ AvailableValue(const AvailableValue &) = delete;
+
+ /// Deleted copy operator. This is a move only type.
+ AvailableValue &operator=(const AvailableValue &) = delete;
+
+ /// Move constructor.
+ AvailableValue(AvailableValue &&Other)
+ : Value(nullptr), SubElementNumber(~0), InsertionPoints() {
+ std::swap(Value, Other.Value);
+ std::swap(SubElementNumber, Other.SubElementNumber);
+ std::swap(InsertionPoints, Other.InsertionPoints);
+ }
+
+ /// Move operator.
+ AvailableValue &operator=(AvailableValue &&Other) {
+ std::swap(Value, Other.Value);
+ std::swap(SubElementNumber, Other.SubElementNumber);
+ std::swap(InsertionPoints, Other.InsertionPoints);
+ return *this;
+ }
+
+ operator bool() const { return bool(Value); }
+
+ bool operator==(const AvailableValue &Other) const {
+ return Value == Other.Value && SubElementNumber == Other.SubElementNumber;
+ }
+
+ bool operator!=(const AvailableValue &Other) const {
+ return !(*this == Other);
+ }
+
+ SILValue getValue() const { return Value; }
+ SILType getType() const { return Value->getType(); }
+ unsigned getSubElementNumber() const { return SubElementNumber; }
+ ArrayRef<SILInstruction *> getInsertionPoints() const {
+ return InsertionPoints.getArrayRef();
+ }
+
+ void mergeInsertionPoints(const AvailableValue &Other) & {
+ assert(Value == Other.Value && SubElementNumber == Other.SubElementNumber);
+ InsertionPoints.set_union(Other.InsertionPoints);
+ }
+
+ void addInsertionPoint(SILInstruction *I) & { InsertionPoints.insert(I); }
+
+ /// TODO: This needs a better name.
+ AvailableValue emitStructExtract(SILBuilder &B, SILLocation Loc, VarDecl *D,
+ unsigned SubElementNumber) const {
+ SILValue NewValue = B.emitStructExtract(Loc, Value, D);
+ return {NewValue, SubElementNumber, InsertionPoints};
+ }
+
+ /// TODO: This needs a better name.
+ AvailableValue emitTupleExtract(SILBuilder &B, SILLocation Loc,
+ unsigned EltNo,
+ unsigned SubElementNumber) const {
+ SILValue NewValue = B.emitTupleExtract(Loc, Value, EltNo);
+ return {NewValue, SubElementNumber, InsertionPoints};
+ }
+
+ void dump() const __attribute__((used));
+ void print(llvm::raw_ostream &os) const;
+
+private:
+ /// Private constructor.
+ AvailableValue(SILValue Value, unsigned SubElementNumber,
+ const SetVector &InsertPoints)
+ : Value(Value), SubElementNumber(SubElementNumber),
+ InsertionPoints(InsertPoints) {}
+};
+
+} // end anonymous namespace
+
+void AvailableValue::dump() const { print(llvm::dbgs()); }
+
+void AvailableValue::print(llvm::raw_ostream &os) const {
+ os << "Available Value Dump. Value: ";
+ if (getValue()) {
+ os << getValue();
+ } else {
+ os << "NoValue;\n";
+ }
+ os << "SubElementNumber: " << getSubElementNumber() << "\n";
+ os << "Insertion Points:\n";
+ for (auto *I : getInsertionPoints()) {
+ os << *I;
+ }
+}
+
+namespace llvm {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const AvailableValue &V) {
+ V.print(os);
+ return os;
+}
+
+} // end llvm namespace
+
+//===----------------------------------------------------------------------===//
+// Subelement Extraction
+//===----------------------------------------------------------------------===//
+
+/// Given an aggregate value and an access path, non-destructively extract the
+/// value indicated by the path.
+static SILValue nonDestructivelyExtractSubElement(const AvailableValue &Val,
+ SILBuilder &B,
+ SILLocation Loc) {
+ SILType ValTy = Val.getType();
+ unsigned SubElementNumber = Val.SubElementNumber;
+
// Extract tuple elements.
if (auto TT = ValTy.getAs<TupleType>()) {
for (unsigned EltNo : indices(TT.getElementTypes())) {
@@ -158,8 +296,8 @@
SILType EltTy = ValTy.getTupleElementType(EltNo);
unsigned NumSubElt = getNumSubElements(EltTy, B.getModule());
if (SubElementNumber < NumSubElt) {
- Val = B.emitTupleExtract(Loc, Val, EltNo, EltTy);
- return extractSubElement(Val, SubElementNumber, B, Loc);
+ auto NewVal = Val.emitTupleExtract(B, Loc, EltNo, SubElementNumber);
+ return nonDestructivelyExtractSubElement(NewVal, B, Loc);
}
SubElementNumber -= NumSubElt;
@@ -175,8 +313,8 @@
unsigned NumSubElt = getNumSubElements(fieldType, B.getModule());
if (SubElementNumber < NumSubElt) {
- Val = B.emitStructExtract(Loc, Val, D);
- return extractSubElement(Val, SubElementNumber, B, Loc);
+ auto NewVal = Val.emitStructExtract(B, Loc, D, SubElementNumber);
+ return nonDestructivelyExtractSubElement(NewVal, B, Loc);
}
SubElementNumber -= NumSubElt;
@@ -187,109 +325,314 @@
// Otherwise, we're down to a scalar.
assert(SubElementNumber == 0 && "Miscalculation indexing subelements");
- return Val;
+ return Val.getValue();
}
//===----------------------------------------------------------------------===//
-// Allocation Optimization
+// Available Value Aggregation
+//===----------------------------------------------------------------------===//
+
+static bool anyMissing(unsigned StartSubElt, unsigned NumSubElts,
+ ArrayRef<AvailableValue> &Values) {
+ while (NumSubElts) {
+ if (!Values[StartSubElt])
+ return true;
+ ++StartSubElt;
+ --NumSubElts;
+ }
+ return false;
+}
+
+namespace {
+
+/// A class that aggregates available values, loading them if they are not
+/// available.
+class AvailableValueAggregator {
+ SILModule &M;
+ SILBuilderWithScope B;
+ SILLocation Loc;
+ MutableArrayRef<AvailableValue> AvailableValueList;
+ SmallVectorImpl<DIMemoryUse> &Uses;
+
+public:
+ AvailableValueAggregator(SILInstruction *Inst,
+ MutableArrayRef<AvailableValue> AvailableValueList,
+ SmallVectorImpl<DIMemoryUse> &Uses)
+ : M(Inst->getModule()), B(Inst), Loc(Inst->getLoc()),
+ AvailableValueList(AvailableValueList), Uses(Uses) {}
+
+ // This is intended to be passed by reference only once constructed.
+ AvailableValueAggregator(const AvailableValueAggregator &) = delete;
+ AvailableValueAggregator(AvailableValueAggregator &&) = delete;
+ AvailableValueAggregator &
+ operator=(const AvailableValueAggregator &) = delete;
+ AvailableValueAggregator &operator=(AvailableValueAggregator &&) = delete;
+
+ SILValue aggregateValues(SILType LoadTy, SILValue Address, unsigned FirstElt);
+
+ void print(llvm::raw_ostream &os) const;
+ void dump() const __attribute__((used));
+
+private:
+ SILValue aggregateFullyAvailableValue(SILType LoadTy, unsigned FirstElt);
+ SILValue aggregateTupleSubElts(TupleType *TT, SILType LoadTy,
+ SILValue Address, unsigned FirstElt);
+ SILValue aggregateStructSubElts(StructDecl *SD, SILType LoadTy,
+ SILValue Address, unsigned FirstElt);
+ SILValue handlePrimitiveValue(SILType LoadTy, SILValue Address,
+ unsigned FirstElt);
+};
+
+} // end anonymous namespace
+
+void AvailableValueAggregator::dump() const { print(llvm::dbgs()); }
+
+void AvailableValueAggregator::print(llvm::raw_ostream &os) const {
+ os << "Available Value List, N = " << AvailableValueList.size()
+ << ". Elts:\n";
+ for (auto &V : AvailableValueList) {
+ os << V;
+ }
+}
+
+/// Given a bunch of primitive subelement values, build out the right aggregate
+/// type (LoadTy) by emitting tuple and struct instructions as necessary.
+SILValue AvailableValueAggregator::aggregateValues(SILType LoadTy,
+ SILValue Address,
+ unsigned FirstElt) {
+ // Check to see if the requested value is fully available, as an aggregate.
+ // This is a super-common case for single-element structs, but is also a
+ // general answer for arbitrary structs and tuples as well.
+ if (SILValue Result = aggregateFullyAvailableValue(LoadTy, FirstElt))
+ return Result;
+
+ // If we have a tuple type, then aggregate the tuple's elements into a full
+ // tuple value.
+ if (TupleType *TT = LoadTy.getAs<TupleType>())
+ return aggregateTupleSubElts(TT, LoadTy, Address, FirstElt);
+
+ // If we have a struct type, then aggregate the struct's elements into a full
+ // struct value.
+ if (auto *SD = getFullyReferenceableStruct(LoadTy))
+ return aggregateStructSubElts(SD, LoadTy, Address, FirstElt);
+
+ // Otherwise, we have a non-aggregate primitive. Load or extract the value.
+ return handlePrimitiveValue(LoadTy, Address, FirstElt);
+}
+
+// See if we have this value is fully available. In such a case, return it as an
+// aggregate. This is a super-common case for single-element structs, but is
+// also a general answer for arbitrary structs and tuples as well.
+SILValue
+AvailableValueAggregator::aggregateFullyAvailableValue(SILType LoadTy,
+ unsigned FirstElt) {
+ if (FirstElt >= AvailableValueList.size()) { // #Elements may be zero.
+ return SILValue();
+ }
+
+ auto &FirstVal = AvailableValueList[FirstElt];
+
+ // Make sure that the first element is available and is the correct type.
+ if (!FirstVal || FirstVal.getType() != LoadTy)
+ return SILValue();
+
+ // If the first element of this value is available, check that any extra
+ // available values are from the same place as our first value.
+ if (llvm::any_of(range(getNumSubElements(LoadTy, M)),
+ [&](unsigned Index) -> bool {
+ auto &Val = AvailableValueList[FirstElt + Index];
+ return Val.getValue() != FirstVal.getValue() ||
+ Val.getSubElementNumber() != Index;
+ }))
+ return SILValue();
+
+ return FirstVal.getValue();
+}
+
+SILValue AvailableValueAggregator::aggregateTupleSubElts(TupleType *TT,
+ SILType LoadTy,
+ SILValue Address,
+ unsigned FirstElt) {
+ SmallVector<SILValue, 4> ResultElts;
+
+ for (unsigned EltNo : indices(TT->getElements())) {
+ SILType EltTy = LoadTy.getTupleElementType(EltNo);
+ unsigned NumSubElt = getNumSubElements(EltTy, M);
+
+ // If we are missing any of the available values in this struct element,
+ // compute an address to load from.
+ SILValue EltAddr;
+ if (anyMissing(FirstElt, NumSubElt, AvailableValueList))
+ EltAddr =
+ B.createTupleElementAddr(Loc, Address, EltNo, EltTy.getAddressType());
+
+ ResultElts.push_back(aggregateValues(EltTy, EltAddr, FirstElt));
+ FirstElt += NumSubElt;
+ }
+
+ return B.createTuple(Loc, LoadTy, ResultElts);
+}
+
+SILValue AvailableValueAggregator::aggregateStructSubElts(StructDecl *SD,
+ SILType LoadTy,
+ SILValue Address,
+ unsigned FirstElt) {
+ SmallVector<SILValue, 4> ResultElts;
+
+ for (auto *FD : SD->getStoredProperties()) {
+ SILType EltTy = LoadTy.getFieldType(FD, M);
+ unsigned NumSubElt = getNumSubElements(EltTy, M);
+
+ // If we are missing any of the available values in this struct element,
+ // compute an address to load from.
+ SILValue EltAddr;
+ if (anyMissing(FirstElt, NumSubElt, AvailableValueList))
+ EltAddr =
+ B.createStructElementAddr(Loc, Address, FD, EltTy.getAddressType());
+
+ ResultElts.push_back(aggregateValues(EltTy, EltAddr, FirstElt));
+ FirstElt += NumSubElt;
+ }
+ return B.createStruct(Loc, LoadTy, ResultElts);
+}
+
+// We have looked through all of the aggregate values and finally found a
+// "primitive value". If the value is available, use it (extracting if we need
+// to), otherwise emit a load of the value with the appropriate qualifier.
+SILValue AvailableValueAggregator::handlePrimitiveValue(SILType LoadTy,
+ SILValue Address,
+ unsigned FirstElt) {
+ auto &Val = AvailableValueList[FirstElt];
+
+ // If the value is not available, load the value and update our use list.
+ if (!Val) {
+ auto *Load =
+ B.createLoad(Loc, Address, LoadOwnershipQualifier::Unqualified);
+ Uses.push_back(DIMemoryUse(Load, DIUseKind::Load, FirstElt,
+ getNumSubElements(Load->getType(), M)));
+ return Load;
+ }
+
+ // If we have 1 insertion point, just extract the value and return.
+ //
+ // This saves us from having to spend compile time in the SSA updater in this
+ // case.
+ ArrayRef<SILInstruction *> InsertPts = Val.getInsertionPoints();
+ if (InsertPts.size() == 1) {
+ SavedInsertionPointRAII SavedInsertPt(B, InsertPts[0]);
+ SILValue EltVal = nonDestructivelyExtractSubElement(Val, B, Loc);
+ assert(EltVal->getType() == LoadTy && "Subelement types mismatch");
+ return EltVal;
+ }
+
+ // If we have an available value, then we want to extract the subelement from
+ // the borrowed aggregate before each insertion point.
+ SILSSAUpdater Updater;
+ Updater.Initialize(LoadTy);
+ for (auto *I : Val.getInsertionPoints()) {
+ SavedInsertionPointRAII SavedInsertPt(B, I);
+ SILValue EltVal = nonDestructivelyExtractSubElement(Val, B, Loc);
+ Updater.AddAvailableValue(I->getParent(), EltVal);
+ }
+
+ // Finally, grab the value from the SSA updater.
+ SILValue EltVal = Updater.GetValueInMiddleOfBlock(B.getInsertionBB());
+ assert(EltVal->getType() == LoadTy && "Subelement types mismatch");
+ return EltVal;
+}
+
+//===----------------------------------------------------------------------===//
+// Available Value Dataflow
//===----------------------------------------------------------------------===//
namespace {
-/// This performs load promotion and deletes synthesized allocations if all
-/// loads can be removed.
-class AllocOptimize {
-
- SILModule &Module;
-
- /// This is either an alloc_box or alloc_stack instruction.
+/// Given a piece of memory, the memory's uses, and destroys perform a single
+/// round of optimistic dataflow switching to intersection when a back edge is
+/// encountered.
+class AvailableValueDataflowContext {
+ /// The base memory we are performing dataflow upon.
AllocationInst *TheMemory;
- /// This is the SILType of the memory object.
- SILType MemoryType;
-
- /// The number of primitive subelements across all elements of this memory
- /// value.
+ /// The number of sub elements of our memory.
unsigned NumMemorySubElements;
- SmallVectorImpl<DIMemoryUse> &Uses;
- SmallVectorImpl<SILInstruction *> &Releases;
+ /// The set of uses that we are tracking. This is only here so we can update
+ /// when exploding copy_addr. It would be great if we did not have to store
+ /// this.
+ llvm::SmallVectorImpl<DIMemoryUse> &Uses;
+ /// The set of blocks with local definitions.
+ ///
+ /// We use this to determine if we should visit a block or look at a block's
+ /// predecessors during dataflow.
llvm::SmallPtrSet<SILBasicBlock *, 32> HasLocalDefinition;
/// This is a map of uses that are not loads (i.e., they are Stores,
/// InOutUses, and Escapes), to their entry in Uses.
llvm::SmallDenseMap<SILInstruction *, unsigned, 16> NonLoadUses;
- /// Does this value escape anywhere in the function.
+ /// Does this value escape anywhere in the function. We use this very
+ /// conservatively.
bool HasAnyEscape = false;
public:
- AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<DIMemoryUse> &Uses,
- SmallVectorImpl<SILInstruction *> &Releases);
+ AvailableValueDataflowContext(AllocationInst *TheMemory,
+ unsigned NumMemorySubElements,
+ llvm::SmallVectorImpl<DIMemoryUse> &Uses);
- bool doIt();
+ /// Try to compute available values for "TheMemory" at the instruction \p
+ /// StartingFrom. We only compute the values for set bits in \p
+ /// RequiredElts. We return the vailable values in \p Result. If any available
+ /// values were found, return true. Otherwise, return false.
+ bool computeAvailableValues(SILInstruction *StartingFrom,
+ unsigned FirstEltOffset,
+ unsigned NumLoadSubElements,
+ llvm::SmallBitVector &RequiredElts,
+ SmallVectorImpl<AvailableValue> &Result);
+
+ /// Return true if the box has escaped at the specified instruction. We are
+ /// not
+ /// allowed to do load promotion in an escape region.
+ bool hasEscapedAt(SILInstruction *I);
+
+ /// Explode a copy_addr, updating the Uses at the same time.
+ void explodeCopyAddr(CopyAddrInst *CAI);
private:
- bool promoteLoad(SILInstruction *Inst);
- bool promoteDestroyAddr(DestroyAddrInst *DAI);
+ SILModule &getModule() const { return TheMemory->getModule(); }
- // Load promotion.
- bool hasEscapedAt(SILInstruction *I);
- void
- updateAvailableValues(SILInstruction *Inst,
- llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
- llvm::SmallBitVector &ConflictingValues);
- void computeAvailableValues(
- SILInstruction *StartingFrom, llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<std::pair<SILValue, unsigned>> &Result);
+ void updateAvailableValues(SILInstruction *Inst,
+ llvm::SmallBitVector &RequiredElts,
+ SmallVectorImpl<AvailableValue> &Result,
+ llvm::SmallBitVector &ConflictingValues);
void computeAvailableValuesFrom(
SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
+ SmallVectorImpl<AvailableValue> &Result,
llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
&VisitedBlocks,
llvm::SmallBitVector &ConflictingValues);
-
- void explodeCopyAddr(CopyAddrInst *CAI);
-
- bool tryToRemoveDeadAllocation();
};
} // end anonymous namespace
-
-AllocOptimize::AllocOptimize(AllocationInst *TheMemory,
- SmallVectorImpl<DIMemoryUse> &Uses,
- SmallVectorImpl<SILInstruction*> &Releases)
-: Module(TheMemory->getModule()), TheMemory(TheMemory), Uses(Uses),
- Releases(Releases) {
-
- // Compute the type of the memory object.
- if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
- assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
- && "optimizing multi-field boxes not implemented");
- MemoryType = ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
- } else {
- assert(isa<AllocStackInst>(TheMemory));
- MemoryType = cast<AllocStackInst>(TheMemory)->getElementType();
- }
-
- NumMemorySubElements = getNumSubElements(MemoryType, Module);
-
+AvailableValueDataflowContext::AvailableValueDataflowContext(
+ AllocationInst *InputTheMemory, unsigned NumMemorySubElements,
+ SmallVectorImpl<DIMemoryUse> &InputUses)
+ : TheMemory(InputTheMemory), NumMemorySubElements(NumMemorySubElements),
+ Uses(InputUses) {
// The first step of processing an element is to collect information about the
// element into data structures we use later.
- for (unsigned ui = 0, e = Uses.size(); ui != e; ++ui) {
+ for (unsigned ui : indices(Uses)) {
auto &Use = Uses[ui];
assert(Use.Inst && "No instruction identified?");
-
+
// Keep track of all the uses that aren't loads.
if (Use.Kind == DIUseKind::Load)
continue;
-
+
NonLoadUses[Use.Inst] = ui;
-
HasLocalDefinition.insert(Use.Inst->getParent());
if (Use.Kind == DIUseKind::Escape) {
@@ -305,34 +648,18 @@
HasLocalDefinition.insert(TheMemory->getParent());
}
-
-/// hasEscapedAt - Return true if the box has escaped at the specified
-/// instruction. We are not allowed to do load promotion in an escape region.
-bool AllocOptimize::hasEscapedAt(SILInstruction *I) {
- // FIXME: This is not an aggressive implementation. :)
-
- // TODO: At some point, we should special case closures that just *read* from
- // the escaped value (by looking at the body of the closure). They should not
- // prevent load promotion, and will allow promoting values like X in regions
- // dominated by "... && X != 0".
- return HasAnyEscape;
-}
-
-
-/// The specified instruction is a non-load access of the element being
-/// promoted. See if it provides a value or refines the demanded element mask
-/// used for load promotion.
-void AllocOptimize::
-updateAvailableValues(SILInstruction *Inst, llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
- llvm::SmallBitVector &ConflictingValues) {
- // Handle store and assign.
- if (isa<StoreInst>(Inst)) {
- unsigned StartSubElt = computeSubelement(Inst->getOperand(1), TheMemory);
+void AvailableValueDataflowContext::updateAvailableValues(
+ SILInstruction *Inst, llvm::SmallBitVector &RequiredElts,
+ SmallVectorImpl<AvailableValue> &Result,
+ llvm::SmallBitVector &ConflictingValues) {
+ // Handle store.
+ if (auto *SI = dyn_cast<StoreInst>(Inst)) {
+ unsigned StartSubElt = computeSubelement(SI->getDest(), TheMemory);
assert(StartSubElt != ~0U && "Store within enum projection not handled");
- SILType ValTy = Inst->getOperand(0)->getType();
-
- for (unsigned i = 0, e = getNumSubElements(ValTy, Module); i != e; ++i) {
+ SILType ValTy = SI->getSrc()->getType();
+
+ for (unsigned i = 0, e = getNumSubElements(ValTy, getModule()); i != e;
+ ++i) {
// If this element is not required, don't fill it in.
if (!RequiredElts[StartSubElt+i]) continue;
@@ -340,11 +667,19 @@
// there already is a result, check it for conflict. If there is no
// conflict, then we're ok.
auto &Entry = Result[StartSubElt+i];
- if (Entry.first == SILValue())
- Entry = { Inst->getOperand(0), i };
- else if (Entry.first != Inst->getOperand(0) || Entry.second != i)
- ConflictingValues[StartSubElt+i] = true;
-
+ if (!Entry) {
+ Entry = {SI->getSrc(), i, Inst};
+ } else {
+ // TODO: This is /really/, /really/, conservative. This basically means
+ // that if we do not have an identical store, we will not promote.
+ if (Entry.getValue() != SI->getSrc() ||
+ Entry.getSubElementNumber() != i) {
+ ConflictingValues[StartSubElt + i] = true;
+ } else {
+ Entry.addInsertionPoint(Inst);
+ }
+ }
+
// This element is now provided.
RequiredElts[StartSubElt+i] = false;
}
@@ -356,12 +691,13 @@
// to see if any loaded subelements are being used, and if so, explode the
// copy_addr to its individual pieces.
if (auto *CAI = dyn_cast<CopyAddrInst>(Inst)) {
- unsigned StartSubElt = computeSubelement(Inst->getOperand(1), TheMemory);
+ unsigned StartSubElt = computeSubelement(CAI->getDest(), TheMemory);
assert(StartSubElt != ~0U && "Store within enum projection not handled");
- SILType ValTy = Inst->getOperand(1)->getType();
-
+ SILType ValTy = CAI->getDest()->getType();
+
bool AnyRequired = false;
- for (unsigned i = 0, e = getNumSubElements(ValTy, Module); i != e; ++i) {
+ for (unsigned i = 0, e = getNumSubElements(ValTy, getModule()); i != e;
+ ++i) {
// If this element is not required, don't fill it in.
AnyRequired = RequiredElts[StartSubElt+i];
if (AnyRequired) break;
@@ -374,7 +710,7 @@
// If the copyaddr is of a non-loadable type, we can't promote it. Just
// consider it to be a clobber.
- if (CAI->getOperand(0)->getType().isLoadable(Module)) {
+ if (CAI->getSrc()->getType().isLoadable(getModule())) {
// Otherwise, some part of the copy_addr's value is demanded by a load, so
// we need to explode it to its component pieces. This only expands one
// level of the copyaddr.
@@ -385,11 +721,9 @@
return;
}
}
-
-
-
+
// TODO: inout apply's should only clobber pieces passed in.
-
+
// Otherwise, this is some unknown instruction, conservatively assume that all
// values are clobbered.
RequiredElts.clear();
@@ -397,42 +731,59 @@
return;
}
-
-/// Try to find available values of a set of subelements of the current value,
-/// starting right before the specified instruction.
-///
-/// The bitvector indicates which subelements we're interested in, and result
-/// captures the available value (plus an indicator of which subelement of that
-/// value is needed).
-///
-void AllocOptimize::
-computeAvailableValues(SILInstruction *StartingFrom,
- llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<std::pair<SILValue, unsigned>> &Result) {
+bool AvailableValueDataflowContext::computeAvailableValues(
+ SILInstruction *StartingFrom, unsigned FirstEltOffset,
+ unsigned NumLoadSubElements, llvm::SmallBitVector &RequiredElts,
+ SmallVectorImpl<AvailableValue> &Result) {
llvm::SmallDenseMap<SILBasicBlock*, llvm::SmallBitVector, 32> VisitedBlocks;
llvm::SmallBitVector ConflictingValues(Result.size());
computeAvailableValuesFrom(StartingFrom->getIterator(),
StartingFrom->getParent(), RequiredElts, Result,
VisitedBlocks, ConflictingValues);
+ // If there are no values available at this load point, then we fail to
+ // promote this load and there is nothing to do.
+ llvm::SmallBitVector AvailableValueIsPresent(NumMemorySubElements);
- // If we have any conflicting values, explicitly mask them out of the result,
- // so we don't pick one arbitrary available value.
- if (!ConflictingValues.none())
- for (unsigned i = 0, e = Result.size(); i != e; ++i)
- if (ConflictingValues[i])
- Result[i] = { SILValue(), 0U };
-
- return;
+ for (unsigned i :
+ range(FirstEltOffset, FirstEltOffset + NumLoadSubElements)) {
+ AvailableValueIsPresent[i] = Result[i].getValue();
+ }
+
+ // If we do not have any values available, bail.
+ if (AvailableValueIsPresent.none())
+ return false;
+
+ // Otherwise, if we have any conflicting values, explicitly mask them out of
+ // the result, so we don't pick one arbitrary available value.
+ if (ConflictingValues.none()) {
+ return true;
+ }
+
+ // At this point, we know that we have /some/ conflicting values and some
+ // available values.
+ if (AvailableValueIsPresent.reset(ConflictingValues).none())
+ return false;
+
+ // Otherwise, mask out the available values and return true. We have at least
+ // 1 available value.
+ int NextIter = ConflictingValues.find_first();
+ while (NextIter != -1) {
+ assert(NextIter >= 0 && "Int can not be represented?!");
+ unsigned Iter = NextIter;
+ Result[Iter] = {};
+ NextIter = ConflictingValues.find_next(Iter);
+ }
+
+ return true;
}
-void AllocOptimize::
-computeAvailableValuesFrom(SILBasicBlock::iterator StartingFrom,
- SILBasicBlock *BB,
- llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<std::pair<SILValue, unsigned>> &Result,
- llvm::SmallDenseMap<SILBasicBlock*, llvm::SmallBitVector, 32> &VisitedBlocks,
- llvm::SmallBitVector &ConflictingValues) {
+void AvailableValueDataflowContext::computeAvailableValuesFrom(
+ SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
+ llvm::SmallBitVector &RequiredElts, SmallVectorImpl<AvailableValue> &Result,
+ llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
+ &VisitedBlocks,
+ llvm::SmallBitVector &ConflictingValues) {
assert(!RequiredElts.none() && "Scanning with a goal of finding nothing?");
// If there is a potential modification in the current block, scan the block
@@ -501,111 +852,202 @@
}
}
+/// Explode a copy_addr instruction of a loadable type into lower level
+/// operations like loads, stores, retains, releases, retain_value, etc.
+void AvailableValueDataflowContext::explodeCopyAddr(CopyAddrInst *CAI) {
+ DEBUG(llvm::dbgs() << " -- Exploding copy_addr: " << *CAI << "\n");
-static bool anyMissing(unsigned StartSubElt, unsigned NumSubElts,
- ArrayRef<std::pair<SILValue, unsigned>> &Values) {
- while (NumSubElts) {
- if (!Values[StartSubElt].first) return true;
- ++StartSubElt;
- --NumSubElts;
+ SILType ValTy = CAI->getDest()->getType().getObjectType();
+ auto &TL = getModule().getTypeLowering(ValTy);
+
+ // Keep track of the new instructions emitted.
+ SmallVector<SILInstruction *, 4> NewInsts;
+ SILBuilder B(CAI, &NewInsts);
+ B.setCurrentDebugScope(CAI->getDebugScope());
+
+ // Use type lowering to lower the copyaddr into a load sequence + store
+ // sequence appropriate for the type.
+ SILValue StoredValue =
+ TL.emitLoadOfCopy(B, CAI->getLoc(), CAI->getSrc(), CAI->isTakeOfSrc());
+
+ TL.emitStoreOfCopy(B, CAI->getLoc(), StoredValue, CAI->getDest(),
+ CAI->isInitializationOfDest());
+
+ // Update our internal state for this being gone.
+ NonLoadUses.erase(CAI);
+
+ // Remove the copy_addr from Uses. A single copy_addr can appear multiple
+ // times if the source and dest are to elements within a single aggregate, but
+ // we only want to pick up the CopyAddrKind from the store.
+ DIMemoryUse LoadUse, StoreUse;
+ for (auto &Use : Uses) {
+ if (Use.Inst != CAI)
+ continue;
+
+ if (Use.Kind == DIUseKind::Load) {
+ assert(LoadUse.isInvalid());
+ LoadUse = Use;
+ } else {
+ assert(StoreUse.isInvalid());
+ StoreUse = Use;
+ }
+
+ Use.Inst = nullptr;
+
+ // Keep scanning in case the copy_addr appears multiple times.
}
- return false;
+
+ assert((LoadUse.isValid() || StoreUse.isValid()) &&
+ "we should have a load or a store, possibly both");
+ assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
+ StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
+
+ // Now that we've emitted a bunch of instructions, including a load and store
+ // but also including other stuff, update the internal state of
+ // LifetimeChecker to reflect them.
+
+ // Update the instructions that touch the memory. NewInst can grow as this
+ // iterates, so we can't use a foreach loop.
+ for (auto *NewInst : NewInsts) {
+ switch (NewInst->getKind()) {
+ default:
+ NewInst->dump();
+ llvm_unreachable("Unknown instruction generated by copy_addr lowering");
+
+ case SILInstructionKind::StoreInst:
+ // If it is a store to the memory object (as oppose to a store to
+ // something else), track it as an access.
+ if (StoreUse.isValid()) {
+ StoreUse.Inst = NewInst;
+ NonLoadUses[NewInst] = Uses.size();
+ Uses.push_back(StoreUse);
+ }
+ continue;
+
+ case SILInstructionKind::LoadInst:
+ // If it is a load from the memory object (as oppose to a load from
+ // something else), track it as an access. We need to explicitly check to
+ // see if the load accesses "TheMemory" because it could either be a load
+ // for the copy_addr source, or it could be a load corresponding to the
+ // "assign" operation on the destination of the copyaddr.
+ if (LoadUse.isValid() &&
+ getAccessPathRoot(NewInst->getOperand(0)) == TheMemory) {
+ LoadUse.Inst = NewInst;
+ Uses.push_back(LoadUse);
+ }
+ continue;
+
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::ReleaseValueInst: // Destroy overwritten value
+ // These are ignored.
+ continue;
+ }
+ }
+
+ // Next, remove the copy_addr itself.
+ CAI->eraseFromParent();
}
+bool AvailableValueDataflowContext::hasEscapedAt(SILInstruction *I) {
+ // Return true if the box has escaped at the specified instruction. We are
+ // not allowed to do load promotion in an escape region.
-/// AggregateAvailableValues - Given a bunch of primitive subelement values,
-/// build out the right aggregate type (LoadTy) by emitting tuple and struct
-/// instructions as necessary.
-static SILValue aggregateAvailableValues(
- SILInstruction *Inst, SILType LoadTy, SILValue Address,
- ArrayRef<std::pair<SILValue, unsigned>> AvailableValues,
- unsigned FirstElt) {
- assert(LoadTy.isObject());
- SILModule &M = Inst->getModule();
-
- // Check to see if the requested value is fully available, as an aggregate.
- // This is a super-common case for single-element structs, but is also a
- // general answer for arbitrary structs and tuples as well.
- if (FirstElt < AvailableValues.size()) { // #Elements may be zero.
- SILValue FirstVal = AvailableValues[FirstElt].first;
- if (FirstVal && AvailableValues[FirstElt].second == 0 &&
- FirstVal->getType() == LoadTy) {
- // If the first element of this value is available, check any extra ones
- // before declaring success.
- bool AllMatch = true;
- for (unsigned i = 0, e = getNumSubElements(LoadTy, M); i != e; ++i)
- if (AvailableValues[FirstElt+i].first != FirstVal ||
- AvailableValues[FirstElt+i].second != i) {
- AllMatch = false;
- break;
- }
-
- if (AllMatch)
- return FirstVal;
- }
- }
-
-
- SILBuilderWithScope B(Inst);
-
- if (TupleType *TT = LoadTy.getAs<TupleType>()) {
- SmallVector<SILValue, 4> ResultElts;
-
- for (unsigned EltNo : indices(TT->getElements())) {
- SILType EltTy = LoadTy.getTupleElementType(EltNo);
- unsigned NumSubElt = getNumSubElements(EltTy, M);
-
- // If we are missing any of the available values in this struct element,
- // compute an address to load from.
- SILValue EltAddr;
- if (anyMissing(FirstElt, NumSubElt, AvailableValues))
- EltAddr = B.createTupleElementAddr(Inst->getLoc(), Address, EltNo,
- EltTy.getAddressType());
+ // FIXME: This is not an aggressive implementation. :)
- ResultElts.push_back(aggregateAvailableValues(Inst, EltTy, EltAddr,
- AvailableValues, FirstElt));
- FirstElt += NumSubElt;
- }
-
- return B.createTuple(Inst->getLoc(), LoadTy, ResultElts);
- }
-
- // Extract struct elements from fully referenceable structs.
- if (auto *SD = getFullyReferenceableStruct(LoadTy)) {
- SmallVector<SILValue, 4> ResultElts;
-
- for (auto *FD : SD->getStoredProperties()) {
- SILType EltTy = LoadTy.getFieldType(FD, M);
- unsigned NumSubElt = getNumSubElements(EltTy, M);
-
- // If we are missing any of the available values in this struct element,
- // compute an address to load from.
- SILValue EltAddr;
- if (anyMissing(FirstElt, NumSubElt, AvailableValues))
- EltAddr = B.createStructElementAddr(Inst->getLoc(), Address, FD,
- EltTy.getAddressType());
-
- ResultElts.push_back(aggregateAvailableValues(Inst, EltTy, EltAddr,
- AvailableValues, FirstElt));
- FirstElt += NumSubElt;
- }
- return B.createStruct(Inst->getLoc(), LoadTy, ResultElts);
- }
-
- // Otherwise, we have a simple primitive. If the value is available, use it,
- // otherwise emit a load of the value.
- auto Val = AvailableValues[FirstElt];
- if (!Val.first)
- return B.createLoad(Inst->getLoc(), Address,
- LoadOwnershipQualifier::Unqualified);
-
- SILValue EltVal = extractSubElement(Val.first, Val.second, B, Inst->getLoc());
- // It must be the same type as LoadTy if available.
- assert(EltVal->getType() == LoadTy &&
- "Subelement types mismatch");
- return EltVal;
+ // TODO: At some point, we should special case closures that just *read* from
+ // the escaped value (by looking at the body of the closure). They should not
+ // prevent load promotion, and will allow promoting values like X in regions
+ // dominated by "... && X != 0".
+ return HasAnyEscape;
}
+//===----------------------------------------------------------------------===//
+// Allocation Optimization
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+/// This performs load promotion and deletes synthesized allocations if all
+/// loads can be removed.
+class AllocOptimize {
+
+ SILModule &Module;
+
+ /// This is either an alloc_box or alloc_stack instruction.
+ AllocationInst *TheMemory;
+
+ /// This is the SILType of the memory object.
+ SILType MemoryType;
+
+ /// The number of primitive subelements across all elements of this memory
+ /// value.
+ unsigned NumMemorySubElements;
+
+ SmallVectorImpl<DIMemoryUse> &Uses;
+ SmallVectorImpl<SILInstruction *> &Releases;
+
+ /// A structure that we use to compute our available values.
+ AvailableValueDataflowContext DataflowContext;
+
+public:
+ AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<DIMemoryUse> &Uses,
+ SmallVectorImpl<SILInstruction *> &Releases);
+
+ bool doIt();
+
+private:
+ bool promoteLoad(SILInstruction *Inst);
+ void promoteDestroyAddr(DestroyAddrInst *DAI,
+ MutableArrayRef<AvailableValue> Values);
+ bool
+ canPromoteDestroyAddr(DestroyAddrInst *DAI,
+ llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
+
+ bool tryToRemoveDeadAllocation();
+};
+
+} // end anonymous namespace
+
+static SILType getMemoryType(AllocationInst *TheMemory) {
+ // Compute the type of the memory object.
+ if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
+ assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 &&
+ "optimizing multi-field boxes not implemented");
+ return ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
+ } else {
+ assert(isa<AllocStackInst>(TheMemory));
+ return cast<AllocStackInst>(TheMemory)->getElementType();
+ }
+}
+
+AllocOptimize::AllocOptimize(AllocationInst *InputMemory,
+ SmallVectorImpl<DIMemoryUse> &InputUses,
+ SmallVectorImpl<SILInstruction *> &InputReleases)
+ : Module(InputMemory->getModule()), TheMemory(InputMemory),
+ MemoryType(getMemoryType(TheMemory)),
+ NumMemorySubElements(getNumSubElements(MemoryType, Module)),
+ Uses(InputUses), Releases(InputReleases),
+ DataflowContext(TheMemory, NumMemorySubElements, Uses) {}
+
+/// If we are able to optimize \p Inst, return the source address that
+/// instruction is loading from. If we can not optimize \p Inst, then just
+/// return an empty SILValue.
+static SILValue tryFindSrcAddrForLoad(SILInstruction *Inst) {
+ // We only handle load [copy], load [trivial] and copy_addr right now.
+ if (auto *LI = dyn_cast<LoadInst>(Inst))
+ return LI->getOperand();
+
+ // If this is a CopyAddr, verify that the element type is loadable. If not,
+ // we can't explode to a load.
+ auto *CAI = dyn_cast<CopyAddrInst>(Inst);
+ if (!CAI || !CAI->getSrc()->getType().isLoadable(CAI->getModule()))
+ return SILValue();
+ return CAI->getSrc();
+}
/// At this point, we know that this element satisfies the definitive init
/// requirements, so we can try to promote loads to enable SSA-based dataflow
@@ -613,40 +1055,31 @@
/// cross element accesses have been scalarized.
///
/// This returns true if the load has been removed from the program.
-///
bool AllocOptimize::promoteLoad(SILInstruction *Inst) {
// Note that we intentionally don't support forwarding of weak pointers,
// because the underlying value may drop be deallocated at any time. We would
// have to prove that something in this function is holding the weak value
// live across the promoted region and that isn't desired for a stable
// diagnostics pass this like one.
-
- // We only handle load and copy_addr right now.
- SILValue src;
- if (auto CAI = dyn_cast<CopyAddrInst>(Inst)) {
- // If this is a CopyAddr, verify that the element type is loadable. If not,
- // we can't explode to a load.
- src = CAI->getSrc();
- if (!src->getType().isLoadable(Module))
- return false;
- } else if (auto load = dyn_cast<LoadInst>(Inst)) {
- src = load->getOperand();
- } else {
+
+ // First attempt to find a source addr for our "load" instruction. If we fail
+ // to find a valid value, just return.
+ SILValue SrcAddr = tryFindSrcAddrForLoad(Inst);
+ if (!SrcAddr)
return false;
- }
// If the box has escaped at this instruction, we can't safely promote the
// load.
- if (hasEscapedAt(Inst))
+ if (DataflowContext.hasEscapedAt(Inst))
return false;
-
- SILType LoadTy = src->getType().getObjectType();
-
+
+ SILType LoadTy = SrcAddr->getType().getObjectType();
+
// If this is a load/copy_addr from a struct field that we want to promote,
// compute the access path down to the field so we can determine precise
// def/use behavior.
- unsigned FirstElt = computeSubelement(src, TheMemory);
-
+ unsigned FirstElt = computeSubelement(SrcAddr, TheMemory);
+
// If this is a load from within an enum projection, we can't promote it since
// we don't track subelements in a type that could be changing.
if (FirstElt == ~0U)
@@ -657,34 +1090,23 @@
// Set up the bitvector of elements being demanded by the load.
llvm::SmallBitVector RequiredElts(NumMemorySubElements);
RequiredElts.set(FirstElt, FirstElt+NumLoadSubElements);
-
- SmallVector<std::pair<SILValue, unsigned>, 8> AvailableValues;
+
+ SmallVector<AvailableValue, 8> AvailableValues;
AvailableValues.resize(NumMemorySubElements);
// Find out if we have any available values. If no bits are demanded, we
// trivially succeed. This can happen when there is a load of an empty struct.
- if (NumLoadSubElements != 0) {
- computeAvailableValues(Inst, RequiredElts, AvailableValues);
-
- // If there are no values available at this load point, then we fail to
- // promote this load and there is nothing to do.
- bool AnyAvailable = false;
- for (unsigned i = FirstElt, e = i+NumLoadSubElements; i != e; ++i)
- if (AvailableValues[i].first) {
- AnyAvailable = true;
- break;
- }
-
- if (!AnyAvailable)
- return false;
- }
-
+ if (NumLoadSubElements != 0 &&
+ !DataflowContext.computeAvailableValues(
+ Inst, FirstElt, NumLoadSubElements, RequiredElts, AvailableValues))
+ return false;
+
// Ok, we have some available values. If we have a copy_addr, explode it now,
// exposing the load operation within it. Subsequent optimization passes will
// see the load and propagate the available values into it.
if (auto *CAI = dyn_cast<CopyAddrInst>(Inst)) {
- explodeCopyAddr(CAI);
-
+ DataflowContext.explodeCopyAddr(CAI);
+
// This is removing the copy_addr, but explodeCopyAddr takes care of
// removing the instruction from Uses for us, so we return false.
return false;
@@ -693,9 +1115,9 @@
// Aggregate together all of the subelements into something that has the same
// type as the load did, and emit smaller) loads for any subelements that were
// not available.
- auto Load = cast<LoadInst>(Inst);
- auto NewVal = aggregateAvailableValues(Load, LoadTy, Load->getOperand(),
- AvailableValues, FirstElt);
+ auto *Load = cast<LoadInst>(Inst);
+ AvailableValueAggregator Agg(Load, AvailableValues, Uses);
+ SILValue NewVal = Agg.aggregateValues(LoadTy, Load->getOperand(), FirstElt);
++NumLoadPromoted;
@@ -711,15 +1133,12 @@
return true;
}
-/// promoteDestroyAddr - DestroyAddr is a composed operation merging
-/// load+strong_release. If the implicit load's value is available, explode it.
-///
-/// Note that we handle the general case of a destroy_addr of a piece of the
-/// memory object, not just destroy_addrs of the entire thing.
-///
-bool AllocOptimize::promoteDestroyAddr(DestroyAddrInst *DAI) {
+/// Return true if we can promote the given destroy.
+bool AllocOptimize::canPromoteDestroyAddr(
+ DestroyAddrInst *DAI,
+ llvm::SmallVectorImpl<AvailableValue> &AvailableValues) {
SILValue Address = DAI->getOperand();
-
+
// We cannot promote destroys of address-only types, because we can't expose
// the load.
SILType LoadTy = Address->getType().getObjectType();
@@ -728,7 +1147,7 @@
// If the box has escaped at this instruction, we can't safely promote the
// load.
- if (hasEscapedAt(DAI))
+ if (DataflowContext.hasEscapedAt(DAI))
return false;
// Compute the access path down to the field so we can determine precise
@@ -740,26 +1159,47 @@
// Set up the bitvector of elements being demanded by the load.
llvm::SmallBitVector RequiredElts(NumMemorySubElements);
RequiredElts.set(FirstElt, FirstElt+NumLoadSubElements);
-
- SmallVector<std::pair<SILValue, unsigned>, 8> AvailableValues;
- AvailableValues.resize(NumMemorySubElements);
-
+
// Find out if we have any available values. If no bits are demanded, we
// trivially succeed. This can happen when there is a load of an empty struct.
- if (NumLoadSubElements != 0) {
- computeAvailableValues(DAI, RequiredElts, AvailableValues);
-
- // If some value is not available at this load point, then we fail.
- for (unsigned i = FirstElt, e = FirstElt+NumLoadSubElements; i != e; ++i)
- if (!AvailableValues[i].first)
- return false;
- }
-
+ if (NumLoadSubElements == 0)
+ return true;
+
+ // Compute our available values. If we do not have any available values,
+ // return false. We have nothing further to do.
+ llvm::SmallVector<AvailableValue, 8> TmpList;
+ TmpList.resize(NumMemorySubElements);
+ if (!DataflowContext.computeAvailableValues(DAI, FirstElt, NumLoadSubElements,
+ RequiredElts, TmpList))
+ return false;
+
+ // Now that we have our final list, move the temporary lists contents into
+ // AvailableValues.
+ std::move(TmpList.begin(), TmpList.end(),
+ std::back_inserter(AvailableValues));
+
+ return true;
+}
+
+/// promoteDestroyAddr - DestroyAddr is a composed operation merging
+/// load+strong_release. If the implicit load's value is available, explode it.
+///
+/// Note that we handle the general case of a destroy_addr of a piece of the
+/// memory object, not just destroy_addrs of the entire thing.
+void AllocOptimize::promoteDestroyAddr(
+ DestroyAddrInst *DAI, MutableArrayRef<AvailableValue> AvailableValues) {
+ SILValue Address = DAI->getOperand();
+ SILType LoadTy = Address->getType().getObjectType();
+
+ // Compute the access path down to the field so we can determine precise
+ // def/use behavior.
+ unsigned FirstElt = computeSubelement(Address, TheMemory);
+
// Aggregate together all of the subelements into something that has the same
// type as the load did, and emit smaller) loads for any subelements that were
// not available.
- auto NewVal =
- aggregateAvailableValues(DAI, LoadTy, Address, AvailableValues, FirstElt);
+ AvailableValueAggregator Agg(DAI, AvailableValues, Uses);
+ SILValue NewVal = Agg.aggregateValues(LoadTy, Address, FirstElt);
++NumDestroyAddrPromoted;
@@ -768,108 +1208,6 @@
SILBuilderWithScope(DAI).emitDestroyValueOperation(DAI->getLoc(), NewVal);
DAI->eraseFromParent();
- return true;
-}
-
-
-
-/// Explode a copy_addr instruction of a loadable type into lower level
-/// operations like loads, stores, retains, releases, retain_value, etc.
-void AllocOptimize::explodeCopyAddr(CopyAddrInst *CAI) {
- DEBUG(llvm::dbgs() << " -- Exploding copy_addr: " << *CAI << "\n");
-
- SILType ValTy = CAI->getDest()->getType().getObjectType();
- auto &TL = Module.getTypeLowering(ValTy);
-
- // Keep track of the new instructions emitted.
- SmallVector<SILInstruction*, 4> NewInsts;
- SILBuilder B(CAI, &NewInsts);
- B.setCurrentDebugScope(CAI->getDebugScope());
-
- // Use type lowering to lower the copyaddr into a load sequence + store
- // sequence appropriate for the type.
- SILValue StoredValue = TL.emitLoadOfCopy(B, CAI->getLoc(), CAI->getSrc(),
- CAI->isTakeOfSrc());
-
- TL.emitStoreOfCopy(B, CAI->getLoc(), StoredValue, CAI->getDest(),
- CAI->isInitializationOfDest());
-
- // Update our internal state for this being gone.
- NonLoadUses.erase(CAI);
-
- // Remove the copy_addr from Uses. A single copy_addr can appear multiple
- // times if the source and dest are to elements within a single aggregate, but
- // we only want to pick up the CopyAddrKind from the store.
- DIMemoryUse LoadUse, StoreUse;
- for (auto &Use : Uses) {
- if (Use.Inst != CAI) continue;
-
- if (Use.Kind == DIUseKind::Load) {
- assert(LoadUse.isInvalid());
- LoadUse = Use;
- } else {
- assert(StoreUse.isInvalid());
- StoreUse = Use;
- }
-
- Use.Inst = nullptr;
-
- // Keep scanning in case the copy_addr appears multiple times.
- }
-
- assert((LoadUse.isValid() || StoreUse.isValid()) &&
- "we should have a load or a store, possibly both");
- assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
- StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
-
- // Now that we've emitted a bunch of instructions, including a load and store
- // but also including other stuff, update the internal state of
- // LifetimeChecker to reflect them.
-
- // Update the instructions that touch the memory. NewInst can grow as this
- // iterates, so we can't use a foreach loop.
- for (auto *NewInst : NewInsts) {
- switch (NewInst->getKind()) {
- default:
- NewInst->dump();
- llvm_unreachable("Unknown instruction generated by copy_addr lowering");
-
- case SILInstructionKind::StoreInst:
- // If it is a store to the memory object (as oppose to a store to
- // something else), track it as an access.
- if (StoreUse.isValid()) {
- StoreUse.Inst = NewInst;
- NonLoadUses[NewInst] = Uses.size();
- Uses.push_back(StoreUse);
- }
- continue;
-
- case SILInstructionKind::LoadInst:
- // If it is a load from the memory object (as oppose to a load from
- // something else), track it as an access. We need to explicitly check to
- // see if the load accesses "TheMemory" because it could either be a load
- // for the copy_addr source, or it could be a load corresponding to the
- // "assign" operation on the destination of the copyaddr.
- if (LoadUse.isValid() &&
- getAccessPathRoot(NewInst->getOperand(0)) == TheMemory) {
- LoadUse.Inst = NewInst;
- Uses.push_back(LoadUse);
- }
- continue;
-
- case SILInstructionKind::RetainValueInst:
- case SILInstructionKind::StrongRetainInst:
- case SILInstructionKind::StrongReleaseInst:
- case SILInstructionKind::UnownedRetainInst:
- case SILInstructionKind::UnownedReleaseInst:
- case SILInstructionKind::ReleaseValueInst: // Destroy overwritten value
- // These are ignored.
- continue;
- }
- }
-
- // Next, remove the copy_addr itself.
- CAI->eraseFromParent();
}
/// tryToRemoveDeadAllocation - If the allocation is an autogenerated allocation
@@ -925,17 +1263,55 @@
// If the memory object has non-trivial type, then removing the deallocation
// will drop any releases. Check that there is nothing preventing removal.
+ llvm::SmallVector<unsigned, 8> DestroyAddrIndices;
+ llvm::SmallVector<AvailableValue, 32> AvailableValueList;
+ llvm::SmallVector<unsigned, 8> AvailableValueStartOffsets;
+
if (!MemoryType.isTrivial(Module)) {
- for (auto *R : Releases) {
+ for (auto P : llvm::enumerate(Releases)) {
+ auto *R = P.value();
if (R == nullptr || isa<DeallocStackInst>(R) || isa<DeallocBoxInst>(R))
continue;
+ // We stash all of the destroy_addr that we see.
+ if (auto *DAI = dyn_cast<DestroyAddrInst>(R)) {
+ AvailableValueStartOffsets.push_back(AvailableValueList.size());
+ // Make sure we can actually promote this destroy addr. If we can not,
+ // then we must bail. In order to not gather available values twice, we
+ // gather the available values here that we will use to promote the
+ // values.
+ if (!canPromoteDestroyAddr(DAI, AvailableValueList))
+ return false;
+ DestroyAddrIndices.push_back(P.index());
+ continue;
+ }
+
DEBUG(llvm::dbgs() << "*** Failed to remove autogenerated alloc: "
"kept alive by release: " << *R);
return false;
}
}
+ // If we reached this point, we can promote all of our destroy_addr.
+ for (auto P : llvm::enumerate(DestroyAddrIndices)) {
+ unsigned DestroyAddrIndex = P.value();
+ unsigned AvailableValueIndex = P.index();
+ unsigned StartOffset = AvailableValueStartOffsets[AvailableValueIndex];
+ unsigned Count;
+
+ if ((AvailableValueStartOffsets.size() - 1) != AvailableValueIndex) {
+ Count = AvailableValueStartOffsets[AvailableValueIndex + 1] - StartOffset;
+ } else {
+ Count = AvailableValueList.size() - StartOffset;
+ }
+
+ MutableArrayRef<AvailableValue> Values(&AvailableValueList[StartOffset],
+ Count);
+ auto *DAI = cast<DestroyAddrInst>(Releases[DestroyAddrIndex]);
+ promoteDestroyAddr(DAI, Values);
+ Releases[DestroyAddrIndex] = nullptr;
+ }
+
DEBUG(llvm::dbgs() << "*** Removing autogenerated alloc_stack: "<<*TheMemory);
// If it is safe to remove, do it. Recursively remove all instructions
@@ -968,22 +1344,11 @@
}
}
- // destroy_addr(p) is strong_release(load(p)), try to promote it too.
- for (unsigned i = 0; i != Releases.size(); ++i) {
- if (auto *DAI = dyn_cast_or_null<DestroyAddrInst>(Releases[i]))
- if (promoteDestroyAddr(DAI)) {
- // remove entry if destroy_addr got deleted.
- Releases[i] = nullptr;
- Changed = true;
- }
- }
-
// If this is an allocation, try to remove it completely.
Changed |= tryToRemoveDeadAllocation();
return Changed;
- }
-
+}
static bool optimizeMemoryAllocations(SILFunction &Fn) {
bool Changed = false;
@@ -1022,15 +1387,15 @@
}
namespace {
-class PredictableMemoryOptimizations : public SILFunctionTransform {
+class PredictableMemoryOptimizations : public SILFunctionTransform {
/// The entry point to the transformation.
void run() override {
if (optimizeMemoryAllocations(*getFunction()))
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
}
-
};
+
} // end anonymous namespace
diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp
index 736ca54..9eb5407 100644
--- a/lib/SILOptimizer/PassManager/PassManager.cpp
+++ b/lib/SILOptimizer/PassManager/PassManager.cpp
@@ -236,8 +236,9 @@
};
-SILPassManager::SILPassManager(SILModule *M, llvm::StringRef Stage) :
- Mod(M), StageName(Stage) {
+SILPassManager::SILPassManager(SILModule *M, llvm::StringRef Stage,
+ bool isMandatoryPipeline) :
+ Mod(M), StageName(Stage), isMandatoryPipeline(isMandatoryPipeline) {
#define ANALYSIS(NAME) \
Analysis.push_back(create##NAME##Analysis(Mod));
@@ -250,14 +251,15 @@
}
SILPassManager::SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
- llvm::StringRef Stage)
- : SILPassManager(M, Stage) {
+ llvm::StringRef Stage, bool isMandatoryPipeline)
+ : SILPassManager(M, Stage, isMandatoryPipeline) {
this->IRMod = IRMod;
}
bool SILPassManager::continueTransforming() {
- return Mod->getStage() == SILStage::Raw ||
- NumPassesRun < SILNumOptPassesToRun;
+ if (isMandatoryPipeline)
+ return true;
+ return NumPassesRun < SILNumOptPassesToRun;
}
bool SILPassManager::analysesUnlocked() {
@@ -389,7 +391,7 @@
// Only include functions that are definitions, and which have not
// been intentionally excluded from optimization.
- if (F.isDefinition() && F.shouldOptimize())
+ if (F.isDefinition() && (isMandatoryPipeline || F.shouldOptimize()))
FunctionWorklist.push_back(*I);
}
@@ -554,8 +556,8 @@
void SILPassManager::addFunctionToWorklist(SILFunction *F,
SILFunction *DerivedFrom) {
- assert(F && F->isDefinition() && F->shouldOptimize() &&
- "Expected optimizable function definition!");
+ assert(F && F->isDefinition() && (isMandatoryPipeline || F->shouldOptimize())
+ && "Expected optimizable function definition!");
constexpr int MaxDeriveLevels = 10;
diff --git a/lib/SILOptimizer/PassManager/Passes.cpp b/lib/SILOptimizer/PassManager/Passes.cpp
index 94d74e7..761a044 100644
--- a/lib/SILOptimizer/PassManager/Passes.cpp
+++ b/lib/SILOptimizer/PassManager/Passes.cpp
@@ -51,7 +51,7 @@
auto &Ctx = Module.getASTContext();
- SILPassManager PM(&Module);
+ SILPassManager PM(&Module, "", /*isMandatoryPipeline=*/ true);
PM.executePassPipelinePlan(
SILPassPipelinePlan::getDiagnosticPassPipeline(Module.getOptions()));
@@ -119,7 +119,9 @@
if (Module.getOptions().VerifyAll)
Module.verify();
- SILPassManager PM(&Module, "Onone");
+ // We want to run the Onone passes also for function which have an explicit
+ // Onone attribute.
+ SILPassManager PM(&Module, "Onone", /*isMandatoryPipeline=*/ true);
PM.executePassPipelinePlan(SILPassPipelinePlan::getOnonePassPipeline());
// Verify the module, if required.
@@ -199,7 +201,7 @@
// convert it to a module pass to ensure that the SIL input is always at the
// same stage of lowering.
void swift::runSILLoweringPasses(SILModule &Module) {
- SILPassManager PM(&Module, "LoweringPasses");
+ SILPassManager PM(&Module, "LoweringPasses", /*isMandatoryPipeline=*/ true);
PM.executePassPipelinePlan(SILPassPipelinePlan::getLoweringPassPipeline());
assert(Module.getStage() == SILStage::Lowered);
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 7c17964..3fad2e2 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -328,7 +328,9 @@
for (auto Arg : ToBeReleasedArgs) {
Builder.emitDestroyValueOperation(PAI->getLoc(), Arg);
}
- Builder.createStrongRelease(AI.getLoc(), PAI, Builder.getDefaultAtomicity());
+ if (!PAI->hasCalleeGuaranteedContext())
+ Builder.createStrongRelease(AI.getLoc(), PAI,
+ Builder.getDefaultAtomicity());
Builder.setInsertionPoint(TAI->getErrorBB()->begin());
// Release the non-consumed parameters.
for (auto Arg : ToBeReleasedArgs) {
@@ -487,13 +489,10 @@
assert(NewOpType.isAddress() && "Addresses should map to addresses.");
auto UAC = Builder.createUncheckedAddrCast(AI.getLoc(), Op, NewOpType);
Args.push_back(UAC);
- } else if (SILType::canRefCast(OldOpType, NewOpType, AI.getModule())) {
- auto URC = Builder.createUncheckedRefCast(AI.getLoc(), Op, NewOpType);
+ } else if (OldOpType.getSwiftRValueType() != NewOpType.getSwiftRValueType()) {
+ auto URC = Builder.createUncheckedBitCast(AI.getLoc(), Op, NewOpType);
Args.push_back(URC);
} else {
- assert((!OldOpType.isHeapObjectReferenceType()
- && !NewOpType.isHeapObjectReferenceType()) &&
- "ref argument types should map to refs.");
Args.push_back(Op);
}
}
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index b92c698..996215f 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -629,7 +629,8 @@
// the parameters promoted.
auto ClonedTy = SILFunctionType::get(
OrigFTI->getGenericSignature(), OrigFTI->getExtInfo(),
- OrigFTI->getCalleeConvention(), ClonedInterfaceArgTys,
+ OrigFTI->getCoroutineKind(), OrigFTI->getCalleeConvention(),
+ ClonedInterfaceArgTys, OrigFTI->getYields(),
OrigFTI->getResults(), OrigFTI->getOptionalErrorResult(),
M.getASTContext(), OrigFTI->getWitnessMethodConformanceOrNone());
diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
index 6d0e0df..5e1bca0 100644
--- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
+++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp
@@ -291,6 +291,8 @@
switch (Term->getTermKind()) {
case TermKind::ReturnInst:
case TermKind::ThrowInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
case TermKind::UnreachableInst:
case TermKind::SwitchValueInst:
@@ -381,6 +383,7 @@
switch (cast<TermInst>(I)->getTermKind()) {
case TermKind::BranchInst:
case TermKind::UnreachableInst:
+ case TermKind::UnwindInst:
return;
case TermKind::ReturnInst:
@@ -396,6 +399,7 @@
case TermKind::TryApplyInst:
case TermKind::SwitchValueInst:
+ case TermKind::YieldInst:
for (auto &O : I->getAllOperands())
markValueLive(O.get());
return;
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index c3304da..d1333cd 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -577,6 +577,12 @@
InterfaceResults.push_back(InterfaceResult);
}
+ llvm::SmallVector<SILYieldInfo, 8> InterfaceYields;
+ for (SILYieldInfo InterfaceYield : FTy->getYields()) {
+ // For now, don't touch the yield types.
+ InterfaceYields.push_back(InterfaceYield);
+ }
+
bool UsesGenerics = false;
if (HasGenericSignature) {
// Not all of the generic type parameters are used by the function
@@ -630,9 +636,9 @@
UsesGenerics ? FTy->getGenericSignature() : nullptr;
return SILFunctionType::get(
- GenericSig, ExtInfo, FTy->getCalleeConvention(), InterfaceParams,
- InterfaceResults, InterfaceErrorResult, F->getModule().getASTContext(),
- witnessMethodConformance);
+ GenericSig, ExtInfo, FTy->getCoroutineKind(), FTy->getCalleeConvention(),
+ InterfaceParams, InterfaceYields, InterfaceResults, InterfaceErrorResult,
+ F->getModule().getASTContext(), witnessMethodConformance);
}
void FunctionSignatureTransform::createFunctionSignatureOptimizedFunction() {
@@ -1142,8 +1148,7 @@
auto *F = getFunction();
// Don't run function signature optimizations at -Os.
- if (F->getModule().getOptions().Optimization ==
- SILOptions::SILOptMode::OptimizeForSize)
+ if (F->optimizeForSize())
return;
// Don't optimize callees that should not be optimized.
diff --git a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
index 20b88e9..51aff14 100644
--- a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
+++ b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
@@ -84,6 +84,9 @@
SILFunction *Callee = Apply.getReferencedFunction();
assert(Callee && "Expected to have a known callee");
+ if (!Callee->shouldOptimize())
+ continue;
+
// We have a call that can potentially be specialized, so
// attempt to do so.
llvm::SmallVector<SILFunction *, 2> NewFunctions;
diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp
index 76741f7..6b2687c 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -290,7 +290,8 @@
SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
/*pseudogeneric*/ false, /*noescape*/ false);
auto FunctionType = SILFunctionType::get(
- nullptr, ExtInfo, ParameterConvention::Direct_Unowned, Parameters,
+ nullptr, ExtInfo, SILCoroutineKind::None,
+ ParameterConvention::Direct_Unowned, Parameters, /*yields*/ {},
Results, None, M.getASTContext());
return FunctionType;
}
@@ -697,6 +698,8 @@
if (!Enum)
return BridgedArgument();
+ if (SILBasicBlock::iterator(Enum) == Enum->getParent()->begin())
+ return BridgedArgument();
auto *BridgeCall =
dyn_cast<ApplyInst>(std::prev(SILBasicBlock::iterator(Enum)));
if (!BridgeCall || BridgeCall->getNumArguments() != 1 ||
@@ -704,11 +707,16 @@
return BridgedArgument();
auto BridgedValue = BridgeCall->getArgument(0);
+ auto Next = std::next(SILBasicBlock::iterator(Enum));
+ if (Next == Enum->getParent()->end())
+ return BridgedArgument();
auto *BridgedValueRelease =
dyn_cast<ReleaseValueInst>(std::next(SILBasicBlock::iterator(Enum)));
if (!BridgedValueRelease || BridgedValueRelease->getOperand() != BridgedValue)
return BridgedArgument();
+ if (SILBasicBlock::iterator(BridgeCall) == BridgeCall->getParent()->begin())
+ return BridgedArgument();
auto *FunRef =
dyn_cast<FunctionRefInst>(std::prev(SILBasicBlock::iterator(BridgeCall)));
if (!FunRef || !FunRef->hasOneUse() || BridgeCall->getCallee() != FunRef)
@@ -1197,7 +1205,8 @@
SILResultInfo(BridgedReturn.getReturnType(), ResultConvention::Owned));
}
auto FunctionType = SILFunctionType::get(
- nullptr, ExtInfo, ParameterConvention::Direct_Unowned, Parameters,
+ nullptr, ExtInfo, SILCoroutineKind::None,
+ ParameterConvention::Direct_Unowned, Parameters, {},
Results, None, M.getASTContext());
return FunctionType;
}
@@ -1280,8 +1289,7 @@
auto *Fun = getFunction();
// Only outline if we optimize for size.
- if (Fun->getModule().getOptions().Optimization !=
- SILOptions::SILOptMode::OptimizeForSize)
+ if (!Fun->optimizeForSize())
return;
// Dump function if requested.
diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
index 8190a3e..e7273a9 100644
--- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
@@ -111,7 +111,7 @@
DefaultApplyLength = 10
};
- SILOptions::SILOptMode OptMode;
+ OptimizationMode OptMode;
#ifndef NDEBUG
SILFunction *LastPrintedCaller = nullptr;
@@ -161,7 +161,7 @@
public:
SILPerformanceInliner(InlineSelection WhatToInline, DominanceAnalysis *DA,
SILLoopAnalysis *LA, SideEffectAnalysis *SEA,
- SILOptions::SILOptMode OptMode, OptRemark::Emitter &ORE)
+ OptimizationMode OptMode, OptRemark::Emitter &ORE)
: WhatToInline(WhatToInline), DA(DA), LA(LA), SEA(SEA), CBI(DA), ORE(ORE),
OptMode(OptMode) {}
@@ -243,7 +243,7 @@
int BaseBenefit = RemovedCallBenefit;
// Osize heuristic.
- if (OptMode == SILOptions::SILOptMode::OptimizeForSize) {
+ if (OptMode == OptimizationMode::ForSize) {
// Don't inline into thunks.
if (AI.getFunction()->isThunk())
return false;
@@ -293,11 +293,6 @@
->getSubstitutionMap(AI.getSubstitutions());
}
- // For some reason -Ounchecked can accept a higher base benefit without
- // increasing the code size too much.
- if (OptMode == SILOptions::SILOptMode::OptimizeUnchecked)
- BaseBenefit *= 2;
-
CallerWeight.updateBenefit(Benefit, BaseBenefit);
// Benefit = 1;
@@ -443,7 +438,8 @@
ORE.emit([&]() {
using namespace OptRemark;
return RemarkMissed("NoInlinedCost", *AI.getInstruction())
- << "Not profitable to inline (cost = " << NV("Cost", CalleeCost)
+ << "Not profitable to inline function " << NV("Callee", Callee)
+ << " (cost = " << NV("Cost", CalleeCost)
<< ", benefit = " << NV("Benefit", Benefit) << ")";
});
return false;
@@ -905,7 +901,7 @@
return;
}
- auto OptMode = getFunction()->getModule().getOptions().Optimization;
+ auto OptMode = getFunction()->getEffectiveOptimizationMode();
SILPerformanceInliner Inliner(WhatToInline, DA, LA, SEA, OptMode, ORE);
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index fe6da5e..145a57b 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -2302,6 +2302,8 @@
case TermKind::ThrowInst:
case TermKind::DynamicMethodBranchInst:
case TermKind::ReturnInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
break;
}
// If the block has a cond_fail, try to move it to the predecessors.
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index c566949..254c6b7 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -555,8 +555,11 @@
auto &CurFn = *getFunction();
// Don't perform speculative devirtualization at -Os.
- if (CurFn.getModule().getOptions().Optimization ==
- SILOptions::SILOptMode::OptimizeForSize)
+ if (CurFn.optimizeForSize())
+ return;
+
+ // Don't speculatively devirtualize calls inside thunks.
+ if (CurFn.isThunk())
return;
ClassHierarchyAnalysis *CHA = PM->getAnalysis<ClassHierarchyAnalysis>();
diff --git a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
index 3d6da3c..4219ac2 100644
--- a/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
+++ b/lib/SILOptimizer/UtilityPasses/BugReducerTester.cpp
@@ -84,7 +84,8 @@
nullptr, SILFunctionType::ExtInfo(SILFunctionType::Representation::Thin,
false /*isPseudoGeneric*/,
false /*noescape*/),
- ParameterConvention::Direct_Unowned, ArrayRef<SILParameterInfo>(),
+ SILCoroutineKind::None, ParameterConvention::Direct_Unowned,
+ ArrayRef<SILParameterInfo>(), ArrayRef<SILYieldInfo>(),
ResultInfoArray, None, getFunction()->getModule().getASTContext());
SILFunction *F = getFunction()->getModule().getOrCreateSharedFunction(
diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFG.cpp
index 452e58d..261512d 100644
--- a/lib/SILOptimizer/Utils/CFG.cpp
+++ b/lib/SILOptimizer/Utils/CFG.cpp
@@ -307,9 +307,25 @@
return;
}
+ case TermKind::YieldInst: {
+ auto *YI = cast<YieldInst>(T);
+ assert((EdgeIdx == 0 || EdgeIdx == 1) && "Invalid edge index");
+ auto *resumeBB = !EdgeIdx ? NewDest : YI->getResumeBB();
+ auto *unwindBB = EdgeIdx ? NewDest : YI->getUnwindBB();
+ SmallVector<SILValue, 4> yieldedValues;
+ for (auto value : YI->getYieldedValues())
+ yieldedValues.push_back(value);
+
+ B.createYield(YI->getLoc(), yieldedValues, resumeBB, unwindBB);
+
+ YI->eraseFromParent();
+ return;
+ }
+
case TermKind::ReturnInst:
case TermKind::ThrowInst:
case TermKind::UnreachableInst:
+ case TermKind::UnwindInst:
llvm_unreachable("Branch target cannot be changed for this terminator instruction!");
}
llvm_unreachable("Not yet implemented!");
@@ -469,6 +485,8 @@
case TermKind::ThrowInst:
case TermKind::TryApplyInst:
case TermKind::UnreachableInst:
+ case TermKind::UnwindInst:
+ case TermKind::YieldInst:
llvm_unreachable("Branch target cannot be replaced for this terminator instruction!");
}
llvm_unreachable("Not yet implemented!");
@@ -830,3 +848,118 @@
}
llvm_unreachable("Destination block not found");
}
+
+void swift::completeJointPostDominanceSet(
+ ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
+ llvm::SmallVectorImpl<SILBasicBlock *> &Result) {
+ assert(!UserBlocks.empty() && "Must have at least 1 user block");
+ assert(!DefBlocks.empty() && "Must have at least 1 def block");
+
+ // If we have only one def block and one user block and they are the same
+ // block, then just return.
+ if (DefBlocks.size() == 1 && UserBlocks.size() == 1 &&
+ UserBlocks[0] == DefBlocks[0]) {
+ return;
+ }
+
+ // Some notes on the algorithm:
+ //
+ // 1. Our VisitedBlocks set just states that a value has been added to the
+ // worklist and should not be added to the worklist.
+ // 2. Our targets of the CFG block are DefBlockSet.
+ // 3. We find the missing post-domination blocks by finding successors of
+ // blocks on our walk that we have not visited by the end of the walk. For
+ // joint post-dominance to be true, no such successors should exist.
+
+ // Our set of target blocks where we stop walking.
+ llvm::SmallPtrSet<SILBasicBlock *, 8> DefBlockSet(DefBlocks.begin(),
+ DefBlocks.end());
+
+ // The set of successor blocks of blocks that we visit. Any blocks still in
+ // this set at the end of the walk act as a post-dominating closure around our
+ // UserBlock set.
+ llvm::SmallSetVector<SILBasicBlock *, 16> MustVisitSuccessorBlocks;
+
+ // Add our user and def blocks to the VisitedBlock set. We never want to find
+ // these in our worklist.
+ llvm::SmallPtrSet<SILBasicBlock *, 32> VisitedBlocks(UserBlocks.begin(),
+ UserBlocks.end());
+
+ // Finally setup our worklist by adding our user block predecessors. We only
+ // add the predecessors to the worklist once.
+ llvm::SmallVector<SILBasicBlock *, 32> Worklist;
+ for (auto *Block : UserBlocks) {
+ copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist),
+ [&](SILBasicBlock *PredBlock) -> bool {
+ return VisitedBlocks.insert(PredBlock).second;
+ });
+ }
+
+ // Then until we reach a fix point.
+ while (!Worklist.empty()) {
+ // Grab the next block from the worklist.
+ auto *Block = Worklist.pop_back_val();
+ assert(VisitedBlocks.count(Block) && "All blocks from worklist should be "
+ "in the visited blocks set.");
+
+ // Since we are visiting this block now, we know that this block can not be
+ // apart of a the post-dominance closure of our UseBlocks.
+ MustVisitSuccessorBlocks.remove(Block);
+
+ // Then add each successor block of Block that has not been visited yet to
+ // the MustVisitSuccessorBlocks set.
+ for (auto *SuccBlock : Block->getSuccessorBlocks()) {
+ if (!VisitedBlocks.count(SuccBlock)) {
+ MustVisitSuccessorBlocks.insert(SuccBlock);
+ }
+ }
+
+ // If this is a def block, then do not add its predecessors to the
+ // worklist.
+ if (DefBlockSet.count(Block))
+ continue;
+
+ // Otherwise add all unvisited predecessors to the worklist.
+ copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist),
+ [&](SILBasicBlock *Block) -> bool {
+ return VisitedBlocks.insert(Block).second;
+ });
+ }
+
+ // Now that we are done, add all remaining must visit blocks to our result
+ // list. These are the remaining parts of our joint post-dominance closure.
+ copy(MustVisitSuccessorBlocks, std::back_inserter(Result));
+}
+
+bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn,
+ DominanceInfo *DT,
+ SILLoopInfo *LI) {
+ // Find our targets.
+ llvm::SmallVector<std::pair<SILBasicBlock *, unsigned>, 8> Targets;
+ for (auto &Block : Fn) {
+ auto *CBI = dyn_cast<CondBranchInst>(Block.getTerminator());
+ if (!CBI)
+ continue;
+
+ // See if our true index is a critical edge. If so, add block to the list
+ // and continue. If the false edge is also critical, we will handle it at
+ // the same time.
+ if (isCriticalEdge(CBI, CondBranchInst::TrueIdx)) {
+ Targets.emplace_back(&Block, CondBranchInst::TrueIdx);
+ }
+
+ if (!isCriticalEdge(CBI, CondBranchInst::FalseIdx)) {
+ continue;
+ }
+
+ Targets.emplace_back(&Block, CondBranchInst::FalseIdx);
+ }
+
+ for (auto P : Targets) {
+ SILBasicBlock *Block = P.first;
+ unsigned Index = P.second;
+ auto *Result = splitCriticalEdge(Block->getTerminator(), Index, DT, LI);
+ (void)Result;
+ assert(Result);
+ }
+}
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 329f349..a24e246 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -528,7 +528,10 @@
return false;
}
- if (!F->shouldOptimize()) {
+ // Mandatory inlining does class method devirtualization. I'm not sure if this
+ // is really needed, but some test rely on this.
+ // So even for Onone functions we have to do it if the SILStage is raw.
+ if (F->getModule().getStage() != SILStage::Raw && !F->shouldOptimize()) {
// Do not consider functions that should not be optimized.
DEBUG(llvm::dbgs() << " FAIL: Could not optimize function "
<< " because it is marked no-opt: " << F->getName()
@@ -712,48 +715,6 @@
// Witness Method Optimization
//===----------------------------------------------------------------------===//
-static SubstitutionMap
-getSubstitutionsForProtocolConformance(ModuleDecl *M,
- ProtocolConformanceRef CRef) {
- auto C = CRef.getConcrete();
-
- // Walk down to the base NormalProtocolConformance.
- SubstitutionList Subs;
- const ProtocolConformance *ParentC = C;
- while (!isa<NormalProtocolConformance>(ParentC)) {
- switch (ParentC->getKind()) {
- case ProtocolConformanceKind::Normal:
- llvm_unreachable("should have exited the loop?!");
- case ProtocolConformanceKind::Inherited:
- ParentC = cast<InheritedProtocolConformance>(ParentC)
- ->getInheritedConformance();
- break;
- case ProtocolConformanceKind::Specialized: {
- auto SC = cast<SpecializedProtocolConformance>(ParentC);
- ParentC = SC->getGenericConformance();
- assert(Subs.empty() && "multiple conformance specializations?!");
- Subs = SC->getGenericSubstitutions();
- break;
- }
- }
- }
- const NormalProtocolConformance *NormalC
- = cast<NormalProtocolConformance>(ParentC);
-
- // If the normal conformance is for a generic type, and we didn't hit a
- // specialized conformance, collect the substitutions from the generic type.
- // FIXME: The AST should do this for us.
- if (!NormalC->getType()->isSpecialized())
- return SubstitutionMap();
-
- if (Subs.empty()) {
- auto *DC = NormalC->getDeclContext();
- return NormalC->getType()->getContextSubstitutionMap(M, DC);
- }
-
- return NormalC->getGenericSignature()->getSubstitutionMap(Subs);
-}
-
/// Compute substitutions for making a direct call to a SIL function with
/// @convention(witness_method) convention.
///
@@ -823,7 +784,7 @@
// If `Self` maps to a bound generic type, this gives us the
// substitutions for the concrete type's generic parameters.
- auto baseSubMap = getSubstitutionsForProtocolConformance(mod, conformanceRef);
+ auto baseSubMap = conformance->getSubstitutions(mod);
unsigned baseDepth = 0;
auto *rootConformance = conformance->getRootNormalConformance();
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index e7dfb6f..5c49d9f 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -347,12 +347,6 @@
static bool shouldNotSpecializeCallee(SILFunction *Callee,
SubstitutionList Subs = {}) {
- if (!Callee->shouldOptimize()) {
- DEBUG(llvm::dbgs() << " Cannot specialize function " << Callee->getName()
- << " marked to be excluded from optimizations.\n");
- return true;
- }
-
if (Callee->hasSemanticsAttr("optimize.sil.specialize.generic.never"))
return true;
@@ -721,8 +715,10 @@
// Use the new specialized generic signature.
auto NewFnTy = SILFunctionType::get(
- CanSpecializedGenericSig, FnTy->getExtInfo(), FnTy->getCalleeConvention(),
- FnTy->getParameters(), FnTy->getResults(), FnTy->getOptionalErrorResult(),
+ CanSpecializedGenericSig, FnTy->getExtInfo(),
+ FnTy->getCoroutineKind(), FnTy->getCalleeConvention(),
+ FnTy->getParameters(), FnTy->getYields(),
+ FnTy->getResults(), FnTy->getOptionalErrorResult(),
M.getASTContext(), FnTy->getWitnessMethodConformanceOrNone());
// This is an interface type. It should not have any archetypes.
@@ -735,6 +731,7 @@
CanSILFunctionType ReabstractionInfo::
createSpecializedType(CanSILFunctionType SubstFTy, SILModule &M) const {
llvm::SmallVector<SILResultInfo, 8> SpecializedResults;
+ llvm::SmallVector<SILYieldInfo, 8> SpecializedYields;
llvm::SmallVector<SILParameterInfo, 8> SpecializedParams;
unsigned IndirectResultIdx = 0;
@@ -769,9 +766,15 @@
SpecializedParams.push_back(PI);
}
}
+ for (SILYieldInfo YI : SubstFTy->getYields()) {
+ // For now, always just use the original, substituted parameter info.
+ SpecializedYields.push_back(YI);
+ }
return SILFunctionType::get(
- SubstFTy->getGenericSignature(), SubstFTy->getExtInfo(),
- SubstFTy->getCalleeConvention(), SpecializedParams, SpecializedResults,
+ SubstFTy->getGenericSignature(),
+ SubstFTy->getExtInfo(), SubstFTy->getCoroutineKind(),
+ SubstFTy->getCalleeConvention(),
+ SpecializedParams, SpecializedYields, SpecializedResults,
SubstFTy->getOptionalErrorResult(), M.getASTContext(),
SubstFTy->getWitnessMethodConformanceOrNone());
}
@@ -1832,12 +1835,10 @@
/// Create a new specialized function if possible, and cache it.
SILFunction *GenericFuncSpecializer::tryCreateSpecialization() {
// Do not create any new specializations at Onone.
- if (M.getOptions().Optimization <= SILOptions::SILOptMode::None)
+ if (!GenericFunc->shouldOptimize())
return nullptr;
- DEBUG(
- if (M.getOptions().Optimization <= SILOptions::SILOptMode::Debug) {
- llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n"; });
+ DEBUG(llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n";);
ReInfo.verify();
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 72791f8..62d2bf6 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -89,7 +89,8 @@
// At Onone, consider all uses, including the debug_info.
// This way, debug_info is preserved at Onone.
if (I->hasUsesOfAnyResult() &&
- I->getModule().getOptions().Optimization <= SILOptions::SILOptMode::None)
+ I->getFunction()->getEffectiveOptimizationMode() <=
+ OptimizationMode::NoOptimization)
return false;
if (!onlyHaveDebugUsesOfAllResults(I) || isa<TermInst>(I))
diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp
index 96c67bb..107b065 100644
--- a/lib/SILOptimizer/Utils/SILInliner.cpp
+++ b/lib/SILOptimizer/Utils/SILInliner.cpp
@@ -338,8 +338,11 @@
case SILInstructionKind::UnreachableInst:
case SILInstructionKind::ReturnInst:
case SILInstructionKind::ThrowInst:
+ case SILInstructionKind::UnwindInst:
+ case SILInstructionKind::YieldInst:
return InlineCost::Free;
+ case SILInstructionKind::AbortApplyInst:
case SILInstructionKind::ApplyInst:
case SILInstructionKind::TryApplyInst:
case SILInstructionKind::AllocBoxInst:
@@ -349,6 +352,7 @@
case SILInstructionKind::AllocStackInst:
case SILInstructionKind::AllocValueBufferInst:
case SILInstructionKind::BindMemoryInst:
+ case SILInstructionKind::BeginApplyInst:
case SILInstructionKind::ValueMetatypeInst:
case SILInstructionKind::WitnessMethodInst:
case SILInstructionKind::AssignInst:
@@ -376,6 +380,7 @@
case SILInstructionKind::DeinitExistentialAddrInst:
case SILInstructionKind::DeinitExistentialValueInst:
case SILInstructionKind::DestroyAddrInst:
+ case SILInstructionKind::EndApplyInst:
case SILInstructionKind::ProjectValueBufferInst:
case SILInstructionKind::ProjectBoxInst:
case SILInstructionKind::ProjectExistentialBoxInst:
diff --git a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
index 75fe849..994d128 100644
--- a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
+++ b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp
@@ -78,16 +78,29 @@
/// Are all available values identicalTo each other.
bool areIdentical(AvailableValsTy &Avails) {
- // TODO: MultiValueInstruction
- auto *First = dyn_cast<SingleValueInstruction>(Avails.begin()->second);
- if (!First)
+ if (auto *First = dyn_cast<SingleValueInstruction>(Avails.begin()->second)) {
+ for (auto Avail : Avails) {
+ auto *Inst = dyn_cast<SingleValueInstruction>(Avail.second);
+ if (!Inst)
+ return false;
+ if (!Inst->isIdenticalTo(First))
+ return false;
+ }
+ return true;
+ }
+
+ auto *MVIR = dyn_cast<MultipleValueInstructionResult>(Avails.begin()->second);
+ if (!MVIR)
return false;
+
for (auto Avail : Avails) {
- auto *Inst = dyn_cast<SingleValueInstruction>(Avail.second);
- if (!Inst)
+ auto *Result = dyn_cast<MultipleValueInstructionResult>(Avail.second);
+ if (!Result)
return false;
- if (!Inst->isIdenticalTo(First))
+ if (!Result->getParent()->isIdenticalTo(MVIR->getParent()) ||
+ Result->getIndex() != MVIR->getIndex()) {
return false;
+ }
}
return true;
}
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index ca96300..8382876 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -474,9 +474,6 @@
tc.conformsToProtocol(baseTy, proto, cs.DC,
(ConformanceCheckFlags::InExpression|
ConformanceCheckFlags::Used));
- assert((!conformance ||
- conformance->getConditionalRequirements().empty()) &&
- "unhandled conditional conformance");
if (conformance && conformance->isConcrete()) {
if (auto witness =
conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
@@ -1318,23 +1315,29 @@
// Apply a key path if we have one.
if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) {
+ auto applicationTy = simplifyType(selected->openedType)
+ ->castTo<FunctionType>();
+
index = cs.coerceToRValue(index);
// The index argument should be (keyPath: KeyPath<Root, Value>).
// Dig the key path expression out of the argument tuple.
auto indexKP = cast<TupleExpr>(index)->getElement(0);
- auto keyPathTTy = cs.getType(indexKP);
-
+ auto keyPathExprTy = cs.getType(indexKP);
+ auto keyPathTy = applicationTy->getInput()->castTo<TupleType>()
+ ->getElementType(0);
+
// Check for the KeyPath being an IUO
- if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathTTy)) {
- keyPathTTy = pathTy;
- indexKP = coerceImplicitlyUnwrappedOptionalToValue(indexKP, keyPathTTy, locator);
+ if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathExprTy)) {
+ keyPathExprTy = pathTy;
+ indexKP = coerceImplicitlyUnwrappedOptionalToValue(
+ indexKP, keyPathExprTy, locator);
}
Type valueTy;
Type baseTy;
bool resultIsLValue;
- if (auto nom = keyPathTTy->getAs<NominalType>()) {
+ if (auto nom = keyPathTy->getAs<NominalType>()) {
// AnyKeyPath is <T> rvalue T -> rvalue Any?
if (nom->getDecl() == cs.getASTContext().getAnyKeyPathDecl()) {
valueTy = ProtocolCompositionType::get(cs.getASTContext(), {},
@@ -1343,12 +1346,25 @@
resultIsLValue = false;
base = cs.coerceToRValue(base);
baseTy = cs.getType(base);
+ // We don't really want to attempt AnyKeyPath application
+ // if we know a more specific key path type is being applied.
+ if (!keyPathTy->isEqual(keyPathExprTy)) {
+ cs.TC.diagnose(base->getLoc(),
+ diag::expr_smart_keypath_application_type_mismatch,
+ keyPathExprTy,
+ baseTy)
+ .highlight(index->getSourceRange());
+ }
} else {
llvm_unreachable("unknown key path class!");
}
} else {
- auto keyPathBGT = keyPathTTy->castTo<BoundGenericType>();
+ auto keyPathBGT = keyPathTy->castTo<BoundGenericType>();
baseTy = keyPathBGT->getGenericArgs()[0];
+
+ // Coerce the base to the key path's expected base type.
+ if (!baseTy->isEqual(cs.getType(base)->getRValueType()))
+ base = coerceToType(base, baseTy, locator);
if (keyPathBGT->getDecl()
== cs.getASTContext().getPartialKeyPathDecl()) {
@@ -1377,12 +1393,6 @@
llvm_unreachable("unknown key path class!");
}
}
-
- // Coerce the base if its anticipated type doesn't match - say we're
- // applying a keypath with an existential base to a concrete base.
- if (baseTy->isExistentialType() && !cs.getType(base)->isExistentialType()) {
- base = coerceToType(base, baseTy, locator);
- }
}
if (resultIsLValue)
valueTy = LValueType::get(valueTy);
@@ -7527,6 +7537,16 @@
DC);
if (!useAs && !useAsBang)
return false;
+
+ // If we're performing pattern matching, "as" means something completely different...
+ if (auto binOpExpr = dyn_cast<BinaryExpr>(expr)) {
+ auto overloadedFn = dyn_cast<OverloadedDeclRefExpr>(binOpExpr->getFn());
+ if (overloadedFn && overloadedFn->getDecls().size() > 0) {
+ ValueDecl *decl0 = overloadedFn->getDecls()[0];
+ if (decl0->getBaseName() == decl0->getASTContext().Id_MatchOperator)
+ return false;
+ }
+ }
bool needsParensInside = exprNeedsParensBeforeAddingAs(TC, DC, affected);
bool needsParensOutside = exprNeedsParensAfterAddingAs(TC, DC, affected,
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bf8f627..90f5bb9 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4844,7 +4844,7 @@
AFD = dyn_cast<AbstractFunctionDecl>(candidate);
}
- if (!AFD || !AFD->isGeneric() || !AFD->hasInterfaceType())
+ if (!AFD || !AFD->getGenericSignature() || !AFD->hasInterfaceType())
return false;
auto env = AFD->getGenericEnvironment();
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index fecfb81..e14dae2 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -563,15 +563,6 @@
break;
}
- if (conformance) {
- assert(relationshipKind == SelfTypeRelationship::ConformsTo ||
- relationshipKind == SelfTypeRelationship::ConformedToBy);
-
- for (auto requirement : conformance->getConditionalRequirements()) {
- cs.addConstraint(requirement, locator);
- }
- }
-
bool fewerEffectiveParameters = false;
switch (checkKind) {
case CheckAll:
@@ -1045,16 +1036,6 @@
continue;
}
- // A concrete type is better than an archetype.
- // FIXME: Total hack.
- if (type1->is<ArchetypeType>() != type2->is<ArchetypeType>()) {
- if (type1->is<ArchetypeType>())
- ++score2;
- else
- ++score1;
- continue;
- }
-
// FIXME:
// This terrible hack is in place to support equality comparisons of non-
// equatable option types to 'nil'. Until we have a way to constrain a type
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 4e2d031..e5a406a 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -18,6 +18,7 @@
#include "ConstraintSystem.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/StringExtras.h"
#include "swift/ClangImporter/ClangModule.h"
#include "llvm/Support/Compiler.h"
@@ -2606,11 +2607,19 @@
// This conformance may be conditional, in which case we need to consider
// those requirements as constraints too.
//
- // FIXME: this doesn't seem to be right; the requirements are sometimes
- // phrased in terms of the type's generic parameters, not type variables
- // in this context.
- for (auto req : conformance->getConditionalRequirements()) {
- addConstraint(req, locator);
+ // If we've got a normal conformance, we must've started with `type` in
+ // the context that declares the conformance, and so these requirements
+ // are automatically satisfied, and thus we can skip adding them. (This
+ // hacks around some representational problems caused by requirements
+ // being stored as interface types and the normal conformance's type being
+ // a contextual type. Once the latter is fixed and everything is interface
+ // types, this shouldn't be necessary.)
+ if (conformance->isConcrete() &&
+ conformance->getConcrete()->getKind() !=
+ ProtocolConformanceKind::Normal) {
+ for (auto req : conformance->getConditionalRequirements()) {
+ addConstraint(req, locator);
+ }
}
return SolutionKind::Solved;
}
@@ -4034,22 +4043,28 @@
// Try to match the root type.
rootTy = getFixedTypeRecursive(rootTy, flags, /*wantRValue=*/false);
- auto rootMatches = matchTypes(kpRootTy, rootTy,
- ConstraintKind::Equal,
- subflags, locator);
- switch (rootMatches) {
- case SolutionKind::Error:
- return SolutionKind::Error;
- case SolutionKind::Solved:
- break;
- case SolutionKind::Unsolved:
- llvm_unreachable("should have generated constraints");
- }
+
+ auto matchRoot = [&](ConstraintKind kind) -> bool {
+ auto rootMatches = matchTypes(rootTy, kpRootTy, kind,
+ subflags, locator);
+ switch (rootMatches) {
+ case SolutionKind::Error:
+ return false;
+ case SolutionKind::Solved:
+ return true;
+ case SolutionKind::Unsolved:
+ llvm_unreachable("should have generated constraints");
+ }
+ };
if (bgt->getDecl() == getASTContext().getPartialKeyPathDecl()) {
// Read-only keypath, whose projected value is upcast to `Any`.
auto resultTy = ProtocolCompositionType::get(getASTContext(), {},
/*explicit AnyObject*/ false);
+
+ if (!matchRoot(ConstraintKind::Conversion))
+ return SolutionKind::Error;
+
return matchTypes(resultTy, valueTy,
ConstraintKind::Bind, subflags, locator);
}
@@ -4060,6 +4075,7 @@
/// Solve for an rvalue base.
auto solveRValue = [&]() -> ConstraintSystem::SolutionKind {
+ // An rvalue base can be converted to a supertype.
return matchTypes(kpValueTy, valueTy,
ConstraintKind::Bind, subflags, locator);
};
@@ -4076,14 +4092,20 @@
return matchTypes(LValueType::get(kpValueTy), valueTy,
ConstraintKind::Bind, subflags, locator);
};
-
if (bgt->getDecl() == getASTContext().getKeyPathDecl()) {
// Read-only keypath.
+ if (!matchRoot(ConstraintKind::Conversion))
+ return SolutionKind::Error;
+
return solveRValue();
}
if (bgt->getDecl() == getASTContext().getWritableKeyPathDecl()) {
// Writable keypath. The result can be an lvalue if the root was.
+ // We can't convert the base without giving up lvalue-ness, though.
+ if (!matchRoot(ConstraintKind::Equal))
+ return SolutionKind::Error;
+
if (rootTy->is<LValueType>())
return solveLValue();
if (rootTy->isTypeVariableOrMember())
@@ -4092,6 +4114,9 @@
return solveRValue();
}
if (bgt->getDecl() == getASTContext().getReferenceWritableKeyPathDecl()) {
+ if (!matchRoot(ConstraintKind::Conversion))
+ return SolutionKind::Error;
+
// Reference-writable keypath. The result can always be an lvalue.
return solveLValue();
}
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 38d6a0d..882d537 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2205,9 +2205,3 @@
return ctor;
}
-
-void TypeChecker::addImplicitDestructor(ClassDecl *CD) {
- auto *DD = CD->addImplicitDestructor();
- if (DD)
- typeCheckDecl(DD, /*isFirstPass=*/true);
-}
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 39c5ae6..8fbfe3d 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -390,14 +390,12 @@
ConstraintLocatorBuilder locator,
OpenedTypeMap &replacements) {
auto unboundDecl = unbound->getDecl();
- if (unboundDecl->isInvalid())
- return ErrorType::get(getASTContext());
// If the unbound decl hasn't been validated yet, we have a circular
// dependency that isn't being diagnosed properly.
if (!unboundDecl->getGenericSignature()) {
TC.diagnose(unboundDecl, diag::circular_reference);
- return ErrorType::get(unbound);
+ return Type();
}
auto parentTy = unbound->getParent();
@@ -458,7 +456,7 @@
if (!type->hasUnboundGenericType())
return type;
- return type.transform([&](Type type) -> Type {
+ type = type.transform([&](Type type) -> Type {
if (auto unbound = type->getAs<UnboundGenericType>()) {
OpenedTypeMap replacements;
return openUnboundGenericType(unbound, locator, replacements);
@@ -466,6 +464,11 @@
return type;
});
+
+ if (!type)
+ return ErrorType::get(getASTContext());
+
+ return type;
}
Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements) {
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 72124cc..fa3707a 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -671,7 +671,7 @@
FunctionType::ExtInfo());
}
eqDecl->setInterfaceType(interfaceTy);
- copyFormalAccess(eqDecl, typeDecl);
+ eqDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -1090,7 +1090,7 @@
AnyFunctionType::ExtInfo());
getterDecl->setInterfaceType(interfaceType);
- copyFormalAccess(getterDecl, typeDecl);
+ getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -1106,7 +1106,7 @@
hashValueDecl->setInterfaceType(intType);
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
nullptr, nullptr, SourceLoc());
- copyFormalAccess(hashValueDecl, typeDecl);
+ hashValueDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
hashValuePat->setType(intType);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index c3fb22a..853e9ed 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -349,7 +349,7 @@
}
initDecl->setInterfaceType(allocIfaceType);
initDecl->setInitializerInterfaceType(initIfaceType);
- copyFormalAccess(initDecl, enumDecl);
+ initDecl->copyFormalAccessAndVersionedAttrFrom(enumDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 0beaf5f..f2e6d36 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -251,7 +251,7 @@
interfaceType = FunctionType::get({selfParam}, interfaceType,
FunctionType::ExtInfo());
getterDecl->setInterfaceType(interfaceType);
- copyFormalAccess(getterDecl, typeDecl);
+ getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -281,7 +281,7 @@
propDecl->setImplicit();
propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
SourceLoc());
- copyFormalAccess(propDecl, typeDecl);
+ propDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
propDecl->setInterfaceType(propertyInterfaceType);
// If this is supposed to be a final property, mark it as such.
@@ -304,14 +304,3 @@
return {propDecl, pbDecl};
}
-
-void DerivedConformance::copyFormalAccess(ValueDecl *dest, ValueDecl *source) {
- dest->setAccess(source->getFormalAccess());
-
- // Inherit the @_versioned attribute.
- if (source->getAttrs().hasAttribute<VersionedAttr>()) {
- auto &ctx = source->getASTContext();
- auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
- dest->getAttrs().add(clonedAttr);
- }
-}
diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h
index 0e6ab8b..2457971 100644
--- a/lib/Sema/DerivedConformances.h
+++ b/lib/Sema/DerivedConformances.h
@@ -185,9 +185,6 @@
/// Build a reference to the 'self' decl of a derived function.
DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
-/// Copy access from the source decl to the destination decl.
-void copyFormalAccess(ValueDecl *dest, ValueDecl *source);
-
}
}
diff --git a/lib/Sema/InstrumenterSupport.h b/lib/Sema/InstrumenterSupport.h
index dd4e71c..f223617 100644
--- a/lib/Sema/InstrumenterSupport.h
+++ b/lib/Sema/InstrumenterSupport.h
@@ -17,6 +17,8 @@
#include "TypeChecker.h"
+#include "swift/AST/ASTWalker.h"
+
namespace swift {
namespace instrumenter_support {
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 0dbc520..27f2bff 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -1418,7 +1418,15 @@
/// x == nil // also !=
///
void checkOptionalPromotions(ApplyExpr *call) {
- auto DRE = dyn_cast<DeclRefExpr>(call->getSemanticFn());
+ // We only care about binary expressions.
+ if (!isa<BinaryExpr>(call)) return;
+
+ // Dig out the function we're calling.
+ auto fnExpr = call->getSemanticFn();
+ if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(fnExpr))
+ fnExpr = dotSyntax->getSemanticFn();
+
+ auto DRE = dyn_cast<DeclRefExpr>(fnExpr);
auto args = dyn_cast<TupleExpr>(call->getArg());
if (!DRE || !DRE->getDecl()->isOperator() ||
!args || args->getNumElements() != 2)
@@ -3724,21 +3732,12 @@
if (params->size() != 0 && !params->get(0)->getName().empty())
firstParamName = params->get(0)->getName().str();
- // Find the set of property names.
- const InheritedNameSet *allPropertyNames = nullptr;
- if (contextType) {
- if (auto classDecl = contextType->getClassOrBoundGenericClass()) {
- allPropertyNames = Context.getAllPropertyNames(classDecl,
- afd->isInstanceMember());
- }
- }
-
StringScratchSpace scratch;
if (!swift::omitNeedlessWords(baseNameStr, argNameStrs, firstParamName,
getTypeNameForOmission(resultType),
getTypeNameForOmission(contextType),
paramTypes, returnsSelf, false,
- allPropertyNames, scratch))
+ /*allPropertyNames=*/nullptr, scratch))
return None;
/// Retrieve a replacement identifier.
@@ -3790,23 +3789,13 @@
while (auto optObjectTy = type->getAnyOptionalObjectType())
type = optObjectTy;
- // Find the set of property names.
- const InheritedNameSet *allPropertyNames = nullptr;
- if (contextType) {
- if (auto classDecl = contextType->getClassOrBoundGenericClass()) {
- allPropertyNames = Context.getAllPropertyNames(classDecl,
- var->isInstanceMember());
- }
- }
-
-
// Omit needless words.
StringScratchSpace scratch;
OmissionTypeName typeName = getTypeNameForOmission(var->getInterfaceType());
OmissionTypeName contextTypeName = getTypeNameForOmission(contextType);
if (::omitNeedlessWords(name, { }, "", typeName, contextTypeName, { },
- /*returnsSelf=*/false, true, allPropertyNames,
- scratch)) {
+ /*returnsSelf=*/false, true,
+ /*allPropertyNames=*/nullptr, scratch)) {
return Context.getIdentifier(name);
}
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index c10325c..6d70db7 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -79,6 +79,7 @@
IGNORED_ATTR(FixedLayout)
IGNORED_ATTR(Infix)
IGNORED_ATTR(Inline)
+ IGNORED_ATTR(Optimize)
IGNORED_ATTR(Inlineable)
IGNORED_ATTR(NSApplicationMain)
IGNORED_ATTR(NSCopying)
@@ -279,7 +280,9 @@
if (auto *VD = dyn_cast<VarDecl>(D)) {
// Stored properties and variables can't be transparent.
if (VD->hasStorage())
- return diagnoseAndRemoveAttr(attr, diag::transparent_stored_property);
+ return diagnoseAndRemoveAttr(attr,
+ diag::attribute_invalid_on_stored_property,
+ attr->getAttrName());
}
}
@@ -866,7 +869,8 @@
void visitFixedLayoutAttr(FixedLayoutAttr *attr);
void visitVersionedAttr(VersionedAttr *attr);
void visitInlineableAttr(InlineableAttr *attr);
-
+ void visitOptimizeAttr(OptimizeAttr *attr);
+
void visitDiscardableResultAttr(DiscardableResultAttr *attr);
void visitImplementsAttr(ImplementsAttr *attr);
};
@@ -1914,7 +1918,8 @@
if (auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasStorage() || VD->getAttrs().hasAttribute<LazyAttr>()) {
TC.diagnose(attr->getLocation(),
- diag::inlineable_stored_property)
+ diag::attribute_invalid_on_stored_property,
+ attr->getAttrName())
.fixItRemove(attr->getRangeWithAt());
attr->setInvalid();
return;
@@ -1947,6 +1952,19 @@
}
}
+void AttributeChecker::visitOptimizeAttr(OptimizeAttr *attr) {
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasStorage()) {
+ TC.diagnose(attr->getLocation(),
+ diag::attribute_invalid_on_stored_property,
+ attr->getAttrName())
+ .fixItRemove(attr->getRangeWithAt());
+ attr->setInvalid();
+ return;
+ }
+ }
+}
+
void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
if (auto *FD = dyn_cast<FuncDecl>(D)) {
if (auto result = FD->getResultInterfaceType()) {
diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp
index 9a42ad4..3025c13 100644
--- a/lib/Sema/TypeCheckAvailability.cpp
+++ b/lib/Sema/TypeCheckAvailability.cpp
@@ -1499,6 +1499,27 @@
IsUnavailable);
}
+bool TypeChecker::isInsideCompatibleUnavailableDeclaration(
+ SourceRange ReferenceRange, const DeclContext *ReferenceDC,
+ const AvailableAttr *attr) {
+ if (!attr->isUnconditionallyUnavailable()) {
+ return false;
+ }
+ PlatformKind platform = attr->Platform;
+ if (platform == PlatformKind::none) {
+ return false;
+ }
+
+ auto IsUnavailable = [platform](const Decl *D) {
+ auto EnclosingUnavailable =
+ D->getAttrs().getUnavailable(D->getASTContext());
+ return EnclosingUnavailable && EnclosingUnavailable->Platform == platform;
+ };
+
+ return someEnclosingDeclMatches(ReferenceRange, ReferenceDC, *this,
+ IsUnavailable);
+}
+
bool TypeChecker::isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
const DeclContext *ReferenceDC){
auto IsDeprecated = [](const Decl *D) {
@@ -2093,6 +2114,14 @@
return false;
}
+ // Calling unavailable code from within code with the same
+ // unavailability is OK -- the eventual caller can't call the
+ // enclosing code in the same situations it wouldn't be able to
+ // call this code.
+ if (isInsideCompatibleUnavailableDeclaration(R, DC, Attr)) {
+ return false;
+ }
+
SourceLoc Loc = R.Start;
auto Name = D->getFullName();
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 55aa7a8..62f9cb5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2086,16 +2086,34 @@
checkGenericParamAccess(TC, CD->getGenericParams(), CD);
if (CD->hasSuperclass()) {
- Type superclass = CD->getSuperclass();
+ const NominalTypeDecl *superclassDecl =
+ CD->getSuperclass()->getAnyNominal();
+ // Be slightly defensive here in the presence of badly-ordered
+ // inheritance clauses.
auto superclassLocIter = std::find_if(CD->getInherited().begin(),
CD->getInherited().end(),
[&](TypeLoc inherited) {
if (!inherited.wasValidated())
return false;
- return inherited.getType().getPointer() == superclass.getPointer();
+ Type ty = inherited.getType();
+ if (ty->is<ProtocolCompositionType>())
+ ty = ty->getExistentialLayout().superclass;
+ return ty->getAnyNominal() == superclassDecl;
});
+ // Sanity check: we couldn't find the superclass for whatever reason
+ // (possibly because it's synthetic or something), so don't bother
+ // checking it.
if (superclassLocIter == CD->getInherited().end())
return;
+
+ auto outerDowngradeToWarning = DowngradeToWarning::No;
+ if (superclassDecl->isGenericContext() &&
+ !TC.getLangOpts().isSwiftVersionAtLeast(5)) {
+ // Swift 4 failed to properly check this if the superclass was generic,
+ // because the above loop was too strict.
+ outerDowngradeToWarning = DowngradeToWarning::Yes;
+ }
+
checkTypeAccess(TC, *superclassLocIter, CD,
[&](AccessScope typeAccessScope,
const TypeRepr *complainRepr,
@@ -2103,8 +2121,10 @@
auto typeAccess = typeAccessScope.accessLevelForDiagnostics();
bool isExplicit = CD->getAttrs().hasAttribute<AccessControlAttr>();
auto diagID = diag::class_super_access;
- if (downgradeToWarning == DowngradeToWarning::Yes)
+ if (downgradeToWarning == DowngradeToWarning::Yes ||
+ outerDowngradeToWarning == DowngradeToWarning::Yes) {
diagID = diag::class_super_access_warn;
+ }
auto diag = TC.diagnose(CD, diagID, isExplicit, CD->getFormalAccess(),
typeAccess,
isa<FileUnit>(CD->getDeclContext()));
@@ -4618,7 +4638,7 @@
if (!IsFirstPass)
TC.addImplicitConstructors(CD);
- TC.addImplicitDestructor(CD);
+ CD->addImplicitDestructor();
if (!IsFirstPass && !CD->isInvalid())
TC.checkConformancesInContext(CD, CD);
@@ -6361,6 +6381,7 @@
UNINTERESTING_ATTR(IBOutlet)
UNINTERESTING_ATTR(Indirect)
UNINTERESTING_ATTR(Inline)
+ UNINTERESTING_ATTR(Optimize)
UNINTERESTING_ATTR(Inlineable)
UNINTERESTING_ATTR(Effects)
UNINTERESTING_ATTR(FixedLayout)
@@ -7192,13 +7213,7 @@
&& "Decl parsing must prevent destructors outside of types!");
TC.checkDeclAttributesEarly(DD);
- if (!DD->hasAccess()) {
- DD->setAccess(enclosingClass->getFormalAccess());
- }
-
- if (enclosingClass->getAttrs().hasAttribute<VersionedAttr>()) {
- DD->getAttrs().add(new (TC.Context) VersionedAttr(/*implicit=*/true));
- }
+ DD->copyFormalAccessAndVersionedAttrFrom(enclosingClass);
configureImplicitSelf(TC, DD);
@@ -7871,7 +7886,11 @@
}
void TypeChecker::requestClassLayout(ClassDecl *classDecl) {
- // FIXME: Check a flag in the class...
+ if (classDecl->hasValidatedLayout())
+ return;
+
+ classDecl->setHasValidatedLayout();
+
if (isa<SourceFile>(classDecl->getModuleScopeContext()))
DeclsToFinalize.insert(classDecl);
}
@@ -7938,7 +7957,7 @@
// class, you shouldn't have to know what the vtable layout is.
if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
TC.addImplicitConstructors(CD);
- TC.addImplicitDestructor(CD);
+ CD->addImplicitDestructor();
}
// validateDeclForNameLookup will not trigger an immediate full
@@ -8045,9 +8064,6 @@
if (auto unbound = type->getAs<UnboundGenericType>()) {
parentType = unbound->getParent();
nominal = cast<NominalTypeDecl>(unbound->getDecl());
- } else if (auto bound = type->getAs<BoundGenericType>()) {
- parentType = bound->getParent();
- nominal = bound->getDecl();
} else {
auto nominalType = type->castTo<NominalType>();
parentType = nominalType->getParent();
@@ -8140,15 +8156,6 @@
return { env, extContextType };
}
-// FIXME: In TypeChecker.cpp; only needed because LLDB creates
-// extensions of typealiases to unbound generic types, which is
-// ill-formed but convenient.
-namespace swift {
-GenericParamList *cloneGenericParams(ASTContext &ctx,
- DeclContext *dc,
- GenericParamList *fromParams);
-} // namespace swift
-
void TypeChecker::validateExtension(ExtensionDecl *ext) {
// If we're currently validating, or have already validated this extension,
// there's nothing more to do now.
@@ -8176,56 +8183,23 @@
if (auto *classDecl = dyn_cast<ClassDecl>(nominal))
requestClassLayout(classDecl);
- if (extendedType->hasUnboundGenericType()) {
+ if (nominal->getGenericParamsOfContext()) {
auto genericParams = ext->getGenericParams();
-
- // The debugger synthesizes typealiases of unbound generic types
- // to produce its extensions, which subverts bindExtensionDecl's
- // ability to create the generic parameter lists. Create the list now.
- if (!genericParams && Context.LangOpts.DebuggerSupport) {
- genericParams = cloneGenericParams(Context, ext,
- nominal->getGenericParams());
- ext->setGenericParams(genericParams);
- }
assert(genericParams && "bindExtensionDecl didn't set generic params?");
// Check generic parameters.
GenericEnvironment *env;
std::tie(env, extendedType) = checkExtensionGenericParams(
- *this, ext, ext->getExtendedType(), ext->getGenericParams());
+ *this, ext, ext->getExtendedType()->getCanonicalType(),
+ genericParams);
ext->getExtendedTypeLoc().setType(extendedType);
ext->setGenericEnvironment(env);
return;
}
-
- // If we're extending a protocol, check the generic parameters.
- //
- // Canonicalize the type to work around the fact that getAs<> cannot
- // "look through" protocol<X, Y> where X and Y both desugar to the same
- // thing.
- //
- // FIXME: Probably the above comes up elsewhere, perhaps getAs<>()
- // should be fixed.
- if (auto proto = extendedType->getCanonicalType()->getAs<ProtocolType>()) {
- GenericEnvironment *env;
- std::tie(env, extendedType) =
- checkExtensionGenericParams(*this, ext, proto, ext->getGenericParams());
-
- ext->getExtendedTypeLoc().setType(extendedType);
- ext->setGenericEnvironment(env);
- return;
- }
-
- // If the nominal type has a generic signature that we didn't otherwise
- // handle yet, use it directly.
- if (auto genericSig = nominal->getGenericSignature()) {
- auto genericEnv = genericSig->createGenericEnvironment();
- ext->setGenericEnvironment(genericEnv);
- return;
- }
assert(extendedType->is<NominalType>());
+ assert(!nominal->isGenericContext());
}
llvm::TinyPtrVector<ProtocolDecl *>
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index f53508b..0cdbf53 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2348,25 +2348,14 @@
// Replace generic type parameters and associated types with their
// witnesses, when we have them.
auto selfTy = conformance->getProtocol()->getSelfInterfaceType();
- type = type.transform([&](Type type) -> Type {
- // If a dependent member refers to an associated type, replace it.
- if (auto member = type->getAs<DependentMemberType>()) {
- if (member->getBase()->isEqual(selfTy)) {
- // FIXME: Could handle inherited conformances here.
- if (conformance->hasTypeWitness(member->getAssocType()))
- return conformance->getTypeWitness(member->getAssocType(), nullptr);
- }
- }
+ return type.subst([&](SubstitutableType *dependentType) {
+ if (dependentType->isEqual(selfTy))
+ return conformance->getType();
- // Replace 'Self' with the conforming type.
- if (type->isEqual(selfTy))
- return conformance->getType();
-
- return type;
- });
-
- //
- return type;
+ return Type(dependentType);
+ },
+ LookUpConformanceInModule(module),
+ SubstFlags::UseErrorType);
}
/// \brief Retrieve the kind of requirement described by the given declaration,
@@ -6356,6 +6345,24 @@
return false;
}
+/// Determine whether this is an unlabeled initializer or subscript.
+static bool isUnlabeledInitializerOrSubscript(ValueDecl *value) {
+ ParameterList *paramList = nullptr;
+ if (auto constructor = dyn_cast<ConstructorDecl>(value))
+ paramList = constructor->getParameterList(1);
+ else if (auto subscript = dyn_cast<SubscriptDecl>(value))
+ paramList = subscript->getIndices();
+ else
+ return false;
+
+ for (auto param : *paramList) {
+ if (!param->getArgumentName().empty()) return false;
+ }
+
+ return true;
+}
+
+/// Determine whether this declaration is an initializer
/// Determine whether we should warn about the given witness being a close
/// match for the given optional requirement.
static bool shouldWarnAboutPotentialWitness(
@@ -6390,6 +6397,12 @@
if (!attr->isImplicit()) return false;
}
+ // Don't warn if the requirement or witness is an initializer or subscript
+ // with no argument labels.
+ if (isUnlabeledInitializerOrSubscript(req) ||
+ isUnlabeledInitializerOrSubscript(witness))
+ return false;
+
// If the score is relatively high, don't warn: this is probably
// unrelated. Allow about one typo for every four properly-typed
// characters, which prevents completely-wacky suggestions in many
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 9cd8bd7..9aa42f8 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1702,17 +1702,25 @@
TypeResolutionOptions options,
FunctionType::ExtInfo extInfo
= FunctionType::ExtInfo());
- Type resolveSILFunctionType(
- FunctionTypeRepr *repr, TypeResolutionOptions options,
- SILFunctionType::ExtInfo extInfo = SILFunctionType::ExtInfo(),
- ParameterConvention calleeConvention = DefaultParameterConvention,
- TypeRepr *witnessmethodProtocol = nullptr);
+ Type resolveSILFunctionType(FunctionTypeRepr *repr,
+ TypeResolutionOptions options,
+ SILCoroutineKind coroutineKind
+ = SILCoroutineKind::None,
+ SILFunctionType::ExtInfo extInfo
+ = SILFunctionType::ExtInfo(),
+ ParameterConvention calleeConvention
+ = DefaultParameterConvention,
+ TypeRepr *witnessmethodProtocol = nullptr);
SILParameterInfo resolveSILParameter(TypeRepr *repr,
TypeResolutionOptions options);
+ SILYieldInfo resolveSILYield(TypeAttributes &remainingAttrs,
+ TypeRepr *repr, TypeResolutionOptions options);
bool resolveSILResults(TypeRepr *repr, TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &results,
Optional<SILResultInfo> &errorResult);
bool resolveSingleSILResult(TypeRepr *repr, TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &results,
Optional<SILResultInfo> &errorResult);
Type resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
@@ -1970,7 +1978,7 @@
static const TypeAttrKind FunctionAttrs[] = {
TAK_convention, TAK_noreturn, TAK_pseudogeneric,
TAK_callee_owned, TAK_callee_guaranteed, TAK_noescape, TAK_autoclosure,
- TAK_escaping
+ TAK_escaping, TAK_yield_once, TAK_yield_many
};
auto checkUnsupportedAttr = [&](TypeAttrKind attr) {
@@ -2018,6 +2026,13 @@
SILFunctionType::Representation rep;
TypeRepr *witnessMethodProtocol = nullptr;
+ auto coroutineKind = SILCoroutineKind::None;
+ if (attrs.has(TAK_yield_once)) {
+ coroutineKind = SILCoroutineKind::YieldOnce;
+ } else if (attrs.has(TAK_yield_many)) {
+ coroutineKind = SILCoroutineKind::YieldMany;
+ }
+
auto calleeConvention = ParameterConvention::Direct_Unowned;
if (attrs.has(TAK_callee_owned)) {
if (attrs.has(TAK_callee_guaranteed)) {
@@ -2065,7 +2080,8 @@
SILFunctionType::ExtInfo extInfo(rep, attrs.has(TAK_pseudogeneric),
attrs.has(TAK_noescape));
- ty = resolveSILFunctionType(fnRepr, options, extInfo, calleeConvention,
+ ty = resolveSILFunctionType(fnRepr, options, coroutineKind,
+ extInfo, calleeConvention,
witnessMethodProtocol);
if (!ty || ty->hasError()) return ty;
} else if (hasFunctionAttr) {
@@ -2257,6 +2273,11 @@
options -= TR_ImmediateFunctionInput;
options -= TR_FunctionInput;
options -= TR_TypeAliasUnderlyingType;
+ // FIXME: Until we remove the IUO type from the type system, we
+ // need to continue to parse IUOs in SIL tests so that we can
+ // match the types we generate from the importer.
+ if (!options.contains(TR_SILMode))
+ options -= TR_AllowIUO;
Type inputTy = resolveType(repr->getArgsTypeRepr(),
options | TR_ImmediateFunctionInput);
@@ -2424,6 +2445,7 @@
Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr,
TypeResolutionOptions options,
+ SILCoroutineKind coroutineKind,
SILFunctionType::ExtInfo extInfo,
ParameterConvention callee,
TypeRepr *witnessMethodProtocol) {
@@ -2436,6 +2458,7 @@
// Resolve parameter and result types using the function's generic
// environment.
SmallVector<SILParameterInfo, 4> params;
+ SmallVector<SILYieldInfo, 4> yields;
SmallVector<SILResultInfo, 4> results;
Optional<SILResultInfo> errorResult;
{
@@ -2484,10 +2507,17 @@
{
// FIXME: Deal with unsatisfied dependencies.
- if (resolveSILResults(repr->getResultTypeRepr(), options,
+ if (resolveSILResults(repr->getResultTypeRepr(), options, yields,
results, errorResult)) {
hasError = true;
}
+
+ // Diagnose non-coroutines that declare yields.
+ if (coroutineKind == SILCoroutineKind::None && !yields.empty()) {
+ TC.diagnose(repr->getResultTypeRepr()->getLoc(),
+ diag::sil_non_coro_yields);
+ hasError = true;
+ }
}
} // restore generic type resolver
@@ -2498,6 +2528,7 @@
// FIXME: Remap the parsed context types to interface types.
CanGenericSignature genericSig;
SmallVector<SILParameterInfo, 4> interfaceParams;
+ SmallVector<SILYieldInfo, 4> interfaceYields;
SmallVector<SILResultInfo, 4> interfaceResults;
Optional<SILResultInfo> interfaceErrorResult;
if (auto *genericEnv = repr->getGenericEnvironment()) {
@@ -2508,6 +2539,11 @@
param.getType())->getCanonicalType();
interfaceParams.push_back(param.getWithType(transParamType));
}
+ for (auto &yield : yields) {
+ auto transYieldType = genericEnv->mapTypeOutOfContext(
+ yield.getType())->getCanonicalType();
+ interfaceYields.push_back(yield.getWithType(transYieldType));
+ }
for (auto &result : results) {
auto transResultType = genericEnv->mapTypeOutOfContext(
result.getType())->getCanonicalType();
@@ -2522,6 +2558,7 @@
}
} else {
interfaceParams = params;
+ interfaceYields = yields;
interfaceResults = results;
interfaceErrorResult = errorResult;
}
@@ -2552,9 +2589,20 @@
"found witness_method without matching conformance");
}
- return SILFunctionType::get(genericSig, extInfo, callee, interfaceParams,
- interfaceResults, interfaceErrorResult, Context,
- witnessMethodConformance);
+ return SILFunctionType::get(genericSig, extInfo, coroutineKind,
+ callee,
+ interfaceParams, interfaceYields,
+ interfaceResults, interfaceErrorResult,
+ Context, witnessMethodConformance);
+}
+
+SILYieldInfo TypeResolver::resolveSILYield(TypeAttributes &attrs,
+ TypeRepr *repr,
+ TypeResolutionOptions options) {
+ AttributedTypeRepr attrRepr(attrs, repr);
+ SILParameterInfo paramInfo =
+ resolveSILParameter(&attrRepr, options | TR_ImmediateFunctionInput);
+ return SILYieldInfo(paramInfo.getType(), paramInfo.getConvention());
}
SILParameterInfo TypeResolver::resolveSILParameter(
@@ -2568,6 +2616,7 @@
if (auto attrRepr = dyn_cast<AttributedTypeRepr>(repr)) {
auto attrs = attrRepr->getAttrs();
+
auto checkFor = [&](TypeAttrKind tak, ParameterConvention attrConv) {
if (!attrs.has(tak)) return;
if (convention != DefaultParameterConvention) {
@@ -2610,6 +2659,7 @@
bool TypeResolver::resolveSingleSILResult(TypeRepr *repr,
TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &ordinaryResults,
Optional<SILResultInfo> &errorResult) {
Type type;
@@ -2620,6 +2670,19 @@
// Copy the attributes out; we're going to destructively modify them.
auto attrs = attrRepr->getAttrs();
+ // Recognize @yields.
+ if (attrs.has(TypeAttrKind::TAK_yields)) {
+ attrs.clearAttribute(TypeAttrKind::TAK_yields);
+
+ // The treatment from this point on is basically completely different.
+ auto yield = resolveSILYield(attrs, attrRepr->getTypeRepr(), options);
+ if (yield.getType()->hasError())
+ return true;
+
+ yields.push_back(yield);
+ return false;
+ }
+
// Recognize @error.
if (attrs.has(TypeAttrKind::TAK_error)) {
attrs.clearAttribute(TypeAttrKind::TAK_error);
@@ -2687,6 +2750,7 @@
bool TypeResolver::resolveSILResults(TypeRepr *repr,
TypeResolutionOptions options,
+ SmallVectorImpl<SILYieldInfo> &yields,
SmallVectorImpl<SILResultInfo> &ordinaryResults,
Optional<SILResultInfo> &errorResult) {
if (auto tuple = dyn_cast<TupleTypeRepr>(repr)) {
@@ -2696,13 +2760,15 @@
TC.diagnose(element.UnderscoreLoc, diag::sil_function_output_label);
}
for (auto elt : tuple->getElements()) {
- if (resolveSingleSILResult(elt.Type, options, ordinaryResults, errorResult))
+ if (resolveSingleSILResult(elt.Type, options,
+ yields, ordinaryResults, errorResult))
hadError = true;
}
return hadError;
}
- return resolveSingleSILResult(repr, options, ordinaryResults, errorResult);
+ return resolveSingleSILResult(repr, options,
+ yields, ordinaryResults, errorResult);
}
Type TypeResolver::resolveSpecifierTypeRepr(SpecifierTypeRepr *repr,
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index eb3f643..b75df46 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -69,7 +69,7 @@
addImplicitStructConformances(SD);
}
if (auto CD = dyn_cast<ClassDecl>(decl)) {
- addImplicitDestructor(CD);
+ CD->addImplicitDestructor();
}
if (auto ED = dyn_cast<EnumDecl>(decl)) {
addImplicitEnumConformances(ED);
@@ -261,13 +261,11 @@
return *boolType;
}
-namespace swift {
-
/// Clone the given generic parameters in the given list. We don't need any
/// of the requirements, because they will be inferred.
-GenericParamList *cloneGenericParams(ASTContext &ctx,
- DeclContext *dc,
- GenericParamList *fromParams) {
+static GenericParamList *cloneGenericParams(ASTContext &ctx,
+ DeclContext *dc,
+ GenericParamList *fromParams) {
// Clone generic parameters.
SmallVector<GenericTypeParamDecl *, 2> toGenericParams;
for (auto fromGP : *fromParams) {
@@ -292,12 +290,6 @@
return toParams;
}
-} // namespace swift
-
-// FIXME: total hack
-GenericParamList *createProtocolGenericParams(ASTContext &ctx,
- ProtocolDecl *proto,
- DeclContext *dc);
static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
if (ED->getExtendedType())
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index bf862ae..fa1ecae 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -741,12 +741,6 @@
/// will need to compute captures for.
std::vector<AnyFunctionRef> ClosuresWithUncomputedCaptures;
- /// Describes an attempt to capture a local function.
- struct LocalFunctionCapture {
- FuncDecl *LocalFunction;
- SourceLoc CaptureLoc;
- };
-
/// Local functions that have been captured before their definitions.
///
/// We need this to guard against functions that would transitively capture
@@ -1517,10 +1511,6 @@
/// struct or class.
void addImplicitConstructors(NominalTypeDecl *typeDecl);
- /// \brief Add an implicitly-defined destructor, if there is no
- /// user-provided destructor.
- void addImplicitDestructor(ClassDecl *CD);
-
/// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an
/// imported NS_OPTIONS struct.
void addImplicitStructConformances(StructDecl *ED);
@@ -2376,6 +2366,12 @@
bool isInsideUnavailableDeclaration(SourceRange ReferenceRange,
const DeclContext *DC);
+ /// Returns true if the reference or any of its parents is an
+ /// unconditional unavailable declaration for the same platform.
+ bool isInsideCompatibleUnavailableDeclaration(SourceRange ReferenceRange,
+ const DeclContext *DC,
+ const AvailableAttr *attr);
+
/// Returns true if the reference is lexically contained in a declaration
/// that is deprecated on all deployment targets.
bool isInsideDeprecatedDeclaration(SourceRange ReferenceRange,
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index 68890a2..0918a5b 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -439,9 +439,11 @@
unsigned kind = Cursor.readRecord(next.ID, scratch);
switch (kind) {
case decls_block::SIL_LAYOUT: {
+ GenericSignatureID rawGenericSig;
unsigned numFields;
ArrayRef<uint64_t> types;
- decls_block::SILLayoutLayout::readRecord(scratch, numFields, types);
+ decls_block::SILLayoutLayout::readRecord(scratch, rawGenericSig,
+ numFields, types);
SmallVector<SILField, 4> fields;
for (auto fieldInfo : types.slice(0, numFields)) {
@@ -452,20 +454,10 @@
isMutable));
}
- SmallVector<GenericTypeParamType*, 4> genericParams;
- for (auto typeId : types.slice(numFields)) {
- auto type = getType(typeId)->castTo<GenericTypeParamType>();
- genericParams.push_back(type);
- }
-
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
- CanGenericSignature sig;
- if (!genericParams.empty() || !requirements.empty()) {
- sig = GenericSignature::get(genericParams, requirements)
- ->getCanonicalSignature();
- }
- return SILLayout::get(getContext(), sig, fields);
+ CanGenericSignature canSig;
+ if (auto sig = getGenericSignature(rawGenericSig))
+ canSig = sig->getCanonicalSignature();
+ return SILLayout::get(getContext(), canSig, fields);
}
default:
error();
@@ -920,6 +912,68 @@
}
}
+GenericSignature *ModuleFile::getGenericSignature(
+ serialization::GenericSignatureID ID) {
+ using namespace decls_block;
+
+ // Zero is a sentinel for having no generic signature.
+ if (ID == 0) return nullptr;
+
+ assert(ID <= GenericSignatures.size() && "invalid GenericSignature ID");
+ auto &sigOrOffset = GenericSignatures[ID-1];
+
+ // If we've already deserialized this generic signature, return it.
+ if (sigOrOffset.isComplete()) {
+ return sigOrOffset.get();
+ }
+
+ // Read the generic signature.
+ BCOffsetRAII restoreOffset(DeclTypeCursor);
+ DeclTypeCursor.JumpToBit(sigOrOffset);
+ DeserializingEntityRAII deserializingEntity(*this);
+
+ // Read the parameter types.
+ SmallVector<GenericTypeParamType *, 4> paramTypes;
+ StringRef blobData;
+ SmallVector<uint64_t, 8> scratch;
+
+ auto entry = DeclTypeCursor.advance(AF_DontPopBlockAtEnd);
+ if (entry.Kind != llvm::BitstreamEntry::Record) {
+ error();
+ return nullptr;
+ }
+
+ unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
+ if (recordID != GENERIC_SIGNATURE) {
+ error();
+ return nullptr;
+ }
+
+ ArrayRef<uint64_t> rawParamIDs;
+ GenericSignatureLayout::readRecord(scratch, rawParamIDs);
+
+ for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
+ auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
+ paramTypes.push_back(paramTy);
+ }
+
+ // Read the generic requirements.
+ SmallVector<Requirement, 4> requirements;
+ readGenericRequirements(requirements, DeclTypeCursor);
+
+ // Construct the generic signature from the loaded parameters and
+ // requirements.
+ auto signature = GenericSignature::get(paramTypes, requirements);
+
+ // If we've already deserialized this generic signature, return it.
+ if (sigOrOffset.isComplete()) {
+ return sigOrOffset.get();
+ }
+
+ sigOrOffset = signature;
+ return signature;
+}
+
llvm::PointerUnion<GenericSignature *, GenericEnvironment *>
ModuleFile::getGenericSignatureOrEnvironment(
serialization::GenericEnvironmentID ID,
@@ -940,13 +994,21 @@
return envOrOffset.get();
}
- // Read the generic environment.
- BCOffsetRAII restoreOffset(DeclTypeCursor);
- DeclTypeCursor.JumpToBit(envOrOffset);
- DeserializingEntityRAII deserializingEntity(*this);
+ // Extract the bit offset or generic signature ID.
+ uint64_t bitOffset = envOrOffset;
+ GenericSignature *signature = nullptr;
+ if (bitOffset & 0x01) {
+ // We have a generic signature ID.
+ signature = getGenericSignature(bitOffset >> 1);
+ } else {
+ bitOffset = bitOffset >> 1;
- SmallVector<GenericTypeParamType *, 4> paramTypes;
- {
+ // Read the generic environment.
+ BCOffsetRAII restoreOffset(DeclTypeCursor);
+ DeclTypeCursor.JumpToBit(bitOffset);
+ DeserializingEntityRAII deserializingEntity(*this);
+
+ SmallVector<GenericTypeParamType *, 4> paramTypes;
using namespace decls_block;
StringRef blobData;
@@ -963,72 +1025,55 @@
return result;
unsigned recordID = DeclTypeCursor.readRecord(entry.ID, scratch, &blobData);
- switch (recordID) {
- case GENERIC_ENVIRONMENT: {
- lastRecordOffset.reset();
-
- ArrayRef<uint64_t> rawParamIDs;
- GenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
-
- for (unsigned i = 0, n = rawParamIDs.size(); i != n; ++i) {
- auto paramTy = getType(rawParamIDs[i])->castTo<GenericTypeParamType>();
- paramTypes.push_back(paramTy);
- }
- break;
- }
-
- case SIL_GENERIC_ENVIRONMENT: {
- ArrayRef<uint64_t> rawParamIDs;
- SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
- lastRecordOffset.reset();
-
- if (rawParamIDs.size() % 2 != 0) {
- error();
- return result;
- }
-
- for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
- Identifier name = getIdentifier(rawParamIDs[i]);
- auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();
-
- if (!name.empty()) {
- auto paramDecl =
- createDecl<GenericTypeParamDecl>(getAssociatedModule(),
- name,
- SourceLoc(),
- paramTy->getDepth(),
- paramTy->getIndex());
- paramTy = paramDecl->getDeclaredInterfaceType()
- ->castTo<GenericTypeParamType>();
- }
-
- paramTypes.push_back(paramTy);
- }
- break;
- }
-
- default:
+ if (recordID != SIL_GENERIC_ENVIRONMENT) {
error();
return result;
}
+
+ ArrayRef<uint64_t> rawParamIDs;
+ SILGenericEnvironmentLayout::readRecord(scratch, rawParamIDs);
+ lastRecordOffset.reset();
+
+ if (rawParamIDs.size() % 2 != 0) {
+ error();
+ return result;
+ }
+
+ for (unsigned i = 0, n = rawParamIDs.size(); i != n; i += 2) {
+ Identifier name = getIdentifier(rawParamIDs[i]);
+ auto paramTy = getType(rawParamIDs[i+1])->castTo<GenericTypeParamType>();
+
+ if (!name.empty()) {
+ auto paramDecl =
+ createDecl<GenericTypeParamDecl>(getAssociatedModule(),
+ name,
+ SourceLoc(),
+ paramTy->getDepth(),
+ paramTy->getIndex());
+ paramTy = paramDecl->getDeclaredInterfaceType()
+ ->castTo<GenericTypeParamType>();
+ }
+
+ paramTypes.push_back(paramTy);
+ }
+
+ // If there are no parameters, the environment is empty.
+ if (paramTypes.empty()) {
+ if (wantEnvironment)
+ envOrOffset = nullptr;
+
+ return result;
+ }
+
+ // Read the generic requirements.
+ SmallVector<Requirement, 4> requirements;
+ readGenericRequirements(requirements, DeclTypeCursor);
+
+ // Construct the generic signature from the loaded parameters and
+ // requirements.
+ signature = GenericSignature::get(paramTypes, requirements);
}
- // If there are no parameters, the environment is empty.
- if (paramTypes.empty()) {
- if (wantEnvironment)
- envOrOffset = nullptr;
-
- return result;
- }
-
- // Read the generic requirements.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
-
- // Construct the generic signature from the loaded parameters and
- // requirements.
- auto signature = GenericSignature::get(paramTypes, requirements);
-
// If we only want the signature, return it now.
if (!wantEnvironment) return signature;
@@ -1232,9 +1277,18 @@
DeclBaseName name = getDeclBaseName(IID);
pathTrace.addValue(name);
- Type filterTy = getType(TID);
- if (!isType)
+ Type filterTy;
+ if (!isType) {
+ auto maybeType = getTypeChecked(TID);
+ if (!maybeType) {
+ // FIXME: Don't throw away the inner error's information.
+ llvm::consumeError(maybeType.takeError());
+ return llvm::make_error<XRefError>("couldn't decode type",
+ pathTrace, name);
+ }
+ filterTy = maybeType.get();
pathTrace.addType(filterTy);
+ }
baseModule->lookupQualified(ModuleType::get(baseModule), name,
NL_QualifiedDefault | NL_KnownNoDependency,
@@ -1437,9 +1491,18 @@
pathTrace.addValue(memberName);
- Type filterTy = getType(TID);
- if (!isType)
+ Type filterTy;
+ if (!isType) {
+ auto maybeType = getTypeChecked(TID);
+ if (!maybeType) {
+ // FIXME: Don't throw away the inner error's information.
+ llvm::consumeError(maybeType.takeError());
+ return llvm::make_error<XRefError>("couldn't decode type",
+ pathTrace, memberName);
+ }
+ filterTy = maybeType.get();
pathTrace.addType(filterTy);
+ }
if (values.size() != 1) {
return llvm::make_error<XRefError>("multiple matching base values",
@@ -1465,23 +1528,13 @@
case XREF_EXTENSION_PATH_PIECE: {
ModuleID ownerID;
- ArrayRef<uint64_t> genericParamIDs;
- XRefExtensionPathPieceLayout::readRecord(scratch, ownerID,
- genericParamIDs);
+ GenericSignatureID rawGenericSig;
+ XRefExtensionPathPieceLayout::readRecord(scratch, ownerID, rawGenericSig);
M = getModule(ownerID);
pathTrace.addExtension(M);
// Read the generic signature, if we have one.
- if (!genericParamIDs.empty()) {
- SmallVector<GenericTypeParamType *, 4> params;
- SmallVector<Requirement, 5> requirements;
- for (TypeID paramID : genericParamIDs) {
- params.push_back(getType(paramID)->castTo<GenericTypeParamType>());
- }
- readGenericRequirements(requirements, DeclTypeCursor);
-
- genericSig = GenericSignature::getCanonical(params, requirements);
- }
+ genericSig = CanGenericSignature(getGenericSignature(rawGenericSig));
continue;
}
@@ -2113,7 +2166,10 @@
Expected<Decl *> deserialized = getDeclCheckedImpl(DID, ForcedContext);
if (deserialized && deserialized.get()) {
if (auto *IDC = dyn_cast<IterableDeclContext>(deserialized.get())) {
- if (IDC->wasDeserialized()) {
+ // Only set the DeclID on the returned Decl if it's one that was loaded
+ // and _wasn't_ one that had its DeclID set elsewhere (a followed XREF).
+ if (IDC->wasDeserialized() &&
+ static_cast<uint32_t>(IDC->getDeclID()) == 0) {
IDC->setDeclID(DID);
}
}
@@ -2280,6 +2336,14 @@
break;
}
+ case decls_block::Optimize_DECL_ATTR: {
+ unsigned kind;
+ serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
+ scratch, kind);
+ Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
+ break;
+ }
+
case decls_block::Effects_DECL_ATTR: {
unsigned kind;
serialization::decls_block::EffectsDeclAttrLayout::readRecord(scratch,
@@ -3771,6 +3835,26 @@
}
}
+/// Translate from the Serialization coroutine kind enum values to the AST
+/// strongly-typed enum.
+///
+/// The former is guaranteed to be stable, but may not reflect this version of
+/// the AST.
+static Optional<swift::SILCoroutineKind>
+getActualSILCoroutineKind(uint8_t rep) {
+ switch (rep) {
+#define CASE(KIND) \
+ case (uint8_t)serialization::SILCoroutineKind::KIND: \
+ return swift::SILCoroutineKind::KIND;
+ CASE(None)
+ CASE(YieldOnce)
+ CASE(YieldMany)
+#undef CASE
+ default:
+ return None;
+ }
+}
+
/// Translate from the serialization Ownership enumerators, which are
/// guaranteed to be stable, to the AST ones.
static
@@ -4248,40 +4332,23 @@
TypeID resultID;
uint8_t rawRep;
bool throws = false;
- ArrayRef<uint64_t> genericParamIDs;
+ GenericSignatureID rawGenericSig;
decls_block::GenericFunctionTypeLayout::readRecord(scratch,
inputID,
resultID,
rawRep,
throws,
- genericParamIDs);
+ rawGenericSig);
auto rep = getActualFunctionTypeRepresentation(rawRep);
if (!rep.hasValue()) {
error();
return nullptr;
}
- // Read the generic parameters.
- SmallVector<GenericTypeParamType *, 4> genericParams;
- for (auto paramID : genericParamIDs) {
- auto param = dyn_cast_or_null<GenericTypeParamType>(
- getType(paramID).getPointer());
- if (!param) {
- error();
- break;
- }
-
- genericParams.push_back(param);
- }
-
- // Read the generic requirements.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
+ auto sig = getGenericSignature(rawGenericSig);
auto info = GenericFunctionType::ExtInfo(*rep, throws);
-
- auto sig = GenericSignature::get(genericParams, requirements);
-
+
auto inputTy = getTypeChecked(inputID);
if (!inputTy)
return inputTy.takeError();
@@ -4354,23 +4421,29 @@
}
case decls_block::SIL_FUNCTION_TYPE: {
+ uint8_t rawCoroutineKind;
uint8_t rawCalleeConvention;
uint8_t rawRepresentation;
bool pseudogeneric = false;
bool noescape;
bool hasErrorResult;
unsigned numParams;
+ unsigned numYields;
unsigned numResults;
+ GenericSignatureID rawGenericSig;
ArrayRef<uint64_t> variableData;
decls_block::SILFunctionTypeLayout::readRecord(scratch,
+ rawCoroutineKind,
rawCalleeConvention,
rawRepresentation,
pseudogeneric,
noescape,
hasErrorResult,
numParams,
+ numYields,
numResults,
+ rawGenericSig,
variableData);
// Process the ExtInfo.
@@ -4382,6 +4455,13 @@
}
SILFunctionType::ExtInfo extInfo(*representation, pseudogeneric, noescape);
+ // Process the coroutine kind.
+ auto coroutineKind = getActualSILCoroutineKind(rawCoroutineKind);
+ if (!coroutineKind.hasValue()) {
+ error();
+ return nullptr;
+ }
+
// Process the callee convention.
auto calleeConvention = getActualParameterConvention(rawCalleeConvention);
if (!calleeConvention.hasValue()) {
@@ -4397,6 +4477,14 @@
return SILParameterInfo(type->getCanonicalType(), *convention);
};
+ auto processYield = [&](TypeID typeID, uint64_t rawConvention)
+ -> Optional<SILYieldInfo> {
+ auto convention = getActualParameterConvention(rawConvention);
+ auto type = getType(typeID);
+ if (!convention || !type) return None;
+ return SILYieldInfo(type->getCanonicalType(), *convention);
+ };
+
auto processResult = [&](TypeID typeID, uint64_t rawConvention)
-> Optional<SILResultInfo> {
auto convention = getActualResultConvention(rawConvention);
@@ -4428,6 +4516,20 @@
allParams.push_back(*param);
}
+ // Process the yields.
+ SmallVector<SILYieldInfo, 8> allYields;
+ allYields.reserve(numYields);
+ for (unsigned i = 0; i != numYields; ++i) {
+ auto typeID = variableData[nextVariableDataIndex++];
+ auto rawConvention = variableData[nextVariableDataIndex++];
+ auto yield = processYield(typeID, rawConvention);
+ if (!yield) {
+ error();
+ return nullptr;
+ }
+ allYields.push_back(*yield);
+ }
+
// Process the results.
SmallVector<SILResultInfo, 8> allResults;
allParams.reserve(numResults);
@@ -4454,30 +4556,19 @@
}
}
- // Process the generic signature parameters.
- SmallVector<GenericTypeParamType *, 8> genericParamTypes;
- for (auto id : variableData.slice(nextVariableDataIndex)) {
- genericParamTypes.push_back(
- cast<GenericTypeParamType>(getType(id)->getCanonicalType()));
- }
-
Optional<ProtocolConformanceRef> witnessMethodConformance;
if (*representation == SILFunctionTypeRepresentation::WitnessMethod) {
witnessMethodConformance = readConformance(DeclTypeCursor);
}
- // Read the generic requirements, if any.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
+ GenericSignature *genericSig = getGenericSignature(rawGenericSig);
- GenericSignature *genericSig = nullptr;
- if (!genericParamTypes.empty() || !requirements.empty())
- genericSig = GenericSignature::get(genericParamTypes, requirements,
- /*isKnownCanonical=*/true);
-
- typeOrOffset = SILFunctionType::get(
- genericSig, extInfo, calleeConvention.getValue(), allParams, allResults,
- errorResult, ctx, witnessMethodConformance);
+ typeOrOffset = SILFunctionType::get(genericSig, extInfo,
+ coroutineKind.getValue(),
+ calleeConvention.getValue(),
+ allParams, allYields, allResults,
+ errorResult,
+ ctx, witnessMethodConformance);
break;
}
@@ -4891,21 +4982,7 @@
// Requirement -> synthetic map.
SmallVector<Substitution, 4> reqToSyntheticSubs;
- if (unsigned numGenericParams = *rawIDIter++) {
- // Generic parameters of the synthetic environment.
- SmallVector<GenericTypeParamType *, 2> genericParams;
- while (numGenericParams--) {
- genericParams.push_back(
- getType(*rawIDIter++)->castTo<GenericTypeParamType>());
- }
-
- // Generic requirements of the synthetic environment.
- SmallVector<Requirement, 4> requirements;
- readGenericRequirements(requirements, DeclTypeCursor);
-
- // Form the generic signature for the synthetic environment.
- syntheticSig = GenericSignature::get(genericParams, requirements);
-
+ if (auto syntheticSig = getGenericSignature(*rawIDIter++)) {
// Create the synthetic environment.
syntheticEnv = syntheticSig->createGenericEnvironment();
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index fcdcb48..d8e587f 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -407,11 +407,12 @@
TypeID funcTyID;
GenericEnvironmentID genericEnvID;
unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
- inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
+ inlineStrategy, optimizationMode, effect, numSpecAttrs,
+ hasQualifiedOwnership;
ArrayRef<uint64_t> SemanticsIDs;
- // TODO: read fragile
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
- isThunk, isGlobal, inlineStrategy, effect,
+ isThunk, isGlobal, inlineStrategy,
+ optimizationMode, effect,
numSpecAttrs, hasQualifiedOwnership, funcTyID,
genericEnvID, clangNodeOwnerID, SemanticsIDs);
@@ -475,6 +476,7 @@
SubclassScope::NotApplicable, (Inline_t)inlineStrategy);
fn->setGlobalInit(isGlobal == 1);
fn->setEffectsKind((EffectsKind)effect);
+ fn->setOptimizationMode((OptimizationMode)optimizationMode);
if (clangNodeOwner)
fn->setClangNodeOwner(clangNodeOwner);
for (auto ID : SemanticsIDs) {
@@ -710,7 +712,7 @@
(SILDeclRef::Kind)ListOfValues[NextIdx+1],
(swift::ResilienceExpansion)ListOfValues[NextIdx+2],
/*isCurried=*/false, ListOfValues[NextIdx+4] > 0);
- if (ListOfValues[NextIdx+3] < DRef.getUncurryLevel())
+ if (ListOfValues[NextIdx+3] < DRef.getParameterListCount() - 1)
DRef = DRef.asCurried();
NextIdx += 5;
return DRef;
@@ -806,6 +808,13 @@
RawOpCode = (unsigned)SILInstructionKind::ApplyInst;
IsNonThrowingApply = true;
break;
+ case SIL_BEGIN_APPLY:
+ RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst;
+ break;
+ case SIL_NON_THROWING_BEGIN_APPLY:
+ RawOpCode = (unsigned)SILInstructionKind::BeginApplyInst;
+ IsNonThrowingApply = true;
+ break;
default:
llvm_unreachable("unexpected apply inst kind");
@@ -1067,7 +1076,8 @@
}
break;
}
- case SILInstructionKind::ApplyInst: {
+ case SILInstructionKind::ApplyInst:
+ case SILInstructionKind::BeginApplyInst: {
// Format: attributes such as transparent, the callee's type, a value for
// the callee and a list of values for the arguments. Each value in the list
// is represented with 2 IDs: ValueID and ValueResultNumber.
@@ -1092,9 +1102,15 @@
Substitutions.push_back(*sub);
}
- ResultVal = Builder.createApply(Loc, getLocalValue(ValID, FnTy),
- Substitutions, Args,
- IsNonThrowingApply != 0);
+ if (OpCode == SILInstructionKind::ApplyInst) {
+ ResultVal = Builder.createApply(Loc, getLocalValue(ValID, FnTy),
+ Substitutions, Args,
+ IsNonThrowingApply != 0);
+ } else {
+ ResultVal = Builder.createBeginApply(Loc, getLocalValue(ValID, FnTy),
+ Substitutions, Args,
+ IsNonThrowingApply != 0);
+ }
break;
}
case SILInstructionKind::TryApplyInst: {
@@ -1417,6 +1433,8 @@
REFCOUNTING_INSTRUCTION(UnownedRelease)
UNARY_INSTRUCTION(IsUnique)
UNARY_INSTRUCTION(IsUniqueOrPinned)
+ UNARY_INSTRUCTION(AbortApply)
+ UNARY_INSTRUCTION(EndApply)
#undef UNARY_INSTRUCTION
#undef REFCOUNTING_INSTRUCTION
@@ -2112,6 +2130,27 @@
ResultVal = Builder.createUnreachable(Loc);
break;
}
+ case SILInstructionKind::UnwindInst: {
+ ResultVal = Builder.createUnwind(Loc);
+ break;
+ }
+ case SILInstructionKind::YieldInst: {
+ SILBasicBlock *unwindBB = getBBForReference(Fn, ListOfValues.back());
+ ListOfValues = ListOfValues.drop_back();
+ SILBasicBlock *resumeBB = getBBForReference(Fn, ListOfValues.back());
+ ListOfValues = ListOfValues.drop_back();
+
+ SmallVector<SILValue, 4> yieldedValues;
+ for (unsigned I = 0, E = ListOfValues.size(); I < E; I += 3) {
+ auto valueTy = MF->getType(ListOfValues[I]);
+ auto valueCategory = (SILValueCategory) ListOfValues[I+1];
+ yieldedValues.push_back(
+ getLocalValue(ListOfValues[I+2], getSILType(valueTy, valueCategory)));
+ }
+
+ ResultVal = Builder.createYield(Loc, yieldedValues, resumeBB, unwindBB);
+ break;
+ }
case SILInstructionKind::KeyPathInst: {
unsigned nextValue = 0;
SILType kpTy
@@ -2337,10 +2376,12 @@
TypeID funcTyID;
GenericEnvironmentID genericEnvID;
unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
- inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
+ inlineStrategy, optimizationMode, effect, numSpecAttrs,
+ hasQualifiedOwnership;
ArrayRef<uint64_t> SemanticsIDs;
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
- isThunk, isGlobal, inlineStrategy, effect,
+ isThunk, isGlobal, inlineStrategy,
+ optimizationMode, effect,
numSpecAttrs, hasQualifiedOwnership, funcTyID,
genericEnvID, clangOwnerID, SemanticsIDs);
auto linkage = fromStableSILLinkage(rawLinkage);
@@ -2465,13 +2506,8 @@
auto DI = FuncTable->find(*KI);
assert(DI != FuncTable->end() && "There should never be a key without data.");
- SILFunction *fn = readSILFunction(*DI, nullptr, *KI, false,
- false/*errorIfEmptyBody*/);
-
- // Update linkage for global addressors to make it pass verifier.
- if (fn && fn->isGlobalInit() && fn->isExternalDeclaration() &&
- fn->getLinkage() == SILLinkage::Public)
- fn->setLinkage(SILLinkage::PublicExternal);
+ readSILFunction(*DI, nullptr, *KI, false,
+ false/*errorIfEmptyBody*/);
}
}
@@ -2667,6 +2703,8 @@
kind = SILCursor.readRecord(entry.ID, scratch);
std::vector<SILWitnessTable::Entry> witnessEntries;
+ std::vector<SILWitnessTable::ConditionalConformance> conditionalConformances;
+
// Another record means the end of this WitnessTable.
while (kind != SIL_WITNESS_TABLE &&
kind != SIL_DEFAULT_WITNESS_TABLE &&
@@ -2697,9 +2735,7 @@
witnessEntries.push_back(SILWitnessTable::AssociatedTypeWitness{
assoc, MF->getType(tyId)->getCanonicalType()
});
- } else {
- assert(kind == SIL_WITNESS_METHOD_ENTRY &&
- "Content of WitnessTable should be in SIL_WITNESS_METHOD_ENTRY.");
+ } else if (kind == SIL_WITNESS_METHOD_ENTRY) {
ArrayRef<uint64_t> ListOfValues;
DeclID NameID;
WitnessMethodEntryLayout::readRecord(scratch, NameID, ListOfValues);
@@ -2713,6 +2749,16 @@
getSILDeclRef(MF, ListOfValues, NextValueIndex), Func
});
}
+ } else {
+ assert(kind == SIL_WITNESS_CONDITIONAL_CONFORMANCE &&
+ "Content of WitnessTable should be in "
+ "SIL_WITNESS_CONDITIONAL_CONFORMANCE.");
+ TypeID assocId;
+ WitnessConditionalConformanceLayout::readRecord(scratch, assocId);
+ CanType type = MF->getType(assocId)->getCanonicalType();
+ auto conformance = MF->readConformance(SILCursor);
+ conditionalConformances.push_back(
+ SILWitnessTable::ConditionalConformance{type, conformance});
}
// Fetch the next record.
@@ -2724,7 +2770,7 @@
kind = SILCursor.readRecord(entry.ID, scratch);
}
- wT->convertToDefinition(witnessEntries,
+ wT->convertToDefinition(witnessEntries, conditionalConformances,
Serialized ? IsSerialized : IsNotSerialized);
wTableOrOffset.set(wT, /*fully deserialized*/ true);
if (Callback)
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index 94c42c2..a9b83c7 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -16,6 +16,7 @@
#include "swift/Subsystems.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTMangler.h"
+#include "swift/AST/GenericSignature.h"
#include "swift/AST/ModuleLoader.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/USRGeneration.h"
@@ -842,6 +843,10 @@
assert(blobData.empty());
LocalDeclContexts.assign(scratch.begin(), scratch.end());
break;
+ case index_block::GENERIC_SIGNATURE_OFFSETS:
+ assert(blobData.empty());
+ GenericSignatures.assign(scratch.begin(), scratch.end());
+ break;
case index_block::GENERIC_ENVIRONMENT_OFFSETS:
assert(blobData.empty());
GenericEnvironments.assign(scratch.begin(), scratch.end());
@@ -2170,6 +2175,17 @@
return File.Bits.HasEntryPoint;
}
+bool SerializedASTFile::getAllGenericSignatures(
+ SmallVectorImpl<GenericSignature*> &genericSignatures) {
+ genericSignatures.clear();
+ for (unsigned index : indices(File.GenericSignatures)) {
+ if (auto genericSig = File.getGenericSignature(index + 1))
+ genericSignatures.push_back(genericSig);
+ }
+
+ return true;
+}
+
ClassDecl *SerializedASTFile::getMainClass() const {
assert(hasEntryPoint());
return cast_or_null<ClassDecl>(File.getDecl(File.Bits.EntryPointDeclID));
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 827a2a3..55267a5 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -159,6 +159,7 @@
SIL_WITNESS_BASE_ENTRY,
SIL_WITNESS_ASSOC_PROTOCOL,
SIL_WITNESS_ASSOC_ENTRY,
+ SIL_WITNESS_CONDITIONAL_CONFORMANCE,
SIL_DEFAULT_WITNESS_TABLE,
SIL_DEFAULT_WITNESS_TABLE_ENTRY,
SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY,
@@ -234,6 +235,12 @@
TypeIDField
>;
+ using WitnessConditionalConformanceLayout = BCRecordLayout<
+ SIL_WITNESS_CONDITIONAL_CONFORMANCE,
+ TypeIDField // ID of associated type
+ // Trailed by the conformance itself if appropriate.
+ >;
+
using DefaultWitnessTableLayout = BCRecordLayout<
SIL_DEFAULT_WITNESS_TABLE,
DeclIDField, // ID of ProtocolDecl
@@ -268,6 +275,7 @@
BCFixed<2>, // thunk/reabstraction_thunk
BCFixed<1>, // global_init
BCFixed<2>, // inlineStrategy
+ BCFixed<2>, // optimizationMode
BCFixed<2>, // side effect info.
BCVBR<8>, // number of specialize attributes
BCFixed<1>, // has qualified ownership
@@ -355,7 +363,9 @@
SIL_PARTIAL_APPLY,
SIL_BUILTIN,
SIL_TRY_APPLY,
- SIL_NON_THROWING_APPLY
+ SIL_NON_THROWING_APPLY,
+ SIL_BEGIN_APPLY,
+ SIL_NON_THROWING_BEGIN_APPLY
};
using SILInstApplyLayout = BCRecordLayout<
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 524bc75..333ab8f 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -531,6 +531,19 @@
return id;
}
+GenericSignatureID Serializer::addGenericSignatureRef(
+ const GenericSignature *env) {
+ if (!env) return 0;
+
+ auto &id = GenericSignatureIDs[env];
+ if (id != 0)
+ return id;
+
+ id = ++LastGenericSignatureID;
+ GenericSignaturesToWrite.push(env);
+ return id;
+}
+
GenericEnvironmentID Serializer::addGenericEnvironmentRef(
const GenericEnvironment *env) {
if (!env) return 0;
@@ -759,10 +772,10 @@
BLOCK_RECORD(index_block, OBJC_METHODS);
BLOCK_RECORD(index_block, ENTRY_POINT);
BLOCK_RECORD(index_block, LOCAL_DECL_CONTEXT_OFFSETS);
+ BLOCK_RECORD(index_block, GENERIC_SIGNATURE_OFFSETS);
BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
BLOCK_RECORD(index_block, DECL_CONTEXT_OFFSETS);
BLOCK_RECORD(index_block, LOCAL_TYPE_DECLS);
- BLOCK_RECORD(index_block, GENERIC_ENVIRONMENT_OFFSETS);
BLOCK_RECORD(index_block, NORMAL_CONFORMANCE_OFFSETS);
BLOCK_RECORD(index_block, SIL_LAYOUT_OFFSETS);
BLOCK_RECORD(index_block, PRECEDENCE_GROUPS);
@@ -794,6 +807,7 @@
BLOCK_RECORD(sil_block, SIL_WITNESS_BASE_ENTRY);
BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_PROTOCOL);
BLOCK_RECORD(sil_block, SIL_WITNESS_ASSOC_ENTRY);
+ BLOCK_RECORD(sil_block, SIL_WITNESS_CONDITIONAL_CONFORMANCE);
BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE);
BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE_ENTRY);
BLOCK_RECORD(sil_block, SIL_DEFAULT_WITNESS_TABLE_NO_ENTRY);
@@ -1349,6 +1363,31 @@
return true;
}
+void Serializer::writeGenericSignature(const GenericSignature *sig) {
+ using namespace decls_block;
+
+ // Record the offset of this generic environment.
+ auto id = GenericSignatureIDs[sig];
+ assert(id != 0 && "generic signature not referenced properly");
+ (void)id;
+
+ assert((id - 1) == GenericSignatureOffsets.size());
+ GenericSignatureOffsets.push_back(Out.GetCurrentBitNo());
+
+ assert(sig != nullptr);
+
+ // Record the generic parameters.
+ SmallVector<uint64_t, 4> rawParamIDs;
+ for (auto *paramTy : sig->getGenericParams()) {
+ rawParamIDs.push_back(addTypeRef(paramTy));
+ }
+
+ auto abbrCode = DeclTypeAbbrCodes[GenericSignatureLayout::Code];
+ GenericSignatureLayout::emitRecord(Out, ScratchRecord, abbrCode, rawParamIDs);
+
+ writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
+}
+
void Serializer::writeGenericEnvironment(const GenericEnvironment *env) {
using namespace decls_block;
@@ -1358,10 +1397,7 @@
(void)id;
assert((id - 1) == GenericEnvironmentOffsets.size());
- GenericEnvironmentOffsets.push_back(Out.GetCurrentBitNo());
-
- if (env == nullptr)
- return;
+ assert(env != nullptr);
// Determine whether we must use SIL mode, because one of the generic
// parameters has a declaration with module context.
@@ -1375,33 +1411,36 @@
}
}
+ // If not in SIL mode, generic environments just contain a reference to
+ // the generic signature.
+ if (!SILMode) {
+ // Record the generic signature directly.
+ auto genericSigID = addGenericSignatureRef(env->getGenericSignature());
+ GenericEnvironmentOffsets.push_back((genericSigID << 1) | 0x01);
+ return;
+ }
+
+ // Record the current bit.
+ GenericEnvironmentOffsets.push_back((Out.GetCurrentBitNo() << 1));
+
// Record the generic parameters.
SmallVector<uint64_t, 4> rawParamIDs;
for (auto *paramTy : env->getGenericParams()) {
auto *decl = paramTy->getDecl();
// In SIL mode, add the name and canonicalize the parameter type.
- if (SILMode) {
- if (decl)
- rawParamIDs.push_back(addDeclBaseNameRef(decl->getName()));
- else
- rawParamIDs.push_back(addDeclBaseNameRef(Identifier()));
+ if (decl)
+ rawParamIDs.push_back(addDeclBaseNameRef(decl->getName()));
+ else
+ rawParamIDs.push_back(addDeclBaseNameRef(Identifier()));
- paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
- }
-
+ paramTy = paramTy->getCanonicalType()->castTo<GenericTypeParamType>();
rawParamIDs.push_back(addTypeRef(paramTy));
}
- if (SILMode) {
- auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
- SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
- rawParamIDs);
- } else {
- auto envAbbrCode = DeclTypeAbbrCodes[GenericEnvironmentLayout::Code];
- GenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
- rawParamIDs);
- }
+ auto envAbbrCode = DeclTypeAbbrCodes[SILGenericEnvironmentLayout::Code];
+ SILGenericEnvironmentLayout::emitRecord(Out, ScratchRecord, envAbbrCode,
+ rawParamIDs);
writeGenericRequirements(env->getGenericSignature()->getRequirements(),
DeclTypeAbbrCodes);
@@ -1425,22 +1464,14 @@
data.push_back(typeRef);
}
- // Save generic params.
- if (auto sig = layout->getGenericSignature()) {
- for (auto param : sig->getGenericParams()) {
- data.push_back(addTypeRef(param));
- }
- }
-
unsigned abbrCode
= DeclTypeAbbrCodes[SILLayoutLayout::Code];
- SILLayoutLayout::emitRecord(Out, ScratchRecord, abbrCode,
- layout->getFields().size(),
- data);
- // Emit requirements.
- if (auto sig = layout->getGenericSignature())
- writeGenericRequirements(sig->getRequirements(), DeclTypeAbbrCodes);
+ SILLayoutLayout::emitRecord(
+ Out, ScratchRecord, abbrCode,
+ addGenericSignatureRef(layout->getGenericSignature()),
+ layout->getFields().size(),
+ data);
}
void Serializer::writeNormalConformance(
@@ -1477,19 +1508,14 @@
if (auto genericEnv = witness.requiresSubstitution()
? witness.getSyntheticEnvironment()
: nullptr) {
+ // Generic signature.
auto *genericSig = genericEnv->getGenericSignature();
-
- // Generic parameters.
- data.push_back(genericSig->getGenericParams().size());
- for (auto gp : genericSig->getGenericParams())
- data.push_back(addTypeRef(gp));
+ data.push_back(addGenericSignatureRef(genericSig));
auto reqToSyntheticSubs = witness.getRequirementToSyntheticSubs();
data.push_back(reqToSyntheticSubs.size());
-
- // Requirements come at the end.
} else {
- data.push_back(/*number of generic parameters*/0);
+ data.push_back(/*null generic signature*/0);
}
data.push_back(witness.getSubstitutions().size());
@@ -1531,12 +1557,6 @@
if (auto genericEnv = witness.requiresSubstitution()
? witness.getSyntheticEnvironment()
: nullptr) {
- auto *genericSig = genericEnv->getGenericSignature();
-
- // Write the generic requirements of the synthetic environment.
- writeGenericRequirements(genericSig->getRequirements(),
- DeclTypeAbbrCodes);
-
// Write requirement-to-synthetic substitutions.
writeSubstitutions(witness.getRequirementToSyntheticSubs(),
DeclTypeAbbrCodes,
@@ -1866,21 +1886,13 @@
writeCrossReference(baseTy->getAnyNominal(), pathLen + 1);
abbrCode = DeclTypeAbbrCodes[XRefExtensionPathPieceLayout::Code];
- SmallVector<TypeID, 4> genericParams;
CanGenericSignature genericSig(nullptr);
if (ext->isConstrainedExtension()) {
genericSig = ext->getGenericSignature()->getCanonicalSignature();
- for (auto param : genericSig->getGenericParams())
- genericParams.push_back(addTypeRef(param));
}
XRefExtensionPathPieceLayout::emitRecord(
Out, ScratchRecord, abbrCode, addModuleRef(DC->getParentModule()),
- genericParams);
-
- if (genericSig) {
- writeGenericRequirements(genericSig->getRequirements(),
- DeclTypeAbbrCodes);
- }
+ addGenericSignatureRef(genericSig));
break;
}
@@ -2224,6 +2236,14 @@
return;
}
+ case DAK_Optimize: {
+ auto *theAttr = cast<OptimizeAttr>(DA);
+ auto abbrCode = DeclTypeAbbrCodes[OptimizeDeclAttrLayout::Code];
+ OptimizeDeclAttrLayout::emitRecord(Out, ScratchRecord, abbrCode,
+ (unsigned)theAttr->getMode());
+ return;
+ }
+
case DAK_Effects: {
auto *theAttr = cast<EffectsAttr>(DA);
auto abbrCode = DeclTypeAbbrCodes[EffectsDeclAttrLayout::Code];
@@ -3354,6 +3374,18 @@
llvm_unreachable("bad calling convention");
}
+/// Translate from the AST coroutine-kind enum to the Serialization enum
+/// values, which are guaranteed to be stable.
+static uint8_t getRawStableSILCoroutineKind(
+ swift::SILCoroutineKind kind) {
+ switch (kind) {
+ SIMPLE_CASE(SILCoroutineKind, None)
+ SIMPLE_CASE(SILCoroutineKind, YieldOnce)
+ SIMPLE_CASE(SILCoroutineKind, YieldMany)
+ }
+ llvm_unreachable("bad kind");
+}
+
/// Translate from the AST ownership enum to the Serialization enum
/// values, which are guaranteed to be stable.
static uint8_t getRawStableOwnership(swift::Ownership ownership) {
@@ -3398,12 +3430,11 @@
#undef SIMPLE_CASE
/// Find the typealias given a builtin type.
-static TypeAliasDecl *findTypeAliasForBuiltin(ASTContext &Ctx,
- BuiltinType *Bt) {
+static TypeAliasDecl *findTypeAliasForBuiltin(ASTContext &Ctx, Type T) {
/// Get the type name by chopping off "Builtin.".
llvm::SmallString<32> FullName;
llvm::raw_svector_ostream OS(FullName);
- Bt->print(OS);
+ T->print(OS);
assert(FullName.startswith("Builtin."));
StringRef TypeName = FullName.substr(8);
@@ -3439,9 +3470,10 @@
case TypeKind::BuiltinBridgeObject:
case TypeKind::BuiltinUnknownObject:
case TypeKind::BuiltinUnsafeValueBuffer:
- case TypeKind::BuiltinVector: {
+ case TypeKind::BuiltinVector:
+ case TypeKind::SILToken: {
TypeAliasDecl *typeAlias =
- findTypeAliasForBuiltin(M->getASTContext(), ty->castTo<BuiltinType>());
+ findTypeAliasForBuiltin(M->getASTContext(), ty);
unsigned abbrCode = DeclTypeAbbrCodes[NameAliasTypeLayout::Code];
NameAliasTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -3616,19 +3648,12 @@
case TypeKind::GenericFunction: {
auto fnTy = cast<GenericFunctionType>(ty.getPointer());
unsigned abbrCode = DeclTypeAbbrCodes[GenericFunctionTypeLayout::Code];
- SmallVector<TypeID, 4> genericParams;
- for (auto param : fnTy->getGenericParams())
- genericParams.push_back(addTypeRef(param));
GenericFunctionTypeLayout::emitRecord(Out, ScratchRecord, abbrCode,
addTypeRef(fnTy->getInput()),
addTypeRef(fnTy->getResult()),
getRawStableFunctionTypeRepresentation(fnTy->getRepresentation()),
fnTy->throws(),
- genericParams);
-
- // Write requirements.
- writeGenericRequirements(fnTy->getRequirements(),
- DeclTypeAbbrCodes);
+ addGenericSignatureRef(fnTy->getGenericSignature()));
break;
}
@@ -3674,6 +3699,11 @@
unsigned conv = getRawStableParameterConvention(param.getConvention());
variableData.push_back(TypeID(conv));
}
+ for (auto yield : fnTy->getYields()) {
+ variableData.push_back(addTypeRef(yield.getType()));
+ unsigned conv = getRawStableParameterConvention(yield.getConvention());
+ variableData.push_back(TypeID(conv));
+ }
for (auto result : fnTy->getResults()) {
variableData.push_back(addTypeRef(result.getType()));
unsigned conv = getRawStableResultConvention(result.getConvention());
@@ -3687,27 +3717,25 @@
}
auto sig = fnTy->getGenericSignature();
- if (sig) {
- for (auto param : sig->getGenericParams())
- variableData.push_back(addTypeRef(param));
- }
+
+ auto stableCoroutineKind =
+ getRawStableSILCoroutineKind(fnTy->getCoroutineKind());
auto stableCalleeConvention =
getRawStableParameterConvention(fnTy->getCalleeConvention());
unsigned abbrCode = DeclTypeAbbrCodes[SILFunctionTypeLayout::Code];
SILFunctionTypeLayout::emitRecord(
- Out, ScratchRecord, abbrCode, stableCalleeConvention,
+ Out, ScratchRecord, abbrCode,
+ stableCoroutineKind, stableCalleeConvention,
stableRepresentation, fnTy->isPseudogeneric(), fnTy->isNoEscape(),
fnTy->hasErrorResult(), fnTy->getParameters().size(),
- fnTy->getNumResults(), variableData);
+ fnTy->getNumYields(), fnTy->getNumResults(),
+ addGenericSignatureRef(sig), variableData);
if (auto conformance = fnTy->getWitnessMethodConformanceOrNone())
writeConformance(*conformance, DeclTypeAbbrCodes);
- if (sig)
- writeGenericRequirements(sig->getRequirements(),
- DeclTypeAbbrCodes);
break;
}
@@ -3891,7 +3919,7 @@
registerDeclTypeAbbr<GenericParamLayout>();
registerDeclTypeAbbr<GenericRequirementLayout>();
registerDeclTypeAbbr<LayoutRequirementLayout>();
- registerDeclTypeAbbr<GenericEnvironmentLayout>();
+ registerDeclTypeAbbr<GenericSignatureLayout>();
registerDeclTypeAbbr<SILGenericEnvironmentLayout>();
registerDeclTypeAbbr<ForeignErrorConventionLayout>();
@@ -3951,6 +3979,12 @@
writeDeclContext(next);
}
+ while (!GenericSignaturesToWrite.empty()) {
+ auto next = GenericSignaturesToWrite.front();
+ GenericSignaturesToWrite.pop();
+ writeGenericSignature(next);
+ }
+
while (!GenericEnvironmentsToWrite.empty()) {
auto next = GenericEnvironmentsToWrite.front();
GenericEnvironmentsToWrite.pop();
@@ -3972,6 +4006,7 @@
!LocalDeclContextsToWrite.empty() ||
!DeclContextsToWrite.empty() ||
!SILLayoutsToWrite.empty() ||
+ !GenericSignaturesToWrite.empty() ||
!GenericEnvironmentsToWrite.empty() ||
!NormalConformancesToWrite.empty());
}
@@ -4769,6 +4804,7 @@
writeOffsets(Offsets, IdentifierOffsets);
writeOffsets(Offsets, DeclContextOffsets);
writeOffsets(Offsets, LocalDeclContextOffsets);
+ writeOffsets(Offsets, GenericSignatureOffsets);
writeOffsets(Offsets, GenericEnvironmentOffsets);
writeOffsets(Offsets, NormalConformanceOffsets);
writeOffsets(Offsets, SILLayoutOffsets);
diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h
index 59a3eba..340f88a 100644
--- a/lib/Serialization/Serialization.h
+++ b/lib/Serialization/Serialization.h
@@ -100,6 +100,10 @@
/// A map from local DeclContexts to their serialized IDs.
llvm::DenseMap<const DeclContext*, DeclContextID> LocalDeclContextIDs;
+ /// A map from generic signatures to their serialized IDs.
+ llvm::DenseMap<const GenericSignature *, GenericSignatureID>
+ GenericSignatureIDs;
+
/// A map from generic environments to their serialized IDs.
llvm::DenseMap<const GenericEnvironment *, GenericEnvironmentID>
GenericEnvironmentIDs;
@@ -167,6 +171,9 @@
/// Local DeclContexts that need to be serialized.
std::queue<const DeclContext*> LocalDeclContextsToWrite;
+ /// Generic signatures that need to be serialized.
+ std::queue<const GenericSignature *> GenericSignaturesToWrite;
+
/// Generic environments that need to be serialized.
std::queue<const GenericEnvironment*> GenericEnvironmentsToWrite;
@@ -202,6 +209,10 @@
/// IdentifierID.
std::vector<CharOffset> IdentifierOffsets;
+ /// The offset of each GenericSignature in the bitstream, indexed by
+ /// GenericSignatureID.
+ std::vector<BitOffset> GenericSignatureOffsets;
+
/// The offset of each GenericEnvironment in the bitstream, indexed by
/// GenericEnvironmentID.
std::vector<BitOffset> GenericEnvironmentOffsets;
@@ -242,6 +253,10 @@
uint32_t /*IdentifierID*/ LastIdentifierID =
serialization::NUM_SPECIAL_IDS - 1;
+ /// The last assigned GenericSignatureID for generic signature from this
+ /// module.
+ uint32_t /*GenericSignatureID*/ LastGenericSignatureID = 0;
+
/// The last assigned GenericEnvironmentID for generic environments from this
/// module.
uint32_t /*GenericEnvironmentID*/ LastGenericEnvironmentID = 0;
@@ -261,6 +276,8 @@
return index_block::DECL_CONTEXT_OFFSETS;
if (&values == &LocalDeclContextOffsets)
return index_block::LOCAL_DECL_CONTEXT_OFFSETS;
+ if (&values == &GenericSignatureOffsets)
+ return index_block::GENERIC_SIGNATURE_OFFSETS;
if (&values == &GenericEnvironmentOffsets)
return index_block::GENERIC_ENVIRONMENT_OFFSETS;
if (&values == &NormalConformanceOffsets)
@@ -354,6 +371,9 @@
/// Writes the given type.
void writeType(Type ty);
+ /// Writes a generic signature.
+ void writeGenericSignature(const GenericSignature *sig);
+
/// Writes a generic environment.
void writeGenericEnvironment(const GenericEnvironment *env);
@@ -436,6 +456,11 @@
/// The DeclContext will be scheduled for serialization if necessary.
DeclContextID addLocalDeclContextRef(const DeclContext *DC);
+ /// Records the use of the given generic signature.
+ ///
+ /// The GenericSignature will be scheduled for serialization if necessary.
+ GenericSignatureID addGenericSignatureRef(const GenericSignature *sig);
+
/// Records the use of the given generic environment.
///
/// The GenericEnvironment will be scheduled for serialization if necessary.
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 237f38f..3ecaf0e 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -389,7 +389,8 @@
Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage),
(unsigned)F.isTransparent(), (unsigned)F.isSerialized(),
(unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
- (unsigned)F.getInlineStrategy(), (unsigned)F.getEffectsKind(),
+ (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
+ (unsigned)F.getEffectsKind(),
(unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
genericEnvID, clangNodeOwnerID, SemanticsIDs);
@@ -482,7 +483,7 @@
ListOfValues.push_back(S.addDeclRef(Ref.getDecl()));
ListOfValues.push_back((unsigned)Ref.kind);
ListOfValues.push_back((unsigned)Ref.getResilienceExpansion());
- ListOfValues.push_back(Ref.getUncurryLevel());
+ ListOfValues.push_back(Ref.getParameterListCount() - 1);
ListOfValues.push_back(Ref.isForeign);
}
@@ -582,6 +583,7 @@
// TODO: decide if we want to serialize those instructions.
return;
+ case SILInstructionKind::UnwindInst:
case SILInstructionKind::UnreachableInst: {
unsigned abbrCode = SILAbbrCodes[SILInstNoOperandLayout::Code];
SILInstNoOperandLayout::emitRecord(Out, ScratchRecord, abbrCode,
@@ -826,6 +828,28 @@
S.writeSubstitutions(AI->getSubstitutions(), SILAbbrCodes);
break;
}
+ case SILInstructionKind::BeginApplyInst: {
+ // Format: attributes such as transparent and number of substitutions,
+ // the callee's substituted and unsubstituted types, a value for
+ // the callee and a list of values for the arguments. Each value in the list
+ // is represented with 2 IDs: ValueID and ValueResultNumber. The record
+ // is followed by the substitution list.
+ const BeginApplyInst *AI = cast<BeginApplyInst>(&SI);
+ SmallVector<ValueID, 4> Args;
+ for (auto Arg: AI->getArguments()) {
+ Args.push_back(addValueRef(Arg));
+ }
+ SILInstApplyLayout::emitRecord(Out, ScratchRecord,
+ SILAbbrCodes[SILInstApplyLayout::Code],
+ AI->isNonThrowing() ? SIL_NON_THROWING_BEGIN_APPLY : SIL_BEGIN_APPLY,
+ AI->getSubstitutions().size(),
+ S.addTypeRef(AI->getCallee()->getType().getSwiftRValueType()),
+ S.addTypeRef(AI->getSubstCalleeType()),
+ addValueRef(AI->getCallee()),
+ Args);
+ S.writeSubstitutions(AI->getSubstitutions(), SILAbbrCodes);
+ break;
+ }
case SILInstructionKind::TryApplyInst: {
// Format: attributes such as transparent and number of substitutions,
// the callee's substituted and unsubstituted types, a value for
@@ -1100,6 +1124,8 @@
case SILInstructionKind::UnownedReleaseInst:
case SILInstructionKind::IsUniqueInst:
case SILInstructionKind::IsUniqueOrPinnedInst:
+ case SILInstructionKind::AbortApplyInst:
+ case SILInstructionKind::EndApplyInst:
case SILInstructionKind::ReturnInst:
case SILInstructionKind::UncheckedOwnershipConversionInst:
case SILInstructionKind::ThrowInst: {
@@ -1124,6 +1150,21 @@
writeOneOperandLayout(SI.getKind(), Attr, SI.getOperand(0));
break;
}
+ case SILInstructionKind::YieldInst: {
+ auto YI = cast<YieldInst>(&SI);
+ SmallVector<ValueID, 4> args;
+ for (auto arg: YI->getYieldedValues()) {
+ args.push_back(S.addTypeRef(arg->getType().getSwiftRValueType()));
+ args.push_back((unsigned)arg->getType().getCategory());
+ args.push_back(addValueRef(arg));
+ }
+ args.push_back(BasicBlockMap[YI->getResumeBB()]);
+ args.push_back(BasicBlockMap[YI->getUnwindBB()]);
+ SILOneTypeValuesLayout::emitRecord(Out, ScratchRecord,
+ SILAbbrCodes[SILOneTypeValuesLayout::Code],
+ (unsigned)YI->getKind(), 0, 0, args);
+ break;
+ }
case SILInstructionKind::FunctionRefInst: {
// Use SILOneOperandLayout to specify the function type and the function
// name (IdentifierID).
@@ -2168,6 +2209,16 @@
witnessID,
ListOfValues);
}
+
+ for (auto conditional : wt.getConditionalConformances()) {
+ WitnessConditionalConformanceLayout::emitRecord(
+ Out, ScratchRecord,
+ SILAbbrCodes[WitnessConditionalConformanceLayout::Code],
+ S.addTypeRef(conditional.Requirement));
+
+ S.writeConformance(conditional.Conformance, SILAbbrCodes);
+ continue;
+ }
}
void SILSerializer::
@@ -2257,6 +2308,7 @@
registerSILAbbr<WitnessBaseEntryLayout>();
registerSILAbbr<WitnessAssocProtocolLayout>();
registerSILAbbr<WitnessAssocEntryLayout>();
+ registerSILAbbr<WitnessConditionalConformanceLayout>();
registerSILAbbr<DefaultWitnessTableLayout>();
registerSILAbbr<DefaultWitnessTableEntryLayout>();
registerSILAbbr<DefaultWitnessTableNoEntryLayout>();
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 1c80bee..4acef87 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -23,6 +23,8 @@
namespace {
static bool isTrivialSyntaxKind(SyntaxKind Kind) {
+ if (isUnknownKind(Kind))
+ return true;
if (isCollectionKind(Kind))
return true;
switch(Kind) {
diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb
index b534351..6a954e6 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -57,6 +57,32 @@
return make<UnknownSyntax>(Raw);
}
+Syntax SyntaxFactory::makeBlankCollectionSyntax(SyntaxKind Kind) {
+ switch(Kind) {
+% for node in SYNTAX_NODES:
+% if node.is_syntax_collection():
+ case SyntaxKind::${node.syntax_kind}: return makeBlank${node.syntax_kind}();
+% end
+% end
+ default: break;
+ }
+ llvm_unreachable("not collection kind.");
+}
+
+std::pair<unsigned, unsigned>
+SyntaxFactory::countChildren(SyntaxKind Kind){
+ switch(Kind) {
+% for node in SYNTAX_NODES:
+ case SyntaxKind::${node.syntax_kind}:
+% child_count = len(node.children)
+% non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.children)
+ return {${non_optional_child_count}, ${child_count}};
+% end
+ default:
+ llvm_unreachable("bad syntax kind.");
+ }
+}
+
Optional<Syntax>
SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements) {
switch(Kind) {
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index eb8e495..af28b2c 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -56,19 +56,34 @@
assert(StartLoc.isValid() == EndLoc.isValid());
return SourceRange(StartLoc, EndLoc);
}
+
+static RawSyntaxInfo createSyntaxAs(ArrayRef<RawSyntaxInfo> Parts,
+ SyntaxKind Kind) {
+ llvm::SmallVector<Syntax, 8> Scratch;
+ auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+
+ // Try to create the node of the given syntax.
+ Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
+ if (!Result) {
+
+ // If unable to create, we should create an unknown node.
+ Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
+ SyntaxParts));
+ }
+ return { getNodesRange(Parts), Result->getRaw() };
+}
} // End of anonymous namespace
struct SyntaxParsingContext::ContextInfo {
bool Enabled;
private:
SourceLoc ContextStartLoc;
- SourceLoc ContextEndLoc;
std::vector<RawSyntaxInfo> PendingSyntax;
// All tokens after the start of this context.
ArrayRef<RawSyntaxInfo> Tokens;
- ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) {
+ ArrayRef<RawSyntaxInfo>::const_iterator findTokenAt(SourceLoc Loc) const {
for (auto It = Tokens.begin(); It != Tokens.end(); It ++) {
assert(It->getStartLoc() == It->getEndLoc());
if (It->getStartLoc() == Loc)
@@ -96,15 +111,19 @@
}
// Squash N syntax nodex from the back of the pending list into one.
- void createFromBack(SyntaxKind Kind, unsigned N = 0);
- std::vector<RawSyntaxInfo> collectAllSyntax();
+ void createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+ unsigned N);
+ void createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse);
+ std::vector<RawSyntaxInfo> collectAllSyntax(SourceLoc EndLoc);
ArrayRef<RawSyntaxInfo> allTokens() const { return Tokens; }
- ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; };
+ ArrayRef<RawSyntaxInfo> getPendingSyntax() const { return PendingSyntax; }
+ SourceLoc getContextStartLoc() const { return ContextStartLoc; }
void addPendingSyntax(RawSyntaxInfo Info) {
assert(Info.isImplicit() || PendingSyntax.empty() ||
PendingSyntax.back().getStartLoc().getOpaquePointerValue() <
Info.getStartLoc().getOpaquePointerValue());
+ assert(!Info.RawNode->isToken() && "Pending syntax should not have tokens");
PendingSyntax.push_back(Info);
}
@@ -114,42 +133,65 @@
Tokens = Tokens.slice(findTokenAt(Loc) - Tokens.begin());
}
- void setContextEnd(SourceLoc Loc) {
- assert(ContextEndLoc.isInvalid());
- ContextEndLoc = Loc;
- Tokens = Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
- }
-
- void promoteTokenAt(SourceLoc Loc) {
- PendingSyntax.push_back(*findTokenAt(Loc));
+ ArrayRef<RawSyntaxInfo> dropTokenAt(SourceLoc Loc) const {
+ return Tokens.take_front(findTokenAt(Loc) - Tokens.begin());
}
// Check if the pending syntax is a token syntax in the given kind.
- bool checkTokenFromBack(tok Kind, unsigned OffsetFromBack = 0) {
- if (PendingSyntax.size() - 1 < OffsetFromBack)
+ bool checkTokenFromBack(tok Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+ unsigned OffsetFromBack = 0) {
+ if (UsedTokens.size() - 1 < OffsetFromBack)
return false;
- auto Back = PendingSyntax[PendingSyntax.size() - 1 - OffsetFromBack].
+ auto Back = UsedTokens[UsedTokens.size() - 1 - OffsetFromBack].
makeSyntax<Syntax>().getAs<TokenSyntax>();
return Back.hasValue() && Back->getTokenKind() == Kind;
}
};
+static void addNodeToResults(std::vector<RawSyntaxInfo> &Results,
+ std::vector<RawSyntaxInfo> &ImplicitNodes,
+ RawSyntaxInfo Info) {
+ // Add implicit nodes before adding the explicit nodes they attach to.
+ assert(!Info.isImplicit());
+ auto StartSize = Results.size();
+
+ // Find all implicit nodes where the attach-to location is the start position
+ // of this non-implicit nodes.
+ Results.insert(Results.end(),
+ std::find_if(ImplicitNodes.begin(), ImplicitNodes.end(),
+ [&](const RawSyntaxInfo &Imp) {
+ return Imp.BeforeLoc == Info.getStartLoc();
+ }),
+ ImplicitNodes.end());
+
+ // If any implicit nodes are inserted to results, we should clear the buffer
+ // to avoid re-inserting them.
+ if (StartSize != Results.size()) {
+ ImplicitNodes.clear();
+ }
+
+ // Add the non-implicit node.
+ Results.emplace_back(Info);
+}
+
std::vector<RawSyntaxInfo>
-SyntaxParsingContext::ContextInfo::collectAllSyntax() {
+SyntaxParsingContext::ContextInfo::collectAllSyntax(SourceLoc EndLoc) {
std::vector<RawSyntaxInfo> Results;
+ std::vector<RawSyntaxInfo> ImplicitNodes;
auto CurSyntax = PendingSyntax.begin();
- for (auto It = Tokens.begin(); It != Tokens.end();) {
+ for (auto It = Tokens.begin(); It->getStartLoc() != EndLoc;) {
auto Tok = *It;
if (CurSyntax == PendingSyntax.end()) {
// If no remaining syntax nodes, add the token.
- Results.emplace_back(Tok);
+ addNodeToResults(Results, ImplicitNodes, Tok);
It ++;
} else if (CurSyntax->isImplicit()) {
+ ImplicitNodes.emplace_back(*CurSyntax);
// Skip implicit syntax node.
CurSyntax ++;
} else if (CurSyntax->getStartLoc() == Tok.getStartLoc()) {
// Prefer syntax nodes to tokens.
- Results.emplace_back(*CurSyntax);
+ addNodeToResults(Results, ImplicitNodes, *CurSyntax);
while(It->getEndLoc() != CurSyntax->getEndLoc()) It++;
assert(It < Tokens.end() && It->getEndLoc() == CurSyntax->getEndLoc());
It ++;
@@ -159,7 +201,7 @@
// started.
assert(Tok.getStartLoc().getOpaquePointerValue() <
CurSyntax->getStartLoc().getOpaquePointerValue());
- Results.push_back(Tok);
+ addNodeToResults(Results, ImplicitNodes, Tok);
It ++;
}
}
@@ -170,40 +212,42 @@
return Results;
}
-void
-SyntaxParsingContext::ContextInfo::createFromBack(SyntaxKind Kind, unsigned N) {
- auto Size = PendingSyntax.size();
- if (!N)
- N = Size;
- assert(Size >= N);
- auto Parts = llvm::makeArrayRef(PendingSyntax).slice(Size - N);
- llvm::SmallVector<Syntax, 8> Scratch;
- auto SyntaxParts = getSyntaxNodes(Parts, Scratch);
+void SyntaxParsingContext::ContextInfo::
+createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse,
+ unsigned N) {
+ auto Size = NodesToUse.size();
+ assert(N && Size >= N);
+ auto Parts = llvm::makeArrayRef(NodesToUse).slice(Size - N);
- // Try to create the node of the given syntax.
- Optional<Syntax> Result = SyntaxFactory::createSyntax(Kind, SyntaxParts);
- if (!Result) {
+ // Count the parts from the pending syntax list.
+ unsigned UsedPending = std::accumulate(Parts.begin(), Parts.end(), 0,
+ [](unsigned Count, RawSyntaxInfo Info) {
+ return Count += Info.RawNode->isToken() ? 0 : 1;
+ });
- // If unable to create, we should create an unknown node.
- Result.emplace(makeUnknownSyntax(SyntaxFactory::getUnknownKind(Kind),
- SyntaxParts));
- }
- RawSyntaxInfo NewSyntaxNode(getNodesRange(Parts), Result->getRaw());
-
- // Remove the building bricks and re-append the result.
- for (unsigned I = 0; I < N; I ++)
+ // Remove all pending syntax ndoes that we used to create the new node.
+ for (unsigned I = 0; I < UsedPending; I ++)
PendingSyntax.pop_back();
- addPendingSyntax(NewSyntaxNode);
- assert(Size - N + 1 == PendingSyntax.size());
+
+ // Add result to the pending syntax list.
+ addPendingSyntax(createSyntaxAs(Parts, Kind));
+}
+
+void SyntaxParsingContext::ContextInfo::
+createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse) {
+ auto Result = createSyntaxAs(NodesToUse, Kind);
+ PendingSyntax.clear();
+ addPendingSyntax(Result);
}
SyntaxParsingContext::
SyntaxParsingContext(SourceFile &SF, unsigned BufferID, Token &Tok):
- ContextData(*new ContextInfo(SF, BufferID)), Tok(Tok) {}
+ ContextData(*new ContextInfo(SF, BufferID)),
+ Tok(Tok) {}
SyntaxParsingContext::SyntaxParsingContext(SyntaxParsingContext &Another):
ContextData(*new ContextInfo(Another.ContextData.allTokens(),
- Another.ContextData.Enabled)), Tok(Another.Tok) {}
+ Another.ContextData.Enabled)), Tok(Another.Tok) {}
SyntaxParsingContext::~SyntaxParsingContext() { delete &ContextData; }
@@ -241,40 +285,58 @@
SyntaxParsingContextChild::
SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder,
- Optional<SyntaxContextKind> Kind, Optional<SyntaxKind> KnownSyntax):
+ Optional<SyntaxContextKind> ContextKind, Optional<SyntaxKind> KnownSyntax):
SyntaxParsingContext(*ContextHolder), Parent(ContextHolder),
- ContextHolder(ContextHolder), Kind(Kind), KnownSyntax(KnownSyntax) {
- assert(Kind.hasValue() != KnownSyntax.hasValue());
+ ContextHolder(ContextHolder), ContextKind(ContextKind),
+ KnownSyntax(KnownSyntax) {
ContextHolder = this;
if (ContextData.Enabled)
ContextData.setContextStart(Tok.getLoc());
}
-
-void SyntaxParsingContextChild::addTokenSyntax(SourceLoc Loc) {
- if (ContextData.Enabled)
- ContextData.promoteTokenAt(Loc);
+void SyntaxParsingContextChild::setSyntaxKind(SyntaxKind SKind) {
+ assert(!KnownSyntax.hasValue() && "reset");
+ KnownSyntax = SKind;
+ ContextKind = None;
}
-void SyntaxParsingContextChild::makeNode(SyntaxKind Kind) {
+void SyntaxParsingContextChild::setContextKind(SyntaxContextKind CKind) {
+ assert(!ContextKind.hasValue() && "reset");
+ ContextKind = CKind;
+ KnownSyntax = None;
+}
+
+SyntaxParsingContextChild::
+SyntaxParsingContextChild(SyntaxParsingContext *&ContextHolder, bool Disable):
+ SyntaxParsingContextChild(ContextHolder, None, None) {
+ if (Disable)
+ disable();
+}
+
+void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc EndLoc) {
+ assert(isTopOfContextStack());
if (!ContextData.Enabled)
return;
+ auto AllNodes = ContextData.collectAllSyntax(EndLoc);
+
// Create syntax nodes according to the given kind.
switch (Kind) {
case SyntaxKind::FloatLiteralExpr:
case SyntaxKind::IntegerLiteralExpr: {
// Integer may include the signs before the digits, so check if the sign
// exists and create.
- ContextData.createFromBack(Kind, ContextData.
- checkTokenFromBack(tok::oper_prefix, 1) ? 2 : 1);
+ ContextData.createPartiallyFromBack(Kind, AllNodes, ContextData.
+ checkTokenFromBack(tok::oper_prefix, AllNodes, 1) ? 2 : 1);
break;
}
+ case SyntaxKind::TernaryExpr:
case SyntaxKind::StringLiteralExpr: {
- ContextData.createFromBack(Kind, 1);
+ auto Pair = SyntaxFactory::countChildren(Kind);
+ assert(Pair.first == Pair.second);
+ ContextData.createPartiallyFromBack(Kind, AllNodes, Pair.first);
break;
}
-
default:
llvm_unreachable("Unrecognized node kind.");
}
@@ -282,17 +344,36 @@
void SyntaxParsingContextChild::makeNodeWhole(SyntaxKind Kind) {
assert(ContextData.Enabled);
+ assert(isTopOfContextStack());
+
+ auto EndLoc = Tok.getLoc();
+ auto AllNodes = ContextData.collectAllSyntax(EndLoc);
switch (Kind) {
+ case SyntaxKind::BooleanLiteralExpr:
+ case SyntaxKind::NilLiteralExpr:
+ case SyntaxKind::DiscardAssignmentExpr:
+ case SyntaxKind::IdentifierExpr:
+ case SyntaxKind::DictionaryExpr:
+ case SyntaxKind::ArrayExpr:
+ case SyntaxKind::DictionaryElement:
+ case SyntaxKind::ArrayElement:
+ case SyntaxKind::FunctionCallArgument:
case SyntaxKind::CodeBlock: {
- ContextData.createFromBack(Kind);
+ ContextData.createWhole(Kind, AllNodes);
break;
}
- case SyntaxKind::StmtList: {
- if (ContextData.getPendingSyntax().empty()) {
- // Create an empty statement list if no statement is in the context.
- ContextData.addPendingSyntax({SyntaxFactory::makeBlankStmtList().getRaw()});
+ case SyntaxKind::DictionaryElementList:
+ case SyntaxKind::ArrayElementList:
+ case SyntaxKind::StmtList:
+ case SyntaxKind::FunctionCallArgumentList: {
+ if (AllNodes.empty()) {
+ // Create an empty argument list if no arguments are in the context.
+ RawSyntaxInfo Empty(SyntaxFactory::
+ makeBlankCollectionSyntax(Kind).getRaw());
+ Empty.setBeforeLoc(EndLoc);
+ ContextData.addPendingSyntax(Empty);
} else {
- ContextData.createFromBack(Kind);
+ ContextData.createWhole(Kind, AllNodes);
}
break;
}
@@ -321,13 +402,27 @@
assert(RawNode->isStmt());
break;
}
- case SyntaxContextKind::Decl:
+ case SyntaxContextKind::Decl: {
+ if (!RawNode->isDecl()) {
+ RawNode = makeUnknownSyntax(SyntaxKind::UnknownDecl,
+ {make<Syntax>(RawNode)}).getRaw();
+ }
+ assert(RawNode->isDecl());
+ break;
+ }
+
case SyntaxContextKind::Expr:
+ if (!RawNode->isExpr()) {
+ RawNode = makeUnknownSyntax(SyntaxKind::UnknownExpr,
+ {make<Syntax>(RawNode)}).getRaw();
+ }
+ assert(RawNode->isExpr());
break;
}
}
-SyntaxParsingContextChild::~SyntaxParsingContextChild() {
+void SyntaxParsingContextChild::finalize() {
+ assert(isTopOfContextStack());
SWIFT_DEFER {
// Reset the context holder to be Parent.
ContextHolder = Parent;
@@ -335,32 +430,29 @@
if (!ContextData.Enabled)
return;
- // Set the end of the context.
- ContextData.setContextEnd(Tok.getLoc());
+ assert(ContextKind.hasValue() != KnownSyntax.hasValue());
+ SourceLoc EndLoc = Tok.getLoc();
if (KnownSyntax) {
// If the entire context should be created to a known syntax kind, create
// all pending syntax nodes into that node.
makeNodeWhole(*KnownSyntax);
assert(ContextData.getPendingSyntax().size() == 1);
- auto AllNodes = ContextData.collectAllSyntax();
- assert(AllNodes.size() == 1);
- Parent->ContextData.addPendingSyntax(AllNodes.front());
+ Parent->ContextData.addPendingSyntax(ContextData.getPendingSyntax().front());
return;
}
- auto AllNodes = ContextData.collectAllSyntax();
+ auto AllNodes = ContextData.collectAllSyntax(EndLoc);
RC<RawSyntax> FinalResult;
if (AllNodes.empty())
return;
// Make sure we used all tokens.
- assert(AllNodes.front().getStartLoc() == ContextData.allTokens().front().getStartLoc());
- assert(AllNodes.back().getEndLoc() == ContextData.allTokens().back().getStartLoc());
+ assert(AllNodes.front().getStartLoc() == ContextData.getContextStartLoc());
if (AllNodes.size() == 1) {
// If we have only one syntax node remaining, we are done.
auto Result = AllNodes.front();
// Bridge the syntax node to the expected context kind.
- Result.brigeWithContext(*Kind);
+ Result.brigeWithContext(*ContextKind);
Parent->ContextData.addPendingSyntax(Result);
return;
}
@@ -370,7 +462,7 @@
SourceLoc Start = AllNodes.front().getStartLoc();
SourceLoc End = AllNodes.back().getEndLoc();
SyntaxKind UnknownKind;
- switch (*Kind) {
+ switch (*ContextKind) {
case SyntaxContextKind::Expr:
UnknownKind = SyntaxKind::UnknownExpr;
break;
@@ -385,3 +477,8 @@
Parent->ContextData.addPendingSyntax({SourceRange(Start, End),
makeUnknownSyntax(UnknownKind, SyntaxNodes).getRaw()});
}
+
+SyntaxParsingContextChild::~SyntaxParsingContextChild() {
+ if (isTopOfContextStack())
+ finalize();
+}
diff --git a/stdlib/public/Platform/Glibc.swift.gyb b/stdlib/public/Platform/Glibc.swift.gyb
index f49c8c7..4c01157 100644
--- a/stdlib/public/Platform/Glibc.swift.gyb
+++ b/stdlib/public/Platform/Glibc.swift.gyb
@@ -12,8 +12,7 @@
@_exported import SwiftGlibc // Clang module
-public let MAP_FAILED =
- UnsafeMutableRawPointer(bitPattern: -1)! as UnsafeMutableRawPointer!
+public let MAP_FAILED: UnsafeMutableRawPointer! = UnsafeMutableRawPointer(bitPattern: -1)
// Constants defined by <math.h>
@available(swift, deprecated: 3.0, message: "Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.")
diff --git a/stdlib/public/Reflection/TypeRef.cpp b/stdlib/public/Reflection/TypeRef.cpp
index 18a0d5a..c782c71 100644
--- a/stdlib/public/Reflection/TypeRef.cpp
+++ b/stdlib/public/Reflection/TypeRef.cpp
@@ -147,9 +147,6 @@
if (flags.isShared())
printHeader("shared");
- if (flags.isEscaping())
- printHeader("escaping");
-
printRec(param.getType());
if (!flags.isNone()) {
diff --git a/stdlib/public/SDK/AppKit/AppKit.swift b/stdlib/public/SDK/AppKit/AppKit.swift
index 3346d89..9ee047b 100644
--- a/stdlib/public/SDK/AppKit/AppKit.swift
+++ b/stdlib/public/SDK/AppKit/AppKit.swift
@@ -73,7 +73,7 @@
extension NSApplication {
@available(swift 4)
public static func loadApplication() {
- NSApplicationLoad()
+ __NSApplicationLoad()
}
}
@@ -90,7 +90,7 @@
extension NSImage : _ExpressibleByImageLiteral {
private convenience init!(failableImageLiteral name: String) {
- self.init(named: name)
+ self.init(named: .init(name))
}
@nonobjc
@@ -100,3 +100,61 @@
}
public typealias _ImageLiteralType = NSImage
+
+// Numeric backed types
+
+@available(swift 4)
+public protocol _AppKitKitNumericRawRepresentable : RawRepresentable, Comparable
+ where RawValue: Comparable & Numeric { }
+
+extension _AppKitKitNumericRawRepresentable {
+ public static func <(lhs: Self, rhs: Self) -> Bool {
+ return lhs.rawValue < rhs.rawValue
+ }
+
+ public static func +(lhs: Self, rhs: RawValue) -> Self {
+ return Self(rawValue: lhs.rawValue + rhs)!
+ }
+
+ public static func +(lhs: RawValue, rhs: Self) -> Self {
+ return Self(rawValue: lhs + rhs.rawValue)!
+ }
+
+ public static func -(lhs: Self, rhs: RawValue) -> Self {
+ return Self(rawValue: lhs.rawValue - rhs)!
+ }
+
+ public static func -(lhs: Self, rhs: Self) -> RawValue {
+ return lhs.rawValue - rhs.rawValue
+ }
+
+ public static func +=(lhs: inout Self, rhs: RawValue) {
+ lhs = Self(rawValue: lhs.rawValue + rhs)!
+ }
+
+ public static func -=(lhs: inout Self, rhs: RawValue) {
+ lhs = Self(rawValue: lhs.rawValue - rhs)!
+ }
+}
+
+@available(swift 4)
+extension NSAppKitVersion : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSLayoutConstraint.Priority : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSStackView.VisibilityPriority : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSToolbarItem.VisibilityPriority : _AppKitKitNumericRawRepresentable { }
+
+@available(macOS 10.12.2, *)
+@available(swift 4)
+extension NSTouchBarItem.Priority : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSWindow.Level : _AppKitKitNumericRawRepresentable { }
+
+@available(swift 4)
+extension NSFont.Weight : _AppKitKitNumericRawRepresentable { }
diff --git a/stdlib/public/SDK/AppKit/CMakeLists.txt b/stdlib/public/SDK/AppKit/CMakeLists.txt
index 34bacd6..32dadc5 100644
--- a/stdlib/public/SDK/AppKit/CMakeLists.txt
+++ b/stdlib/public/SDK/AppKit/CMakeLists.txt
@@ -8,7 +8,7 @@
NSGraphics.swift
NSOpenGL.swift
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ SWIFT_COMPILE_FLAGS ${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS} -swift-version 4
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS OSX
SWIFT_MODULE_DEPENDS_OSX Darwin CoreData CoreGraphics CoreImage Dispatch Foundation IOKit ObjectiveC QuartzCore XPC # auto-updated
diff --git a/stdlib/public/SDK/AppKit/NSGraphics.swift b/stdlib/public/SDK/AppKit/NSGraphics.swift
index a453f47..6cc836c 100644
--- a/stdlib/public/SDK/AppKit/NSGraphics.swift
+++ b/stdlib/public/SDK/AppKit/NSGraphics.swift
@@ -21,10 +21,10 @@
/// - precondition: There must be a set current NSGraphicsContext.
@available(swift 4)
public func fill(using operation: NSCompositingOperation =
- NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
- precondition(NSGraphicsContext.current() != nil,
+ NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+ precondition(NSGraphicsContext.current != nil,
"There must be a set current NSGraphicsContext")
- NSRectFillUsingOperation(self, operation)
+ __NSRectFillUsingOperation(self, operation)
}
/// Draws a frame around the inside of this rect in the current
@@ -35,10 +35,10 @@
@available(swift 4)
public func frame(withWidth width: CGFloat = 1.0,
using operation: NSCompositingOperation =
- NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
- precondition(NSGraphicsContext.current() != nil,
+ NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+ precondition(NSGraphicsContext.current != nil,
"There must be a set current NSGraphicsContext")
- NSFrameRectWithWidthUsingOperation(self, width, operation)
+ __NSFrameRectWithWidthUsingOperation(self, width, operation)
}
/// Modifies the current graphics context clipping path by intersecting it
@@ -48,9 +48,9 @@
/// - precondition: There must be a set current NSGraphicsContext.
@available(swift 4)
public func clip() {
- precondition(NSGraphicsContext.current() != nil,
+ precondition(NSGraphicsContext.current != nil,
"There must be a set current NSGraphicsContext")
- NSRectClip(self)
+ __NSRectClip(self)
}
}
@@ -62,15 +62,15 @@
/// - precondition: There must be a set current NSGraphicsContext.
@available(swift 4)
public func fill(using operation: NSCompositingOperation =
- NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
- precondition(NSGraphicsContext.current() != nil,
+ NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+ precondition(NSGraphicsContext.current != nil,
"There must be a set current NSGraphicsContext")
let rects = Array(self)
let count = rects.count
guard count > 0 else { return }
rects.withUnsafeBufferPointer { rectBufferPointer in
guard let rectArray = rectBufferPointer.baseAddress else { return }
- NSRectFillListUsingOperation(rectArray, count, operation)
+ __NSRectFillListUsingOperation(rectArray, count, operation)
}
}
@@ -81,14 +81,14 @@
/// - precondition: There must be a set current NSGraphicsContext.
@available(swift 4)
public func clip() {
- precondition(NSGraphicsContext.current() != nil,
+ precondition(NSGraphicsContext.current != nil,
"There must be a set current NSGraphicsContext")
let rects = Array(self)
let count = rects.count
guard count > 0 else { return }
rects.withUnsafeBufferPointer { rectBufferPointer in
guard let rectArray = rectBufferPointer.baseAddress else { return }
- NSRectClipList(rectArray, count)
+ __NSRectClipList(rectArray, count)
}
}
}
@@ -101,8 +101,8 @@
/// - precondition: There must be a set current NSGraphicsContext.
@available(swift 4)
public func fill(using operation: NSCompositingOperation =
- NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
- precondition(NSGraphicsContext.current() != nil,
+ NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
+ precondition(NSGraphicsContext.current != nil,
"There must be a set current NSGraphicsContext")
let rects = map { $0.0 }
let colors = map { $0.1 }
@@ -112,7 +112,7 @@
colors.withUnsafeBufferPointer { colorBufferPointer in
guard let rectArray = rectBufferPointer.baseAddress else { return }
guard let colorArray = colorBufferPointer.baseAddress else { return }
- NSRectFillListWithColorsUsingOperation(
+ __NSRectFillListWithColorsUsingOperation(
rectArray, colorArray, count, operation)
}
}
@@ -128,10 +128,10 @@
/// - precondition: There must be a set current NSGraphicsContext.
@available(swift 4)
public func fill(using operation: NSCompositingOperation =
- NSGraphicsContext.current()?.compositingOperation ?? .sourceOver) {
+ NSGraphicsContext.current?.compositingOperation ?? .sourceOver) {
// NSRectFillListWithGrays does not have a variant taking an operation, but
// is added here for consistency with the other drawing operations.
- guard let graphicsContext = NSGraphicsContext.current() else {
+ guard let graphicsContext = NSGraphicsContext.current else {
fatalError("There must be a set current NSGraphicsContext")
}
let cgContext: CGContext
@@ -144,31 +144,31 @@
cgContext.saveGState()
forEach {
cgContext.setFillColor(gray: $0.gray, alpha: 1.0)
- NSRectFillUsingOperation($0.0, operation)
+ __NSRectFillUsingOperation($0.0, operation)
}
cgContext.restoreGState()
}
}
-extension NSWindowDepth {
+extension NSWindow.Depth {
@available(swift 4)
public static func bestDepth(
colorSpaceName: NSColorSpaceName,
bitsPerSample: Int,
bitsPerPixel: Int,
isPlanar: Bool
- ) -> (NSWindowDepth, isExactMatch: Bool) {
+ ) -> (NSWindow.Depth, isExactMatch: Bool) {
var isExactMatch: ObjCBool = false
- let depth = NSBestDepth(
- colorSpaceName as String,
+ let depth = __NSBestDepth(
+ colorSpaceName,
bitsPerSample, bitsPerPixel, isPlanar, &isExactMatch)
return (depth, isExactMatch: isExactMatch.boolValue)
}
@available(swift 4)
- public static var availableDepths: [NSWindowDepth] {
+ public static var availableDepths: [NSWindow.Depth] {
// __NSAvailableWindowDepths is NULL terminated, the length is not known up front
- let depthsCArray = NSAvailableWindowDepths()
- var depths: [NSWindowDepth] = []
+ let depthsCArray = __NSAvailableWindowDepths()
+ var depths: [NSWindow.Depth] = []
var length = 0
var depth = depthsCArray[length]
while depth.rawValue != 0 {
@@ -194,7 +194,7 @@
delegate.completionHandler = completionHandler
// Note that the delegate of `__NSShowAnimationEffect` is retained for the
// duration of the animation.
- NSShowAnimationEffect(
+ __NSShowAnimationEffect(
self,
centerLocation,
size,
@@ -207,6 +207,6 @@
extension NSSound {
@available(swift 4)
public static func beep() {
- NSBeep()
+ __NSBeep()
}
}
diff --git a/stdlib/public/SDK/AppKit/NSOpenGL.swift b/stdlib/public/SDK/AppKit/NSOpenGL.swift
index 100a517..02f967d 100644
--- a/stdlib/public/SDK/AppKit/NSOpenGL.swift
+++ b/stdlib/public/SDK/AppKit/NSOpenGL.swift
@@ -18,11 +18,11 @@
public var globalValue: GLint {
get {
var value: GLint = 0
- NSOpenGLGetOption(self, &value)
+ __NSOpenGLGetOption(self, &value)
return value
}
set {
- NSOpenGLSetOption(self, newValue)
+ __NSOpenGLSetOption(self, newValue)
}
}
}
@@ -32,7 +32,7 @@
public static var openGLVersion: (major: GLint, minor: GLint) {
var major: GLint = 0
var minor: GLint = 0
- NSOpenGLGetVersion(&major, &minor)
+ __NSOpenGLGetVersion(&major, &minor)
return (major: major, minor: minor)
}
}
diff --git a/stdlib/public/SDK/CoreGraphics/CMakeLists.txt b/stdlib/public/SDK/CoreGraphics/CMakeLists.txt
index da36b64..09101e8 100644
--- a/stdlib/public/SDK/CoreGraphics/CMakeLists.txt
+++ b/stdlib/public/SDK/CoreGraphics/CMakeLists.txt
@@ -6,7 +6,7 @@
CGFloat.swift.gyb
Private.swift
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation Dispatch IOKit ObjectiveC # auto-updated
SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation Dispatch ObjectiveC # auto-updated
diff --git a/stdlib/public/SDK/Foundation/CMakeLists.txt b/stdlib/public/SDK/Foundation/CMakeLists.txt
index 0436cf1..b6cdce9 100644
--- a/stdlib/public/SDK/Foundation/CMakeLists.txt
+++ b/stdlib/public/SDK/Foundation/CMakeLists.txt
@@ -57,7 +57,7 @@
UUID.swift
CheckClass.mm
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-Xllvm" "-sil-inline-generics" "-Xllvm" "-sil-partial-specialization"
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-Xllvm" "-sil-inline-generics" "-Xllvm" "-sil-partial-specialization" "-swift-version" "3"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch IOKit ObjectiveC # auto-updated
diff --git a/stdlib/public/SDK/Foundation/Data.swift b/stdlib/public/SDK/Foundation/Data.swift
index a0b6e88..8083b9e 100644
--- a/stdlib/public/SDK/Foundation/Data.swift
+++ b/stdlib/public/SDK/Foundation/Data.swift
@@ -198,20 +198,20 @@
switch _backing {
case .swift: fallthrough
case .mutable:
- return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
+ return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
case .customMutableReference(let d):
let len = d.length
- return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
+ return try apply(UnsafeMutableRawBufferPointer(start: d.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
case .immutable(let d):
let data = d.mutableCopy() as! NSMutableData
_backing = .mutable(data)
_bytes = data.mutableBytes
- return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length - range.lowerBound)))
+ return try apply(UnsafeMutableRawBufferPointer(start: _bytes!.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, _length)))
case .customReference(let d):
let data = d.mutableCopy() as! NSMutableData
_backing = .customMutableReference(data)
let len = data.length
- return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len - range.lowerBound)))
+ return try apply(UnsafeMutableRawBufferPointer(start: data.mutableBytes.advanced(by:range.lowerBound - _offset), count: Swift.min(range.count, len)))
}
}
diff --git a/stdlib/public/SDK/Foundation/JSONEncoder.swift b/stdlib/public/SDK/Foundation/JSONEncoder.swift
index 9901552..a8d5e6a 100644
--- a/stdlib/public/SDK/Foundation/JSONEncoder.swift
+++ b/stdlib/public/SDK/Foundation/JSONEncoder.swift
@@ -867,8 +867,8 @@
}
let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
- guard let value = try decoder.unbox(topLevel, as: T.self) else {
- throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
+ guard let value = try decoder.unbox(topLevel, as: type) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
@@ -1236,7 +1236,7 @@
self.decoder.codingPath.append(key)
defer { self.decoder.codingPath.removeLast() }
- guard let value = try self.decoder.unbox(entry, as: T.self) else {
+ guard let value = try self.decoder.unbox(entry, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
}
@@ -1575,7 +1575,7 @@
self.decoder.codingPath.append(_JSONKey(index: self.currentIndex))
defer { self.decoder.codingPath.removeLast() }
- guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+ guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
@@ -1734,8 +1734,8 @@
}
public func decode<T : Decodable>(_ type: T.Type) throws -> T {
- try expectNonNull(T.self)
- return try self.unbox(self.storage.topContainer, as: T.self)!
+ try expectNonNull(type)
+ return try self.unbox(self.storage.topContainer, as: type)!
}
}
@@ -2094,13 +2094,13 @@
fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
let decoded: T
- if T.self == Date.self || T.self == NSDate.self {
+ if type == Date.self || type == NSDate.self {
guard let date = try self.unbox(value, as: Date.self) else { return nil }
decoded = date as! T
- } else if T.self == Data.self || T.self == NSData.self {
+ } else if type == Data.self || type == NSData.self {
guard let data = try self.unbox(value, as: Data.self) else { return nil }
decoded = data as! T
- } else if T.self == URL.self || T.self == NSURL.self {
+ } else if type == URL.self || type == NSURL.self {
guard let urlString = try self.unbox(value, as: String.self) else {
return nil
}
@@ -2111,12 +2111,12 @@
}
decoded = (url as! T)
- } else if T.self == Decimal.self || T.self == NSDecimalNumber.self {
+ } else if type == Decimal.self || type == NSDecimalNumber.self {
guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
decoded = decimal as! T
} else {
self.storage.push(container: value)
- decoded = try T(from: self)
+ decoded = try type.init(from: self)
self.storage.popContainer()
}
diff --git a/stdlib/public/SDK/Foundation/PlistEncoder.swift b/stdlib/public/SDK/Foundation/PlistEncoder.swift
index 059e237..9544870 100644
--- a/stdlib/public/SDK/Foundation/PlistEncoder.swift
+++ b/stdlib/public/SDK/Foundation/PlistEncoder.swift
@@ -612,7 +612,7 @@
/// - throws: An error if any value throws an error during decoding.
open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
var format: PropertyListSerialization.PropertyListFormat = .binary
- return try decode(T.self, from: data, format: &format)
+ return try decode(type, from: data, format: &format)
}
/// Decodes a top-level value of the given type from the given property list representation.
@@ -631,7 +631,7 @@
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not a valid property list.", underlyingError: error))
}
- return try decode(T.self, fromTopLevel: topLevel)
+ return try decode(type, fromTopLevel: topLevel)
}
/// Decodes a top-level value of the given type from the given property list container (top-level array or dictionary).
@@ -643,8 +643,8 @@
/// - throws: An error if any value throws an error during decoding.
internal func decode<T : Decodable>(_ type: T.Type, fromTopLevel container: Any) throws -> T {
let decoder = _PlistDecoder(referencing: container, options: self.options)
- guard let value = try decoder.unbox(container, as: T.self) else {
- throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
+ guard let value = try decoder.unbox(container, as: type) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
@@ -1015,7 +1015,7 @@
self.decoder.codingPath.append(key)
defer { self.decoder.codingPath.removeLast() }
- guard let value = try self.decoder.unbox(entry, as: T.self) else {
+ guard let value = try self.decoder.unbox(entry, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
}
@@ -1354,7 +1354,7 @@
self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
defer { self.decoder.codingPath.removeLast() }
- guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+ guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
@@ -1516,8 +1516,8 @@
}
public func decode<T : Decodable>(_ type: T.Type) throws -> T {
- try expectNonNull(T.self)
- return try self.unbox(self.storage.topContainer, as: T.self)!
+ try expectNonNull(type)
+ return try self.unbox(self.storage.topContainer, as: type)!
}
}
@@ -1756,15 +1756,15 @@
fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
let decoded: T
- if T.self == Date.self || T.self == NSDate.self {
+ if type == Date.self || type == NSDate.self {
guard let date = try self.unbox(value, as: Date.self) else { return nil }
decoded = date as! T
- } else if T.self == Data.self || T.self == NSData.self {
+ } else if type == Data.self || type == NSData.self {
guard let data = try self.unbox(value, as: Data.self) else { return nil }
decoded = data as! T
} else {
self.storage.push(container: value)
- decoded = try T(from: self)
+ decoded = try type.init(from: self)
self.storage.popContainer()
}
diff --git a/stdlib/public/SDK/Intents/INRideOption.swift b/stdlib/public/SDK/Intents/INRideOption.swift
index c6b8959..4ae1f29 100644
--- a/stdlib/public/SDK/Intents/INRideOption.swift
+++ b/stdlib/public/SDK/Intents/INRideOption.swift
@@ -26,7 +26,7 @@
extension _INRideOptionMeteredFare {
@available(swift, obsoleted: 4)
@nonobjc
- public final var usesMeteredFare: NSNumber? {
+ public var usesMeteredFare: NSNumber? {
get {
return __usesMeteredFare
}
diff --git a/stdlib/public/SDK/Metal/CMakeLists.txt b/stdlib/public/SDK/Metal/CMakeLists.txt
index f3fe951..4ea2491 100644
--- a/stdlib/public/SDK/Metal/CMakeLists.txt
+++ b/stdlib/public/SDK/Metal/CMakeLists.txt
@@ -4,7 +4,7 @@
add_swift_library(swiftMetal ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
Metal.swift
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR
SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch Foundation IOKit ObjectiveC XPC # auto-updated
diff --git a/stdlib/public/SDK/MetalKit/CMakeLists.txt b/stdlib/public/SDK/MetalKit/CMakeLists.txt
index b0a2013..a1f8a96 100644
--- a/stdlib/public/SDK/MetalKit/CMakeLists.txt
+++ b/stdlib/public/SDK/MetalKit/CMakeLists.txt
@@ -4,7 +4,7 @@
add_swift_library(swiftMetalKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
MetalKit.swift
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR
SWIFT_MODULE_DEPENDS_OSX Darwin AppKit CoreData CoreFoundation CoreGraphics CoreImage Dispatch Foundation IOKit Metal ModelIO ObjectiveC QuartzCore simd XPC # auto-updated
diff --git a/stdlib/public/SDK/SceneKit/CMakeLists.txt b/stdlib/public/SDK/SceneKit/CMakeLists.txt
index 0f3a360..72b8e44 100644
--- a/stdlib/public/SDK/SceneKit/CMakeLists.txt
+++ b/stdlib/public/SDK/SceneKit/CMakeLists.txt
@@ -4,7 +4,7 @@
add_swift_library(swiftSceneKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
SceneKit.swift.gyb
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR WATCHOS WATCHOS_SIMULATOR
SWIFT_MODULE_DEPENDS_OSX Darwin AppKit CoreData CoreGraphics CoreImage Dispatch Foundation GLKit IOKit ObjectiveC QuartzCore simd XPC # auto-updated
diff --git a/stdlib/public/SDK/UIKit/CMakeLists.txt b/stdlib/public/SDK/UIKit/CMakeLists.txt
index 0022cb83..d8df4eb 100644
--- a/stdlib/public/SDK/UIKit/CMakeLists.txt
+++ b/stdlib/public/SDK/UIKit/CMakeLists.txt
@@ -6,7 +6,7 @@
UIKit.swift
UIKit_FoundationExtensions.swift.gyb
- SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
+ SWIFT_COMPILE_FLAGS ${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS} -swift-version 4
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
TARGET_SDKS IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR WATCHOS WATCHOS_SIMULATOR
SWIFT_MODULE_DEPENDS_IOS Darwin CoreFoundation CoreGraphics CoreImage Dispatch Foundation ObjectiveC QuartzCore os # auto-updated
diff --git a/stdlib/public/SDK/UIKit/UIKit.swift b/stdlib/public/SDK/UIKit/UIKit.swift
index 3823d39..9be02a5 100644
--- a/stdlib/public/SDK/UIKit/UIKit.swift
+++ b/stdlib/public/SDK/UIKit/UIKit.swift
@@ -57,6 +57,52 @@
extension UIOffset : Equatable {}
+//===----------------------------------------------------------------------===//
+// Numeric backed types
+//===----------------------------------------------------------------------===//
+
+@available(swift 4)
+public protocol _UIKitNumericRawRepresentable : RawRepresentable, Comparable where RawValue: Comparable & Numeric {}
+
+extension _UIKitNumericRawRepresentable {
+
+ public static func <(lhs: Self, rhs: Self) -> Bool {
+ return lhs.rawValue < rhs.rawValue
+ }
+
+ public static func +(lhs: Self, rhs: RawValue) -> Self {
+ return Self(rawValue: lhs.rawValue + rhs)!
+ }
+
+ public static func +(lhs: RawValue, rhs: Self) -> Self {
+ return Self(rawValue: lhs + rhs.rawValue)!
+ }
+
+ public static func -(lhs: Self, rhs: RawValue) -> Self {
+ return Self(rawValue: lhs.rawValue - rhs)!
+ }
+
+ public static func -(lhs: Self, rhs: Self) -> RawValue {
+ return lhs.rawValue - rhs.rawValue
+ }
+
+ public static func +=(lhs: inout Self, rhs: RawValue) {
+ lhs = Self(rawValue: lhs.rawValue + rhs)!
+ }
+
+ public static func -=(lhs: inout Self, rhs: RawValue) {
+ lhs = Self(rawValue: lhs.rawValue - rhs)!
+ }
+}
+
+@available(swift 4)
+extension UIFont.Weight : _UIKitNumericRawRepresentable {}
+
+#if !os(watchOS)
+@available(swift 4)
+extension UILayoutPriority : _UIKitNumericRawRepresentable {}
+#endif
+
// These are un-imported macros in UIKit.
//===----------------------------------------------------------------------===//
@@ -247,6 +293,7 @@
#if !os(watchOS) // UIContentSizeCategory not available on watchOS
extension UIContentSizeCategory {
+
@available(iOS 11.0, tvOS 11.0, *)
public var isAccessibilityCategory: Bool {
return __UIContentSizeCategoryIsAccessibilityCategory(self)
diff --git a/stdlib/public/SDK/XCTest/XCTest.swift b/stdlib/public/SDK/XCTest/XCTest.swift
index 918b4b9..01a8494 100644
--- a/stdlib/public/SDK/XCTest/XCTest.swift
+++ b/stdlib/public/SDK/XCTest/XCTest.swift
@@ -42,7 +42,7 @@
@available(macOS 10.11, *)
public extension XCUIElement {
/// Types a single key from the XCUIKeyboardKey enumeration with the specified modifier flags.
- @nonobjc public func typeKey(_ key: XCUIKeyboardKey, modifierFlags: XCUIKeyModifierFlags) {
+ @nonobjc public func typeKey(_ key: XCUIKeyboardKey, modifierFlags: XCUIElement.KeyModifierFlags) {
// Call the version of the method defined in XCTest.framework.
typeKey(key.rawValue, modifierFlags: modifierFlags)
}
@@ -55,11 +55,11 @@
func _XCTRegisterFailure(_ expected: Bool, _ condition: String, _ message: @autoclosure () -> String, _ file: StaticString, _ line: UInt) {
// Call the real _XCTFailureHandler.
let test = _XCTCurrentTestCase()
- _XCTPreformattedFailureHandler(test, expected, file.description, line, condition, message())
+ _XCTPreformattedFailureHandler(test, expected, file.description, Int(line), condition, message())
}
/// Produce a failure description for the given assertion type.
-func _XCTFailureDescription(_ assertionType: _XCTAssertionType, _ formatIndex: UInt, _ expressionStrings: CVarArg...) -> String {
+func _XCTFailureDescription(_ assertionType: _XCTAssertionType, _ formatIndex: Int, _ expressionStrings: CVarArg...) -> String {
// In order to avoid revlock/submission issues between XCTest and the Swift XCTest overlay,
// we are using the convention with _XCTFailureFormat that (formatIndex >= 100) should be
// treated just like (formatIndex - 100), but WITHOUT the expression strings. (Swift can't
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index 260d04e..6aa7709 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -1,3 +1,6 @@
+# HACK: Force this library to build with undefined symbols.
+string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+
# libswiftRemoteMirror.dylib should not have runtime dependencies; it's
# always built as a shared library.
if(SWIFT_BUILD_DYNAMIC_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
diff --git a/stdlib/public/SwiftShims/HeapObject.h b/stdlib/public/SwiftShims/HeapObject.h
index 29b78b9..8c9ae82 100644
--- a/stdlib/public/SwiftShims/HeapObject.h
+++ b/stdlib/public/SwiftShims/HeapObject.h
@@ -16,8 +16,7 @@
#include "System.h"
#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 16
-// TODO: Should be 8
-#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 12
+#define SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 8
#ifdef __cplusplus
#include <type_traits>
@@ -39,12 +38,12 @@
InlineRefCounts refCounts
/// The Swift heap-object header.
+/// This must match RefCountedStructTy in IRGen.
struct HeapObject {
/// This is always a valid pointer to a metadata object.
HeapMetadata const *metadata;
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
- // FIXME: allocate two words of metadata on 32-bit platforms
#ifdef __cplusplus
HeapObject() = default;
@@ -75,15 +74,8 @@
static_assert(std::is_trivially_destructible<HeapObject>::value,
"HeapObject must be trivially destructible");
-// FIXME: small header for 32-bit
-//static_assert(sizeof(HeapObject) == 2*sizeof(void*),
-// "HeapObject must be two pointers long");
-//
-static_assert(sizeof(HeapObject) ==
- (sizeof(void*) == 8 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_64 :
- sizeof(void*) == 4 ? SWIFT_ABI_HEAP_OBJECT_HEADER_SIZE_32 :
- 0 && "unexpected pointer size"),
- "HeapObject must match ABI heap object header size");
+static_assert(sizeof(HeapObject) == 2*sizeof(void*),
+ "HeapObject must be two pointers long");
static_assert(alignof(HeapObject) == alignof(void*),
"HeapObject must be pointer-aligned");
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index 211de02..e1cd7aa 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -15,19 +15,17 @@
#include "Visibility.h"
#include "SwiftStdint.h"
+// This definition is a placeholder for importing into Swift.
+// It provides size and alignment but cannot be manipulated safely there.
+typedef struct {
+ __swift_uintptr_t refCounts SWIFT_ATTRIBUTE_UNAVAILABLE;
+} InlineRefCountsPlaceholder;
+
#if !defined(__cplusplus)
-// These definitions are placeholders for importing into Swift.
-// They provide size and alignment but cannot be manipulated safely there.
+typedef InlineRefCountsPlaceholder InlineRefCounts;
-typedef struct {
- _Alignas(__swift_uintptr_t) __swift_uint32_t refCounts1 SWIFT_ATTRIBUTE_UNAVAILABLE;
- __swift_uint32_t refCounts2 SWIFT_ATTRIBUTE_UNAVAILABLE;
-} InlineRefCounts;
-
-// not __cplusplus
#else
-// __cplusplus
#include <type_traits>
#include <atomic>
@@ -733,11 +731,6 @@
template <typename RefCountBits>
class RefCounts {
std::atomic<RefCountBits> refCounts;
-#if __POINTER_WIDTH__ == 32
- // FIXME: hack - something somewhere is assuming a 3-word header on 32-bit
- // See also other fixmes marked "small header for 32-bit"
- uintptr_t : 32;
-#endif
// Out-of-line slow paths.
@@ -1572,15 +1565,11 @@
#endif
// These assertions apply to both the C and the C++ declarations.
-_Static_assert(_Alignof(InlineRefCounts) == _Alignof(__swift_uintptr_t),
- "InlineRefCounts must be pointer-aligned");
-// FIXME: small header for 32-bit
-#if 0
+_Static_assert(sizeof(InlineRefCounts) == sizeof(InlineRefCountsPlaceholder),
+ "InlineRefCounts and InlineRefCountsPlaceholder must match");
_Static_assert(sizeof(InlineRefCounts) == sizeof(__swift_uintptr_t),
"InlineRefCounts must be pointer-sized");
-#else
-_Static_assert(sizeof(InlineRefCounts) == 2*sizeof(__swift_uint32_t),
- "InlineRefCounts must be 8 bytes");
-#endif
+_Static_assert(_Alignof(InlineRefCounts) == _Alignof(__swift_uintptr_t),
+ "InlineRefCounts must be pointer-aligned");
#endif
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index c9eeeee..d80b233 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -178,7 +178,7 @@
/// can store any kind of elements---from integers to strings to classes.
///
/// Swift makes it easy to create arrays in your code using an array literal:
-/// simply surround a comma separated list of values with square brackets.
+/// simply surround a comma-separated list of values with square brackets.
/// Without any other information, Swift creates an array that includes the
/// specified values, automatically inferring the array's `Element` type. For
/// example:
@@ -2181,57 +2181,55 @@
// that are the same, e.g. Array<Int> and Array<Int>, not
// ArraySlice<Int> and Array<Int>.
-/// Returns `true` if these arrays contain the same elements.
-@_inlineable
-public func == <Element : Equatable>(
- lhs: ${Self}<Element>, rhs: ${Self}<Element>
-) -> Bool {
- let lhsCount = lhs.count
- if lhsCount != rhs.count {
- return false
- }
+extension ${Self} : Equatable where Element : Equatable {
+ /// Returns `true` if these arrays contain the same elements.
+ @_inlineable
+ public static func ==(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
+ let lhsCount = lhs.count
+ if lhsCount != rhs.count {
+ return false
+ }
- // Test referential equality.
- if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
+ // Test referential equality.
+ if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
+ return true
+ }
+
+ %if Self == 'ArraySlice':
+
+ var streamLHS = lhs.makeIterator()
+ var streamRHS = rhs.makeIterator()
+
+ var nextLHS = streamLHS.next()
+ while nextLHS != nil {
+ let nextRHS = streamRHS.next()
+ if nextLHS != nextRHS {
+ return false
+ }
+ nextLHS = streamLHS.next()
+ }
+
+ %else:
+
+ _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
+ _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)
+
+ // We know that lhs.count == rhs.count, compare element wise.
+ for idx in 0..<lhsCount {
+ if lhs[idx] != rhs[idx] {
+ return false
+ }
+ }
+ %end
+
return true
}
-%if Self == 'ArraySlice':
-
- var streamLHS = lhs.makeIterator()
- var streamRHS = rhs.makeIterator()
-
- var nextLHS = streamLHS.next()
- while nextLHS != nil {
- let nextRHS = streamRHS.next()
- if nextLHS != nextRHS {
- return false
- }
- nextLHS = streamLHS.next()
+ /// Returns `true` if the arrays do not contain the same elements.
+ @_inlineable
+ public static func !=(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
+ return !(lhs == rhs)
}
-
-%else:
-
- _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
- _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)
-
- // We know that lhs.count == rhs.count, compare element wise.
- for idx in 0..<lhsCount {
- if lhs[idx] != rhs[idx] {
- return false
- }
- }
-%end
-
- return true
-}
-
-/// Returns `true` if the arrays do not contain the same elements.
-@_inlineable
-public func != <Element : Equatable>(
- lhs: ${Self}<Element>, rhs: ${Self}<Element>
-) -> Bool {
- return !(lhs == rhs)
}
extension ${Self} {
diff --git a/stdlib/public/core/Builtin.swift b/stdlib/public/core/Builtin.swift
index 72e2592..2f06587 100644
--- a/stdlib/public/core/Builtin.swift
+++ b/stdlib/public/core/Builtin.swift
@@ -144,8 +144,13 @@
return !(lhs == rhs)
}
-/// Returns `true` iff `t0` is identical to `t1`; i.e. if they are both
-/// `nil` or they both represent the same type.
+/// Returns a Boolean value indicating whether two types are identical.
+///
+/// - Parameters:
+/// - t0: A type to compare.
+/// - t1: Another type to compare.
+/// - Returns: `true` if both `t0` and `t1` are `nil` or if they represent the
+/// same type; otherwise, `false`.
@_inlineable
public func == (t0: Any.Type?, t1: Any.Type?) -> Bool {
switch (t0, t1) {
@@ -156,8 +161,13 @@
}
}
-/// Returns `false` iff `t0` is identical to `t1`; i.e. if they are both
-/// `nil` or they both represent the same type.
+/// Returns a Boolean value indicating whether two types are not identical.
+///
+/// - Parameters:
+/// - t0: A type to compare.
+/// - t1: Another type to compare.
+/// - Returns: `true` if one, but not both, of `t0` and `t1` are `nil`, or if
+/// they represent different types; otherwise, `false`.
@_inlineable
public func != (t0: Any.Type?, t1: Any.Type?) -> Bool {
return !(t0 == t1)
diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift
index 018b1da..0d3af0d 100644
--- a/stdlib/public/core/CTypes.swift
+++ b/stdlib/public/core/CTypes.swift
@@ -42,17 +42,19 @@
/// The C 'int' type.
public typealias CInt = Int32
-/// The C 'long' type.
#if os(Windows) && arch(x86_64)
+/// The C 'long' type.
public typealias CLong = Int32
#else
+/// The C 'long' type.
public typealias CLong = Int
#endif
-/// The C 'long long' type.
#if os(Windows) && arch(x86_64)
+/// The C 'long long' type.
public typealias CLongLong = Int
#else
+/// The C 'long long' type.
public typealias CLongLong = Int64
#endif
@@ -200,7 +202,7 @@
}
}
-/// The corresponding Swift type to `va_list` in imported C APIs.
+/// A wrapper around a C `va_list` pointer.
@_fixed_layout
public struct CVaListPointer {
@_versioned // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 9526057..dcad518 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -18,8 +18,7 @@
where
// FIXME(ABI)#176 (Type checker)
// WORKAROUND rdar://25214598 - should be Bound : Strideable
- Bound : _Strideable & Comparable,
- Bound.Stride : BinaryInteger {
+ Bound : _Strideable & Comparable {
case pastEnd
case inRange(Bound)
}
@@ -36,7 +35,7 @@
// CountableClosedRange is not interchangeable with CountableRange in all
// contexts.
Bound : _Strideable & Comparable,
- Bound.Stride : SignedInteger {
+ Bound.Stride : SignedNumeric {
/// Creates the "past the end" position.
@_inlineable
@_versioned
diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift
index 462c6cc..e7e2e05 100644
--- a/stdlib/public/core/Codable.swift
+++ b/stdlib/public/core/Codable.swift
@@ -1166,8 +1166,8 @@
// An implementation of _KeyedDecodingContainerBase and _KeyedDecodingContainerBox are given at the bottom of this file.
-/// A concrete container that provides a view into an decoder's storage, making
-/// the encoded properties of an decodable type accessible by keys.
+/// A concrete container that provides a view into a decoder's storage, making
+/// the encoded properties of a decodable type accessible by keys.
@_fixed_layout // FIXME(sil-serialize-all)
public struct KeyedDecodingContainer<K : CodingKey> : KeyedDecodingContainerProtocol {
public typealias Key = K
@@ -2307,7 +2307,8 @@
mutating func encode<T : Encodable>(_ value: T) throws
}
-/// A `SingleValueDecodingContainer` is a container which can support the storage and direct decoding of a single non-keyed value.
+/// A container that can support the storage and direct decoding of a single
+/// nonkeyed value.
public protocol SingleValueDecodingContainer {
/// The path of coding keys taken to get to this point in encoding.
var codingPath: [CodingKey] { get }
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 567c036..79c021f 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -559,11 +559,11 @@
// in angles in the wrong quadrant if users aren't careful. This is
// not a problem for Double or Float80, as pi rounds down in both of
// those formats.
- return Float(0x1.921fb4p1)
+ return 0x1.921fb4p1
%elif bits == 64:
- return Double(0x1.921fb54442d18p1)
+ return 0x1.921fb54442d18p1
%elif bits == 80:
- return Float80(0x1.921fb54442d1846ap1)
+ return 0x1.921fb54442d1846ap1
%end
}
@@ -1503,8 +1503,9 @@
public init?(exactly value: ${That}) {
_value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(value._value)
-% if srcBits < SignificandBitCount:
- if ${That}(self) != value {
+% if srcBits >= SignificandBitCount:
+ guard let roundTrip = ${That}(exactly: self),
+ roundTrip == value else {
return nil
}
% end
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/HashedCollections.swift.gyb
index 36f88c8..12433e3 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/HashedCollections.swift.gyb
@@ -2708,7 +2708,7 @@
}
}
-extension Dictionary where Value : Equatable {
+extension Dictionary : Equatable where Value : Equatable {
@_inlineable // FIXME(sil-serialize-all)
public static func == (lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
switch (lhs._variantBuffer, rhs._variantBuffer) {
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 020ff15..2f8a39d 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -1620,8 +1620,8 @@
// on `Self` to prevent dynamically-typed methods from being inherited by
// statically-typed key paths.
-/// This protocol is an implementation detail of key path expressions; do not
-/// use it directly.
+/// An implementation detail of key path expressions; do not use this protocol
+/// directly.
@_show_in_interface
public protocol _AppendKeyPath {}
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index 1f41bd5..92f5b09 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -12,15 +12,31 @@
// FIXME: ExistentialCollection needs to be supported before this will work
// without the ObjC Runtime.
-/// Representation of the sub-structure and optional "display style"
-/// of any arbitrary subject instance.
+/// A representation of the substructure and display style of an instance of
+/// any type.
///
-/// Describes the parts---such as stored properties, collection
-/// elements, tuple elements, or the active enumeration case---that
-/// make up a particular instance. May also supply a "display style"
-/// property that suggests how this structure might be rendered.
+/// A mirror describes the parts that make up a particular instance, such as
+/// the instance's stored properties, collection or tuple elements, or its
+/// active enumeration case. Mirrors also provide a "display style" property
+/// that suggests how this mirror might be rendered.
///
-/// Mirrors are used by playgrounds and the debugger.
+/// Playgrounds and the debugger use the `Mirror` type to display
+/// representations of values of any type. For example, when you pass an
+/// instance to the `dump(_:_:_:_:)` function, a mirror is used to render that
+/// instance's runtime contents.
+///
+/// struct Point {
+/// let x: Int, y: Int
+/// }
+///
+/// let p = Point(x: 21, y: 30)
+/// print(String(reflecting: p))
+/// // Prints "▿ Point
+/// // - x: 21
+/// // - y: 30"
+///
+/// To customize the mirror representation of a custom type, add conformance to
+/// the `CustomReflectable` protocol.
@_fixed_layout // FIXME(sil-serialize-all)
public struct Mirror {
/// Representation of descendant classes that don't override
@@ -46,56 +62,58 @@
case suppressed
}
- /// Representation of ancestor classes.
+ /// The representation to use for ancestor classes.
///
- /// A `CustomReflectable` class can control how its mirror will
- /// represent ancestor classes by initializing the mirror with a
- /// `AncestorRepresentation`. This setting has no effect on mirrors
+ /// A class that conforms to the `CustomReflectable` protocol can control how
+ /// its mirror represents ancestor classes by initializing the mirror
+ /// with an `AncestorRepresentation`. This setting has no effect on mirrors
/// reflecting value type instances.
public enum AncestorRepresentation {
- /// Generate a default mirror for all ancestor classes.
+ /// Generates a default mirror for all ancestor classes.
///
- /// This case is the default.
+ /// This case is the default when initializing a `Mirror` instance.
///
- /// - Note: This option generates default mirrors even for
- /// ancestor classes that may implement `CustomReflectable`'s
- /// `customMirror` requirement. To avoid dropping an ancestor class
- /// customization, an override of `customMirror` should pass
- /// `ancestorRepresentation: .Customized(super.customMirror)` when
- /// initializing its `Mirror`.
+ /// When you use this option, a subclass's mirror generates default mirrors
+ /// even for ancestor classes that conform to the `CustomReflectable`
+ /// protocol. To avoid dropping the customization provided by ancestor
+ /// classes, an override of `customMirror` should pass
+ /// `.customized({ super.customMirror })` as `ancestorRepresentation` when
+ /// initializing its mirror.
case generated
- /// Use the nearest ancestor's implementation of `customMirror` to
- /// create a mirror for that ancestor. Other classes derived from
- /// such an ancestor are given a default mirror.
+ /// Uses the nearest ancestor's implementation of `customMirror` to create
+ /// a mirror for that ancestor.
///
- /// The payload for this option should always be
- /// "`{ super.customMirror }`":
+ /// Other classes derived from such an ancestor are given a default mirror.
+ /// The payload for this option should always be `{ super.customMirror }`:
///
/// var customMirror: Mirror {
- /// return Mirror(
- /// self,
- /// children: ["someProperty": self.someProperty],
- /// ancestorRepresentation: .Customized({ super.customMirror })) // <==
+ /// return Mirror(
+ /// self,
+ /// children: ["someProperty": self.someProperty],
+ /// ancestorRepresentation: .customized({ super.customMirror })) // <==
/// }
case customized(() -> Mirror)
- /// Suppress the representation of all ancestor classes. The
- /// resulting `Mirror`'s `superclassMirror` is `nil`.
+ /// Suppresses the representation of all ancestor classes.
+ ///
+ /// In a mirror created with this ancestor representation, the
+ /// `superclassMirror` property is `nil`.
case suppressed
}
- /// Reflect upon the given `subject`.
+ /// Creates a mirror that reflects on the given instance.
///
- /// If the dynamic type of `subject` conforms to `CustomReflectable`,
- /// the resulting mirror is determined by its `customMirror` property.
+ /// If the dynamic type of `subject` conforms to `CustomReflectable`, the
+ /// resulting mirror is determined by its `customMirror` property.
/// Otherwise, the result is generated by the language.
///
- /// - Note: If the dynamic type of `subject` has value semantics,
- /// subsequent mutations of `subject` will not observable in
- /// `Mirror`. In general, though, the observability of such
- /// mutations is unspecified.
+ /// If the dynamic type of `subject` has value semantics, subsequent
+ /// mutations of `subject` will not observable in `Mirror`. In general,
+ /// though, the observability of mutations is unspecified.
+ ///
+ /// - Parameter subject: The instance for which to create a mirror.
@_inlineable // FIXME(sil-serialize-all)
public init(reflecting subject: Any) {
if case let customized as CustomReflectable = subject {
@@ -107,36 +125,33 @@
}
}
- /// An element of the reflected instance's structure. The optional
- /// `label` may be used when appropriate, e.g. to represent the name
- /// of a stored property or of an active `enum` case, and will be
- /// used for lookup when `String`s are passed to the `descendant`
- /// method.
+ /// An element of the reflected instance's structure.
+ ///
+ /// When the `label` component in not `nil`, it may represent the name of a
+ /// stored property or an active `enum` case. If you pass strings to the
+ /// `descendant(_:_:)` method, labels are used for lookup.
public typealias Child = (label: String?, value: Any)
- /// The type used to represent sub-structure.
+ /// The type used to represent substructure.
///
- /// Depending on your needs, you may find it useful to "upgrade"
- /// instances of this type to `AnyBidirectionalCollection` or
- /// `AnyRandomAccessCollection`. For example, to display the last
- /// 20 children of a mirror if they can be accessed efficiently, you
- /// might write:
+ /// When working with a mirror that reflects a bidirectional or random access
+ /// collection, you may find it useful to "upgrade" instances of this type
+ /// to `AnyBidirectionalCollection` or `AnyRandomAccessCollection`. For
+ /// example, to display the last twenty children of a mirror if they can be
+ /// accessed efficiently, you write the following code:
///
/// if let b = AnyBidirectionalCollection(someMirror.children) {
- /// var i = xs.index(b.endIndex, offsetBy: -20,
- /// limitedBy: b.startIndex) ?? b.startIndex
- /// while i != xs.endIndex {
- /// print(b[i])
- /// b.formIndex(after: &i)
- /// }
+ /// for element in b.suffix(20) {
+ /// print(element)
+ /// }
/// }
public typealias Children = AnyCollection<Child>
- /// A suggestion of how a `Mirror`'s `subject` is to be interpreted.
+ /// A suggestion of how a mirror's subject is to be interpreted.
///
/// Playgrounds and the debugger will show a representation similar
/// to the one used for instances of the kind indicated by the
- /// `DisplayStyle` case name when the `Mirror` is used for display.
+ /// `DisplayStyle` case name when the mirror is used for display.
@_fixed_layout // FIXME(sil-serialize-all)
public enum DisplayStyle {
case `struct`, `class`, `enum`, tuple, optional, collection
@@ -200,26 +215,31 @@
return Mirror._noSuperclassMirror
}
- /// Represent `subject` with structure described by `children`,
- /// using an optional `displayStyle`.
+ /// Creates a mirror representing the given subject with a specified
+ /// structure.
///
- /// If `subject` is not a class instance, `ancestorRepresentation`
- /// is ignored. Otherwise, `ancestorRepresentation` determines
+ /// You use this initializer from within your type's `customMirror`
+ /// implementation to create a customized mirror.
+ ///
+ /// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
- /// `customMirror` implementations will be used. By default, a
- /// representation is automatically generated and any `customMirror`
- /// implementation is bypassed. To prevent bypassing customized
- /// ancestors, `customMirror` overrides should initialize the
- /// `Mirror` with:
+ /// `customMirror` implementations will be used. By default, the
+ /// `customMirror` implementation of any ancestors is ignored. To prevent
+ /// bypassing customized ancestors, pass
+ /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+ /// parameter when implementing your type's `customMirror` property.
///
- /// ancestorRepresentation: .customized({ super.customMirror })
- ///
- /// - Note: The traversal protocol modeled by `children`'s indices
- /// (`ForwardIndex`, `BidirectionalIndex`, or
- /// `RandomAccessIndex`) is captured so that the resulting
- /// `Mirror`'s `children` may be upgraded later. See the failable
- /// initializers of `AnyBidirectionalCollection` and
- /// `AnyRandomAccessCollection` for details.
+ /// - Parameters:
+ /// - subject: The instance to represent in the new mirror.
+ /// - children: The structure to use for the mirror. The collection
+ /// traversal modeled by `children` is captured so that the resulting
+ /// mirror's children may be upgraded to a bidirectional or random
+ /// access collection later. See the `children` property for details.
+ /// - displayStyle: The preferred display style for the mirror when
+ /// presented in the debugger or in a playground. The default is `nil`.
+ /// - ancestorRepresentation: The means of generating the subject's
+ /// ancestor representation. `ancestorRepresentation` is ignored if
+ /// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject, C : Collection>(
_ subject: Subject,
@@ -239,36 +259,33 @@
= subject is CustomLeafReflectable ? .suppressed : .generated
}
- /// Represent `subject` with child values given by
- /// `unlabeledChildren`, using an optional `displayStyle`. The
- /// result's child labels will all be `nil`.
+ /// Creates a mirror representing the given subject with unlabeled children.
///
- /// This initializer is especially useful for the mirrors of
- /// collections, e.g.:
+ /// You use this initializer from within your type's `customMirror`
+ /// implementation to create a customized mirror, particularly for custom
+ /// types that are collections. The labels of the resulting mirror's
+ /// `children` collection are all `nil`.
///
- /// extension MyArray : CustomReflectable {
- /// var customMirror: Mirror {
- /// return Mirror(self, unlabeledChildren: self, displayStyle: .collection)
- /// }
- /// }
- ///
- /// If `subject` is not a class instance, `ancestorRepresentation`
- /// is ignored. Otherwise, `ancestorRepresentation` determines
+ /// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
- /// `customMirror` implementations will be used. By default, a
- /// representation is automatically generated and any `customMirror`
- /// implementation is bypassed. To prevent bypassing customized
- /// ancestors, `customMirror` overrides should initialize the
- /// `Mirror` with:
+ /// `customMirror` implementations will be used. By default, the
+ /// `customMirror` implementation of any ancestors is ignored. To prevent
+ /// bypassing customized ancestors, pass
+ /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+ /// parameter when implementing your type's `customMirror` property.
///
- /// ancestorRepresentation: .Customized({ super.customMirror })
- ///
- /// - Note: The traversal protocol modeled by `children`'s indices
- /// (`ForwardIndex`, `BidirectionalIndex`, or
- /// `RandomAccessIndex`) is captured so that the resulting
- /// `Mirror`'s `children` may be upgraded later. See the failable
- /// initializers of `AnyBidirectionalCollection` and
- /// `AnyRandomAccessCollection` for details.
+ /// - Parameters:
+ /// - subject: The instance to represent in the new mirror.
+ /// - unlabeledChildren: The children to use for the mirror. The collection
+ /// traversal modeled by `unlabeledChildren` is captured so that the
+ /// resulting mirror's children may be upgraded to a bidirectional or
+ /// random access collection later. See the `children` property for
+ /// details.
+ /// - displayStyle: The preferred display style for the mirror when
+ /// presented in the debugger or in a playground. The default is `nil`.
+ /// - ancestorRepresentation: The means of generating the subject's
+ /// ancestor representation. `ancestorRepresentation` is ignored if
+ /// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject, C : Collection>(
_ subject: Subject,
@@ -291,29 +308,35 @@
= subject is CustomLeafReflectable ? .suppressed : .generated
}
- /// Represent `subject` with labeled structure described by
- /// `children`, using an optional `displayStyle`.
+ /// Creates a mirror representing the given subject using a dictionary
+ /// literal for the structure.
///
- /// Pass a dictionary literal with `String` keys as `children`. Be
- /// aware that although an *actual* `Dictionary` is
- /// arbitrarily-ordered, the ordering of the `Mirror`'s `children`
- /// will exactly match that of the literal you pass.
+ /// You use this initializer from within your type's `customMirror`
+ /// implementation to create a customized mirror. Pass a dictionary literal
+ /// with string keys as `children`. Although an *actual* dictionary is
+ /// arbitrarily-ordered, when you create a mirror with a dictionary literal,
+ /// the ordering of the mirror's `children` will exactly match that of the
+ /// literal you pass.
///
- /// If `subject` is not a class instance, `ancestorRepresentation`
- /// is ignored. Otherwise, `ancestorRepresentation` determines
+ /// If `subject` is a class instance, `ancestorRepresentation` determines
/// whether ancestor classes will be represented and whether their
- /// `customMirror` implementations will be used. By default, a
- /// representation is automatically generated and any `customMirror`
- /// implementation is bypassed. To prevent bypassing customized
- /// ancestors, `customMirror` overrides should initialize the
- /// `Mirror` with:
+ /// `customMirror` implementations will be used. By default, the
+ /// `customMirror` implementation of any ancestors is ignored. To prevent
+ /// bypassing customized ancestors, pass
+ /// `.customized({ super.customMirror })` as the `ancestorRepresentation`
+ /// parameter when implementing your type's `customMirror` property.
///
- /// ancestorRepresentation: .customized({ super.customMirror })
- ///
- /// - Note: The resulting `Mirror`'s `children` may be upgraded to
- /// `AnyRandomAccessCollection` later. See the failable
- /// initializers of `AnyBidirectionalCollection` and
- /// `AnyRandomAccessCollection` for details.
+ /// - Parameters:
+ /// - subject: The instance to represent in the new mirror.
+ /// - children: A dictionary literal to use as the structure for the
+ /// mirror. The `children` collection of the resulting mirror may be
+ /// upgraded to a random access collection later. See the `children`
+ /// property for details.
+ /// - displayStyle: The preferred display style for the mirror when
+ /// presented in the debugger or in a playground. The default is `nil`.
+ /// - ancestorRepresentation: The means of generating the subject's
+ /// ancestor representation. `ancestorRepresentation` is ignored if
+ /// `subject` is not a class instance. The default is `.generated`.
@_inlineable // FIXME(sil-serialize-all)
public init<Subject>(
_ subject: Subject,
@@ -335,7 +358,7 @@
/// The static type of the subject being reflected.
///
- /// This type may differ from the subject's dynamic type when `self`
+ /// This type may differ from the subject's dynamic type when this mirror
/// is the `superclassMirror` of another mirror.
public let subjectType: Any.Type
@@ -343,9 +366,10 @@
/// reflected subject.
public let children: Children
- /// Suggests a display style for the reflected subject.
+ /// A suggested display style for the reflected subject.
public let displayStyle: DisplayStyle?
+ /// A mirror of the subject's superclass, if one exists.
@_inlineable // FIXME(sil-serialize-all)
public var superclassMirror: Mirror? {
return _makeSuperclassMirror()
@@ -359,7 +383,7 @@
/// A type that explicitly supplies its own mirror.
///
-/// You can create a mirror for any type using the `Mirror(reflect:)`
+/// You can create a mirror for any type using the `Mirror(reflecting:)`
/// initializer, but if you are not satisfied with the mirror supplied for
/// your type by default, you can make it conform to `CustomReflectable` and
/// return a custom `Mirror` instance.
@@ -383,9 +407,10 @@
///
/// Do not declare new conformances to this protocol; they will not
/// work as expected.
-// FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and you shouldn't be able to
-// create conformances.
-public protocol MirrorPath {}
+public protocol MirrorPath {
+ // FIXME(ABI)#49 (Sealed Protocols): this protocol should be "non-open" and
+ // you shouldn't be able to create conformances.
+}
extension Int : MirrorPath {}
extension String : MirrorPath {}
@@ -405,42 +430,50 @@
internal var customMirror: Mirror { return mirror }
}
- /// Return a specific descendant of the reflected subject, or `nil`
- /// Returns a specific descendant of the reflected subject, or `nil`
- /// if no such descendant exists.
+ /// Returns a specific descendant of the reflected subject, or `nil` if no
+ /// such descendant exists.
///
- /// A `String` argument selects the first `Child` with a matching label.
- /// An integer argument *n* select the *n*th `Child`. For example:
+ /// Pass a variadic list of string and integer arguments. Each string
+ /// argument selects the first child with a matching label. Each integer
+ /// argument selects the child at that offset. For example, passing
+ /// `1, "two", 3` as arguments to `myMirror.descendant(_:_:)` is equivalent
+ /// to:
///
- /// var d = Mirror(reflecting: x).descendant(1, "two", 3)
- ///
- /// is equivalent to:
- ///
- /// var d = nil
- /// let children = Mirror(reflecting: x).children
- /// if let p0 = children.index(children.startIndex,
- /// offsetBy: 1, limitedBy: children.endIndex) {
- /// let grandChildren = Mirror(reflecting: children[p0].value).children
- /// SeekTwo: for g in grandChildren {
- /// if g.label == "two" {
- /// let greatGrandChildren = Mirror(reflecting: g.value).children
- /// if let p1 = greatGrandChildren.index(
- /// greatGrandChildren.startIndex,
- /// offsetBy: 3, limitedBy: greatGrandChildren.endIndex) {
- /// d = greatGrandChildren[p1].value
- /// }
- /// break SeekTwo
+ /// var result: Any? = nil
+ /// let children = myMirror.children
+ /// if let i0 = children.index(
+ /// children.startIndex, offsetBy: 1, limitedBy: children.endIndex),
+ /// i0 != children.endIndex
+ /// {
+ /// let grandChildren = Mirror(reflecting: children[i0].value).children
+ /// if let i1 = grandChildren.index(where: { $0.label == "two" }) {
+ /// let greatGrandChildren =
+ /// Mirror(reflecting: grandChildren[i1].value).children
+ /// if let i2 = greatGrandChildren.index(
+ /// greatGrandChildren.startIndex,
+ /// offsetBy: 3,
+ /// limitedBy: greatGrandChildren.endIndex),
+ /// i2 != greatGrandChildren.endIndex
+ /// {
+ /// // Success!
+ /// result = greatGrandChildren[i2].value
+ /// }
/// }
- /// }
/// }
///
- /// As you can see, complexity for each element of the argument list
- /// depends on the argument type and capabilities of the collection
- /// used to initialize the corresponding subject's parent's mirror.
- /// Each `String` argument results in a linear search. In short,
- /// this function is suitable for exploring the structure of a
- /// `Mirror` in a REPL or playground, but don't expect it to be
- /// efficient.
+ /// This function is suitable for exploring the structure of a mirror in a
+ /// REPL or playground, but is not intended to be efficient. The efficiency
+ /// of finding each element in the argument list depends on the argument
+ /// type and the capabilities of the each level of the mirror's `children`
+ /// collections. Each string argument requires a linear search, and unless
+ /// the underlying collection supports random-access traversal, each integer
+ /// argument also requires a linear operation.
+ ///
+ /// - Parameters:
+ /// - first: The first mirror path component to access.
+ /// - rest: Any remaining mirror path components.
+ /// - Returns: The descendant of this mirror specified by the given mirror
+ /// path components if such a descendant exists; otherwise, `nil`.
@_inlineable // FIXME(sil-serialize-all)
public func descendant(
_ first: MirrorPath, _ rest: MirrorPath...
@@ -698,19 +731,20 @@
}
extension PlaygroundQuickLook {
- /// Initialize for the given `subject`.
+ /// Creates a new Quick Look for the given instance.
///
/// If the dynamic type of `subject` conforms to
- /// `CustomPlaygroundQuickLookable`, returns the result of calling
- /// its `customPlaygroundQuickLook` property. Otherwise, returns
- /// a `PlaygroundQuickLook` synthesized for `subject` by the
- /// language. Note that in some cases the result may be
- /// `.Text(String(reflecting: subject))`.
+ /// `CustomPlaygroundQuickLookable`, the result is found by calling its
+ /// `customPlaygroundQuickLook` property. Otherwise, the result is
+ /// synthesized by the language. In some cases, the synthesized result may
+ /// be `.text(String(reflecting: subject))`.
///
- /// - Note: If the dynamic type of `subject` has value semantics,
- /// subsequent mutations of `subject` will not observable in
- /// `Mirror`. In general, though, the observability of such
- /// mutations is unspecified.
+ /// - Note: If the dynamic type of `subject` has value semantics, subsequent
+ /// mutations of `subject` will not observable in the Quick Look. In
+ /// general, though, the observability of such mutations is unspecified.
+ ///
+ /// - Parameter subject: The instance to represent with the resulting Quick
+ /// Look.
@_inlineable // FIXME(sil-serialize-all)
public init(reflecting subject: Any) {
if let customized = subject as? CustomPlaygroundQuickLookable {
diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift
index 72ce864..459b249 100644
--- a/stdlib/public/core/Optional.swift
+++ b/stdlib/public/core/Optional.swift
@@ -313,98 +313,100 @@
line: UInt(_line))
}
-/// Returns a Boolean value indicating whether two optional instances are
-/// equal.
-///
-/// Use this equal-to operator (`==`) to compare any two optional instances of
-/// a type that conforms to the `Equatable` protocol. The comparison returns
-/// `true` if both arguments are `nil` or if the two arguments wrap values
-/// that are equal. Conversely, the comparison returns `false` if only one of
-/// the arguments is `nil` or if the two arguments wrap values that are not
-/// equal.
-///
-/// let group1 = [1, 2, 3, 4, 5]
-/// let group2 = [1, 3, 5, 7, 9]
-/// if group1.first == group2.first {
-/// print("The two groups start the same.")
-/// }
-/// // Prints "The two groups start the same."
-///
-/// You can also use this operator to compare a non-optional value to an
-/// optional that wraps the same type. The non-optional value is wrapped as an
-/// optional before the comparison is made. In the following example, the
-/// `numberToMatch` constant is wrapped as an optional before comparing to the
-/// optional `numberFromString`:
-///
-/// let numberToFind: Int = 23
-/// let numberFromString: Int? = Int("23") // Optional(23)
-/// if numberToFind == numberFromString {
-/// print("It's a match!")
-/// }
-/// // Prints "It's a match!"
-///
-/// An instance that is expressed as a literal can also be used with this
-/// operator. In the next example, an integer literal is compared with the
-/// optional integer `numberFromString`. The literal `23` is inferred as an
-/// `Int` instance and then wrapped as an optional before the comparison is
-/// performed.
-///
-/// if 23 == numberFromString {
-/// print("It's a match!")
-/// }
-/// // Prints "It's a match!"
-///
-/// - Parameters:
-/// - lhs: An optional value to compare.
-/// - rhs: Another optional value to compare.
-@_inlineable
-public func == <T: Equatable>(lhs: T?, rhs: T?) -> Bool {
- switch (lhs, rhs) {
- case let (l?, r?):
- return l == r
- case (nil, nil):
- return true
- default:
- return false
+extension Optional : Equatable where Wrapped : Equatable {
+ /// Returns a Boolean value indicating whether two optional instances are
+ /// equal.
+ ///
+ /// Use this equal-to operator (`==`) to compare any two optional instances of
+ /// a type that conforms to the `Equatable` protocol. The comparison returns
+ /// `true` if both arguments are `nil` or if the two arguments wrap values
+ /// that are equal. Conversely, the comparison returns `false` if only one of
+ /// the arguments is `nil` or if the two arguments wrap values that are not
+ /// equal.
+ ///
+ /// let group1 = [1, 2, 3, 4, 5]
+ /// let group2 = [1, 3, 5, 7, 9]
+ /// if group1.first == group2.first {
+ /// print("The two groups start the same.")
+ /// }
+ /// // Prints "The two groups start the same."
+ ///
+ /// You can also use this operator to compare a non-optional value to an
+ /// optional that wraps the same type. The non-optional value is wrapped as an
+ /// optional before the comparison is made. In the following example, the
+ /// `numberToMatch` constant is wrapped as an optional before comparing to the
+ /// optional `numberFromString`:
+ ///
+ /// let numberToFind: Int = 23
+ /// let numberFromString: Int? = Int("23") // Optional(23)
+ /// if numberToFind == numberFromString {
+ /// print("It's a match!")
+ /// }
+ /// // Prints "It's a match!"
+ ///
+ /// An instance that is expressed as a literal can also be used with this
+ /// operator. In the next example, an integer literal is compared with the
+ /// optional integer `numberFromString`. The literal `23` is inferred as an
+ /// `Int` instance and then wrapped as an optional before the comparison is
+ /// performed.
+ ///
+ /// if 23 == numberFromString {
+ /// print("It's a match!")
+ /// }
+ /// // Prints "It's a match!"
+ ///
+ /// - Parameters:
+ /// - lhs: An optional value to compare.
+ /// - rhs: Another optional value to compare.
+ @_inlineable
+ public static func ==(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
+ switch (lhs, rhs) {
+ case let (l?, r?):
+ return l == r
+ case (nil, nil):
+ return true
+ default:
+ return false
+ }
}
-}
-
-/// Returns a Boolean value indicating whether two optional instances are not
-/// equal.
-///
-/// Use this not-equal-to operator (`!=`) to compare any two optional instances
-/// of a type that conforms to the `Equatable` protocol. The comparison
-/// returns `true` if only one of the arguments is `nil` or if the two
-/// arguments wrap values that are not equal. The comparison returns `false`
-/// if both arguments are `nil` or if the two arguments wrap values that are
-/// equal.
-///
-/// let group1 = [2, 4, 6, 8, 10]
-/// let group2 = [1, 3, 5, 7, 9]
-/// if group1.first != group2.first {
-/// print("The two groups start differently.")
-/// }
-/// // Prints "The two groups start differently."
-///
-/// You can also use this operator to compare a non-optional value to an
-/// optional that wraps the same type. The non-optional value is wrapped as an
-/// optional before the comparison is made. In this example, the
-/// `numberToMatch` constant is wrapped as an optional before comparing to the
-/// optional `numberFromString`:
-///
-/// let numberToFind: Int = 23
-/// let numberFromString: Int? = Int("not-a-number") // nil
-/// if numberToFind != numberFromString {
-/// print("No match.")
-/// }
-/// // Prints "No match."
-///
-/// - Parameters:
-/// - lhs: An optional value to compare.
-/// - rhs: Another optional value to compare.
-@_inlineable
-public func != <T : Equatable>(lhs: T?, rhs: T?) -> Bool {
- return !(lhs == rhs)
+
+ /// Returns a Boolean value indicating whether two optional instances are not
+ /// equal.
+ ///
+ /// Use this not-equal-to operator (`!=`) to compare any two optional instances
+ /// of a type that conforms to the `Equatable` protocol. The comparison
+ /// returns `true` if only one of the arguments is `nil` or if the two
+ /// arguments wrap values that are not equal. The comparison returns `false`
+ /// if both arguments are `nil` or if the two arguments wrap values that are
+ /// equal.
+ ///
+ /// let group1 = [2, 4, 6, 8, 10]
+ /// let group2 = [1, 3, 5, 7, 9]
+ /// if group1.first != group2.first {
+ /// print("The two groups start differently.")
+ /// }
+ /// // Prints "The two groups start differently."
+ ///
+ /// You can also use this operator to compare a non-optional value to an
+ /// optional that wraps the same type. The non-optional value is wrapped as an
+ /// optional before the comparison is made. In this example, the
+ /// `numberToMatch` constant is wrapped as an optional before comparing to the
+ /// optional `numberFromString`:
+ ///
+ /// let numberToFind: Int = 23
+ /// let numberFromString: Int? = Int("not-a-number") // nil
+ /// if numberToFind != numberFromString {
+ /// print("No match.")
+ /// }
+ /// // Prints "No match."
+ ///
+ /// - Parameters:
+ /// - lhs: An optional value to compare.
+ /// - rhs: Another optional value to compare.
+ @_inlineable
+ public static func !=(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
+ return !(lhs == rhs)
+ }
}
// Enable pattern matching against the nil literal, even if the element type
@@ -418,175 +420,177 @@
}
}
-/// Returns a Boolean value indicating whether an argument matches `nil`.
-///
-/// You can use the pattern-matching operator (`~=`) to test whether an
-/// optional instance is `nil` even when the wrapped value's type does not
-/// conform to the `Equatable` protocol. The pattern-matching operator is used
-/// internally in `case` statements for pattern matching.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type, and then uses a `switch`
-/// statement to determine whether the stream is `nil` or has a configured
-/// value. When evaluating the `nil` case of the `switch` statement, this
-/// operator is called behind the scenes.
-///
-/// var stream: DataStream? = nil
-/// switch stream {
-/// case nil:
-/// print("No data stream is configured.")
-/// case let x?:
-/// print("The data stream has \(x.availableBytes) bytes available.")
-/// }
-/// // Prints "No data stream is configured."
-///
-/// - Note: To test whether an instance is `nil` in an `if` statement, use the
-/// equal-to operator (`==`) instead of the pattern-matching operator. The
-/// pattern-matching operator is primarily intended to enable `case`
-/// statement pattern matching.
-///
-/// - Parameters:
-/// - lhs: A `nil` literal.
-/// - rhs: A value to match against `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func ~= <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
- switch rhs {
- case .some(_):
- return false
- case .none:
- return true
+extension Optional {
+ /// Returns a Boolean value indicating whether an argument matches `nil`.
+ ///
+ /// You can use the pattern-matching operator (`~=`) to test whether an
+ /// optional instance is `nil` even when the wrapped value's type does not
+ /// conform to the `Equatable` protocol. The pattern-matching operator is used
+ /// internally in `case` statements for pattern matching.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type, and then uses a `switch`
+ /// statement to determine whether the stream is `nil` or has a configured
+ /// value. When evaluating the `nil` case of the `switch` statement, this
+ /// operator is called behind the scenes.
+ ///
+ /// var stream: DataStream? = nil
+ /// switch stream {
+ /// case nil:
+ /// print("No data stream is configured.")
+ /// case let x?:
+ /// print("The data stream has \(x.availableBytes) bytes available.")
+ /// }
+ /// // Prints "No data stream is configured."
+ ///
+ /// - Note: To test whether an instance is `nil` in an `if` statement, use the
+ /// equal-to operator (`==`) instead of the pattern-matching operator. The
+ /// pattern-matching operator is primarily intended to enable `case`
+ /// statement pattern matching.
+ ///
+ /// - Parameters:
+ /// - lhs: A `nil` literal.
+ /// - rhs: A value to match against `nil`.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func ~=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+ switch rhs {
+ case .some(_):
+ return false
+ case .none:
+ return true
+ }
}
-}
-// Enable equality comparisons against the nil literal, even if the
-// element type isn't equatable
+ // Enable equality comparisons against the nil literal, even if the
+ // element type isn't equatable
-/// Returns a Boolean value indicating whether the left-hand-side argument is
-/// `nil`.
-///
-/// You can use this equal-to operator (`==`) to test whether an optional
-/// instance is `nil` even when the wrapped value's type does not conform to
-/// the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` is
-/// `nil`.
-///
-/// var stream: DataStream? = nil
-/// if stream == nil {
-/// print("No data stream is configured.")
-/// }
-/// // Prints "No data stream is configured."
-///
-/// - Parameters:
-/// - lhs: A value to compare to `nil`.
-/// - rhs: A `nil` literal.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func == <T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {
- switch lhs {
- case .some(_):
- return false
- case .none:
- return true
+ /// Returns a Boolean value indicating whether the left-hand-side argument is
+ /// `nil`.
+ ///
+ /// You can use this equal-to operator (`==`) to test whether an optional
+ /// instance is `nil` even when the wrapped value's type does not conform to
+ /// the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` is
+ /// `nil`.
+ ///
+ /// var stream: DataStream? = nil
+ /// if stream == nil {
+ /// print("No data stream is configured.")
+ /// }
+ /// // Prints "No data stream is configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A value to compare to `nil`.
+ /// - rhs: A `nil` literal.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool {
+ switch lhs {
+ case .some(_):
+ return false
+ case .none:
+ return true
+ }
}
-}
-/// Returns a Boolean value indicating whether the left-hand-side argument is
-/// not `nil`.
-///
-/// You can use this not-equal-to operator (`!=`) to test whether an optional
-/// instance is not `nil` even when the wrapped value's type does not conform
-/// to the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` wraps
-/// a value and is therefore not `nil`.
-///
-/// var stream: DataStream? = fetchDataStream()
-/// if stream != nil {
-/// print("The data stream has been configured.")
-/// }
-/// // Prints "The data stream has been configured."
-///
-/// - Parameters:
-/// - lhs: A value to compare to `nil`.
-/// - rhs: A `nil` literal.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func != <T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {
- switch lhs {
- case .some(_):
- return true
- case .none:
- return false
+ /// Returns a Boolean value indicating whether the left-hand-side argument is
+ /// not `nil`.
+ ///
+ /// You can use this not-equal-to operator (`!=`) to test whether an optional
+ /// instance is not `nil` even when the wrapped value's type does not conform
+ /// to the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` wraps
+ /// a value and is therefore not `nil`.
+ ///
+ /// var stream: DataStream? = fetchDataStream()
+ /// if stream != nil {
+ /// print("The data stream has been configured.")
+ /// }
+ /// // Prints "The data stream has been configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A value to compare to `nil`.
+ /// - rhs: A `nil` literal.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func !=(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool {
+ switch lhs {
+ case .some(_):
+ return true
+ case .none:
+ return false
+ }
}
-}
-/// Returns a Boolean value indicating whether the right-hand-side argument is
-/// `nil`.
-///
-/// You can use this equal-to operator (`==`) to test whether an optional
-/// instance is `nil` even when the wrapped value's type does not conform to
-/// the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` is
-/// `nil`.
-///
-/// var stream: DataStream? = nil
-/// if nil == stream {
-/// print("No data stream is configured.")
-/// }
-/// // Prints "No data stream is configured."
-///
-/// - Parameters:
-/// - lhs: A `nil` literal.
-/// - rhs: A value to compare to `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func == <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
- switch rhs {
- case .some(_):
- return false
- case .none:
- return true
+ /// Returns a Boolean value indicating whether the right-hand-side argument is
+ /// `nil`.
+ ///
+ /// You can use this equal-to operator (`==`) to test whether an optional
+ /// instance is `nil` even when the wrapped value's type does not conform to
+ /// the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` is
+ /// `nil`.
+ ///
+ /// var stream: DataStream? = nil
+ /// if nil == stream {
+ /// print("No data stream is configured.")
+ /// }
+ /// // Prints "No data stream is configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A `nil` literal.
+ /// - rhs: A value to compare to `nil`.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func ==(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+ switch rhs {
+ case .some(_):
+ return false
+ case .none:
+ return true
+ }
}
-}
-/// Returns a Boolean value indicating whether the right-hand-side argument is
-/// not `nil`.
-///
-/// You can use this not-equal-to operator (`!=`) to test whether an optional
-/// instance is not `nil` even when the wrapped value's type does not conform
-/// to the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` wraps
-/// a value and is therefore not `nil`.
-///
-/// var stream: DataStream? = fetchDataStream()
-/// if nil != stream {
-/// print("The data stream has been configured.")
-/// }
-/// // Prints "The data stream has been configured."
-///
-/// - Parameters:
-/// - lhs: A `nil` literal.
-/// - rhs: A value to compare to `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func != <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
- switch rhs {
- case .some(_):
- return true
- case .none:
- return false
+ /// Returns a Boolean value indicating whether the right-hand-side argument is
+ /// not `nil`.
+ ///
+ /// You can use this not-equal-to operator (`!=`) to test whether an optional
+ /// instance is not `nil` even when the wrapped value's type does not conform
+ /// to the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` wraps
+ /// a value and is therefore not `nil`.
+ ///
+ /// var stream: DataStream? = fetchDataStream()
+ /// if nil != stream {
+ /// print("The data stream has been configured.")
+ /// }
+ /// // Prints "The data stream has been configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A `nil` literal.
+ /// - rhs: A value to compare to `nil`.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func !=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+ switch rhs {
+ case .some(_):
+ return true
+ case .none:
+ return false
+ }
}
}
diff --git a/stdlib/public/core/Policy.swift b/stdlib/public/core/Policy.swift
index e4649b7..8128f8c 100644
--- a/stdlib/public/core/Policy.swift
+++ b/stdlib/public/core/Policy.swift
@@ -15,8 +15,8 @@
//===----------------------------------------------------------------------===//
// Standardized uninhabited type
//===----------------------------------------------------------------------===//
-/// The return type of functions that do not return normally; a type with no
-/// values.
+/// The return type of functions that do not return normally, that is, a type
+/// with no values.
///
/// Use `Never` as the return type when declaring a closure, function, or
/// method that unconditionally throws an error, traps, or otherwise does
@@ -31,16 +31,16 @@
//===----------------------------------------------------------------------===//
// Standardized aliases
//===----------------------------------------------------------------------===//
-/// The return type of functions that don't explicitly specify a return type;
-/// an empty tuple (i.e., `()`).
+/// The return type of functions that don't explicitly specify a return type,
+/// that is, an empty tuple `()`.
///
/// When declaring a function or method, you don't need to specify a return
/// type if no value will be returned. However, the type of a function,
/// method, or closure always includes a return type, which is `Void` if
/// otherwise unspecified.
///
-/// Use `Void` or an empty tuple as the return type when declaring a
-/// closure, function, or method that doesn't return a value.
+/// Use `Void` or an empty tuple as the return type when declaring a closure,
+/// function, or method that doesn't return a value.
///
/// // No return type declared:
/// func logMessage(_ s: String) {
diff --git a/stdlib/public/core/Sort.swift.gyb b/stdlib/public/core/Sort.swift.gyb
index b59c8cb..f7992d1 100644
--- a/stdlib/public/core/Sort.swift.gyb
+++ b/stdlib/public/core/Sort.swift.gyb
@@ -406,9 +406,15 @@
% end
// for p in preds
-/// Exchange the values of `a` and `b`.
+/// Exchanges the values of the two arguments.
///
-/// - Precondition: `a` and `b` do not alias each other.
+/// The two arguments must not alias each other. To swap two elements of a
+/// mutable collection, use the `swapAt(_:_:)` method of that collection
+/// instead of this function.
+///
+/// - Parameters:
+/// - a: The first value to swap.
+/// - b: The second value to swap.
@_inlineable
public func swap<T>(_ a: inout T, _ b: inout T) {
// Semantically equivalent to (a, b) = (b, a).
diff --git a/stdlib/public/core/Stride.swift.gyb b/stdlib/public/core/Stride.swift.gyb
index 74792b6..40e2298 100644
--- a/stdlib/public/core/Stride.swift.gyb
+++ b/stdlib/public/core/Stride.swift.gyb
@@ -274,8 +274,126 @@
public var customMirror: Mirror {
return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
}
+
+ // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+ // here until a proper Collection conformance is possible
+ @_inlineable
+ public var underestimatedCount: Int {
+ var it = self.makeIterator()
+ var count = 0
+ while it.next() != nil {
+ count += 1
+ }
+ return count
+ }
}
+// FIXME(conditional-conformances): these extra types can easily be turned into
+// conditional extensions to StrideTo type
+% for Self, ElementConstraint, Where in [
+% ('IntegerStrideToCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
+% ('FloatingPointStrideToCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
+% ]:
+% ElementIsInteger = ElementConstraint == 'BinaryInteger'
+
+internal struct ${Self}<
+ Element : ${ElementConstraint}
+> : RandomAccessCollection, CustomReflectable
+where ${Where} {
+
+//===----------------------------------------------------------------------===//
+// This block is copied from StrideTo struct definition //
+//===----------------------------------------------------------------------===//
+ @_inlineable
+ public func makeIterator() -> StrideToIterator<Element> {
+ return StrideToIterator(_start: _start, end: _end, stride: _stride)
+ }
+
+ @_inlineable
+ public func _customContainsEquatableElement(
+ _ element: Element
+ ) -> Bool? {
+ if element < _start || _end <= element {
+ return false
+ }
+ return nil
+ }
+
+ @_inlineable
+ @_versioned
+ internal init(_start: Element, end: Element, stride: Element.Stride) {
+ _precondition(stride != 0, "Stride size must not be zero")
+ // At start, striding away from end is allowed; it just makes for an
+ // already-empty Sequence.
+ self._start = _start
+ self._end = end
+ self._stride = stride
+ }
+
+ @_versioned
+ internal let _start: Element
+
+ @_versioned
+ internal let _end: Element
+
+ @_versioned
+ internal let _stride: Element.Stride
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public var customMirror: Mirror {
+ return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
+ }
+//===----------------------------------------------------------------------===//
+// The end of the copied block
+//===----------------------------------------------------------------------===//
+
+ // RandomAccessCollection conformance
+ public typealias Index = Int
+ public typealias SubSequence = RandomAccessSlice<${Self}>
+ public typealias Indices = CountableRange<Int>
+
+ public var startIndex: Index { return 0 }
+ public var endIndex: Index { return count }
+
+ public var count: Int {
+ let (start, end, stride) =
+ (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
+% if ElementIsInteger:
+ return Int((start.distance(to: end) - 1) / stride) + 1
+% else:
+ let nonExactCount = (start.distance(to: end)) / stride
+ return Int(nonExactCount.rounded(.toNearestOrAwayFromZero))
+% end
+ }
+
+ public subscript(position: Index) -> Element {
+ _failEarlyRangeCheck(position, bounds: startIndex ..< endIndex)
+ return _indexToElement(position)
+ }
+
+ public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+ _failEarlyRangeCheck(bounds, bounds: startIndex ..< endIndex)
+ return RandomAccessSlice(base: self, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ _failEarlyRangeCheck(i, bounds: startIndex-1 ..< endIndex)
+ return i+1
+ }
+
+ public func index(before i: Index) -> Index {
+ _failEarlyRangeCheck(i, bounds: startIndex+1 ... endIndex)
+ return i-1
+ }
+
+ @inline(__always)
+ internal func _indexToElement(_ i: Index) -> Element {
+ return _start.advanced(by: Element.Stride(i) * _stride)
+ }
+}
+
+% end
+
/// Returns the sequence of values (`self`, `self + stride`, `self +
/// 2 * stride`, ... *last*) where *last* is the last value in the
/// progression that is less than `end`.
@@ -388,8 +506,148 @@
return Mirror(self,
children: ["from": _start, "through": _end, "by": _stride])
}
+
+ // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+ // here until a proper Collection conformance is possible
+ @_inlineable
+ public var underestimatedCount: Int {
+ var it = self.makeIterator()
+ var count = 0
+ while it.next() != nil {
+ count += 1
+ }
+ return count
+ }
}
+// FIXME(conditional-conformances): these extra types can easily be turned into
+// conditional extensions to StrideThrough type
+% for Self, ElementConstraint, Where in [
+% ('IntegerStrideThroughCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
+% ('FloatingPointStrideThroughCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
+% ]:
+% ElementIsInteger = ElementConstraint == 'BinaryInteger'
+
+internal struct ${Self}<
+ Element : ${ElementConstraint}
+> : RandomAccessCollection, CustomReflectable
+where ${Where} {
+
+//===----------------------------------------------------------------------===//
+// This block is copied from StrideThrough struct definition //
+//===----------------------------------------------------------------------===//
+ /// Returns an iterator over the elements of this sequence.
+ ///
+ /// - Complexity: O(1).
+ @_inlineable
+ public func makeIterator() -> StrideThroughIterator<Element> {
+ return StrideThroughIterator(_start: _start, end: _end, stride: _stride)
+ }
+
+ @_inlineable
+ public func _customContainsEquatableElement(
+ _ element: Element
+ ) -> Bool? {
+ if element < _start || _end < element {
+ return false
+ }
+ return nil
+ }
+
+ @_inlineable
+ @_versioned
+ internal init(_start: Element, end: Element, stride: Element.Stride) {
+ _precondition(stride != 0, "Stride size must not be zero")
+ self._start = _start
+ self._end = end
+ self._stride = stride
+ }
+
+ @_versioned
+ internal let _start: Element
+ @_versioned
+ internal let _end: Element
+ @_versioned
+ internal let _stride: Element.Stride
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public var customMirror: Mirror {
+ return Mirror(self,
+ children: ["from": _start, "through": _end, "by": _stride])
+ }
+//===----------------------------------------------------------------------===//
+// The end of the copied block
+//===----------------------------------------------------------------------===//
+
+ // RandomAccessCollection conformance
+ public typealias Index = ClosedRangeIndex<Int>
+ public typealias IndexDistance = Int
+ public typealias SubSequence = RandomAccessSlice<${Self}>
+
+ @_inlineable
+ public var startIndex: Index { return ClosedRangeIndex(0) }
+ @_inlineable
+ public var endIndex: Index { return ClosedRangeIndex() }
+
+ @_inlineable
+ public var count: Int {
+ let (start, end, stride) =
+ (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
+% if ElementIsInteger:
+ return Int(start.distance(to: end) / stride) + 1
+% else:
+ let nonExactCount = start.distance(to: end) / stride
+ return Int(nonExactCount.rounded(.toNearestOrAwayFromZero)) + 1
+% end
+ }
+
+ public subscript(position: Index) -> Element {
+ let offset = Element.Stride(position._dereferenced) * _stride
+ return _start.advanced(by: offset)
+ }
+
+ public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+ return RandomAccessSlice(base: self, bounds: bounds)
+ }
+
+ @_inlineable
+ public func index(before i: Index) -> Index {
+ switch i._value {
+ case .inRange(let n):
+ _precondition(n > 0, "Incrementing past start index")
+ return ClosedRangeIndex(n - 1)
+ case .pastEnd:
+ _precondition(_end >= _start, "Incrementing past start index")
+ return ClosedRangeIndex(count - 1)
+ }
+ }
+
+ @_inlineable
+ public func index(after i: Index) -> Index {
+ switch i._value {
+ case .inRange(let n):
+ return n == (count - 1)
+ ? ClosedRangeIndex()
+ : ClosedRangeIndex(n + 1)
+ case .pastEnd:
+ _preconditionFailure("Incrementing past end index")
+ }
+ }
+
+ // FIXME(ABI)#175 (Type checker)
+ @_inlineable
+ public // WORKAROUND: needed because of rdar://25584401
+ var indices: DefaultRandomAccessIndices<${Self}> {
+ return DefaultRandomAccessIndices(
+ _elements: self,
+ startIndex: self.startIndex,
+ endIndex: self.endIndex)
+ }
+
+}
+
+% end
+
/// Returns the sequence of values (`self`, `self + stride`, `self +
/// 2 * stride`, ... *last*) where *last* is the last value in the
/// progression less than or equal to `end`.
@@ -401,3 +659,4 @@
) -> StrideThrough<T> {
return StrideThrough(_start: start, end: end, stride: stride)
}
+
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 7552225..7339112 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -48,7 +48,7 @@
/// encoding.
///
/// - Parameters:
- /// - codeUnits: A collection of code units encoded in the ecoding
+ /// - codeUnits: A collection of code units encoded in the encoding
/// specified in `sourceEncoding`.
/// - sourceEncoding: The encoding in which `codeUnits` should be
/// interpreted.
@@ -280,7 +280,7 @@
/// encoding.
///
/// - Parameters:
- /// - codeUnits: A collection of code units encoded in the ecoding
+ /// - codeUnits: A collection of code units encoded in the encoding
/// specified in `sourceEncoding`.
/// - sourceEncoding: The encoding in which `codeUnits` should be
/// interpreted.
@@ -673,6 +673,12 @@
@_fixed_layout
public struct String {
/// Creates an empty string.
+ ///
+ /// Using this initializer is equivalent to initializing a string with an
+ /// empty string literal.
+ ///
+ /// let empty = ""
+ /// let alsoEmpty = String()
@_inlineable // FIXME(sil-serialize-all)
public init() {
_core = _StringCore()
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
index 6be2abd..5af0bcd 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -29,6 +29,11 @@
/// let zeroes = String(repeating: "0" as Character, count: 10)
/// print(zeroes)
/// // Prints "0000000000"
+ ///
+ /// - Parameters:
+ /// - repeatedValue: The character to repeat.
+ /// - count: The number of times to repeat `repeatedValue` in the
+ /// resulting string.
@_inlineable // FIXME(sil-serialize-all)
public init(repeating repeatedValue: Character, count: Int) {
self.init(repeating: String(repeatedValue), count: count)
@@ -38,6 +43,22 @@
// that String conforms to Collection:
// - init<T>(_ value: T) where T : LosslessStringConvertible
// - init<S>(_ characters: S) where S : Sequence, S.Element == Character
+
+ /// Creates a new string containing the characters in the given sequence.
+ ///
+ /// You can use this initializer to create a new string from the result of
+ /// one or more collection operations on a string's characters. For example:
+ ///
+ /// let str = "The rain in Spain stays mainly in the plain."
+ ///
+ /// let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
+ /// let disemvoweled = String(str.lazy.filter { !vowels.contains($0) })
+ ///
+ /// print(disemvoweled)
+ /// // Prints "Th rn n Spn stys mnly n th pln."
+ ///
+ /// - Parameter other: A string instance or another sequence of
+ /// characters.
@_inlineable // FIXME(sil-serialize-all)
public init<S : Sequence & LosslessStringConvertible>(_ other: S)
where S.Element == Character {
@@ -171,14 +192,16 @@
/// Accesses the character at the given position.
///
- /// Indices for a subscripting a string are shared with the string's
- /// `characters` view. For example:
+ /// You can use the same indices for subscripting a string and its substring.
+ /// For example, this code finds the first letter after the first space:
///
- /// let greeting = "Hello, friend!"
- /// if let i = greeting.characters.index(where: { $0 >= "A" && $0 <= "Z" }) {
- /// print("First capital letter: \(greeting[i])")
+ /// let str = "Greetings, friend! How are you?"
+ /// let firstSpace = str.index(of: " ") ?? str.endIndex
+ /// let substr = str[firstSpace...]
+ /// if let nextCapital = substr.index(where: { $0 >= "A" && $0 <= "Z" }) {
+ /// print("Capital after a space: \(str[nextCapital])")
/// }
- /// // Prints "First capital letter: H"
+ /// // Prints "Capital after a space: H"
///
/// - Parameter i: A valid index of the string. `i` must be less than the
/// string's end index.
@@ -190,17 +213,18 @@
/// Creates a new string containing the characters in the given sequence.
///
/// You can use this initializer to create a new string from the result of
- /// one or more operations on a string's `characters` view. For example:
+ /// one or more collection operations on a string's characters. For example:
///
/// let str = "The rain in Spain stays mainly in the plain."
///
/// let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
- /// let disemvoweled = String(str.characters.lazy.filter { !vowels.contains($0) })
+ /// let disemvoweled = String(str.lazy.filter { !vowels.contains($0) })
///
/// print(disemvoweled)
/// // Prints "Th rn n Spn stys mnly n th pln."
///
- /// - Parameter characters: A sequence of characters.
+ /// - Parameter characters: A string instance or another sequence of
+ /// characters.
@_inlineable // FIXME(sil-serialize-all)
public init<S : Sequence>(_ characters: S)
where S.Iterator.Element == Character {
@@ -326,7 +350,7 @@
/// removes the hyphen from the middle of a string.
///
/// var nonempty = "non-empty"
- /// if let i = nonempty.characters.index(of: "-") {
+ /// if let i = nonempty.index(of: "-") {
/// nonempty.remove(at: i)
/// }
/// print(nonempty)
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 4c6208d..8c0f007 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -205,7 +205,7 @@
/// encoding.
///
/// - Parameters:
- /// - codeUnits: A collection of code units encoded in the ecoding
+ /// - codeUnits: A collection of code units encoded in the encoding
/// specified in `sourceEncoding`.
/// - sourceEncoding: The encoding in which `codeUnits` should be
/// interpreted.
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index 9b29437..0541c78 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -42,7 +42,7 @@
% for mutable in (True, False):
% Self = 'UnsafeMutableBufferPointer' if mutable else 'UnsafeBufferPointer'
% Mutable = 'Mutable' if mutable else ''
-/// A non-owning collection interface to a buffer of ${Mutable.lower()}
+/// A nonowning collection interface to a buffer of ${Mutable.lower()}
/// elements stored contiguously in memory.
///
/// You can use an `${Self}` instance in low level operations to eliminate
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index cffeb4f..d80f6be 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -10,28 +10,30 @@
//
//===----------------------------------------------------------------------===//
-/// Instances of conforming types can be encoded, and appropriately
-/// passed, as elements of a C `va_list`.
+/// A type whose instances can be encoded, and appropriately passed, as
+/// elements of a C `va_list`.
///
-/// This protocol is useful in presenting C "varargs" APIs natively in
-/// Swift. It only works for APIs that have a `va_list` variant, so
-/// for example, it isn't much use if all you have is:
+/// You use this protocol to present a native Swift interface to a C "varargs"
+/// API. For example, a program can import a C API like the one defined here:
///
-/// ~~~ c
-/// int c_api(int n, ...)
-/// ~~~
-///
-/// Given a version like this, though,
-///
-/// ~~~ c
+/// ~~~c
/// int c_api(int, va_list arguments)
/// ~~~
///
-/// you can write:
+/// To create a wrapper for the `c_api` function, write a function that takes
+/// `CVarArg` arguments, and then call the imported C function using the
+/// `withVaList(_:_:)` function:
///
/// func swiftAPI(_ x: Int, arguments: CVarArg...) -> Int {
-/// return withVaList(arguments) { c_api(x, $0) }
+/// return withVaList(arguments) { c_api(x, $0) }
/// }
+///
+/// Swift only imports C variadic functions that use a `va_list` for their
+/// arguments. C functions that use the `...` syntax for variadic arguments
+/// are not imported, and therefore can't be called using `CVarArg` arguments.
+///
+/// - Note: Declaring conformance to the `CVarArg` protocol for types defined
+/// outside the standard library is not supported.
public protocol CVarArg {
// Note: the protocol is public, but its requirement is stdlib-private.
// That's because there are APIs operating on CVarArg instances, but
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 12536a0..175e17f 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -1920,12 +1920,18 @@
// The result and argument types must match.
if (srcFn->ResultType != targetFn->ResultType)
return _fail(src, srcType, targetType, flags);
- if (srcFn->getNumArguments() != targetFn->getNumArguments())
+ if (srcFn->getNumParameters() != targetFn->getNumParameters())
return _fail(src, srcType, targetType, flags);
- for (unsigned i = 0, e = srcFn->getNumArguments(); i < e; ++i)
- if (srcFn->getArguments()[i] != targetFn->getArguments()[i])
+
+ if (srcFn->hasParameterFlags() != targetFn->hasParameterFlags())
+ return _fail(src, srcType, targetType, flags);
+
+ for (unsigned i = 0, e = srcFn->getNumParameters(); i < e; ++i) {
+ if (srcFn->getParameter(i) != targetFn->getParameter(i) ||
+ srcFn->getParameterFlags(i) != targetFn->getParameterFlags(i))
return _fail(src, srcType, targetType, flags);
-
+ }
+
return _succeed(dest, src, srcType, flags);
}
@@ -3196,7 +3202,7 @@
const Metadata *swift::_swift_class_getSuperclass(const Metadata *theClass) {
if (const ClassMetadata *classType = theClass->getClassObject())
if (classHasSuperclass(classType))
- return swift_getObjCClassMetadata(classType->SuperClass);
+ return getMetadataForClass(classType->SuperClass);
return nullptr;
}
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 3f2aaa1..379151e 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -319,13 +319,19 @@
}
std::vector<NodePointer> inputs;
- for (unsigned i = 0, e = func->getNumArguments(); i < e; ++i) {
- auto arg = func->getArguments()[i];
- auto input = _swift_buildDemanglingForMetadata(arg.getPointer(), Dem);
- if (arg.getFlag()) {
+ for (unsigned i = 0, e = func->getNumParameters(); i < e; ++i) {
+ auto param = func->getParameter(i);
+ auto flags = func->getParameterFlags(i);
+ auto input = _swift_buildDemanglingForMetadata(param, Dem);
+
+ if (flags.isInOut()) {
NodePointer inout = Dem.createNode(Node::Kind::InOut);
inout->addChild(input, Dem);
input = inout;
+ } else if (flags.isShared()) {
+ NodePointer shared = Dem.createNode(Node::Kind::Shared);
+ shared->addChild(input, Dem);
+ input = shared;
}
inputs.push_back(input);
}
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index eb74d49..dfcbea4 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -14,22 +14,23 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/MathExtras.h"
-#include "swift/Demangling/Demangler.h"
+#include "swift/Runtime/Metadata.h"
+#include "MetadataCache.h"
#include "swift/Basic/LLVM.h"
-#include "swift/Basic/Range.h"
#include "swift/Basic/Lazy.h"
+#include "swift/Basic/Range.h"
+#include "swift/Demangling/Demangler.h"
#include "swift/Runtime/Casting.h"
#include "swift/Runtime/HeapObject.h"
-#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Mutex.h"
#include "swift/Strings.h"
-#include "MetadataCache.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
#include <algorithm>
-#include <condition_variable>
-#include <new>
#include <cctype>
+#include <condition_variable>
#include <iostream>
+#include <new>
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
// Avoid defining macro max(), min() which conflict with std::max(), std::min()
@@ -281,8 +282,6 @@
/// The uniquing structure for ObjC class-wrapper metadata.
static SimpleGlobalCache<ObjCClassCacheEntry> ObjCClassWrappers;
-#endif
-
const Metadata *
swift::swift_getObjCClassMetadata(const ClassMetadata *theClass) {
// Make calls resilient against receiving a null Objective-C class. This can
@@ -295,14 +294,24 @@
return theClass;
}
-#if SWIFT_OBJC_INTEROP
return &ObjCClassWrappers.getOrInsert(theClass).first->Data;
-#else
- fatalError(/* flags = */ 0,
- "swift_getObjCClassMetadata: no Objective-C interop");
-#endif
}
+const ClassMetadata *
+swift::swift_getObjCClassFromMetadata(const Metadata *theMetadata) {
+ // Unwrap ObjC class wrappers.
+ if (auto wrapper = dyn_cast<ObjCClassWrapperMetadata>(theMetadata)) {
+ return wrapper->Class;
+ }
+
+ // Otherwise, the input should already be a Swift class object.
+ auto theClass = cast<ClassMetadata>(theMetadata);
+ assert(theClass->isTypeMetadata() && !theClass->isArtificialSubclass());
+ return theClass;
+}
+
+#endif
+
/***************************************************************************/
/*** Functions *************************************************************/
/***************************************************************************/
@@ -314,20 +323,34 @@
FullMetadata<FunctionTypeMetadata> Data;
struct Key {
- const void * const *FlagsArgsAndResult;
+ const FunctionTypeFlags Flags;
- FunctionTypeFlags getFlags() const {
- return FunctionTypeFlags::fromIntValue(size_t(FlagsArgsAndResult[0]));
+ const Metadata *const *Parameters;
+ const uint32_t *ParameterFlags;
+ const Metadata *Result;
+
+ Key(FunctionTypeFlags flags,
+ const Metadata *const *params,
+ const uint32_t *paramFlags,
+ const Metadata *result)
+ : Flags(flags), Parameters(params), ParameterFlags(paramFlags),
+ Result(result) {}
+
+ FunctionTypeFlags getFlags() const { return Flags; }
+ const Metadata *getParameter(unsigned index) const {
+ assert(index < Flags.getNumParameters());
+ return Parameters[index];
+ }
+ const Metadata *getResult() const { return Result; }
+
+ const uint32_t *getParameterFlags() const {
+ return ParameterFlags;
}
- const Metadata *getResult() const {
- auto opaqueResult = FlagsArgsAndResult[getFlags().getNumArguments() + 1];
- return reinterpret_cast<const Metadata *>(opaqueResult);
- }
-
- const void * const *getArguments() const {
- return getFlags().getNumArguments() == 0
- ? nullptr : &FlagsArgsAndResult[1];
+ ::ParameterFlags getParameterFlags(unsigned index) const {
+ assert(index < Flags.getNumParameters());
+ auto flags = Flags.hasParameterFlags() ? ParameterFlags[index] : 0;
+ return ParameterFlags::fromIntValue(flags);
}
};
@@ -346,23 +369,35 @@
if (auto result = comparePointers(key.getResult(), Data.ResultType))
return result;
- for (unsigned i = 0, e = keyFlags.getNumArguments(); i != e; ++i) {
+ for (unsigned i = 0, e = keyFlags.getNumParameters(); i != e; ++i) {
if (auto result =
- comparePointers(key.getArguments()[i],
- Data.getArguments()[i].getOpaqueValue()))
+ comparePointers(key.getParameter(i), Data.getParameter(i)))
+ return result;
+
+ if (auto result =
+ compareIntegers(key.getParameterFlags(i).getIntValue(),
+ Data.getParameterFlags(i).getIntValue()))
return result;
}
return 0;
}
-
static size_t getExtraAllocationSize(Key key) {
- return key.getFlags().getNumArguments()
- * sizeof(FunctionTypeMetadata::Argument);
+ return getExtraAllocationSize(key.Flags);
}
+
size_t getExtraAllocationSize() const {
- return Data.Flags.getNumArguments()
- * sizeof(FunctionTypeMetadata::Argument);
+ return getExtraAllocationSize(Data.Flags);
+ }
+
+ static size_t getExtraAllocationSize(const FunctionTypeFlags flags) {
+ const auto numParams = flags.getNumParameters();
+ auto size = numParams * sizeof(FunctionTypeMetadata::Parameter);
+ if (flags.hasParameterFlags())
+ size += numParams * sizeof(uint32_t);
+
+ const auto alignment = sizeof(void *);
+ return (size + alignment - 1) & ~(alignment - 1);
}
};
@@ -373,53 +408,101 @@
const FunctionTypeMetadata *
swift::swift_getFunctionTypeMetadata1(FunctionTypeFlags flags,
- const void *arg0,
+ const Metadata *arg0,
const Metadata *result) {
- assert(flags.getNumArguments() == 1
+ assert(flags.getNumParameters() == 1
&& "wrong number of arguments in function metadata flags?!");
- const void *flagsArgsAndResult[] = {
- reinterpret_cast<const void*>(flags.getIntValue()),
- arg0,
- static_cast<const void *>(result)
- };
- return swift_getFunctionTypeMetadata(flagsArgsAndResult);
-}
-const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const Metadata *result) {
- assert(flags.getNumArguments() == 2
- && "wrong number of arguments in function metadata flags?!");
- const void *flagsArgsAndResult[] = {
- reinterpret_cast<const void*>(flags.getIntValue()),
- arg0,
- arg1,
- static_cast<const void *>(result)
- };
- return swift_getFunctionTypeMetadata(flagsArgsAndResult);
-}
-const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
- const void *arg0,
- const void *arg1,
- const void *arg2,
- const Metadata *result) {
- assert(flags.getNumArguments() == 3
- && "wrong number of arguments in function metadata flags?!");
- const void *flagsArgsAndResult[] = {
- reinterpret_cast<const void*>(flags.getIntValue()),
- arg0,
- arg1,
- arg2,
- static_cast<const void *>(result)
- };
- return swift_getFunctionTypeMetadata(flagsArgsAndResult);
+ const Metadata *parameters[] = { arg0 };
+ return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
}
const FunctionTypeMetadata *
-swift::swift_getFunctionTypeMetadata(const void *flagsArgsAndResult[]) {
- FunctionCacheEntry::Key key = { flagsArgsAndResult };
+swift::swift_getFunctionTypeMetadata1WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 1
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0 };
+ const uint32_t parameterFlags[] = { flags0.getIntValue() };
+ return swift_getFunctionTypeMetadata(flags,
+ parameters,
+ parameterFlags,
+ result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata2(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 2
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1 };
+ return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata2WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 2
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1 };
+ const uint32_t parameterFlags[] = {
+ flags0.getIntValue(),
+ flags1.getIntValue()
+ };
+ return swift_getFunctionTypeMetadata(flags,
+ parameters,
+ parameterFlags,
+ result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata3(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ const Metadata *arg1,
+ const Metadata *arg2,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 3
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1, arg2 };
+ return swift_getFunctionTypeMetadata(flags, parameters, nullptr, result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata3WithFlags(FunctionTypeFlags flags,
+ const Metadata *arg0,
+ ParameterFlags flags0,
+ const Metadata *arg1,
+ ParameterFlags flags1,
+ const Metadata *arg2,
+ ParameterFlags flags2,
+ const Metadata *result) {
+ assert(flags.getNumParameters() == 3
+ && "wrong number of arguments in function metadata flags?!");
+ const Metadata *parameters[] = { arg0, arg1, arg2 };
+ const uint32_t parameterFlags[] = {
+ flags0.getIntValue(),
+ flags1.getIntValue(),
+ flags2.getIntValue()
+ };
+ return swift_getFunctionTypeMetadata(flags,
+ parameters,
+ parameterFlags,
+ result);
+}
+
+const FunctionTypeMetadata *
+swift::swift_getFunctionTypeMetadata(FunctionTypeFlags flags,
+ const Metadata *const *parameters,
+ const uint32_t *parameterFlags,
+ const Metadata *result) {
+ FunctionCacheEntry::Key key = { flags, parameters, parameterFlags, result };
return &FunctionTypes.getOrInsert(key).first->Data;
}
@@ -450,16 +533,16 @@
break;
}
- unsigned numArguments = flags.getNumArguments();
+ unsigned numParameters = flags.getNumParameters();
Data.setKind(MetadataKind::Function);
Data.Flags = flags;
Data.ResultType = key.getResult();
- for (size_t i = 0; i < numArguments; ++i) {
- auto opaqueArg = key.getArguments()[i];
- auto arg = FunctionTypeMetadata::Argument::getFromOpaqueValue(opaqueArg);
- Data.getArguments()[i] = arg;
+ for (unsigned i = 0; i < numParameters; ++i) {
+ Data.getParameters()[i] = key.getParameter(i);
+ if (flags.hasParameterFlags())
+ Data.getParameterFlags()[i] = key.getParameterFlags(i).getIntValue();
}
}
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index b13716b..f092b76 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -137,8 +137,9 @@
}
case TypeMetadataRecordKind::UniqueDirectClass:
if (auto *ClassMetadata =
- static_cast<const ::ClassMetadata *>(getDirectType()))
- return swift_getObjCClassMetadata(ClassMetadata);
+ static_cast<const ::ClassMetadata *>(getDirectType())) {
+ return getMetadataForClass(ClassMetadata);
+ }
else
return nullptr;
default:
diff --git a/stdlib/public/runtime/Private.h b/stdlib/public/runtime/Private.h
index 0740d8c..7ad8ec9 100644
--- a/stdlib/public/runtime/Private.h
+++ b/stdlib/public/runtime/Private.h
@@ -190,6 +190,14 @@
void (*function)(void *));
#endif
+ static inline const Metadata *getMetadataForClass(const ClassMetadata *c) {
+#if SWIFT_OBJC_INTEROP
+ return swift_getObjCClassMetadata(c);
+#else
+ return c;
+#endif
+ }
+
} // end namespace swift
#endif /* SWIFT_RUNTIME_PRIVATE_H */
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index bd3ce06..2bb5ee1 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -108,14 +108,14 @@
// metadata. The class additionally may be weak-linked, so we have to check
// for null.
if (auto *ClassMetadata = *getIndirectClass())
- return swift_getObjCClassMetadata(ClassMetadata);
+ return getMetadataForClass(ClassMetadata);
return nullptr;
case TypeMetadataRecordKind::UniqueDirectClass:
// The class may be ObjC, in which case we need to instantiate its Swift
// metadata.
if (auto *ClassMetadata = getDirectClass())
- return swift_getObjCClassMetadata(ClassMetadata);
+ return getMetadataForClass(ClassMetadata);
return nullptr;
case TypeMetadataRecordKind::UniqueNominalTypeDescriptor:
@@ -136,7 +136,8 @@
return getStaticWitnessTable();
case ProtocolConformanceReferenceKind::WitnessTableAccessor:
- return getWitnessTableAccessor()(type);
+ // FIXME: this needs information about conditional conformances.
+ return getWitnessTableAccessor()(type, nullptr, 0);
}
swift_runtime_unreachable(
@@ -394,7 +395,7 @@
// If the type is a class, try its superclass.
if (const ClassMetadata *classType = type->getClassObject()) {
if (classHasSuperclass(classType)) {
- type = swift_getObjCClassMetadata(classType->SuperClass);
+ type = getMetadataForClass(classType->SuperClass);
goto recur;
}
}
@@ -433,7 +434,7 @@
// If the type is a class, try its superclass.
if (const ClassMetadata *classType = type->getClassObject()) {
if (classHasSuperclass(classType)) {
- type = swift_getObjCClassMetadata(classType->SuperClass);
+ type = getMetadataForClass(classType->SuperClass);
continue;
}
}
diff --git a/stdlib/public/runtime/Reflection.mm b/stdlib/public/runtime/Reflection.mm
index f407811..be6dc26 100644
--- a/stdlib/public/runtime/Reflection.mm
+++ b/stdlib/public/runtime/Reflection.mm
@@ -295,7 +295,7 @@
const Metadata *type) {
void *object = *reinterpret_cast<void * const *>(value);
auto isa = _swift_getClass(object);
- return swift_getObjCClassMetadata(isa);
+ return getMetadataForClass(isa);
}
static std::tuple<const Metadata *, const OpaqueValue *>
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index d007461..80fa66a 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -105,12 +105,7 @@
const Metadata *swift::swift_getObjectType(HeapObject *object) {
auto classAsMetadata = _swift_getClass(object);
-#if !SWIFT_OBJC_INTEROP
- assert(classAsMetadata &&
- classAsMetadata->isTypeMetadata() &&
- !classAsMetadata->isArtificialSubclass());
- return classAsMetadata;
-#else
+#if SWIFT_OBJC_INTEROP
// Walk up the superclass chain skipping over artifical Swift classes.
// If we find a non-Swift class use the result of [object class] instead.
@@ -129,6 +124,11 @@
}
classAsMetadata = reinterpret_cast<const ClassMetadata *>(objcClass);
return swift_getObjCClassMetadata(classAsMetadata);
+#else
+ assert(classAsMetadata &&
+ classAsMetadata->isTypeMetadata() &&
+ !classAsMetadata->isArtificialSubclass());
+ return classAsMetadata;
#endif
}
diff --git a/stdlib/public/stubs/Stubs.cpp b/stdlib/public/stubs/Stubs.cpp
index 09c7661..0c1fedf 100644
--- a/stdlib/public/stubs/Stubs.cpp
+++ b/stdlib/public/stubs/Stubs.cpp
@@ -35,6 +35,7 @@
#include <unistd.h>
#endif
#include <climits>
+#include <clocale>
#include <cstdarg>
#include <cstdint>
#include <cstdio>
diff --git a/test/ClangImporter/objc_ir.swift b/test/ClangImporter/objc_ir.swift
index 545cab8..51a6692 100644
--- a/test/ClangImporter/objc_ir.swift
+++ b/test/ClangImporter/objc_ir.swift
@@ -5,7 +5,7 @@
// REQUIRES: objc_interop
// REQUIRES: OS=macosx
-// CHECK: [[B:%TSo1BC]] = type
+// CHECK: %TSo1BC = type
import ObjectiveC
import Foundation
@@ -18,7 +18,7 @@
// 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: define hidden swiftcc void @_T07objc_ir15instanceMethodsySo1BCF([[B]]*
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir15instanceMethodsySo1BCF(%TSo1BC*
func instanceMethods(_ b: B) {
// CHECK: load i8*, i8** @"\01L_selector(method:withFloat:)"
// CHECK: call i32 bitcast (void ()* @objc_msgSend to i32
@@ -28,7 +28,7 @@
i = i + b.method(1, with: 2.5 as Double)
}
-// CHECK: define hidden swiftcc void @_T07objc_ir16extensionMethodsySo1BC1b_tF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir16extensionMethodsySo1BC1b_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*
@@ -38,18 +38,18 @@
b.method(1, separateExtMethod:1.5)
}
-// CHECK: define hidden swiftcc void @_T07objc_ir19initCallToAllocInitys5Int32V1i_tF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir19initCallToAllocInitys5Int32V1i_tF
func initCallToAllocInit(i i: CInt) {
// CHECK: call {{.*}} @_T0So1BCSQyABGs5Int32V3int_tcfC
B(int: i)
}
-// CHECK: linkonce_odr hidden {{.*}} @_T0So1BCSQyABGs5Int32V3int_tcfC
+// CHECK-LABEL: linkonce_odr hidden {{.*}} @_T0So1BCSQyABGs5Int32V3int_tcfC
// CHECK: call [[OPAQUE:%.*]]* @objc_allocWithZone
// Indexed subscripting
-// CHECK: define hidden swiftcc void @_T07objc_ir19indexedSubscriptingySo1BC1b_Si3idxSo1AC1atF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir19indexedSubscriptingySo1BC1b_Si3idxSo1AC1atF
func indexedSubscripting(b b: B, idx: Int, a: A) {
// CHECK: load i8*, i8** @"\01L_selector(setObject:atIndexedSubscript:)", align 8
b[idx] = a
@@ -58,7 +58,7 @@
var a2 = b[idx] as! A
}
-// CHECK: define hidden swiftcc void @_T07objc_ir17keyedSubscriptingySo1BC1b_So1AC3idxAG1atF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir17keyedSubscriptingySo1BC1b_So1AC3idxAG1atF
func keyedSubscripting(b b: B, idx: A, a: A) {
// CHECK: load i8*, i8** @"\01L_selector(setObject:forKeyedSubscript:)"
b[a] = a
@@ -66,20 +66,19 @@
var a2 = b[a] as! A
}
-// CHECK: define hidden swiftcc void @_T07objc_ir14propertyAccessySo1BC1b_tF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir14propertyAccessySo1BC1b_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: call %swift.type* @_T0So1BCMa()
- // CHECK: bitcast %swift.type* {{%.+}} to %objc_class*
+ // 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: define hidden swiftcc [[B]]* @_T07objc_ir8downcastSo1BCSo1AC1a_tF(
+// CHECK-LABEL: define hidden swiftcc %TSo1BC* @_T07objc_ir8downcastSo1BCSo1AC1a_tF(
func downcast(a a: A) -> B {
// CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
// CHECK: [[T0:%.*]] = call %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class* [[CLASS]])
@@ -88,12 +87,12 @@
return a as! B
}
-// CHECK: define hidden swiftcc void @_T07objc_ir19almostSubscriptableySo06AlmostD0C3as1_So1AC1atF
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir19almostSubscriptableySo06AlmostD0C3as1_So1AC1atF
func almostSubscriptable(as1 as1: AlmostSubscriptable, a: A) {
as1.objectForKeyedSubscript(a)
}
-// CHECK: define hidden swiftcc void @_T07objc_ir13protocolTypesySo7NSMinceC1a_So9NSRuncing_p1btF(%TSo7NSMinceC*, %objc_object*) {{.*}} {
+// CHECK-LABEL: define hidden swiftcc void @_T07objc_ir13protocolTypesySo7NSMinceC1a_So9NSRuncing_p1btF(%TSo7NSMinceC*, %objc_object*) {{.*}} {
func protocolTypes(a a: NSMince, b: NSRuncing) {
// - (void)eatWith:(id <NSRuncing>)runcer;
a.eat(with: b)
diff --git a/test/Compatibility/accessibility.swift b/test/Compatibility/accessibility.swift
new file mode 100644
index 0000000..fda6d32
--- /dev/null
+++ b/test/Compatibility/accessibility.swift
@@ -0,0 +1,689 @@
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+public protocol PublicProto {
+ func publicReq()
+}
+
+// expected-note@+1 * {{type declared here}}
+internal protocol InternalProto {
+ func internalReq()
+}
+
+fileprivate protocol FilePrivateProto {
+ func filePrivateReq()
+}
+
+// expected-note@+1 * {{type declared here}}
+private protocol PrivateProto {
+ func privateReq()
+}
+
+public struct PublicStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+ private func publicReq() {} // expected-error {{method 'publicReq()' must be declared public because it matches a requirement in public protocol 'PublicProto'}} {{3-10=public}}
+ private func internalReq() {} // expected-error {{method 'internalReq()' must be declared internal because it matches a requirement in internal protocol 'InternalProto'}} {{3-10=internal}}
+ private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+ private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+ public var publicVar = 0
+}
+
+// expected-note@+1 * {{type declared here}}
+internal struct InternalStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+ private func publicReq() {} // expected-error {{method 'publicReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicProto'}} {{3-10=internal}}
+ private func internalReq() {} // expected-error {{method 'internalReq()' must be declared internal because it matches a requirement in internal protocol 'InternalProto'}} {{3-10=internal}}
+ private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+ private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+ public var publicVar = 0
+}
+
+// expected-note@+1 * {{type declared here}}
+fileprivate struct FilePrivateStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+ private func publicReq() {} // expected-error {{method 'publicReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicProto'}} {{3-10=fileprivate}}
+ private func internalReq() {} // expected-error {{method 'internalReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'InternalProto'}} {{3-10=fileprivate}}
+ private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+ private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+ public var publicVar = 0
+}
+
+// expected-note@+1 * {{type declared here}}
+private struct PrivateStruct: PublicProto, InternalProto, FilePrivateProto, PrivateProto {
+ private func publicReq() {} // expected-error {{method 'publicReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicProto'}} {{3-10=fileprivate}}
+ private func internalReq() {} // expected-error {{method 'internalReq()' must be as accessible as its enclosing type because it matches a requirement in protocol 'InternalProto'}} {{3-10=fileprivate}}
+ private func filePrivateReq() {} // expected-error {{method 'filePrivateReq()' must be declared fileprivate because it matches a requirement in fileprivate protocol 'FilePrivateProto'}} {{3-10=fileprivate}}
+ private func privateReq() {} // expected-error {{method 'privateReq()' must be declared fileprivate because it matches a requirement in private protocol 'PrivateProto'}} {{3-10=fileprivate}}
+
+ public var publicVar = 0
+}
+
+extension PublicStruct {
+ public init(x: Int) { self.init() }
+}
+
+extension InternalStruct {
+ public init(x: Int) { self.init() }
+}
+
+extension FilePrivateStruct {
+ public init(x: Int) { self.init() }
+}
+
+extension PrivateStruct {
+ public init(x: Int) { self.init() }
+}
+
+public extension PublicStruct {
+ public func extMemberPublic() {}
+ private func extImplPublic() {}
+}
+internal extension PublicStruct {
+ public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+ private func extImplInternal() {}
+}
+private extension PublicStruct {
+ public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+ private func extImplPrivate() {}
+}
+fileprivate extension PublicStruct {
+ public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+ private func extImplFilePrivate() {}
+}
+public extension InternalStruct { // expected-error {{extension of internal struct cannot be declared public}} {{1-8=}}
+ public func extMemberPublic() {}
+ private func extImplPublic() {}
+}
+internal extension InternalStruct {
+ public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+ private func extImplInternal() {}
+}
+fileprivate extension InternalStruct {
+ public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+ private func extImplFilePrivate() {}
+}
+private extension InternalStruct {
+ public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+ private func extImplPrivate() {}
+}
+public extension FilePrivateStruct { // expected-error {{extension of fileprivate struct cannot be declared public}} {{1-8=}}
+ public func extMemberPublic() {}
+ private func extImplPublic() {}
+}
+internal extension FilePrivateStruct { // expected-error {{extension of fileprivate struct cannot be declared internal}} {{1-10=}}
+ public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+ private func extImplInternal() {}
+}
+fileprivate extension FilePrivateStruct {
+ public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+ private func extImplFilePrivate() {}
+}
+private extension FilePrivateStruct {
+ public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+ private func extImplPrivate() {}
+}
+public extension PrivateStruct { // expected-error {{extension of private struct cannot be declared public}} {{1-8=}}
+ public func extMemberPublic() {}
+ private func extImplPublic() {}
+}
+internal extension PrivateStruct { // expected-error {{extension of private struct cannot be declared internal}} {{1-10=}}
+ public func extMemberInternal() {} // expected-warning {{declaring a public instance method in an internal extension}} {{3-9=internal}}
+ private func extImplInternal() {}
+}
+fileprivate extension PrivateStruct { // expected-error {{extension of private struct cannot be declared fileprivate}} {{1-13=}}
+ public func extMemberFilePrivate() {} // expected-warning {{declaring a public instance method in a fileprivate extension}} {{3-9=fileprivate}}
+ private func extImplFilePrivate() {}
+}
+private extension PrivateStruct {
+ public func extMemberPrivate() {} // expected-warning {{declaring a public instance method in a private extension}} {{3-9=private}}
+ private func extImplPrivate() {}
+}
+
+
+public struct PublicStructDefaultMethods: PublicProto, InternalProto, PrivateProto {
+ func publicReq() {} // expected-error {{method 'publicReq()' must be declared public because it matches a requirement in public protocol 'PublicProto'}} {{3-3=public }}
+ func internalReq() {}
+ func privateReq() {}
+}
+
+
+public class Base {
+ required public init() {}
+ // expected-note@+1 * {{overridden declaration is here}}
+ public func foo() {}
+ // expected-note@+1 * {{overridden declaration is here}}
+ public internal(set) var bar: Int = 0
+ // expected-note@+1 * {{overridden declaration is here}}
+ public subscript () -> () { return () }
+}
+
+
+public extension Base {
+ open func extMemberPublic() {} // expected-warning {{declaring open instance method in public extension}}
+}
+internal extension Base {
+ open func extMemberInternal() {} // expected-warning {{declaring open instance method in an internal extension}}
+}
+
+public class PublicSub: Base {
+ required init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-12=public }}
+ override func foo() {} // expected-error {{overriding instance method must be as accessible as the declaration it overrides}} {{12-12=public }}
+ override var bar: Int { // expected-error {{overriding var must be as accessible as the declaration it overrides}} {{12-12=public }}
+ get { return 0 }
+ set {}
+ }
+ override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as the declaration it overrides}} {{12-12=public }}
+}
+
+internal class InternalSub: Base {
+ required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=internal}}
+ private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=internal}}
+ private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=internal}}
+ get { return 0 }
+ set {}
+ }
+ private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=internal}}
+}
+
+internal class InternalSubGood: Base {
+ required init() {} // no-warning
+ override func foo() {}
+ override var bar: Int {
+ get { return 0 }
+ set {}
+ }
+ override subscript () -> () { return () }
+}
+
+internal class InternalSubPrivateSet: Base {
+ required init() {}
+ private(set) override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-16=}}
+ get { return 0 }
+ set {}
+ }
+ private(set) override subscript () -> () { // okay; read-only in base class
+ get { return () }
+ set {}
+ }
+}
+
+fileprivate class FilePrivateSub: Base {
+ required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=fileprivate}}
+ private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+ private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+ get { return 0 }
+ set {}
+ }
+ private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+}
+
+fileprivate class FilePrivateSubGood: Base {
+ required init() {} // no-warning
+ override func foo() {}
+ override var bar: Int {
+ get { return 0 }
+ set {}
+ }
+ override subscript () -> () { return () }
+}
+
+fileprivate class FilePrivateSubGood2: Base {
+ fileprivate required init() {} // no-warning
+ fileprivate override func foo() {}
+ fileprivate override var bar: Int {
+ get { return 0 }
+ set {}
+ }
+ fileprivate override subscript () -> () { return () }
+}
+
+fileprivate class FilePrivateSubPrivateSet: Base {
+ required init() {}
+ private(set) override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+ get { return 0 }
+ set {}
+ }
+ private(set) override subscript () -> () { // okay; read-only in base class
+ get { return () }
+ set {}
+ }
+}
+
+private class PrivateSub: Base {
+ required private init() {} // expected-error {{'required' initializer must be as accessible as its enclosing type}} {{12-19=fileprivate}}
+ private override func foo() {} // expected-error {{overriding instance method must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+ private override var bar: Int { // expected-error {{overriding var must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+ get { return 0 }
+ set {}
+ }
+ private override subscript () -> () { return () } // expected-error {{overriding subscript must be as accessible as its enclosing type}} {{3-10=fileprivate}}
+}
+
+private class PrivateSubGood: Base {
+ required fileprivate init() {}
+ fileprivate override func foo() {}
+ fileprivate override var bar: Int {
+ get { return 0 }
+ set {}
+ }
+ fileprivate override subscript () -> () { return () }
+}
+
+private class PrivateSubPrivateSet: Base {
+ required fileprivate init() {}
+ fileprivate override func foo() {}
+ private(set) override var bar: Int { // expected-error {{setter of overriding var must be as accessible as its enclosing type}}
+ get { return 0 }
+ set {}
+ }
+ private(set) override subscript () -> () { // okay; read-only in base class
+ get { return () }
+ set {}
+ }
+}
+
+public typealias PublicTA1 = PublicStruct
+public typealias PublicTA2 = InternalStruct // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias PublicTA3 = FilePrivateStruct // expected-error {{type alias cannot be declared public because its underlying type uses a fileprivate type}}
+public typealias PublicTA4 = PrivateStruct // expected-error {{type alias cannot be declared public because its underlying type uses a private type}}
+
+// expected-note@+1 {{type declared here}}
+internal typealias InternalTA1 = PublicStruct
+internal typealias InternalTA2 = InternalStruct
+internal typealias InternalTA3 = FilePrivateStruct // expected-error {{type alias cannot be declared internal because its underlying type uses a fileprivate type}}
+internal typealias InternalTA4 = PrivateStruct // expected-error {{type alias cannot be declared internal because its underlying type uses a private type}}
+
+public typealias PublicFromInternal = InternalTA1 // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+
+typealias FunctionType1 = (PrivateStruct) -> PublicStruct // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias FunctionType2 = (PublicStruct) -> PrivateStruct // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias FunctionType3 = (PrivateStruct) -> PrivateStruct // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+
+typealias ArrayType = [PrivateStruct] // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias DictType = [String : PrivateStruct] // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+typealias GenericArgs = Optional<PrivateStruct> // expected-error {{type alias must be declared private or fileprivate because its underlying type uses a private type}}
+
+
+public protocol HasAssocType {
+ associatedtype Inferred
+ func test(input: Inferred)
+}
+
+public struct AssocTypeImpl: HasAssocType {
+ public func test(input: Bool) {}
+}
+public let _: AssocTypeImpl.Inferred?
+
+
+public let x: PrivateStruct = PrivateStruct() // expected-error {{constant cannot be declared public because its type uses a private type}}
+public var a: PrivateStruct?, b: PrivateStruct? // expected-error 2 {{variable cannot be declared public because its type uses a private type}}
+public var (c, d): (PrivateStruct?, PrivateStruct?) // expected-error {{variable cannot be declared public because its type uses a private type}}
+
+var internalVar: PrivateStruct? // expected-error {{variable must be declared private or fileprivate because its type uses a private type}}
+
+let internalConstant = PrivateStruct() // expected-error {{constant must be declared private or fileprivate because its type 'PrivateStruct' uses a private type}}
+public let publicConstant = [InternalStruct]() // expected-error {{constant cannot be declared public because its type '[InternalStruct]' uses an internal type}}
+
+public struct Properties {
+ public let x: PrivateStruct = PrivateStruct() // expected-error {{property cannot be declared public because its type uses a private type}}
+ public var a: PrivateStruct?, b: PrivateStruct? // expected-error 2 {{property cannot be declared public because its type uses a private type}}
+ public var (c, d): (PrivateStruct?, PrivateStruct?) // expected-error {{property cannot be declared public because its type uses a private type}}
+
+ let y = PrivateStruct() // expected-error {{property must be declared fileprivate because its type 'PrivateStruct' uses a private type}}
+}
+
+public struct Subscripts {
+ subscript (a: PrivateStruct) -> Int { return 0 } // expected-error {{subscript must be declared fileprivate because its index uses a private type}}
+ subscript (a: Int) -> PrivateStruct { return PrivateStruct() } // expected-error {{subscript must be declared fileprivate because its element type uses a private type}}
+
+ public subscript (a: PrivateStruct, b: Int) -> Int { return 0 } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+ public subscript (a: Int, b: PrivateStruct) -> Int { return 0 } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+ public subscript (a: InternalStruct, b: PrivateStruct) -> InternalStruct { return InternalStruct() } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+ public subscript (a: PrivateStruct, b: InternalStruct) -> PrivateStruct { return PrivateStruct() } // expected-error {{subscript cannot be declared public because its index uses a private type}}
+ public subscript (a: Int, b: Int) -> InternalStruct { return InternalStruct() } // expected-error {{subscript cannot be declared public because its element type uses an internal type}}
+}
+
+public struct Methods {
+ func foo(a: PrivateStruct) -> Int { return 0 } // expected-error {{method must be declared fileprivate because its parameter uses a private type}}
+ func bar(a: Int) -> PrivateStruct { return PrivateStruct() } // expected-error {{method must be declared fileprivate because its result uses a private type}}
+
+ public func a(a: PrivateStruct, b: Int) -> Int { return 0 } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+ public func b(a: Int, b: PrivateStruct) -> Int { return 0 } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+ public func c(a: InternalStruct, b: PrivateStruct) -> InternalStruct { return InternalStruct() } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+ public func d(a: PrivateStruct, b: InternalStruct) -> PrivateStruct { return PrivateStruct() } // expected-error {{method cannot be declared public because its parameter uses a private type}}
+ public func e(a: Int, b: Int) -> InternalStruct { return InternalStruct() } // expected-error {{method cannot be declared public because its result uses an internal type}}
+}
+
+func privateParam(a: PrivateStruct) {} // expected-error {{function must be declared private or fileprivate because its parameter uses a private type}}
+
+public struct Initializers {
+ init(a: PrivateStruct) {} // expected-error {{initializer must be declared fileprivate because its parameter uses a private type}}
+
+ public init(a: PrivateStruct, b: Int) {} // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+ public init(a: Int, b: PrivateStruct) {} // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+ public init(a: InternalStruct, b: PrivateStruct) {} // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+ public init(a: PrivateStruct, b: InternalStruct) { } // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+}
+
+
+public class PublicClass {}
+// expected-note@+2 * {{type declared here}}
+// expected-note@+1 * {{superclass is declared here}}
+internal class InternalClass {}
+// expected-note@+1 * {{type declared here}}
+private class PrivateClass {}
+
+public protocol AssocTypes {
+ associatedtype Foo
+
+ associatedtype Internal: InternalClass // expected-error {{associated type in a public protocol uses an internal type in its requirement}}
+ associatedtype InternalConformer: InternalProto // expected-error {{associated type in a public protocol uses an internal type in its requirement}}
+
+ associatedtype PrivateConformer: PrivateProto // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+ associatedtype PI: PrivateProto, InternalProto // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+ associatedtype IP: InternalProto, PrivateProto // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+
+ associatedtype PrivateDefault = PrivateStruct // expected-error {{associated type in a public protocol uses a private type in its default definition}}
+ associatedtype PublicDefault = PublicStruct
+ associatedtype PrivateDefaultConformer: PublicProto = PrivateStruct // expected-error {{associated type in a public protocol uses a private type in its default definition}}
+ associatedtype PublicDefaultConformer: PrivateProto = PublicStruct // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+ associatedtype PrivatePrivateDefaultConformer: PrivateProto = PrivateStruct // expected-error {{associated type in a public protocol uses a private type in its requirement}}
+ associatedtype PublicPublicDefaultConformer: PublicProto = PublicStruct
+}
+
+public protocol RequirementTypes {
+ var x: PrivateStruct { get } // expected-error {{property cannot be declared public because its type uses a private type}}
+ subscript(x: Int) -> InternalStruct { get set } // expected-error {{subscript cannot be declared public because its element type uses an internal type}}
+ func foo() -> PrivateStruct // expected-error {{method cannot be declared public because its result uses a private type}}
+ init(x: PrivateStruct) // expected-error {{initializer cannot be declared public because its parameter uses a private type}}
+}
+
+protocol DefaultRefinesPrivate : PrivateProto {} // expected-error {{protocol must be declared private or fileprivate because it refines a private protocol}}
+public protocol PublicRefinesPrivate : PrivateProto {} // expected-error {{public protocol cannot refine a private protocol}}
+public protocol PublicRefinesInternal : InternalProto {} // expected-error {{public protocol cannot refine an internal protocol}}
+public protocol PublicRefinesPI : PrivateProto, InternalProto {} // expected-error {{public protocol cannot refine a private protocol}}
+public protocol PublicRefinesIP : InternalProto, PrivateProto {} // expected-error {{public protocol cannot refine a private protocol}}
+
+
+// expected-note@+1 * {{type declared here}}
+private typealias PrivateInt = Int
+enum DefaultRawPrivate : PrivateInt { // expected-error {{enum must be declared private or fileprivate because its raw type uses a private type}}
+ case A
+}
+public enum PublicRawPrivate : PrivateInt { // expected-error {{enum cannot be declared public because its raw type uses a private type}}
+ case A
+}
+public enum MultipleConformance : PrivateProto, PrivateInt { // expected-error {{enum cannot be declared public because its raw type uses a private type}} expected-error {{must appear first}} {{35-35=PrivateInt, }} {{47-59=}}
+ case A
+ func privateReq() {}
+}
+
+open class OpenSubclassInternal : InternalClass {} // expected-error {{class cannot be declared open because its superclass is internal}} expected-error {{superclass 'InternalClass' of open class must be open}}
+public class PublicSubclassPublic : PublicClass {}
+public class PublicSubclassInternal : InternalClass {} // expected-error {{class cannot be declared public because its superclass is internal}}
+public class PublicSubclassPrivate : PrivateClass {} // expected-error {{class cannot be declared public because its superclass is private}}
+
+class DefaultSubclassPublic : PublicClass {}
+class DefaultSubclassInternal : InternalClass {}
+class DefaultSubclassPrivate : PrivateClass {} // expected-error {{class must be declared private or fileprivate because its superclass is private}}
+
+public class PublicGenericClass<T> {}
+// expected-note@+2 * {{type declared here}}
+// expected-note@+1 * {{superclass is declared here}}
+internal class InternalGenericClass<T> {}
+// expected-note@+1 * {{type declared here}}
+private class PrivateGenericClass<T> {}
+
+open class OpenConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-warning {{class should not be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<Int>' of open class must be open}}
+public class PublicConcreteSubclassPublic : PublicGenericClass<Int> {}
+public class PublicConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-warning {{class should not be declared public because its superclass is internal}}
+public class PublicConcreteSubclassPrivate : PrivateGenericClass<Int> {} // expected-warning {{class should not be declared public because its superclass is private}}
+public class PublicConcreteSubclassPublicPrivateArg : PublicGenericClass<PrivateStruct> {} // expected-warning {{class should not be declared public because its superclass is private}}
+
+open class OpenGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-warning {{class should not be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<T>' of open class must be open}}
+public class PublicGenericSubclassPublic<T> : PublicGenericClass<T> {}
+public class PublicGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-warning {{class should not be declared public because its superclass is internal}}
+public class PublicGenericSubclassPrivate<T> : PrivateGenericClass<T> {} // expected-warning {{class should not be declared public because its superclass is private}}
+
+
+
+public enum PublicEnumPrivate {
+ case A(PrivateStruct) // expected-error {{enum case in a public enum uses a private type}}
+}
+enum DefaultEnumPrivate {
+ case A(PrivateStruct) // expected-error {{enum case in an internal enum uses a private type}}
+}
+public enum PublicEnumPI {
+ case A(InternalStruct) // expected-error {{enum case in a public enum uses an internal type}}
+ case B(PrivateStruct, InternalStruct) // expected-error {{enum case in a public enum uses a private type}}
+ case C(InternalStruct, PrivateStruct) // expected-error {{enum case in a public enum uses a private type}}
+}
+enum DefaultEnumPublic {
+ case A(PublicStruct) // no-warning
+}
+
+
+struct DefaultGeneric<T> {}
+
+struct DefaultGenericPrivate<T: PrivateProto> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
+struct DefaultGenericPrivate2<T: PrivateClass> {} // expected-error {{generic struct must be declared private or fileprivate because its generic parameter uses a private type}}
+struct DefaultGenericPrivateReq<T> where T == PrivateClass {} // expected-error {{same-type requirement makes generic parameter 'T' non-generic}}
+// expected-error@-1 {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
+struct DefaultGenericPrivateReq2<T> where T: PrivateProto {} // expected-error {{generic struct must be declared private or fileprivate because its generic requirement uses a private type}}
+
+public struct PublicGenericInternal<T: InternalProto> {} // expected-error {{generic struct cannot be declared public because its generic parameter uses an internal type}}
+
+public struct PublicGenericPI<T: PrivateProto, U: InternalProto> {} // expected-error {{generic struct cannot be declared public because its generic parameter uses a private type}}
+public struct PublicGenericIP<T: InternalProto, U: PrivateProto> {} // expected-error {{generic struct cannot be declared public because its generic parameter uses a private type}}
+public struct PublicGenericPIReq<T: PrivateProto> where T: InternalProto {} // expected-error {{generic struct cannot be declared public because its generic parameter uses a private type}}
+public struct PublicGenericIPReq<T: InternalProto> where T: PrivateProto {} // expected-error {{generic struct cannot be declared public because its generic requirement uses a private type}}
+
+public func genericFunc<T: InternalProto>(_: T) {} // expected-error {{function cannot be declared public because its generic parameter uses an internal type}} {}
+public class GenericClass<T: InternalProto> { // expected-error {{generic class cannot be declared public because its generic parameter uses an internal type}}
+ public init<T: PrivateProto>(_: T) {} // expected-error {{initializer cannot be declared public because its generic parameter uses a private type}}
+ public func genericMethod<T: PrivateProto>(_: T) {} // expected-error {{instance method cannot be declared public because its generic parameter uses a private type}}
+}
+public enum GenericEnum<T: InternalProto> { // expected-error {{generic enum cannot be declared public because its generic parameter uses an internal type}}
+ case A
+}
+
+
+public protocol PublicMutationOperations {
+ var size: Int { get set }
+ subscript (_: Int) -> Int { get set }
+}
+
+internal protocol InternalMutationOperations {
+ var size: Int { get set }
+ subscript (_: Int) -> Int { get set }
+}
+
+public struct AccessorsControl : InternalMutationOperations {
+ private var size = 0 // expected-error {{property 'size' must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{3-10=internal}}
+ private subscript (_: Int) -> Int { // expected-error {{subscript must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{3-10=internal}}
+ get { return 42 }
+ set {}
+ }
+}
+
+public struct PrivateSettersPublic : InternalMutationOperations {
+ // Please don't change the formatting here; it's a precise fix-it test.
+ public private(set) var size = 0 // expected-error {{setter for property 'size' must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{10-17=internal}}
+ public private(set) subscript (_: Int) -> Int { // expected-error {{subscript setter must be declared internal because it matches a requirement in internal protocol 'InternalMutationOperations'}} {{10-17=internal}}
+ get { return 42 }
+ set {}
+ }
+}
+
+internal struct PrivateSettersInternal : PublicMutationOperations {
+ // Please don't change the formatting here; it's a precise fix-it test.
+ private(set)var size = 0 // expected-error {{setter for property 'size' must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicMutationOperations'}} {{3-15=}}
+
+ internal private(set)subscript (_: Int) -> Int { // expected-error {{subscript setter must be as accessible as its enclosing type because it matches a requirement in protocol 'PublicMutationOperations'}} {{12-24=}}
+ get { return 42 }
+ set {}
+ }
+}
+
+public protocol PublicReadOnlyOperations {
+ var size: Int { get }
+ subscript (_: Int) -> Int { get }
+}
+
+internal struct PrivateSettersForReadOnlyInternal : PublicReadOnlyOperations {
+ public private(set) var size = 0
+ internal private(set) subscript (_: Int) -> Int { // no-warning
+ get { return 42 }
+ set {}
+ }
+}
+
+public struct PrivateSettersForReadOnlyPublic : PublicReadOnlyOperations {
+ public private(set) var size = 0 // no-warning
+ internal private(set) subscript (_: Int) -> Int { // expected-error {{subscript must be declared public because it matches a requirement in public protocol 'PublicReadOnlyOperations'}} {{3-11=public}}
+ get { return 42 }
+ set {}
+ }
+}
+
+
+public protocol PublicOperatorProto {
+ static prefix func !(_: Self) -> Self
+}
+
+internal protocol InternalOperatorProto {
+ static prefix func !(_: Self) -> Self
+}
+
+fileprivate protocol FilePrivateOperatorProto {
+ static prefix func !(_: Self) -> Self
+}
+
+private protocol PrivateOperatorProto {
+ static prefix func !(_: Self) -> Self
+}
+
+public struct PublicOperatorAdopter : PublicOperatorProto {
+ fileprivate struct Inner : PublicOperatorProto {
+ }
+}
+private prefix func !(input: PublicOperatorAdopter) -> PublicOperatorAdopter { // expected-error {{method '!' must be declared public because it matches a requirement in public protocol 'PublicOperatorProto'}} {{1-8=public}}
+ return input
+}
+private prefix func !(input: PublicOperatorAdopter.Inner) -> PublicOperatorAdopter.Inner {
+ return input
+}
+
+public struct InternalOperatorAdopter : InternalOperatorProto {
+ fileprivate struct Inner : InternalOperatorProto {
+ }
+}
+private prefix func !(input: InternalOperatorAdopter) -> InternalOperatorAdopter { // expected-error {{method '!' must be declared internal because it matches a requirement in internal protocol 'InternalOperatorProto'}} {{1-8=internal}}
+ return input
+}
+private prefix func !(input: InternalOperatorAdopter.Inner) -> InternalOperatorAdopter.Inner {
+ return input
+}
+
+public struct FilePrivateOperatorAdopter : FilePrivateOperatorProto {
+ fileprivate struct Inner : FilePrivateOperatorProto {
+ }
+}
+private prefix func !(input: FilePrivateOperatorAdopter) -> FilePrivateOperatorAdopter {
+ return input
+}
+private prefix func !(input: FilePrivateOperatorAdopter.Inner) -> FilePrivateOperatorAdopter.Inner {
+ return input
+}
+
+public struct PrivateOperatorAdopter : PrivateOperatorProto {
+ fileprivate struct Inner : PrivateOperatorProto {
+ }
+}
+private prefix func !(input: PrivateOperatorAdopter) -> PrivateOperatorAdopter {
+ return input
+}
+private prefix func !(input: PrivateOperatorAdopter.Inner) -> PrivateOperatorAdopter.Inner {
+ return input
+}
+
+
+public protocol Equatablish {
+ static func ==(lhs: Self, rhs: Self) /* -> bool */ // expected-note {{protocol requires function '=='}}
+}
+
+fileprivate struct EquatablishOuter {
+ internal struct Inner : Equatablish {}
+}
+private func ==(lhs: EquatablishOuter.Inner, rhs: EquatablishOuter.Inner) {}
+// expected-note@-1 {{candidate has non-matching type}}
+
+fileprivate struct EquatablishOuter2 {
+ internal struct Inner : Equatablish {
+ fileprivate static func ==(lhs: Inner, rhs: Inner) {}
+ // expected-note@-1 {{candidate has non-matching type}}
+ }
+}
+
+fileprivate struct EquatablishOuterProblem {
+ internal struct Inner : Equatablish { // expected-error {{type 'EquatablishOuterProblem.Inner' does not conform to protocol 'Equatablish'}}
+ private static func ==(lhs: Inner, rhs: Inner) {}
+ }
+}
+
+internal struct EquatablishOuterProblem2 {
+ public struct Inner : Equatablish {
+ fileprivate static func ==(lhs: Inner, rhs: Inner) {} // expected-error {{method '==' must be as accessible as its enclosing type because it matches a requirement in protocol 'Equatablish'}} {{5-16=internal}}
+ // expected-note@-1 {{candidate has non-matching type}}
+ }
+}
+
+internal struct EquatablishOuterProblem3 {
+ public struct Inner : Equatablish {
+ }
+}
+private func ==(lhs: EquatablishOuterProblem3.Inner, rhs: EquatablishOuterProblem3.Inner) {} // expected-error {{method '==' must be as accessible as its enclosing type because it matches a requirement in protocol 'Equatablish'}} {{1-8=internal}}
+// expected-note@-1 {{candidate has non-matching type}}
+
+
+public protocol AssocTypeProto {
+ associatedtype Assoc
+}
+
+fileprivate struct AssocTypeOuter {
+ internal struct Inner : AssocTypeProto {
+ fileprivate typealias Assoc = Int
+ }
+}
+
+fileprivate struct AssocTypeOuterProblem {
+ internal struct Inner : AssocTypeProto {
+ private typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-12=fileprivate}}
+ }
+}
+
+internal struct AssocTypeOuterProblem2 {
+ public struct Inner : AssocTypeProto {
+ fileprivate typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-16=internal}}
+ }
+}
+
+internal typealias InternalComposition = PublicClass & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalComposition : InternalComposition { // expected-error {{class cannot be declared public because its superclass is internal}}
+ public func publicReq() {}
+}
+
+internal typealias InternalGenericComposition<T> = PublicGenericClass<T> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalGenericComposition : InternalGenericComposition<Int> { // expected-warning {{class should not be declared public because its superclass is internal}}
+ public func publicReq() {}
+}
+
+internal typealias InternalConcreteGenericComposition = PublicGenericClass<Int> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalConcreteGenericComposition : InternalConcreteGenericComposition { // expected-warning {{class should not be declared public because its superclass is internal}}
+ public func publicReq() {}
+}
+
+public typealias BadPublicComposition1 = InternalClass & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition2 = PublicClass & InternalProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition3<T> = InternalGenericClass<T> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition4 = InternalGenericClass<Int> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition5 = PublicGenericClass<InternalStruct> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift
index 5b52394..1ba1e45 100644
--- a/test/Constraints/bridging.swift
+++ b/test/Constraints/bridging.swift
@@ -181,8 +181,9 @@
struct NotEquatable {}
func notEquatableError(_ d: Dictionary<Int, NotEquatable>) -> Bool {
// FIXME: Another awful diagnostic.
- return d == d // expected-error{{binary operator '==' cannot be applied to two 'Dictionary<Int, NotEquatable>' operands}}
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+ return d == d // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+ // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+ // expected-note @-2 {{requirement from conditional conformance of 'Dictionary<Int, NotEquatable>' to 'Equatable'}}
}
// NSString -> String
diff --git a/test/Constraints/dictionary_literal.swift b/test/Constraints/dictionary_literal.swift
index c128c4b..efac19a 100644
--- a/test/Constraints/dictionary_literal.swift
+++ b/test/Constraints/dictionary_literal.swift
@@ -72,10 +72,10 @@
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any>'; add explicit type annotation if this is intentional}}{{46-46= as Dictionary<String, Any>}}
let _: [String : Any] = ["a" : 1, "b" : 2.5, "c" : "hello"]
-
+
let _ = ["a" : 1, "b" : nil, "c" : "hello"]
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<String, Any?>'; add explicit type annotation if this is intentional}}{{46-46= as Dictionary<String, Any?>}}
-
+
let _: [String : Any?] = ["a" : 1, "b" : nil, "c" : "hello"]
let d2 = [:]
@@ -102,8 +102,7 @@
func rdar32330004_1() -> [String: Any] {
return ["a""one": 1, "two": 2, "three": 3] // expected-note {{did you mean to use a dictionary literal instead?}}
// expected-error@-1 2 {{expected ',' separator}}
- // expected-error@-2 {{expected expression in container literal}}
- // expected-error@-3 {{contextual type '[String : Any]' cannot be used with array literal}}
+ // expected-error@-2 {{contextual type '[String : Any]' cannot be used with array literal}}
}
func rdar32330004_2() -> [String: Any] {
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index b56e228..022c4e1 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -163,9 +163,8 @@
default: break
}
-// <rdar://problem/21995744> QoI: Binary operator '~=' cannot be applied to operands of type 'String' and 'String?'
switch ("foo" as String?) {
-case "what": break // expected-error{{expression pattern of type 'String' cannot match values of type 'String?'}} {{12-12=?}}
+case "what": break
default: break
}
diff --git a/test/DebugInfo/basic.swift b/test/DebugInfo/basic.swift
index 4f9673a..bbc2bc6 100644
--- a/test/DebugInfo/basic.swift
+++ b/test/DebugInfo/basic.swift
@@ -1,5 +1,3 @@
-// FIXME(integers): started to fail due to the new integer protocols
-// XFAIL: *
// A (no longer) basic test for debug info.
// --------------------------------------------------------------------
// Verify that we don't emit any debug info by default.
@@ -43,8 +41,8 @@
// CHECK-DAG: store i64 %1, i64* [[BADDR:.*]], align
// CHECK-DAG: [[AVAL:%.*]] = getelementptr inbounds {{.*}}, [[AMEM:.*]], i32 0, i32 0
// CHECK-DAG: [[BVAL:%.*]] = getelementptr inbounds {{.*}}, [[BMEM:.*]], i32 0, i32 0
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[AADDR]], metadata ![[AARG:.*]], metadata !{{[0-9]+}}), !dbg ![[ASCOPE]]
- // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[BADDR]], metadata ![[BARG:.*]], metadata !{{[0-9]+}})
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[AADDR]], metadata ![[AARG:.*]], metadata !DIExpression()), !dbg ![[ASCOPE]]
+ // CHECK-DAG: call void @llvm.dbg.declare(metadata i64* [[BADDR]], metadata ![[BARG:.*]], metadata !DIExpression())
// CHECK-DAG: ![[AARG]] = !DILocalVariable(name: "a", arg: 1
// CHECK-DAG: ![[BARG]] = !DILocalVariable(name: "b", arg: 2
if b != 0 {
@@ -53,7 +51,7 @@
// CHECK-DAG: smul{{.*}}, !dbg ![[MUL:[0-9]+]]
// CHECK-DAG: [[MUL]] = !DILocation(line: [[@LINE+4]], column: 16,
// Runtime call to multiply function:
- // CHECK-NOSIL: @_T0s1mois5Int64VAC_ACtF{{.*}}, !dbg ![[MUL:[0-9]+]]
+ // CHECK-NOSIL: @_T0s5Int64V1moiA2B_ABtFZ{{.*}}, !dbg ![[MUL:[0-9]+]]
// CHECK-NOSIL: [[MUL]] = !DILocation(line: [[@LINE+1]], column: 16,
return a*b
} else {
@@ -79,7 +77,7 @@
// CHECK-DAG: ![[INT64:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Int64", {{.*}}, identifier: "_T0s5Int64VD")
// CHECK-DAG: ![[PARAMTYPES]] = !{![[INT64]], ![[INT64]], ![[INT64]]}
// Import of the main module with the implicit name.
-// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[MAINFILE]], entity: ![[MAINMODULE:[0-9]+]], file: ![[MAINFILE]], line: 1)
+// CHECK-DAG: !DIImportedEntity(tag: DW_TAG_imported_module, scope: ![[MAINFILE]], entity: ![[MAINMODULE:[0-9]+]], file: ![[MAINFILE]])
// CHECK-DAG: ![[MAINMODULE]] = !DIModule({{.*}}, name: "basic"
// DWARF Version
diff --git a/test/DebugInfo/callexpr.swift b/test/DebugInfo/callexpr.swift
index 4b738f2..e401c12 100644
--- a/test/DebugInfo/callexpr.swift
+++ b/test/DebugInfo/callexpr.swift
@@ -9,8 +9,9 @@
// CHECK: call {{.*}}foo{{.*}}, !dbg ![[ARG1:.*]]
// CHECK: call {{.*}}foo{{.*}}, !dbg ![[ARG2:.*]]
// CHECK: call {{.*}}foo{{.*}}, !dbg ![[OUTER:.*]]
-let r = foo(foo(1, 23), // CHECK: ![[ARG1]] = !DILocation(line: [[@LINE]],
+let r = foo(
+ foo(1, 23), // CHECK: ![[ARG1]] = !DILocation(line: [[@LINE]],
foo(2, 42) // CHECK: ![[ARG2]] = !DILocation(line: [[@LINE]],
- ) // CHECK: ![[OUTER]] = !DILocation(line: [[@LINE]],
+ ) // CHECK: ![[OUTER]] = !DILocation(line: [[@LINE-3]],
markUsed(r)
diff --git a/test/DebugInfo/inlinedAt.swift b/test/DebugInfo/inlinedAt.swift
index 2d781ea..40e47ef 100644
--- a/test/DebugInfo/inlinedAt.swift
+++ b/test/DebugInfo/inlinedAt.swift
@@ -40,7 +40,7 @@
// CHECK: ![[F:.*]] = distinct !DISubprogram(name: "f",
// CHECK: ![[G:.*]] = distinct !DISubprogram(name: "g",
-// CHECK: ![[L3:.*]] = !DILocation(line: 302, column: 13,
+// CHECK: ![[L3:.*]] = !DILocation(line: 302, column: 10,
// CHECK-SAME: scope: ![[F_SCOPE:.*]])
// CHECK: ![[F_SCOPE]] = distinct !DILexicalBlock(scope: ![[F]],
// CHECK-SAME: line: 301, column: 33)
@@ -49,6 +49,6 @@
// CHECK: ![[H:.*]] = distinct !DISubprogram(name: "h",
// CHECK: ![[L1]] = !DILocation(line: 101, column: 8, scope: ![[H]],
// CHECK-SAME: inlinedAt: ![[L2:.*]])
-// CHECK: ![[L2]] = !DILocation(line: 203, column: 13, scope: ![[G_SCOPE]],
+// CHECK: ![[L2]] = !DILocation(line: 203, column: 10, scope: ![[G_SCOPE]],
// CHECK-SAME: inlinedAt: ![[L3]])
diff --git a/test/DebugInfo/linetable-assign.swift b/test/DebugInfo/linetable-assign.swift
new file mode 100644
index 0000000..f679808
--- /dev/null
+++ b/test/DebugInfo/linetable-assign.swift
@@ -0,0 +1,17 @@
+// RUN: %target-swift-frontend -Xllvm -sil-full-demangle %s \
+// RUN: -emit-sil -emit-verbose-sil -Xllvm -sil-print-debuginfo -g -o - \
+// RUN: | %FileCheck %s
+public func g<T>(_ t: T) {}
+public func f(_ i: Int32) {
+ // CHECK: function_ref @_T04main1fys5Int32VFyycfU_
+ // CHECK-SAME: loc "{{.*}}":13:3,
+ // CHECK: %[[CLOSURE:.*]] = partial_apply
+ // CHECK-SAME: loc "{{.*}}":13:3,{{.*}}auto_gen
+ // CHECK: store %[[CLOSURE]]
+ // CHECK-SAME: loc "{{.*}}":12:3,
+ var closure = // line 12
+ {
+ g(i)
+ }
+ return closure()
+}
diff --git a/test/DebugInfo/linetable-cleanups.swift b/test/DebugInfo/linetable-cleanups.swift
index 9183355..4531191 100644
--- a/test/DebugInfo/linetable-cleanups.swift
+++ b/test/DebugInfo/linetable-cleanups.swift
@@ -27,7 +27,8 @@
// CHECK: call void @swift_bridgeObjectRelease({{.*}}) {{#[0-9]+}}, !dbg ![[CLEANUPS:.*]]
// CHECK-NEXT: !dbg ![[CLEANUPS]]
// CHECK-NEXT: llvm.lifetime.end
-// CHECK-NEXT: bitcast
+// CHECK-NEXT: load
+// CHECK-NEXT: swift_rt_swift_release
// CHECK-NEXT: bitcast
// CHECK-NEXT: llvm.lifetime.end
// CHECK-NEXT: ret void, !dbg ![[CLEANUPS]]
diff --git a/test/DebugInfo/linetable.swift b/test/DebugInfo/linetable.swift
index 3a020f8..489b15e 100644
--- a/test/DebugInfo/linetable.swift
+++ b/test/DebugInfo/linetable.swift
@@ -22,14 +22,14 @@
}
func main(_ x: Int64) -> Void
-// CHECK: define hidden {{.*}} void @_T09linetable4main{{[_0-9a-zA-Z]*}}F
+// CHECK-LABEL: define hidden {{.*}} void @_T09linetable4main{{[_0-9a-zA-Z]*}}F
{
var my_class = MyClass(input: 10)
// Linetable continuity. Don't go into the closure expression.
// ASM-CHECK: .loc [[FILEID:[0-9]]] [[@LINE+1]] 5
call_me (
// ASM-CHECK-NOT: .loc [[FILEID]] [[@LINE+1]] 5
-// CHECK: define {{.*}} @_T09linetable4mainys5Int64VFyycfU_Tf2in_n({{.*}})
+// CHECK-LABEL: define {{.*}} @_T09linetable4mainys5Int64VFyycfU_Tf2in_n({{.*}})
{
var result = my_class.do_something(x)
markUsed(result)
diff --git a/test/DebugInfo/patternmatching.swift b/test/DebugInfo/patternmatching.swift
index d9c8f33..b98d31a 100644
--- a/test/DebugInfo/patternmatching.swift
+++ b/test/DebugInfo/patternmatching.swift
@@ -15,10 +15,9 @@
switch p {
case (let x, let y) where
// CHECK: call {{.*}}double {{.*}}return_same{{.*}}, !dbg ![[LOC1:.*]]
- // CHECK: br {{.*}}, label {{.*}}, label {{.*}}, !dbg ![[LOC2:.*]]
+ // CHECK: br {{.*}}, label {{.*}}, label {{.*}}, !dbg ![[LOC1]]
// CHECK: call{{.*}}markUsed{{.*}}, !dbg ![[LOC3:.*]]
- // CHECK: ![[LOC1]] = !DILocation(line: [[@LINE+2]],
- // CHECK: ![[LOC2]] = !DILocation(line: [[@LINE+1]],
+ // CHECK: ![[LOC1]] = !DILocation(line: [[@LINE+1]],
return_same(x) == return_same(y):
// CHECK: ![[LOC3]] = !DILocation(line: [[@LINE+1]],
markUsed(x)
diff --git a/test/DebugInfo/return.swift b/test/DebugInfo/return.swift
index bf7057d..5bff35e 100644
--- a/test/DebugInfo/return.swift
+++ b/test/DebugInfo/return.swift
@@ -7,16 +7,19 @@
// CHECK: define {{.*}}ifelseexpr
public func ifelseexpr() -> Int64 {
- var x = X(i:0)
+ var x = X(i:0)
+ // CHECK: [[ALLOCA:%.*]] = alloca %T6return1XC*
// CHECK: [[META:%.*]] = call %swift.type* @_T06return1XCMa()
// CHECK: [[X:%.*]] = call {{.*}}%T6return1XC* @_T06return1XCACs5Int64V1i_tcfC(
// CHECK-SAME: i64 0, %swift.type* swiftself [[META]])
+ // CHECK: store %T6return1XC* [[X]], %T6return1XC** [[ALLOCA]]
// CHECK: @swift_rt_swift_release to void (%T6return1XC*)*)(%T6return1XC* [[X]])
if true {
x.x += 1
} else {
x.x -= 1
}
+ // CHECK: [[X:%.*]] = load %T6return1XC*, %T6return1XC** [[ALLOCA]]
// CHECK: @swift_rt_swift_release to void (%T6return1XC*)*)(%T6return1XC* [[X]])
// CHECK-SAME: , !dbg ![[RELEASE:.*]]
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index f31301d..1cbdc47 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -4,6 +4,7 @@
_TtBO ---> Builtin.UnknownObject
_TtBo ---> Builtin.NativeObject
_TtBp ---> Builtin.RawPointer
+_TtBt ---> Builtin.SILToken
_TtBv4Bi8_ ---> Builtin.Vec4xInt8
_TtBv4Bf16_ ---> Builtin.Vec4xFloat16
_TtBv4Bp ---> Builtin.Vec4xRawPointer
diff --git a/test/Driver/actions.swift b/test/Driver/actions.swift
index cc8ee4d..3e21f12 100644
--- a/test/Driver/actions.swift
+++ b/test/Driver/actions.swift
@@ -28,6 +28,19 @@
// BASICMODULE: 1: compile, {0}, swiftmodule
// BASICMODULE: 2: merge-module, {1}, swiftmodule
+// RUN: touch %t/a.swiftmodule
+// RUN: %swiftc_driver -driver-print-actions -emit-module -module-name foo %s %t/a.swiftmodule 2>&1 | %FileCheck %s -check-prefix=SWIFTMODULE-INPUT
+// SWIFTMODULE-INPUT: 0: input, "{{.*}}actions.swift", swift
+// SWIFTMODULE-INPUT: 1: compile, {0}, swiftmodule
+// SWIFTMODULE-INPUT: 2: input, "{{.*}}a.swiftmodule", swift
+// SWIFTMODULE-INPUT: 3: merge-module, {1, 2}, swiftmodule
+
+// RUN: %swiftc_driver -driver-print-actions -g -emit-module -module-name foo %s %t/a.swiftmodule 2>&1 | %FileCheck %s -check-prefix=SWIFTMODULE-INPUT
+// SWIFTMODULE-DEBUG-INPUT: 0: input, "{{.*}}actions.swift", swift
+// SWIFTMODULE-DEBUG-INPUT: 1: compile, {0}, swiftmodule
+// SWIFTMODULE-DEBUG-INPUT: 2: input, "{{.*}}a.swiftmodule", swift
+// SWIFTMODULE-DEBUG-INPUT: 3: merge-module, {1, 2}, swiftmodule
+
// RUN: %swiftc_driver -driver-print-actions -emit-executable -emit-module %s 2>&1 | %FileCheck %s -check-prefix=EXEC-AND-MODULE
// EXEC-AND-MODULE: 0: input, "{{.*}}actions.swift", swift
// EXEC-AND-MODULE: 1: compile, {0}, object
@@ -114,9 +127,8 @@
// DEBUG-LINK-ONLY: 1: input, "{{.*}}/b.o", object
// DEBUG-LINK-ONLY: 2: input, "{{.*}}/a.swiftmodule", swiftmodule
// DEBUG-LINK-ONLY: 3: input, "{{.*}}/b.swiftmodule", swiftmodule
-// DEBUG-LINK-ONLY: 4: merge-module, {2, 3}, swiftmodule
-// DEBUG-LINK-ONLY: 5: link, {0, 1, 4}, image
-// DEBUG-LINK-ONLY: 6: generate-dSYM, {5}, dSYM
+// DEBUG-LINK-ONLY: 4: link, {0, 1, 2, 3}, image
+// DEBUG-LINK-ONLY: 5: generate-dSYM, {4}, dSYM
// RUN: touch %t/c.swift
// RUN: %swiftc_driver -driver-print-actions %t/c.swift %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=LINK-SWIFTMODULES
@@ -128,6 +140,16 @@
// LINK-SWIFTMODULES: 5: input, "{{.*}}/b.swiftmodule", swiftmodule
// LINK-SWIFTMODULES: 6: link, {1, 2, 3, 4, 5}, image
+// RUN: %swiftc_driver -driver-print-actions -g %t/c.swift %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=LINK-DEBUG-SWIFTMODULES
+// LINK-DEBUG-SWIFTMODULES: 0: input, "{{.*}}/c.swift", swift
+// LINK-DEBUG-SWIFTMODULES: 1: compile, {0}, object
+// LINK-DEBUG-SWIFTMODULES: 2: input, "{{.*}}/a.o", object
+// LINK-DEBUG-SWIFTMODULES: 3: input, "{{.*}}/b.o", object
+// LINK-DEBUG-SWIFTMODULES: 4: input, "{{.*}}/a.swiftmodule", swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 5: input, "{{.*}}/b.swiftmodule", swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 6: merge-module, {1}, swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 7: link, {1, 2, 3, 4, 5, 6}, image
+
// RUN: touch %t/a.o %t/b.o
// RUN: %swiftc_driver -driver-print-actions %t/a.o %s -o main 2>&1 | %FileCheck %s -check-prefix=COMPILE-PLUS-OBJECT
// COMPILE-PLUS-OBJECT: 0: input, "{{.*}}/a.o", object
diff --git a/test/Driver/bindings.swift b/test/Driver/bindings.swift
index 423c61b..c516545 100644
--- a/test/Driver/bindings.swift
+++ b/test/Driver/bindings.swift
@@ -50,5 +50,5 @@
// RUN: touch %t/a.swiftmodule %t/b.swiftmodule
// RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -g %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=DEBUG-LINK-ONLY
-// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {swiftmodule: "[[MERGED:.+\.swiftmodule]]", swiftdoc: "{{.+}}.swiftdoc"}
-// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "[[MERGED]]"], output: {image: "main"}
+// DEBUG-LINK-ONLY-NOT: "swift"
+// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {image: "main"}
diff --git a/test/Driver/filelists.swift b/test/Driver/filelists.swift
index a5e605d..6d9132e 100644
--- a/test/Driver/filelists.swift
+++ b/test/Driver/filelists.swift
@@ -42,8 +42,8 @@
// RUN: ls %t/tmp-crash/sources-* %t/tmp-crash/outputs-*
-// RUN: (cd %t && env PATH=%t/bin/:$PATH %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
-// RUN: (cd %t && env PATH=%t/bin/:$PATH %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json -force-single-frontend-invocation -num-threads 1 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
+// RUN: (cd %t && env PATH="%t/bin/:$PATH" %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
+// RUN: (cd %t && env PATH="%t/bin/:$PATH" %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json -force-single-frontend-invocation -num-threads 1 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
// CHECK-LINK: Handled link
diff --git a/test/Driver/opt-record.swift b/test/Driver/opt-record.swift
index 823f519..15fcd93 100644
--- a/test/Driver/opt-record.swift
+++ b/test/Driver/opt-record.swift
@@ -20,15 +20,15 @@
// YAML-NEXT: File: {{.*}}opt-record.swift
// YAML-NEXT: Line: 42
// YAML-NEXT: Column: 3
- // YAML-NEXT: Function: _T012optrecordmod3baryyF
+ // YAML-NEXT: Function: 'bar()'
// YAML-NEXT: Args:
- // YAML-NEXT: - Callee: _T012optrecordmod3fooyyF
+ // YAML-NEXT: - Callee: '"foo()"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}opt-record.swift
// YAML-NEXT: Line: 11
// YAML-NEXT: Column: 6
// YAML-NEXT: - String: ' inlined into '
- // YAML-NEXT: - Caller: _T012optrecordmod3baryyF
+ // YAML-NEXT: - Caller: '"bar()"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}opt-record.swift
// YAML-NEXT: Line: 15
diff --git a/test/Driver/opt-remark.swift b/test/Driver/opt-remark.swift
index 0e54d56..aa2fb52 100644
--- a/test/Driver/opt-remark.swift
+++ b/test/Driver/opt-remark.swift
@@ -38,11 +38,11 @@
func foo() {
// REMARK_MISSED-NOT: remark: {{.*}} inlined
- // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline (cost = {{.*}}, benefit = {{.*}})
+ // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline function "big()" (cost = {{.*}}, benefit = {{.*}})
// REMARK_MISSED-NOT: remark: {{.*}} inlined
big()
// REMARK_PASSED-NOT: remark: Not profitable
- // REMARK_PASSED: opt-remark.swift:47:3: remark: _T04null5smallyyF inlined into _T04null3fooyyF (cost = {{.*}}, benefit = {{.*}})
+ // REMARK_PASSED: opt-remark.swift:47:3: remark: "small()" inlined into "foo()" (cost = {{.*}}, benefit = {{.*}})
// REMARK_PASSED-NOT: remark: Not profitable
small()
}
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 3d8889b..6e32e9c 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -6,11 +6,16 @@
protocol P2 {}
protocol P3 {}
protocol P4: P1 {}
+protocol P5: P2 {}
+// expected-note@-1{{type 'InheritImplicitGood<T>' does not conform to inherited protocol 'P2'}}
+// expected-note@-2{{type 'InheritImplicitBad<T>' does not conform to inherited protocol 'P2'}}
+protocol P6: P2 {}
+// expected-note@-1{{type 'InheritImplicitBad<T>' does not conform to inherited protocol 'P2'}}
protocol Assoc { associatedtype AT }
func takes_P2<X: P2>(_: X) {}
-// expected-note@-1{{in call to function 'takes_P2'}}
+
// expected-note@-2{{candidate requires that the types 'U' and 'V' be equivalent (requirement specified as 'U' == 'V')}}
// expected-note@-3{{requirement from conditional conformance of 'SameTypeGeneric<U, V>' to 'P2'}}
// expected-note@-4{{candidate requires that the types 'U' and 'Int' be equivalent (requirement specified as 'U' == 'Int')}}
@@ -21,6 +26,9 @@
// expected-note@-9{{requirement from conditional conformance of 'ClassFree<U>' to 'P2'}}
// expected-note@-10{{candidate requires that 'C3' inherit from 'U' (requirement specified as 'U' : 'C3')}}
// expected-note@-11{{requirement from conditional conformance of 'ClassMoreSpecific<U>' to 'P2'}}
+// expected-note@-12{{candidate requires that 'C1' inherit from 'Int' (requirement specified as 'Int' : 'C1')}}
+// expected-note@-13{{requirement from conditional conformance of 'SubclassBad' to 'P2'}}
+func takes_P5<X: P5>(_: X) {}
struct Free<T> {}
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Free<T>
@@ -83,13 +91,8 @@
// CHECK-NEXT: (normal_conformance type=SameType<Int> protocol=P2
// CHECK-NEXT: same_type: τ_0_0 Int)
extension SameType: P2 where T == Int {}
-// FIXME: the compiler gets this... exactly backwards. :( For the incorrectly
-// accepted cases, it seems the compiler ends up with a (specialized_conformance
-// type=SameType<Float> ... same_type: Int Int ...) for the (normal_conformance
-// type=SameType<Int> ...).
func same_type_good() {
takes_P2(SameType<Int>())
- // expected-error@-1{{generic parameter 'X' could not be inferred}}
}
func same_type_bad<U>(_: U) {
takes_P2(SameType<U>())
@@ -190,6 +193,116 @@
extension ClassLessSpecific: P2 where T: C1 {}
+// Inherited conformances:
+class Base<T> {}
+extension Base: P2 where T: C1 {}
+
+class SubclassGood: Base<C1> {}
+func subclass_good() {
+ takes_P2(SubclassGood())
+}
+class SubclassBad: Base<Int> {}
+func subclass_bad() {
+ takes_P2(SubclassBad())
+ // expected-error@-1{{cannot invoke 'takes_P2(_:)' with an argument list of type '(SubclassBad)'}}
+}
+
+// Inheriting conformances:
+
+struct InheritEqual<T> {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
+// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P2
+// CHECK-NEXT: conforms_to: τ_0_0 P1)
+extension InheritEqual: P2 where T: P1 {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
+// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P5
+// CHECK-NEXT: conforms_to: τ_0_0 P1)
+extension InheritEqual: P5 where T: P1 {}
+func inheritequal_good<U: P1>(_: U) {
+ takes_P2(InheritEqual<U>())
+ takes_P5(InheritEqual<U>())
+}
+func inheritequal_bad<U>(_: U) {
+ takes_P2(InheritEqual<U>())
+ // expected-error@-1{{'<X where X : P2> (X) -> ()' requires that 'U' conform to 'P1'}}
+ // expected-note@-2{{requirement specified as 'U' : 'P1'}}
+ // expected-note@-3{{requirement from conditional conformance of 'InheritEqual<U>' to 'P2'}}
+ takes_P5(InheritEqual<U>())
+ // expected-error@-1{{'<X where X : P5> (X) -> ()' requires that 'U' conform to 'P1'}}
+ // expected-note@-2{{requirement specified as 'U' : 'P1'}}
+ // expected-note@-3{{requirement from conditional conformance of 'InheritEqual<U>' to 'P5'}}
+}
+
+struct InheritLess<T> {}
+extension InheritLess: P2 where T: P1 {}
+extension InheritLess: P5 {}
+// expected-error@-1{{'P5' requires that 'T' conform to 'P1'}}
+// expected-note@-2{{requirement specified as 'T' : 'P1'}}
+// expected-note@-3{{requirement from conditional conformance of 'InheritLess<T>' to 'P2'}}
+
+
+struct InheritMore<T> {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
+// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P2
+// CHECK-NEXT: conforms_to: τ_0_0 P1)
+extension InheritMore: P2 where T: P1 {}
+// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
+// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P5
+// CHECK-NEXT: conforms_to: τ_0_0 P4)
+extension InheritMore: P5 where T: P4 {}
+func inheritequal_good_good<U: P4>(_: U) {
+ takes_P2(InheritMore<U>())
+ takes_P5(InheritMore<U>())
+}
+func inheritequal_good_bad<U: P1>(_: U) {
+ takes_P2(InheritMore<U>())
+ takes_P5(InheritMore<U>())
+ // expected-error@-1{{'<X where X : P5> (X) -> ()' requires that 'U' conform to 'P4'}}
+ // expected-note@-2{{requirement specified as 'U' : 'P4'}}
+ // expected-note@-3{{requirement from conditional conformance of 'InheritMore<U>' to 'P5'}}
+}
+func inheritequal_bad_bad<U>(_: U) {
+ takes_P2(InheritMore<U>())
+ // expected-error@-1{{'<X where X : P2> (X) -> ()' requires that 'U' conform to 'P1'}}
+ // expected-note@-2{{requirement specified as 'U' : 'P1'}}
+ // expected-note@-3{{requirement from conditional conformance of 'InheritMore<U>' to 'P2'}}
+ takes_P5(InheritMore<U>())
+ // expected-error@-1{{'<X where X : P5> (X) -> ()' requires that 'U' conform to 'P4'}}
+ // expected-note@-2{{requirement specified as 'U' : 'P4'}}
+ // expected-note@-3{{requirement from conditional conformance of 'InheritMore<U>' to 'P5'}}
+}
+
+struct InheritImplicitGood<T> {}
+// FIXME: per SE-0143, this should result in an implicit conformance
+// InheritImplicitGood: P2.
+extension InheritImplicitGood: P5 where T: P1 {}
+// expected-error@-1{{type 'InheritImplicitGood<T>' does not conform to protocol 'P2'}}
+
+struct InheritImplicitBad<T> {}
+// This shouldn't give anything implicit since either conformance could imply
+// InheritImplicitBad: P2.
+extension InheritImplicitBad: P5 where T: P1 {}
+// expected-error@-1{{type 'InheritImplicitBad<T>' does not conform to protocol 'P2'}}
+extension InheritImplicitBad: P6 where T: P1 {}
+// expected-error@-1{{type 'InheritImplicitBad<T>' does not conform to protocol 'P2'}}
+
+
+
+// "Multiple conformances" from SE0143
+
+struct TwoConformances<T> {}
+extension TwoConformances: P2 where T: P1 {}
+// expected-error@-1{{redundant conformance of 'TwoConformances<T>' to protocol 'P2'}}
+extension TwoConformances: P2 where T: P3 {}
+// expected-note@-1{{'TwoConformances<T>' declares conformance to protocol 'P2' here}}
+
+struct TwoDisjointConformances<T> {}
+extension TwoDisjointConformances: P2 where T == Int {}
+// expected-error@-1{{redundant conformance of 'TwoDisjointConformances<T>' to protocol 'P2'}}
+extension TwoDisjointConformances: P2 where T == String {}
+// expected-note@-1{{'TwoDisjointConformances<T>' declares conformance to protocol 'P2' here}}
+
+
// FIXME: these cases should be equivalent (and both with the same output as the
// first), but the second one choses T as the representative of the
// equivalence class containing both T and U in the extension's generic
diff --git a/test/Generics/conditional_conformances_execute_smoke.swift b/test/Generics/conditional_conformances_execute_smoke.swift
new file mode 100644
index 0000000..eb2ad6f
--- /dev/null
+++ b/test/Generics/conditional_conformances_execute_smoke.swift
@@ -0,0 +1,84 @@
+// RUN: %target-run-simple-swift | %FileCheck %s
+
+// Smoke test to see that various conditional conformances correctly execute
+
+protocol P1 {
+ func method1()
+}
+var isp1_count = 0
+struct IsP1: P1 {
+ var id: Int
+ init() {
+ id = isp1_count
+ isp1_count += 1
+ }
+ func method1() {
+ print("IsP1", id)
+ }
+}
+protocol P2 {
+ func method2()
+}
+protocol P3 {
+ func method3()
+}
+protocol P4: P1 {
+ func method4()
+}
+
+protocol Assoc { associatedtype AT }
+
+func takes_P2<X: P2>(_ x: X) {
+ x.method2()
+}
+
+struct NoRecur<T> {
+ var x: T
+}
+extension NoRecur: P2 where T: P1 {
+ func method2() {
+ print("NoRecur")
+ x.method1()
+ }
+}
+
+var noRecur = NoRecur(x: IsP1())
+print("noRecur.method2()")
+noRecur.method2()
+// CHECK-LABEL: noRecur.method2()
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 0
+
+print("takes_P2(NoRecur(...))")
+takes_P2(NoRecur(x: IsP1()))
+// CHECK-LABEL: takes_P2(NoRecur(...))
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 1
+
+struct Recur<T> {
+ var id: Int
+ var x: T
+}
+extension Recur: P2 where T: P2 {
+ func method2() {
+ print("Recur", id)
+ x.method2()
+ }
+}
+
+var recur = Recur(id: 0, x: Recur(id: 1, x: NoRecur(x: IsP1())))
+print("recur.method2()")
+recur.method2()
+// CHECK-LABEL: recur.method2()
+// CHECK-NEXT: Recur 0
+// CHECK-NEXT: Recur 1
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 2
+
+print("takes_P2(Recur(...))")
+takes_P2(Recur(id: 2, x: Recur(id: 3, x: NoRecur(x: IsP1()))))
+// CHECK-LABEL: takes_P2(Recur(...))
+// CHECK-NEXT: Recur 2
+// CHECK-NEXT: Recur 3
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 3
diff --git a/test/Generics/conditional_conformances_operators.swift b/test/Generics/conditional_conformances_operators.swift
new file mode 100644
index 0000000..91b6a54
--- /dev/null
+++ b/test/Generics/conditional_conformances_operators.swift
@@ -0,0 +1,17 @@
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify
+
+// rdar://problem/35480952
+
+postfix operator %%%
+protocol P {
+ static postfix func %%%(lhs: Self)
+}
+protocol Q {}
+struct Foo<T> {}
+extension Foo: P where T : Q {
+ static postfix func %%%(lhs: Foo<T>) {}
+}
+
+func useIt<T: Q>(_: T.Type) {
+ Foo<T>()%%%
+}
diff --git a/test/Generics/validate_stdlib_generic_signatures.swift b/test/Generics/validate_stdlib_generic_signatures.swift
new file mode 100644
index 0000000..eae4985
--- /dev/null
+++ b/test/Generics/validate_stdlib_generic_signatures.swift
@@ -0,0 +1,6 @@
+// Verifies that all of the generic signatures in the standard library are
+// minimal and canonical.
+
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify-generic-signatures Swift
+
+// expected-no-diagnostics
diff --git a/test/IRGen/abitypes.swift b/test/IRGen/abitypes.swift
index 934643e..5bffd1b 100644
--- a/test/IRGen/abitypes.swift
+++ b/test/IRGen/abitypes.swift
@@ -214,9 +214,8 @@
// x86_64-macosx: define hidden i8* @_T08abitypes3FooC9copyClass{{[_0-9a-zA-Z]*}}FTo(i8*, i8*, i8*) unnamed_addr {{.*}} {
// x86_64-macosx: [[VALUE:%[0-9]+]] = call swiftcc [[TYPE:%.*]]* @_T08abitypes3FooC9copyClass{{[_0-9a-zA-Z]*}}F
- // x86_64-macosx: [[T0:%.*]] = phi [[TYPE]]* [ [[VALUE]],
- // x86_64-macosx: [[T1:%.*]] = bitcast [[TYPE]]* [[T0]] to [[OBJC:%objc_class]]*
- // x86_64-macosx: [[RESULT:%[0-9]+]] = bitcast [[OBJC]]* [[T1]] to i8*
+ // x86_64-macosx: [[T0:%.*]] = call [[OBJC:%objc_class]]* @swift_getObjCClassFromMetadata([[TYPE]]* [[VALUE]])
+ // x86_64-macosx: [[RESULT:%[0-9]+]] = bitcast [[OBJC]]* [[T0]] to i8*
// x86_64-macosx: ret i8* [[RESULT]]
dynamic func copyClass(_ a: AnyClass) -> AnyClass {
return a
diff --git a/test/IRGen/associated_type_witness.swift b/test/IRGen/associated_type_witness.swift
index 933102a..83a6746 100644
--- a/test/IRGen/associated_type_witness.swift
+++ b/test/IRGen/associated_type_witness.swift
@@ -117,10 +117,16 @@
// CHECK-NEXT: store atomic %swift.type* [[FETCH_RESULT]], %swift.type** [[CACHE]] release, align 8
// CHECK-NEXT: br label %cont
-// Witness table instantiation function for Computed : Assocked.
-// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWa(%swift.type*)
+// Witness table accessor function for Computed : Assocked.
+// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWa(%swift.type*, i8***, i64)
// CHECK: entry:
-// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWG, %swift.type* %0, i8** null)
+// CHECK-NEXT: %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT: [[TABLES:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT: store i8*** %1, i8**** [[TABLES]], align 8
+// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT: store i64 %2, i64* [[COUNT]], align 8
+// CHECK-NEXT: [[INSTANTIATION_ARGS:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWG, %swift.type* %0, i8** [[INSTANTIATION_ARGS]])
// CHECK-NEXT: ret i8** [[WTABLE]]
@@ -151,17 +157,23 @@
// Instantiation function for GenericComputed : DerivedFromSimpleAssoc.
// CHECK-LABEL: define internal void @_T023associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWI(i8**, %swift.type*, i8**)
-// CHECK: [[T0:%.*]] = call i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type* %1)
+// CHECK: [[T0:%.*]] = call i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type* %1, i8*** undef, i64 0)
// CHECK-NEXT: [[T1:%.*]] = bitcast i8** [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8*, i8** %0, i32 0
// CHECK-NEXT: store i8* [[T1]], i8** [[T2]], align 8
// CHECK-NEXT: ret void
-// Witness table instantiation function for GenericComputed : HasSimpleAssoc..
-// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type*)
+// Witness table accessor function for GenericComputed : HasSimpleAssoc..
+// CHECK-LABEL: define hidden i8** @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWa(%swift.type*, i8***, i64)
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWG, %swift.type* %0, i8** null)
-// CHECK-NEXT: ret i8** %1
+// CHECK-NEXT: %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT: [[TABLES:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT: store i8*** %1, i8**** [[TABLES]], align 8
+// CHECK-NEXT: [[COUNT:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT: store i64 %2, i64* [[COUNT]], align 8
+// CHECK-NEXT: [[INSTANTIATION_ARGS:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T023associated_type_witness15GenericComputedVyxGAA14HasSimpleAssocAAWG, %swift.type* %0, i8** [[INSTANTIATION_ARGS]])
+// CHECK-NEXT: ret i8** [[WTABLE]]
protocol HasAssocked {
diff --git a/test/IRGen/c_function_pointer.sil b/test/IRGen/c_function_pointer.sil
index 760918c..8f74c62 100644
--- a/test/IRGen/c_function_pointer.sil
+++ b/test/IRGen/c_function_pointer.sil
@@ -27,5 +27,4 @@
// CHECK-LABEL: define linkonce_odr hidden %swift.type* @_T0yyXCMa()
// -- 0x3000001 -- C convention, 1 argument
-// CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3)
-
+// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 196608, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
diff --git a/test/IRGen/class_bounded_generics.swift b/test/IRGen/class_bounded_generics.swift
index 573a13b..21ea905 100644
--- a/test/IRGen/class_bounded_generics.swift
+++ b/test/IRGen/class_bounded_generics.swift
@@ -91,10 +91,10 @@
// 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: call %objc_object* @swift_unknownRetain(%objc_object* returned [[Y:%.*]])
// CHECK: [[WITNESS_ENTRY:%.*]] = getelementptr inbounds i8*, i8** %T.ClassBoundBinary, i32 1
// 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 %objc_object* @swift_unknownRetain(%objc_object* returned [[Y:%.*]])
// CHECK: call swiftcc void [[WITNESS_FUNC]](%objc_object* [[Y]], %objc_object* swiftself %0, %swift.type* %T, i8** %T.ClassBoundBinary)
}
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index e7c2b20..5a4851d 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -13,14 +13,14 @@
// CHECK: @_T016class_resilience33ClassWithResilientlySizedPropertyC1r16resilient_struct9RectangleVvpWvd = {{(protected )?}}global [[INT]] 0
// CHECK: @_T016class_resilience33ClassWithResilientlySizedPropertyC5colors5Int32VvpWvd = {{(protected )?}}global [[INT]] 0
-// CHECK: @_T016class_resilience14ResilientChildC5fields5Int32VvpWvd = {{(protected )?}}global [[INT]] {{12|16}}
+// CHECK: @_T016class_resilience14ResilientChildC5fields5Int32VvpWvd = {{(protected )?}}global [[INT]] {{8|16}}
// CHECK: @_T016class_resilience21ResilientGenericChildC5fields5Int32VvpWvi = {{(protected )?}}global [[INT]] {{56|88}}
-// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd = {{(protected )?}}constant [[INT]] {{12|16}}
-// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{16|20}}
+// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC1rAA0eF6StructVvpWvd = {{(protected )?}}constant [[INT]] {{8|16}}
+// CHECK: @_T016class_resilience28ClassWithMyResilientPropertyC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{12|20}}
-// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC1s14resilient_enum10FunnyShapeOvpWvd = {{(protected )?}}constant [[INT]] {{12|16}}
-// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{16|24}}
+// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC1s14resilient_enum10FunnyShapeOvpWvd = {{(protected )?}}constant [[INT]] {{8|16}}
+// CHECK: @_T016class_resilience30ClassWithIndirectResilientEnumC5colors5Int32VvpWvd = {{(protected )?}}constant [[INT]] {{12|24}}
import resilient_class
import resilient_struct
diff --git a/test/IRGen/conditional_conformances.swift b/test/IRGen/conditional_conformances.swift
new file mode 100644
index 0000000..c8b6a2c
--- /dev/null
+++ b/test/IRGen/conditional_conformances.swift
@@ -0,0 +1,7 @@
+// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift
+// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc.swift
+// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass.swift
+
+// Too many pointer-sized integers in the IR
+// REQUIRES: PTRSIZE=64
+
diff --git a/test/IRGen/dynamic_cast_functions.swift b/test/IRGen/dynamic_cast_functions.swift
index a6dc73e..16f6141 100644
--- a/test/IRGen/dynamic_cast_functions.swift
+++ b/test/IRGen/dynamic_cast_functions.swift
@@ -48,3 +48,72 @@
// CHECK: ok
print((t1 == t2) ? "fail" : "ok")
+
+let i: (inout Int) -> Void = { _ in }
+let j: (__shared Int) -> Void = { _ in }
+let k: (Int, inout Int) -> Void = { _,_ in }
+let l: (inout Int, Float, inout String) -> Void = { _,_,_ in }
+let m: (__shared Int, String, inout Float, Double) -> Void = { _,_,_,_ in }
+
+let i_any: Any = i
+let j_any: Any = j
+let k_any: Any = k
+let l_any: Any = l
+let m_any: Any = m
+
+// CHECK: ok
+print((i_any as? (Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((i_any as? (__shared Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((i_any as? (inout Int) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((j_any as? (Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((j_any as? (inout Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((j_any as? (__shared Int) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((k_any as? (Int, Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((k_any as? (Int, inout Int) -> Void) != nil ? "ok" : "fail")
+// CHECK: ok
+print((k_any as? (inout Int, Int) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((k_any as? (inout Int, __shared Int) -> Void) != nil ? "fail" : "ok")
+
+// CHECK: ok
+print((l_any as? (Int, Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (Int, Float, inout String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (Int, inout Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, inout Float, String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, __shared String) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((l_any as? (inout Int, Float, inout String) -> Void) != nil ? "ok" : "fail")
+
+// CHECK: ok
+print((m_any as? (Int, String, Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, Float, inout Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, Float, __shared Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, String, inout Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, __shared String, Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (inout Int, String, __shared Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (__shared Int, String, Float, inout Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (Int, __shared String, inout Float, Double) -> Void) != nil ? "fail" : "ok")
+// CHECK: ok
+print((m_any as? (__shared Int, String, inout Float, Double) -> Void) != nil ? "ok" : "fail")
diff --git a/test/IRGen/existentials_opaque_boxed.sil b/test/IRGen/existentials_opaque_boxed.sil
index 02c153a..2a57c9f 100644
--- a/test/IRGen/existentials_opaque_boxed.sil
+++ b/test/IRGen/existentials_opaque_boxed.sil
@@ -80,7 +80,7 @@
// CHECK: [[CONTAINER:%.*]] = alloca %T25existentials_opaque_boxed11ExistentialP
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
-// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64|i32)}} 48, {{(i64|i32)}} 7)
+// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata, i32 0, i32 2), {{(i64 48|i32 40)}}, {{(i64|i32)}} 7)
// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>*
// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>, <{ %swift.refcounted{{(, \[4 x i8\])?}}, [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14NotInlineFixedV*
@@ -136,7 +136,7 @@
// CHECK: [[VW2:%.*]] = load i8*, i8** [[VW_ADDR2]]
// CHECK: [[SIZE:%.*]] = ptrtoint i8* [[VW2]] to {{(i64|i32)}}
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
-// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64|i32)}} {{(16|12)}}, [[ALIGNMASK]]
+// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
// CHECK: [[HEAPSIZE:%.*]] = add {{(i64|i32)}} [[ALIGNEDSTART]], [[SIZE]]
@@ -179,7 +179,7 @@
// CHECK: [[REFADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.refcounted**
// CHECK: [[REF:%.*]] = load %swift.refcounted*, %swift.refcounted** [[REFADDR]]
// CHECK: [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
-// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64|i32)}} {{(16|12)}}, [[ALIGNMASK]]
+// CHECK: [[HEADERSIZEPLUSALIGN:%.*]] = add {{(i64 16|i32 8)}}, [[ALIGNMASK]]
// CHECK: [[NOTALIGNMASK:%.*]] = xor {{(i64|i32)}} [[ALIGNMASK]], -1
// CHECK: [[ALIGNEDSTART:%.*]] = and {{(i64|i32)}} [[HEADERSIZEPLUSALIGN]], [[NOTALIGNMASK]]
// CHECK: [[HEAPOBJ:%.*]] = bitcast %swift.refcounted* %9 to i8*
@@ -519,8 +519,8 @@
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[INLINEBUFFER:%.*]] = getelementptr inbounds %T25existentials_opaque_boxed11ExistentialP, %T25existentials_opaque_boxed11ExistentialP* [[CONTAINER]], i32 0, i32 0
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* getelementptr inbounds (%swift.full_boxmetadata, %swift.full_boxmetadata* @metadata.3, i32 0, i32 2), {{(i64|i32)}} 64, {{(i64|i32)}} 31)
-// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>*
-// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(20|16)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
+// CHECK: [[BOX_ADDR:%.*]] = bitcast %swift.refcounted* [[BOX]] to <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>*
+// CHECK: [[VALUE_ADDR:%.*]] = getelementptr inbounds <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>, <{ %swift.refcounted, [{{(16|24)}} x i8], [32 x i8] }>* [[BOX_ADDR]], i32 0, i32 {{(1|2)}}
// CHECK: [[INIT_EXIST_ADDR:%.*]] = bitcast [32 x i8]* [[VALUE_ADDR]] to %T25existentials_opaque_boxed14FixedOveralignV*
// CHECK: [[INLINEBUFFER_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* [[INLINEBUFFER]] to %swift.refcounted**
// CHECK: store %swift.refcounted* [[BOX]], %swift.refcounted** [[INLINEBUFFER_ADDR]]
diff --git a/test/IRGen/function_metadata.swift b/test/IRGen/function_metadata.swift
index 5dec8d0..8cb6f87 100644
--- a/test/IRGen/function_metadata.swift
+++ b/test/IRGen/function_metadata.swift
@@ -4,45 +4,42 @@
// CHECK: define hidden swiftcc void @_T017function_metadata9test_archyyF()
func test_arch() {
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3) {{#[0-9]+}}
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 0, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch( {() -> () in } )
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD:i(32|64)]] 1, i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)) {{#[0-9]+}}
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD:i(32|64)]] 1, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)) {{#[0-9]+}}
arch({(x: Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* bitcast (%swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1) to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(_: ()) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1WithFlags([[WORD]] 33554433, %swift.type* @_T0SiN, i32 1, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, i8* %3, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata1([[WORD]] 1, %swift.type* %2, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: (Int, Float)) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2WithFlags([[WORD]] 33554434, %swift.type* @_T0SiN, i32 1, %swift.type* @_T0SiN, i32 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int, y: Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata2([[WORD]] 2, %swift.type* @_T0SfN, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(a: Float, b: Int) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*), i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SSN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3WithFlags([[WORD]] 33554435, %swift.type* @_T0SiN, i32 1, %swift.type* @_T0SfN, i32 0, %swift.type* @_T0SSN, i32 0, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int, y: Float, z: String) -> () in })
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SfN to i8*), i8* bitcast (%swift.type* @_T0SiN to i8*), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata3([[WORD]] 3, %swift.type* @_T0SfN, %swift.type* @_T0SfN, %swift.type* @_T0SiN, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(a: Float, b: Float, c: Int) -> () in })
- // CHECK: [[T0:%.*]] = getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 0
- // CHECK: store [[WORD]] 4
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 1
- // CHECK: store i8* inttoptr ([[WORD]] or ([[WORD]] ptrtoint (%swift.type* @_T0SiN to [[WORD]]), [[WORD]] 1) to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 2
- // CHECK: store i8* bitcast (%swift.type* @_T0SdN to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 3
- // CHECK: store i8* bitcast (%swift.type* @_T0SSN to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 4
- // CHECK: store i8* bitcast (%swift.type* @_T0s4Int8VN to i8*)
- // CHECK: getelementptr inbounds [6 x i8*], [6 x i8*]* %function-arguments, i32 0, i32 5
- // CHECK: store %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1)
- // CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** [[T0]]) {{#[0-9]+}}
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 0
+ // CHECK: store %swift.type* @_T0SiN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 1
+ // CHECK: store %swift.type* @_T0SdN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 2
+ // CHECK: store %swift.type* @_T0SSN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 3
+ // CHECK: store %swift.type* @_T0s4Int8VN, %swift.type** [[T:%.*]], align [[ALIGN:(4|8)]]
+ // CHECK: [[T:%.*]] = getelementptr inbounds [4 x %swift.type*], [4 x %swift.type*]* %function-parameters, i32 0, i32 0
+ // CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD]] 33554436, %swift.type** %7, i32* getelementptr inbounds ([4 x i32], [4 x i32]* @parameter-flags, i32 0, i32 0), %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
arch({(x: inout Int, y: Double, z: String, w: Int8) -> () in })
}
diff --git a/test/IRGen/keypaths.sil b/test/IRGen/keypaths.sil
index 8e5d64e..56f038f 100644
--- a/test/IRGen/keypaths.sil
+++ b/test/IRGen/keypaths.sil
@@ -75,7 +75,7 @@
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.x
-// CHECK-32-SAME: <i32 0x4000_000c> }>
+// CHECK-32-SAME: <i32 0x4000_0008> }>
// CHECK-64-SAME: <i32 0x4000_0010> }>
// -- %e: C.y
@@ -87,7 +87,7 @@
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.y
-// CHECK-32-SAME: <i32 0x4000_0010> }>
+// CHECK-32-SAME: <i32 0x4000_000c> }>
// CHECK-64-SAME: <i32 0x4000_0018> }>
// -- %f: C.z
@@ -99,7 +99,7 @@
// CHECK-SAME: <i32 0x8000_0004>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.z
-// CHECK-32-SAME: <i32 0x4000_001c> }>
+// CHECK-32-SAME: <i32 0x4000_0018> }>
// CHECK-64-SAME: <i32 0x4000_0030> }>
// -- %g: S.z.x
@@ -118,7 +118,7 @@
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK: %swift.type* (i8*)*
// -- 0x4000_0000 (class) + offset of C.x
-// CHECK-32-SAME: <i32 0x4000_000c> }>
+// CHECK-32-SAME: <i32 0x4000_0008> }>
// CHECK-64-SAME: <i32 0x4000_0010> }>
// -- %h: C.z.x
@@ -132,7 +132,7 @@
// CHECK-64-SAME: <i32 0x8000_0014>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// -- 0x4000_0000 (class) + offset of C.z
-// CHECK-32-SAME: <i32 0x4000_001c>,
+// CHECK-32-SAME: <i32 0x4000_0018>,
// CHECK-64-SAME: <i32 0x4000_0030>,
// CHECK-64-SAME: [4 x i8] zeroinitializer,
// CHECK: %swift.type* (i8*)*
diff --git a/test/IRGen/literals.sil b/test/IRGen/literals.sil
index ce5987b..b45a16b 100644
--- a/test/IRGen/literals.sil
+++ b/test/IRGen/literals.sil
@@ -7,11 +7,11 @@
// CHECK: [[U16_0:@.*]] = private unnamed_addr constant [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0]
// CHECK: [[U16_1:@.*]] = private unnamed_addr constant [4 x i16] [i16 0, i16 120, i16 427, i16 0]
// CHECK: @_T0s19_UTF16StringStorageCN = external global %objc_class
-// CHECK: [[UTF16_CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [8 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 7, i32 8, i8 0, i8 0, [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0] }
-// CHECK: [[UTF16_CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [9 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 8, i32 9, i8 0, i8 0, [9 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0, i16 0] }
+// CHECK: [[UTF16_CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [8 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i64 8589934594 }, i32 7, i32 8, i8 0, i8 0, [8 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0] }
+// CHECK: [[UTF16_CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, i8, [9 x i16] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s19_UTF16StringStorageCN to %swift.type*), i64 8589934594 }, i32 8, i32 9, i8 0, i8 0, [9 x i16] [i16 104, i16 101, i16 108, i16 112, i16 9, i16 109, i16 101, i16 0, i16 0] }
// CHECK: @_T0s20_Latin1StringStorageCN = external global %objc_class
-// CHECK: [[CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [12 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 11, i32 12, i8 0, [12 x i8] c"help\09me too\00" }
-// CHECK: [[CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [13 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i32 4, i32 0 }, i32 12, i32 13, i8 0, [13 x i8] c"help\09me too\00\00" }
+// CHECK: [[CSTR_0:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [12 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i64 8589934594 }, i32 11, i32 12, i8 0, [12 x i8] c"help\09me too\00" }
+// CHECK: [[CSTR_1:@.*]] = private unnamed_addr constant { %swift.refcounted, i32, i32, i8, [13 x i8] } { %swift.refcounted { %swift.type* bitcast (%objc_class* @_T0s20_Latin1StringStorageCN to %swift.type*), i64 8589934594 }, i32 12, i32 13, i8 0, [13 x i8] c"help\09me too\00\00" }
sil_stage canonical
diff --git a/test/IRGen/metatype.sil b/test/IRGen/metatype.sil
index 6d82c1d..ba052b9 100644
--- a/test/IRGen/metatype.sil
+++ b/test/IRGen/metatype.sil
@@ -31,10 +31,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc %objc_class* @foreign_thick_to_objc(%swift.type*)
sil @foreign_thick_to_objc : $@convention(thin) (@thick Gizmo.Type) -> @objc_metatype Gizmo.Type {
bb0(%0 : $@thick Gizmo.Type):
- // CHECK: [[KIND_GEP:%[0-9A-Za-z_.]+]] = getelementptr inbounds %swift.type, %swift.type* %0, i32 0, i32 0
- // CHECK-NEXT: [[KIND:%[0-9A-Za-z_.]+]] = load i64, i64* [[KIND_GEP]], align 8
- // CHECK-NEXT: [[IS_WRAPPER:%[0-9A-Za-z_.]+]] = icmp eq i64 [[KIND]], 14
- // CHECK-NEXT: br i1
+ // CHECK: call %objc_class* @swift_getObjCClassFromMetadata
%1 = thick_to_objc_metatype %0 : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
// CHECK: ret %objc_class*
return %1 : $@objc_metatype Gizmo.Type
@@ -61,12 +58,7 @@
protocol CP: class {}
// CHECK-LABEL: define{{( protected)?}} swiftcc %objc_class* @archetype_objc_metatype(%swift.type* %T, i8** %T.CP)
-// CHECK: [[IS_OBJC_WRAPPER:%.*]] = icmp eq i64 {{%.*}}, 14
-// CHECK: br i1 [[IS_OBJC_WRAPPER]], label %isWrapper, label %metadataForClass.cont
-// CHECK: isWrapper:
-// CHECK: [[WRAPPED_CLASS:%.*]] = load %swift.type*, %swift.type**
-// CHECK: metadataForClass.cont:
-// CHECK: phi %swift.type* [ %T, %entry ], [ [[WRAPPED_CLASS]], %isWrapper ]
+// CHECK: call %objc_class* @swift_getObjCClassFromMetadata
sil @archetype_objc_metatype : $@convention(thin) <T: CP> () -> @objc_metatype T.Type {
entry:
%m = metatype $@objc_metatype T.Type
diff --git a/test/IRGen/objc_block.sil b/test/IRGen/objc_block.sil
index ce8a344..3f6bf1b 100644
--- a/test/IRGen/objc_block.sil
+++ b/test/IRGen/objc_block.sil
@@ -38,5 +38,4 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @generic_with_block(%objc_block** noalias nocapture dereferenceable({{.*}}))
// -- 0x100_0001 = block convention, 1 arg
-// CHECK: call %swift.type* @swift_getFunctionTypeMetadata(i8** %3)
-
+// CHECK: call %swift.type* @swift_getFunctionTypeMetadata([[WORD:i(32|64)]] 65536, %swift.type** null, i32* null, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @_T0ytN, i32 0, i32 1))
diff --git a/test/IRGen/objc_class_empty_fields.swift b/test/IRGen/objc_class_empty_fields.swift
index 5a3e204..dfdb5fd 100644
--- a/test/IRGen/objc_class_empty_fields.swift
+++ b/test/IRGen/objc_class_empty_fields.swift
@@ -5,7 +5,7 @@
// SR-1055
// CHECK-64: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 16, i32 24
-// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 12, i32 16
+// CHECK-32: @_DATA__TtC23objc_class_empty_fields14OneEnumWrapper = private constant { {{.*}}* } { i32 {{[0-9]+}}, i32 8, i32 12
enum OneCaseEnum {
case X
diff --git a/test/IRGen/partial_apply_forwarder.sil b/test/IRGen/partial_apply_forwarder.sil
index 984c1e9..408a54f 100644
--- a/test/IRGen/partial_apply_forwarder.sil
+++ b/test/IRGen/partial_apply_forwarder.sil
@@ -94,7 +94,7 @@
// CHECK: [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
// CHECK: [[PARAMTYADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}}
// CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[PARAMTYADDR]]
-// CHECK: [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>")
+// CHECK: [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>", i8*** undef, {{i32|i64}} 0)
// CHECK: [[OBJ:%.*]] = bitcast %swift.refcounted* %0 to %T23partial_apply_forwarder7WeakBoxC.1*
// CHECK: tail call swiftcc void @takingQ(%T23partial_apply_forwarder7WeakBoxC.1* [[OBJ]], i8** [[WITNESS]])
// CHECK: }
@@ -151,7 +151,7 @@
// CHECK: [[TYPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
// CHECK: [[TYPARAM:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[TYPARAMSADDR]], {{(i64 10|i32 13)}}
// CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[TYPARAM]]
-// CHECK: [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>")
+// CHECK: [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>", i8*** undef, {{i32|i64}} 0)
// CHECK: tail call swiftcc void @takingQ(%T23partial_apply_forwarder7WeakBoxC.1* [[CAST]], i8** [[WITNESS]])
// CHECK: ret void
@@ -203,7 +203,7 @@
// CHECK: [[GENPARAMSADDR:%.*]] = bitcast %swift.type* [[TY]] to %swift.type**
// CHECK: [[GENPARAMADDR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[GENPARAMSADDR]], {{(i64 10|i32 13)}}
// CHECK: %"BaseProducer<\CF\84_0_1>" = load %swift.type*, %swift.type** [[GENPARAMADDR]]
-// CHECK: [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>")
+// CHECK: [[WITNESS:%.*]] = call i8** @_T023partial_apply_forwarder12BaseProducerVyxGAA1QAAWa(%swift.type* %"BaseProducer<\CF\84_0_1>", i8*** undef, {{i32|i64}} 0)
// CHECK: tail call swiftcc void @takingQAndS(i64 [[X]], %T23partial_apply_forwarder7WeakBoxC.1* %.asUnsubstituted, i8** [[WITNESS]])
sil public @bind_polymorphic_param_from_context_with_layout : $@convention(thin) <τ_0_1>(@in τ_0_1, S) -> @owned @callee_owned () -> () {
diff --git a/test/IRGen/partial_apply_objc.sil b/test/IRGen/partial_apply_objc.sil
index ffd59ee..d6c16ca 100644
--- a/test/IRGen/partial_apply_objc.sil
+++ b/test/IRGen/partial_apply_objc.sil
@@ -225,3 +225,49 @@
%p = partial_apply %m(%c) : $@convention(objc_method) (Fob, Gizmo) -> ()
return %p : $@callee_owned (Fob) -> ()
}
+
+// CHECK-LABEL: define {{.*}}@objc_partial_apply_callee_guaranteed
+// CHECK: [[CONTEXT:%.*]] = call {{.*}}@swift_rt_swift_allocObject
+// CHECK: store
+// CHECK: [[CLOSURE:%.*]] = insertvalue {{.*}}@_T0Ta.20{{.*}}, {{.*}}[[CONTEXT]], 1
+// CHECK: ret {{.*}}[[CLOSURE]]
+
+sil @objc_partial_apply_callee_guaranteed : $@convention(thin) ObjCClass -> @callee_guaranteed Int -> () {
+entry(%c : $ObjCClass):
+ %m = objc_method %c : $ObjCClass, #ObjCClass.method!1.foreign : (ObjCClass) -> (Int) -> (), $@convention(objc_method) (Int, ObjCClass) -> ()
+ %p = partial_apply [callee_guaranteed] %m(%c) : $@convention(objc_method) (Int, ObjCClass) -> ()
+ return %p : $@callee_guaranteed Int -> ()
+}
+
+// CHECK-LABEL: define {{.*}}swiftcc void @_T0Ta.20(i64, %swift.refcounted* swiftself)
+// CHECK: entry:
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK: call {{.*}}@objc_msgSend
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK: ret void
+// CHECK: }
+
+// CHECK-LABEL: define {{.*}}@objc_partial_apply_2_callee_guaranteed
+// CHECK: [[CONTEXT:%.*]] = call {{.*}}@swift_rt_swift_allocObject
+// CHECK: store
+// CHECK: [[CLOSURE:%.*]] = insertvalue {{.*}}@_T0Ta.23{{.*}}, {{.*}}[[CONTEXT]], 1
+// CHECK: ret {{.*}}[[CLOSURE]]
+
+sil @objc_partial_apply_2_callee_guaranteed : $@convention(thin) Gizmo -> @callee_guaranteed (Fob) -> () {
+entry(%c : $Gizmo):
+ %m = objc_method %c : $Gizmo, #Gizmo.test!1.foreign : (Gizmo) -> (Fob) -> (), $@convention(objc_method) (Fob, Gizmo) -> ()
+ %p = partial_apply [callee_guaranteed] %m(%c) : $@convention(objc_method) (Fob, Gizmo) -> ()
+ return %p : $@callee_guaranteed (Fob) -> ()
+}
+
+// CHECK-LABEL: define {{.*}}swiftcc void @_T0Ta.23(i64, i64, i64, %swift.refcounted* swiftself)
+// CHECK: entry:
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK: call {{.*}}@objc_msgSend
+// CHECK-NOT: retain
+// CHECK-NOT: release
+// CHECK: ret void
+// CHECK: }
diff --git a/test/IRGen/protocol_resilience.sil b/test/IRGen/protocol_resilience.sil
index c3b86ab..ddfbb61 100644
--- a/test/IRGen/protocol_resilience.sil
+++ b/test/IRGen/protocol_resilience.sil
@@ -296,7 +296,11 @@
// CHECK-LABEL: define{{( protected)?}} i8** @_T019protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWa()
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T019protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWG, %swift.type* null, i8** null)
+// CHECK-NEXT: %conditional.tables = alloca %swift.witness_table_slice
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT: store [[WORD:i(32|64)]] 0, [[WORD:i(32|64)]]* [[COUNT_PTR]]
+// CHECK-NEXT: [[INSTANTIATION_ARGS:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT: [[WTABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T019protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWG, %swift.type* null, i8** [[INSTANTIATION_ARGS]])
// CHECK-NEXT: ret i8** [[WTABLE]]
diff --git a/test/IRGen/sil_linkage.sil b/test/IRGen/sil_linkage.sil
index f0f3149..0fdbe7a 100644
--- a/test/IRGen/sil_linkage.sil
+++ b/test/IRGen/sil_linkage.sil
@@ -3,7 +3,7 @@
sil_stage canonical
// CHECK: define{{( protected)?}} swiftcc void @public_fragile_function_test() {{.*}} {
-// CHECK: define{{( protected)?}} internal swiftcc void @public_transparent_fragile_function_test() {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @public_transparent_fragile_function_test() {{.*}} {
// CHECK: define{{( protected)?}} swiftcc void @public_transparent_function_test() {{.*}} {
// CHECK: define{{( hidden)?}} swiftcc void @hidden_fragile_function_test() {{.*}} {
// CHECK: define linkonce_odr hidden swiftcc void @shared_fragile_function_test() {{.*}} {
diff --git a/test/IRGen/superclass_constraint.swift b/test/IRGen/superclass_constraint.swift
index 620b1e7..1466e37 100644
--- a/test/IRGen/superclass_constraint.swift
+++ b/test/IRGen/superclass_constraint.swift
@@ -8,9 +8,9 @@
// CHECK-LABEL: define{{.*}} @_T021superclass_constraint3CVCCACyxGycfc
public init() {
// CHECK: [[A:%.*]] = alloca %T21superclass_constraint3CVCC*
- // CHECK-NOT: ret
+ // CHECK-NOT: ret %T21superclass_constraint3CVCC*
// CHECK: store %T21superclass_constraint3CVCC* %0, %T21superclass_constraint3CVCC** [[A]]
- // CHECK: ret
+ // CHECK: ret %T21superclass_constraint3CVCC*
var a = self
}
}
diff --git a/test/IRGen/typed_boxes.sil b/test/IRGen/typed_boxes.sil
index 8999242..502d614 100644
--- a/test/IRGen/typed_boxes.sil
+++ b/test/IRGen/typed_boxes.sil
@@ -7,15 +7,13 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @pod_box_8_8_a
sil @pod_box_8_8_a : $@convention(thin) () -> () {
entry:
- // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD:i[0-9]+]] 24, [[WORD]] 7)
+ // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA:@metadata[0-9.]*]], i32 0, i32 2), [[WORD:i[0-9]+]] [[POD_8_8_SIZE:[0-9]+]], [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.Int64>
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
- // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
- // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
- // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+ // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+ // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to i64*
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>, 0
- // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] 24, [[WORD]] 7)
+ // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
dealloc_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>
return undef : $()
}
@@ -23,15 +21,13 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @pod_box_8_8_b
sil @pod_box_8_8_b : $@convention(thin) () -> () {
entry:
- // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA]], {{.*}} [[WORD]] 24, [[WORD]] 7)
+ // CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_8_8_METADATA]], i32 0, i32 2), [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
- // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
- // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
- // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+ // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+ // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to double*
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>, 0
- // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] 24, [[WORD]] 7)
+ // CHECK: call void @swift_rt_swift_deallocUninitializedObject(%swift.refcounted* [[BOX]], [[WORD]] [[POD_8_8_SIZE]], [[WORD]] 7)
dealloc_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.FPIEEE64>
return undef : $()
}
@@ -46,7 +42,7 @@
entry:
// CHECK: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[POD_32_32_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 64, [[WORD]] 31)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <OverAligned>
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[20 x i8\], \[32 x i8\] \}>]]*
+ // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[24 x i8\], \[32 x i8\] \}>]]*
// CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* [[BOX]] to [[POD_32_32_LAYOUT:<\{ %swift.refcounted, \[16 x i8\], \[32 x i8\] \}>]]*
// CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_32_32_LAYOUT]], [[POD_32_32_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [32 x i8]* [[BOX_DATA]] to %T11typed_boxes11OverAlignedV*
@@ -65,7 +61,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @rc_box_a
sil @rc_box_a : $@convention(thin) () -> () {
entry:
- // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+ // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 12, [[WORD]] 3)
// CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 24, [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <C>
// CHECK: bitcast %swift.refcounted** {{%.*}} to %T11typed_boxes1CC**
@@ -78,7 +74,7 @@
sil @rc_box_b : $@convention(thin) () -> () {
entry:
// TODO: Should reuse metadata
- // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+ // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 12, [[WORD]] 3)
// CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[NATIVE_RC_METADATA]], {{.*}} [[WORD]] 24, [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <D>
// CHECK: bitcast %swift.refcounted** {{%.*}} to %T11typed_boxes1DC**
@@ -90,7 +86,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @unknown_rc_box
sil @unknown_rc_box : $@convention(thin) () -> () {
entry:
- // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 16, [[WORD]] 3)
+ // CHECK-32: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 12, [[WORD]] 3)
// CHECK-64: [[BOX:%.*]] = call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* {{.*}} [[UNKNOWN_RC_METADATA:@metadata[0-9.]*]], {{.*}} [[WORD]] 24, [[WORD]] 7)
%a = alloc_box $<τ_0_0> { var τ_0_0 } <Builtin.UnknownObject>
%b = project_box %a : $<τ_0_0> { var τ_0_0 } <Builtin.UnknownObject>, 0
@@ -158,10 +154,8 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc i64 @proj_box
sil @proj_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Builtin.Int64>) -> Builtin.Int64 {
entry(%0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>):
- // CHECK-32: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[4 x i8\], \[8 x i8\] \}>]]*
- // CHECK-32: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 2
- // CHECK-64: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
- // CHECK-64: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
+ // CHECK: [[BOX_RAW:%.*]] = bitcast %swift.refcounted* %0 to [[POD_8_8_LAYOUT:<\{ %swift.refcounted, \[8 x i8\] \}>]]*
+ // CHECK: [[BOX_DATA:%.*]] = getelementptr inbounds [[POD_8_8_LAYOUT]], [[POD_8_8_LAYOUT]]* [[BOX_RAW]], i32 0, i32 1
// CHECK: [[BOX_DATA_1:%.*]] = bitcast [8 x i8]* [[BOX_DATA]] to i64*
%p = project_box %0 : $<τ_0_0> { var τ_0_0 } <Builtin.Int64>, 0
// CHECK: [[R:%.*]] = load i64, i64* [[BOX_DATA_1]]
diff --git a/test/IRGen/vector_reduction.swift b/test/IRGen/vector_reduction.swift
index aa93041..8ebc383 100644
--- a/test/IRGen/vector_reduction.swift
+++ b/test/IRGen/vector_reduction.swift
@@ -7,7 +7,7 @@
// We were missing target transform info and not vectorizing the loop below.
-// CHECK: xor <2 x i64>
+// CHECK: xor <{{(2|4|8)}} x i64>
public func f(a: UnsafePointer<Int>, b: UnsafePointer<Int>, count: Int) -> Int {
var c = 0
diff --git a/test/IRGen/witness_method.sil b/test/IRGen/witness_method.sil
index 9188def..3669da7 100644
--- a/test/IRGen/witness_method.sil
+++ b/test/IRGen/witness_method.sil
@@ -63,7 +63,7 @@
// CHECK-LABEL: define{{( protected)?}} swiftcc void @testGenericWitnessMethod(%swift.opaque* noalias nocapture sret, %T14witness_method6SyncUpV* noalias nocapture, %swift.type* %T)
// CHECK: entry:
// CHECK: [[METADATA:%.*]] = call %swift.type* @_T014witness_method6SyncUpVMa(%swift.type* %T)
-// CHECK: [[WTABLE:%.*]] = call i8** @_T014witness_method6SyncUpVyxGAA7SynergyAAWa(%swift.type* [[METADATA]])
+// CHECK: [[WTABLE:%.*]] = call i8** @_T014witness_method6SyncUpVyxGAA7SynergyAAWa(%swift.type* [[METADATA]], i8*** undef, {{i32|i64}} 0)
// CHECK: [[WITNESS_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[WTABLE]], i32 1
// CHECK: [[WITNESS_FN:%.*]] = load i8*, i8** [[WITNESS_ADDR]]
// CHECK: [[WITNESS:%.*]] = bitcast i8* [[WITNESS_FN]] to void (%swift.opaque*, %swift.opaque*, %swift.type*, i8**)*
diff --git a/test/Inputs/conditional_conformance_basic_conformances.swift b/test/Inputs/conditional_conformance_basic_conformances.swift
new file mode 100644
index 0000000..e5b2681
--- /dev/null
+++ b/test/Inputs/conditional_conformance_basic_conformances.swift
@@ -0,0 +1,336 @@
+public func takes_p1<T: P1>(_: T.Type) {}
+public protocol P1 {
+ func normal()
+ func generic<T: P3>(_: T)
+}
+public protocol P2 {}
+public protocol P3 {}
+
+public struct IsP2: P2 {}
+public struct IsP3: P3 {}
+
+
+public struct Single<A> {}
+extension Single: P1 where A: P2 {
+ public func normal() {}
+ public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Single.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlAaEP6normalyyFTW(%T42conditional_conformance_basic_conformances6SingleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[A_P2_i8star:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT: [[A_P2:%.*]] = bitcast i8* [[A_P2_i8star]] to i8**
+// CHECK-NEXT: [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* undef to i8*
+// CHECK-NEXT: [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* %0 to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[A_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT: [[A:%.*]] = load %swift.type*, %swift.type** [[A_PTR]], align 8
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances6SingleVA2A2P2RzlE6normalyyF(%swift.type* [[A]], i8** [[A_P2]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// witness method for Single.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T42conditional_conformance_basic_conformances6SingleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[A_P2_i8star:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT: [[A_P2:%.*]] = bitcast i8* [[A_P2_i8star]] to i8**
+// CHECK-NEXT: [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* undef to i8*
+// CHECK-NEXT: [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6SingleV* %1 to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[A_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT: [[A:%.*]] = load %swift.type*, %swift.type** [[A_PTR]], align 8
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances6SingleVA2A2P2RzlE7genericyqd__AA2P3Rd__lF(%swift.opaque* noalias nocapture %0, %swift.type* [[A]], %swift.type* %"\CF\84_1_0", i8** [[A_P2]], i8** %"\CF\84_1_0.P3")
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+public func single_generic<T: P2>(_: T.Type) {
+ takes_p1(Single<T>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances14single_genericyxmAA2P2RzlF(%swift.type*, %swift.type* %T, i8** %T.P2) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT: [[Single_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6SingleVMa(%swift.type* %T)
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[T_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** %T.P2, i8*** [[T_P2_PTR]], align 8
+// CHECK-NEXT: [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type* [[Single_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Single_TYPE]], %swift.type* [[Single_TYPE]], i8** [[Single_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// Witness table accessor for Single : P1
+
+// CHECK-LABEL: define{{( protected)?}} i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type*, i8***, i64) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT: store i8*** %1, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT: store i64 %2, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[CAST_CONDITIONAL_TABLES:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT: [[TABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWG, %swift.type* %0, i8** [[CAST_CONDITIONAL_TABLES]])
+// CHECK-NEXT: ret i8** [[TABLE]]
+// CHECK-NEXT: }
+
+
+public func single_concrete() {
+ takes_p1(Single<IsP2>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances15single_concreteyyF() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[Single_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa()
+// CHECK-NEXT: [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWl()
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Single_TYPE]], %swift.type* [[Single_TYPE]], i8** [[Single_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+
+// Lazy witness table accessor for the concrete Single<IsP2> : P1.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWl() #1 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL, align 8
+// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: [[Single_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGMa()
+
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP2VAA0F0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+
+// CHECK-NEXT: [[Single_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWa(%swift.type* [[Single_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT: store atomic i8** [[Single_P1]], i8*** @_T042conditional_conformance_basic_conformances6SingleVyAA4IsP2VGACyxGAA2P1A2A0G0RzlWL release, align 8
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: %6 = phi i8** [ [[CACHE]], %entry ], [ [[Single_P1]], %cacheIsNull ]
+// CHECK-NEXT: ret i8** %6
+// CHECK-NEXT: }
+
+
+public struct Double<B, C> {}
+extension Double: P1 where B: P2, C: P3 {
+ public func normal() {}
+ public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Double.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlAaEP6normalyyFTW(%T42conditional_conformance_basic_conformances6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[B_P2_i8star:%.*]] = load i8*, i8** [[B_P2_PTR]], align 8
+// CHECK-NEXT: [[B_P2:%.*]] = bitcast i8* [[B_P2_i8star]] to i8**
+
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT: [[C_P3_i8star:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT: [[C_P3:%.*]] = bitcast i8* [[C_P3_i8star]] to i8**
+
+// CHECK-NEXT: [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* undef to i8*
+// CHECK-NEXT: [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* %0 to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT: [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT: [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVA2A2P2RzAA2P3R_rlE6normalyyF(%swift.type* [[B]], %swift.type* [[C]], i8** [[B_P2]], i8** [[C_P3]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// witness method for Double.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlAaEP7genericyqd__AaGRd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T42conditional_conformance_basic_conformances6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[B_P2_i8star:%.*]] = load i8*, i8** [[B_P2_PTR]], align 8
+// CHECK-NEXT: [[B_P2:%.*]] = bitcast i8* [[B_P2_i8star]] to i8**
+
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT: [[C_P3_i8star:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT: [[C_P3:%.*]] = bitcast i8* [[C_P3_i8star]] to i8**
+
+// CHECK-NEXT: [[DEST:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* undef to i8*
+// CHECK-NEXT: [[SRC:%.*]] = bitcast %T42conditional_conformance_basic_conformances6DoubleV* %1 to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT: [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT: [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances6DoubleVA2A2P2RzAA2P3R_rlE7genericyqd__AaERd__lF(%swift.opaque* noalias nocapture %0, %swift.type* [[B]], %swift.type* [[C]], %swift.type* %"\CF\84_1_0", i8** [[B_P2]], i8** [[C_P3]], i8** %"\CF\84_1_0.P3")
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+
+public func double_generic_generic<U: P2, V: P3>(_: U.Type, _: V.Type) {
+ takes_p1(Double<U, V>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances015double_generic_F0yxm_q_mtAA2P2RzAA2P3R_r0_lF(%swift.type*, %swift.type*, %swift.type* %U, %swift.type* %V, i8** %U.P2, i8** %V.P3) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [2 x i8**], align 8
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVMa(%swift.type* %U, %swift.type* %V)
+
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** %U.P2, i8*** [[B_P2_PTR]], align 8
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** %V.P3, i8*** [[C_P3_PTR]], align 8
+
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 2)
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// witness table accessor for Double : P1
+
+// CHECK-LABEL: define{{( protected)?}} i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type*, i8***, i64) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT: store i8*** %1, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT: store i64 %2, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[CAST_CONDITIONAL_TABLES:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT: [[TABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWG, %swift.type* %0, i8** [[CAST_CONDITIONAL_TABLES]])
+// CHECK-NEXT: ret i8** [[TABLE]]
+// CHECK-NEXT: }
+
+
+public func double_generic_concrete<X: P2>(_: X.Type) {
+ takes_p1(Double<X, IsP3>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances23double_generic_concreteyxmAA2P2RzlF(%swift.type*, %swift.type* %X, i8** %X.P2) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [2 x i8**], align 8
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVMa(%swift.type* %X, %swift.type* bitcast (i64* getelementptr inbounds (<{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>* @_T042conditional_conformance_basic_conformances4IsP3VMf, i32 0, i32 1) to %swift.type*))
+
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** %X.P2, i8*** [[B_P2_PTR]], align 8
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type* %1, i8*** [[CONDITIONAL_REQUIREMENTS]], i64 2)
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+public func double_concrete_concrete() {
+ takes_p1(Double<IsP2, IsP3>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T042conditional_conformance_basic_conformances016double_concrete_F0yyF() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa()
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWl()
+// CHECK-NEXT: call swiftcc void @_T042conditional_conformance_basic_conformances8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// Lazy witness table accessor for the concrete Double<IsP2, IsP3> : P1.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWl() #1 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [2 x i8**], align 8
+// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWL, align 8
+// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGMa()
+
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [2 x i8**], [2 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP2VAA0F0AAWP, i32 0, i32 0), i8*** [[B_P2_PTR]], align 8
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T042conditional_conformance_basic_conformances4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 2)
+// CHECK-NEXT: store atomic i8** [[Double_P1]], i8*** @_T042conditional_conformance_basic_conformances6DoubleVyAA4IsP2VAA0F2P3VGACyxq_GAA2P1A2A0G0RzAA0H0R_rlWL release, align 8
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: %7 = phi i8** [ [[CACHE]], %entry ], [ [[Double_P1]], %cacheIsNull ]
+// CHECK-NEXT: ret i8** %7
+// CHECK-NEXT: }
+
+
+// # Witness table instantiators
+
+// witness table instantiator for Single : P1
+
+// CHECK-LABEL: define internal void @_T042conditional_conformance_basic_conformances6SingleVyxGAA2P1A2A2P2RzlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT: [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT: [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[COUNT]], 1
+// CHECK-NEXT: br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK: cont:
+// CHECK-NEXT: [[A_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT: [[A_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT: [[A_P2:%.*]] = load i8**, i8*** [[A_P2_SRC]], align 8
+// CHECK-NEXT: [[CAST_A_P2_DEST:%.*]] = bitcast i8** [[A_P2_DEST]] to i8***
+// CHECK-NEXT: store i8** [[A_P2]], i8*** [[CAST_A_P2_DEST]], align 8
+
+// CHECK-NEXT: ret void
+
+// CHECK: bad_witness_table_count:
+// CHECK-NEXT: call void @llvm.trap()
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+// witness table instantiator for Double : P1
+
+// CHECK-LABEL: define internal void @_T042conditional_conformance_basic_conformances6DoubleVyxq_GAA2P1A2A2P2RzAA2P3R_rlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT: [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT: [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[COUNT]], 2
+// CHECK-NEXT: br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK: cont:
+// CHECK-NEXT: [[B_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT: [[B_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT: [[B_P2:%.*]] = load i8**, i8*** [[B_P2_SRC]], align 8
+// CHECK-NEXT: [[CAST_B_P2_DEST:%.*]] = bitcast i8** [[B_P2_DEST]] to i8***
+// CHECK-NEXT: store i8** [[B_P2]], i8*** [[CAST_B_P2_DEST]], align 8
+
+// CHECK-NEXT: [[C_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 1
+// CHECK-NEXT: [[C_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -2
+// CHECK-NEXT: [[C_P3:%.*]] = load i8**, i8*** [[C_P3_SRC]], align 8
+// CHECK-NEXT: [[CAST_C_P3_DEST:%.*]] = bitcast i8** [[C_P3_DEST]] to i8***
+// CHECK-NEXT: store i8** [[C_P3]], i8*** [[CAST_C_P3_DEST]], align 8
+
+// CHECK-NEXT: ret void
+
+// CHECK: bad_witness_table_count:
+// CHECK-NEXT: call void @llvm.trap()
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
diff --git a/test/Inputs/conditional_conformance_subclass.swift b/test/Inputs/conditional_conformance_subclass.swift
new file mode 100644
index 0000000..96d0525
--- /dev/null
+++ b/test/Inputs/conditional_conformance_subclass.swift
@@ -0,0 +1,209 @@
+public func takes_p1<T: P1>(_: T.Type) {}
+public protocol P1 {
+ func normal()
+ func generic<T: P3>(_: T)
+}
+public protocol P2 {}
+public protocol P3 {}
+
+public struct IsP2: P2 {}
+
+public class Base<A> {}
+extension Base: P1 where A: P2 {
+ public func normal() {}
+ public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Base.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlAaEP6normalyyFTW(%T32conditional_conformance_subclass4BaseC.0** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
+// CHECK-NEXT: [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.0*, %T32conditional_conformance_subclass4BaseC.0** %0
+// CHECK-NEXT: [[RC_SELF:%.*]] = bitcast %T32conditional_conformance_subclass4BaseC.0* [[SELF]] to %swift.refcounted*
+// CHECK-NEXT: [[RETAINED:%.*]] = call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned [[RC_SELF]])
+// CHECK-NEXT: call swiftcc void @_T032conditional_conformance_subclass4BaseCA2A2P2RzlE6normalyyF(i8** %"\CF\84_0_0.P2", %T32conditional_conformance_subclass4BaseC.0* swiftself [[SELF]])
+// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_rt_swift_release to void (%T32conditional_conformance_subclass4BaseC.0*)*)(%T32conditional_conformance_subclass4BaseC.0* [[SELF]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// witness method for Base.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1** noalias nocapture swiftself dereferenceable(8), %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
+// CHECK-NEXT: [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.1*, %T32conditional_conformance_subclass4BaseC.1** %1, align 8
+// CHECK-NEXT: [[RC_SELF:%.*]] = bitcast %T32conditional_conformance_subclass4BaseC.1* [[SELF]] to %swift.refcounted*
+// CHECK-NEXT: [[RETAINED:%.*]] = call %swift.refcounted* @swift_rt_swift_retain(%swift.refcounted* returned [[RC_SELF]])
+// CHECK-NEXT: call swiftcc void @_T032conditional_conformance_subclass4BaseCA2A2P2RzlE7genericyqd__AA2P3Rd__lF(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1* swiftself [[SELF]])
+// CHECK-NEXT: call void bitcast (void (%swift.refcounted*)* @swift_rt_swift_release to void (%T32conditional_conformance_subclass4BaseC.1*)*)(%T32conditional_conformance_subclass4BaseC.1* [[SELF]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+
+public class SubclassGeneric<T>: Base<T> {}
+public class SubclassConcrete: Base<IsP2> {}
+public class SubclassGenericConcrete: SubclassGeneric<IsP2> {}
+
+public func subclassgeneric_generic<T: P2>(_: T.Type) {
+ takes_p1(SubclassGeneric<T>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass23subclassgeneric_genericyxmAA2P2RzlF(%swift.type*, %swift.type* %T, i8** %T.P2) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass15SubclassGenericCMa(%swift.type* %T)
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[T_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** %T.P2, i8*** [[T_P2_PTR]], align 8
+// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT: call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassGeneric_TYPE]], %swift.type* [[SubclassGeneric_TYPE]], i8** [[Base_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// witness table accessor for Base : P1
+
+// CHECK-LABEL: define{{( protected)?}} i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type*, i8***, i64) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.tables = alloca %swift.witness_table_slice, align 8
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 0
+// CHECK-NEXT: store i8*** %1, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* %conditional.tables, i32 0, i32 1
+// CHECK-NEXT: store i64 %2, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[CAST_CONDITIONAL_TABLES:%.*]] = bitcast %swift.witness_table_slice* %conditional.tables to i8**
+// CHECK-NEXT: [[TABLE:%.*]] = call i8** @swift_rt_swift_getGenericWitnessTable(%swift.generic_witness_table_cache* @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWG, %swift.type* %0, i8** [[CAST_CONDITIONAL_TABLES]])
+// CHECK-NEXT: ret i8** [[TABLE]]
+// CHECK-NEXT: }
+
+public func subclassgeneric_concrete() {
+ takes_p1(SubclassGeneric<IsP2>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass24subclassgeneric_concreteyyF() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa()
+// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWl()
+// CHECK-NEXT: call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassGeneric_TYPE]], %swift.type* [[SubclassGeneric_TYPE]], i8** [[Base_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// Lazy witness table accessor for the concrete SubclassGeneric<IsP2> : Base.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWl() #2 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWL, align 8
+// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMa()
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T032conditional_conformance_subclass4IsP2VAA0E0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT: store atomic i8** [[Base_P1]], i8*** @_T032conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWL release, align 8
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: %6 = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
+// CHECK-NEXT: ret i8** %6
+// CHECK-NEXT: }
+
+public func subclassconcrete() {
+ takes_p1(SubclassConcrete.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass16subclassconcreteyyF() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass16SubclassConcreteCMa()
+// CHECK-NEXT: [[SubclassConcrete_P1:%.*]] = call i8** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl()
+// CHECK-NEXT: call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassConcrete_TYPE]], %swift.type* [[SubclassConcrete_TYPE]], i8** [[SubclassConcrete_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl() #2 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL, align 8
+// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass16SubclassConcreteCMa()
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T032conditional_conformance_subclass4IsP2VAA0E0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT: store atomic i8** [[Base_P1]], i8*** @_T032conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL release, align 8
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: %6 = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
+// CHECK-NEXT: ret i8** %6
+// CHECK-NEXT: }
+
+public func subclassgenericconcrete() {
+ takes_p1(SubclassGenericConcrete.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T032conditional_conformance_subclass23subclassgenericconcreteyyF() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass23SubclassGenericConcreteCMa()
+// CHECK-NEXT: [[SubclassGenericConcrete_P1:%.*]] = call i8** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl()
+// CHECK-NEXT: call swiftcc void @_T032conditional_conformance_subclass8takes_p1yxmAA2P1RzlF(%swift.type* [[SubclassGenericConcrete_TYPE]], %swift.type* [[SubclassGenericConcrete_TYPE]], i8** [[SubclassGenericConcrete_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl() #2 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
+// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL, align 8
+// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = call %swift.type* @_T032conditional_conformance_subclass23SubclassGenericConcreteCMa()
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([0 x i8*], [0 x i8*]* @_T032conditional_conformance_subclass4IsP2VAA0E0AAWP, i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
+// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWa(%swift.type* [[SubclassGeneric_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 1)
+// CHECK-NEXT: store atomic i8** [[Base_P1]], i8*** @_T032conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL release, align 8
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: %6 = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
+// CHECK-NEXT: ret i8** %6
+// CHECK-NEXT: }
+
+
+// witness tabel instantiation function for Base : P1
+
+// CHECK-LABEL: define internal void @_T032conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT: [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT: [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[COUNT]], 1
+// CHECK-NEXT: br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK: cont:
+// CHECK-NEXT: [[A_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT: [[A_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT: [[A_P2:%.*]] = load i8**, i8*** [[A_P2_SRC]], align 8
+// CHECK-NEXT: [[CAST_A_P2_DEST:%.*]] = bitcast i8** [[A_P2_DEST]] to i8***
+// CHECK-NEXT: store i8** [[A_P2]], i8*** [[CAST_A_P2_DEST]], align 8
+// CHECK-NEXT: ret void
+
+// CHECK: bad_witness_table_count:
+// CHECK-NEXT: call void @llvm.trap()
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
+
diff --git a/test/Inputs/conditional_conformance_with_assoc.swift b/test/Inputs/conditional_conformance_with_assoc.swift
new file mode 100644
index 0000000..63af461
--- /dev/null
+++ b/test/Inputs/conditional_conformance_with_assoc.swift
@@ -0,0 +1,263 @@
+public func takes_p1<T: P1>(_: T.Type) {}
+public protocol P1 {
+ associatedtype AT1
+
+ func normal()
+ func generic<T: P3>(_: T)
+}
+public protocol P2 {
+ associatedtype AT2: P3
+}
+public protocol P3 {
+ associatedtype AT3
+}
+
+public struct Nothing {}
+
+public struct IsP2: P2 {
+ public typealias AT2 = IsP3
+}
+public struct IsP3: P3 {
+ public typealias AT3 = Nothing
+}
+
+public struct IsAlsoP2: P2 {
+ public typealias AT2 = IsBoth
+}
+public struct IsBoth: P2, P3 {
+ public typealias AT2 = HoldsP3
+ public typealias AT3 = Nothing
+}
+public struct HoldsP3: P3 {
+ public typealias AT3 = IsP3
+}
+
+public struct Double<B: P2, C> {}
+extension Double: P1 where B.AT2: P2, C: P3, B.AT2.AT2.AT3: P3 {
+ public typealias AT1 = C
+ public func normal() {}
+ public func generic<T: P3>(_: T) {}
+}
+
+// witness method for Double.normal
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlAaEP6normalyyFTW(%T34conditional_conformance_with_assoc6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[C_P3:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_1.P3" = bitcast i8* [[C_P3]] to i8**
+
+// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT: [[B_AT2_P2:%.*]] = load i8*, i8** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_0.AT2.P2" = bitcast i8* [[B_AT2_P2]] to i8**
+
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -3
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3:%.*]] = load i8*, i8** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_0.AT2.AT2.AT3.P3" = bitcast i8* [[B_AT2_AT2_AT3_P3]] to i8**
+
+// CHECK-NEXT: [[DEST:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* undef to i8*
+// CHECK-NEXT: [[SRC:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* %0 to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT: [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT: [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT: [[SELF_AS_WT_ARRAY:%.*]] = bitcast %swift.type* %Self to i8***
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[SELF_AS_WT_ARRAY]], i64 4
+// CHECK-NEXT: %"\CF\84_0_0.P2" = load i8**, i8*** [[B_P2_PTR]], align 8
+
+// CHECK-NEXT: call swiftcc void @_T034conditional_conformance_with_assoc6DoubleVA2A2P3R_AA2P23AT2RpzAadF_AfaEP3AT3RPzrlE6normalyyF(%swift.type* %"\CF\84_0_0", %swift.type* %"\CF\84_0_1", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_0_1.P3", i8** %"\CF\84_0_0.AT2.P2", i8** %"\CF\84_0_0.AT2.AT2.AT3.P3")
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// witness method for Double.generic
+
+// CHECK-LABEL: define linkonce_odr hidden swiftcc void @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlAaEP7genericyqd__AaFRd__lFTW(%swift.opaque* noalias nocapture, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T34conditional_conformance_with_assoc6DoubleV* noalias nocapture swiftself, %swift.type* %Self, i8** %SelfWitnessTable) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
+// CHECK-NEXT: [[C_P3:%.*]] = load i8*, i8** [[C_P3_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_1.P3" = bitcast i8* [[C_P3]] to i8**
+
+// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -2
+// CHECK-NEXT: [[B_AT2_P2:%.*]] = load i8*, i8** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_0.AT2.P2" = bitcast i8* [[B_AT2_P2]] to i8**
+
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -3
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3:%.*]] = load i8*, i8** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT: %"\CF\84_0_0.AT2.AT2.AT3.P3" = bitcast i8* [[B_AT2_AT2_AT3_P3]] to i8**
+
+// CHECK-NEXT: [[DEST:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* undef to i8*
+// CHECK-NEXT: [[SRC:%.*]] = bitcast %T34conditional_conformance_with_assoc6DoubleV* %1 to i8*
+// CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DEST]], i8* [[SRC]], i64 0, i32 1, i1 false)
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[B_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY]], i64 2
+// CHECK-NEXT: [[B:%.*]] = load %swift.type*, %swift.type** [[B_PTR]], align 8
+
+// CHECK-NEXT: [[SELF_AS_TYPE_ARRAY_2:%.*]] = bitcast %swift.type* %Self to %swift.type**
+// CHECK-NEXT: [[C_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[SELF_AS_TYPE_ARRAY_2]], i64 3
+// CHECK-NEXT: [[C:%.*]] = load %swift.type*, %swift.type** [[C_PTR]], align 8
+
+// CHECK-NEXT: [[SELF_AS_WT_ARRAY:%.*]] = bitcast %swift.type* %Self to i8***
+// CHECK-NEXT: [[B_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[SELF_AS_WT_ARRAY]], i64 4
+// CHECK-NEXT: %"\CF\84_0_0.P2" = load i8**, i8*** [[B_P2_PTR]], align 8
+
+// CHECK-NEXT: call swiftcc void @_T034conditional_conformance_with_assoc6DoubleVA2A2P3R_AA2P23AT2RpzAadF_AfaEP3AT3RPzrlE7genericyqd__AaDRd__lF(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_0_0", %swift.type* %"\CF\84_0_1", %swift.type* %"\CF\84_1_0", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_0_1.P3", i8** %"\CF\84_1_0.P3", i8** %"\CF\84_0_0.AT2.P2", i8** %"\CF\84_0_0.AT2.AT2.AT3.P3")
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+
+public func generic_generic<T: P2, U>(_: T.Type, _: U.Type)
+ where T.AT2: P2, U: P3, T.AT2.AT2.AT3: P3
+{
+ takes_p1(Double<T, U>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc08generic_E0yxm_q_mtAA2P2RzAA2P3R_AaC3AT2RpzAadE_AeaCP3AT3RPzr0_lF(%swift.type*, %swift.type*, %swift.type* %T, %swift.type* %U, i8** %T.P2, i8** %U.P3, i8** %T.AT2.P2, i8** %T.AT2.AT2.AT3.P3) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVMa(%swift.type* %T, %swift.type* %U, i8** %T.P2)
+
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** %U.P3, i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** %T.AT2.P2, i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT: store i8** %T.AT2.AT2.AT3.P3, i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT: call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+public func generic_concrete<T: P2>(_: T.Type)
+ where T.AT2: P2, T.AT2.AT2.AT3: P3
+{
+ takes_p1(Double<T, IsP3>.self)
+}
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc16generic_concreteyxmAA2P2RzAaC3AT2RpzAA2P3AD_AdaCP3AT3RPzlF(%swift.type*, %swift.type* %T, i8** %T.P2, i8** %T.AT2.P2, i8** %T.AT2.AT2.AT3.P3) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVMa(%swift.type* %T, %swift.type* bitcast (i64* getelementptr inbounds (<{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>* @_T034conditional_conformance_with_assoc4IsP3VMf, i32 0, i32 1) to %swift.type*), i8** %T.P2)
+
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** %T.AT2.P2, i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT: store i8** %T.AT2.AT2.AT3.P3, i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT: call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+
+public func concrete_generic<U>(_: U.Type)
+ where U: P3
+{
+ takes_p1(Double<IsAlsoP2, U>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc16concrete_genericyxmAA2P3RzlF(%swift.type*, %swift.type* %U, i8** %U.P3) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVMa(%swift.type* bitcast (i64* getelementptr inbounds (<{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>, <{ i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>* }>* @_T034conditional_conformance_with_assoc8IsAlsoP2VMf, i32 0, i32 1) to %swift.type*), %swift.type* %U, i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_T034conditional_conformance_with_assoc8IsAlsoP2VAA0G0AAWP, i32 0, i32 0))
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** %U.P3, i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_T034conditional_conformance_with_assoc6IsBothVAA2P2AAWP, i32 0, i32 0), i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT: call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* [[Double_TYPE]], %swift.type* [[Double_TYPE]], i8** [[Double_P1]])
+// CHECK-NEXT: ret void
+// CHECK-NEXT:}
+
+
+public func concrete_concrete() {
+ takes_p1(Double<IsAlsoP2, IsP3>.self)
+}
+
+// CHECK-LABEL: define{{( protected)?}} swiftcc void @_T034conditional_conformance_with_assoc09concrete_E0yyF() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %0 = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa() #10
+// CHECK-NEXT: %1 = call i8** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWl() #10
+// CHECK-NEXT: call swiftcc void @_T034conditional_conformance_with_assoc8takes_p1yxmAA2P1RzlF(%swift.type* %0, %swift.type* %0, i8** %1)
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// Lazy witness table accessor for the concrete Double<IsAlsoP2, IsP3> : P1.
+
+// CHECK-LABEL: define linkonce_odr hidden i8** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWl() #1 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %conditional.requirement.buffer = alloca [3 x i8**], align 8
+// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWL, align 8
+// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
+// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
+
+// CHECK: cacheIsNull:
+// CHECK-NEXT: [[Double_TYPE:%.*]] = call %swift.type* @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGMa() #10
+// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [3 x i8**], [3 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
+// CHECK-NEXT: [[C_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
+// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[C_P3_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 1
+// CHECK-NEXT: store i8** getelementptr inbounds ([2 x i8*], [2 x i8*]* @_T034conditional_conformance_with_assoc6IsBothVAA2P2AAWP, i32 0, i32 0), i8*** [[B_AT2_P2_PTR]], align 8
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 2
+// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @_T034conditional_conformance_with_assoc4IsP3VAA0F0AAWP, i32 0, i32 0), i8*** [[B_AT2_AT2_AT3_P3_PTR]], align 8
+// CHECK-NEXT: [[Double_P1:%.*]] = call i8** @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWa(%swift.type* [[Double_TYPE]], i8*** [[CONDITIONAL_REQUIREMENTS]], i64 3)
+// CHECK-NEXT: store atomic i8** [[Double_P1]], i8*** @_T034conditional_conformance_with_assoc6DoubleVyAA8IsAlsoP2VAA0F2P3VGACyxq_GAA2P1A2A0I0R_AA0H03AT2RpzAakM_AmaLP3AT3RPzrlWL release, align 8
+// CHECK-NEXT: br label %cont
+
+// CHECK: cont:
+// CHECK-NEXT: %8 = phi i8** [ [[CACHE]], %entry ], [ [[Double_P1]], %cacheIsNull ]
+// CHECK-NEXT: ret i8** %8
+// CHECK-NEXT: }
+
+
+
+// witness table instantiator for Double : P1
+
+// CHECK-LABEL: define internal void @_T034conditional_conformance_with_assoc6DoubleVyxq_GAA2P1A2A2P3R_AA2P23AT2RpzAafH_AhaGP3AT3RPzrlWI(i8**, %swift.type*, i8**) #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[CONDITIONAL_TABLE_SLICE:%.*]] = bitcast i8** %2 to %swift.witness_table_slice*
+// CHECK-NEXT: [[TABLES_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 0
+// CHECK-NEXT: [[TABLES:%.*]] = load i8***, i8**** [[TABLES_PTR]], align 8
+// CHECK-NEXT: [[COUNT_PTR:%.*]] = getelementptr inbounds %swift.witness_table_slice, %swift.witness_table_slice* [[CONDITIONAL_TABLE_SLICE]], i32 0, i32 1
+// CHECK-NEXT: [[COUNT:%.*]] = load i64, i64* [[COUNT_PTR]], align 8
+// CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[COUNT]],
+// CHECK-NEXT: br i1 [[COND]], label %cont, label %bad_witness_table_count
+
+// CHECK: cont:
+// CHECK-NEXT: [[C_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 0
+// CHECK-NEXT: [[C_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -1
+// CHECK-NEXT: [[C_P3:%.*]] = load i8**, i8*** [[C_P3_SRC]], align 8
+// CHECK-NEXT: [[CAST_C_P3_DEST:%.*]] = bitcast i8** [[C_P3_DEST]] to i8***
+// CHECK-NEXT: store i8** [[C_P3]], i8*** [[CAST_C_P3_DEST]], align 8
+
+// CHECK-NEXT: [[B_AT2_P2_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 1
+// CHECK-NEXT: [[B_AT2_P2_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -2
+// CHECK-NEXT: [[B_AT2_P2:%.*]] = load i8**, i8*** [[B_AT2_P2_SRC]], align 8
+// CHECK-NEXT: [[CAST_B_AT2_P2_DEST:%.*]] = bitcast i8** [[B_AT2_P2_DEST]] to i8***
+// CHECK-NEXT: store i8** [[B_AT2_P2]], i8*** [[CAST_B_AT2_P2_DEST]], align 8
+
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_SRC:%.*]] = getelementptr inbounds i8**, i8*** [[TABLES]], i32 2
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3_DEST:%.*]] = getelementptr inbounds i8*, i8** %0, i32 -3
+// CHECK-NEXT: [[B_AT2_AT2_AT3_P3:%.*]] = load i8**, i8*** [[B_AT2_AT2_AT3_P3_SRC]], align 8
+// CHECK-NEXT: [[CAST_B_AT2_AT2_AT3_P3_DEST:%.*]] = bitcast i8** [[B_AT2_AT2_AT3_P3_DEST]] to i8***
+// CHECK-NEXT: store i8** [[B_AT2_AT2_AT3_P3]], i8*** [[CAST_B_AT2_AT2_AT3_P3_DEST]], align 8
+
+// CHECK-NEXT: ret void
+
+// CHECK: bad_witness_table_count:
+// CHECK-NEXT: call void @llvm.trap()
+// CHECK-NEXT: unreachable
+// CHECK-NEXT: }
+
diff --git a/test/Interpreter/conditional_conformances.swift b/test/Interpreter/conditional_conformances.swift
new file mode 100644
index 0000000..8c686dc
--- /dev/null
+++ b/test/Interpreter/conditional_conformances.swift
@@ -0,0 +1,35 @@
+// RUN: %empty-directory(%t)
+// The file that's `main` needs to be called that.
+// RUN: cp %s %t/main.swift
+// RUN: %target-build-swift -D basic %t/main.swift %S/../Inputs/conditional_conformance_basic_conformances.swift -o %t/basic && %target-run %t/basic
+// RUN: %target-build-swift -D with_assoc %t/main.swift %S/../Inputs/conditional_conformance_with_assoc.swift -o %t/with_assoc && %target-run %t/with_assoc
+// RUN: %target-build-swift -D subclass %t/main.swift %S/../Inputs/conditional_conformance_subclass.swift -o %t/subclass && %target-run %t/subclass
+
+// REQUIRES: executable_test
+
+// Call the various functions from each of the IRGen conditional conformance
+// tests. These can't be put in the file themselves because that changes it from
+// being treated as a library to an executable.
+
+#if basic
+single_generic(IsP2.self)
+single_concrete()
+
+double_generic_generic(IsP2.self, IsP3.self)
+double_generic_concrete(IsP2.self)
+double_concrete_concrete()
+
+#elseif with_assoc
+generic_generic(IsAlsoP2.self, IsP3.self)
+generic_concrete(IsAlsoP2.self)
+concrete_generic(IsP3.self)
+concrete_concrete()
+
+#elseif subclass
+subclassgeneric_generic(IsP2.self)
+subclassgeneric_concrete()
+subclassconcrete()
+subclassgenericconcrete()
+#endif
+
+
diff --git a/test/Interpreter/conditional_conformances_modules.swift b/test/Interpreter/conditional_conformances_modules.swift
new file mode 100644
index 0000000..b5c94ae
--- /dev/null
+++ b/test/Interpreter/conditional_conformances_modules.swift
@@ -0,0 +1,91 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift-dylib(%t/libBasic.%target-dylib-extension) %S/../Inputs/conditional_conformance_basic_conformances.swift -module-name Basic -emit-module -emit-module-path %t/Basic.swiftmodule
+// RUN: %target-build-swift-dylib(%t/libWithAssoc.%target-dylib-extension) %S/../Inputs/conditional_conformance_with_assoc.swift -module-name WithAssoc -emit-module -emit-module-path %t/WithAssoc.swiftmodule
+// FIXME: currently fails due to incorrect modeling of type parameters in inherited conformances.
+// %target-build-swift-dylib(%t/libSubclass.%target-dylib-extension) %S/../Inputs/conditional_conformance_subclass.swift -module-name Subclass -emit-module -emit-module-path %t/Subclass.swiftmodule
+// RUN: %target-build-swift -I%t -L%t -lBasic -lWithAssoc %s -o %t/conditional_conformances_modules -Xlinker -rpath -Xlinker %t
+// RUN: %target-run %t/conditional_conformances_modules %t/libBasic.%target-dylib-extension %t/libWithAssoc.%target-dylib-extension
+
+// REQUIRES: executable_test
+// FIXME: seems to fail on 32-bit simulator?
+// REQUIRES: OS=macosx || OS=linux
+
+import Basic
+import WithAssoc
+// FIXME: see above
+// import Subclass
+
+
+public func basic_single_generic<T: Basic.P2>(_: T.Type) {
+ Basic.takes_p1(Basic.Single<T>.self)
+}
+public func basic_single_concrete() {
+ Basic.takes_p1(Basic.Single<Basic.IsP2>.self)
+}
+public func basic_double_generic_generic<U: Basic.P2, V: Basic.P3>(_: U.Type, _: V.Type) {
+ Basic.takes_p1(Basic.Double<U, V>.self)
+}
+public func basic_double_generic_concrete<X: Basic.P2>(_: X.Type) {
+ Basic.takes_p1(Basic.Double<X, Basic.IsP3>.self)
+}
+public func basic_double_concrete_concrete() {
+ Basic.takes_p1(Basic.Double<Basic.IsP2, Basic.IsP3>.self)
+}
+
+
+public func with_assoc_generic_generic<T: WithAssoc.P2, U>(_: T.Type, _: U.Type)
+ where T.AT2: WithAssoc.P2, U: WithAssoc.P3, T.AT2.AT2.AT3: WithAssoc.P3
+{
+ WithAssoc.takes_p1(WithAssoc.Double<T, U>.self)
+}
+public func with_assoc_generic_concrete<T: WithAssoc.P2>(_: T.Type)
+ where T.AT2: WithAssoc.P2, T.AT2.AT2.AT3: WithAssoc.P3
+{
+ WithAssoc.takes_p1(WithAssoc.Double<T, WithAssoc.IsP3>.self)
+}
+public func with_assoc_concrete_generic<U>(_: U.Type)
+ where U: WithAssoc.P3
+{
+ WithAssoc.takes_p1(WithAssoc.Double<WithAssoc.IsAlsoP2, U>.self)
+}
+public func with_assoc_concrete_concrete() {
+ WithAssoc.takes_p1(WithAssoc.Double<WithAssoc.IsAlsoP2, WithAssoc.IsP3>.self)
+}
+
+/*
+FIXME: see above
+public func subclass_subclassgeneric_generic<T: Subclass.P2>(_: T.Type) {
+ Subclass.takes_p1(Subclass.SubclassGeneric<T>.self)
+}
+public func subclass_subclassgeneric_concrete() {
+ Subclass.takes_p1(Subclass.SubclassGeneric<Subclass.IsP2>.self)
+}
+public func subclass_subclassconcrete() {
+ Subclass.takes_p1(Subclass.SubclassConcrete.self)
+}
+public func subclass_subclassgenericconcrete() {
+ Subclass.takes_p1(Subclass.SubclassGenericConcrete.self)
+}
+*/
+
+
+basic_single_generic(Basic.IsP2.self)
+basic_single_concrete()
+basic_double_generic_generic(Basic.IsP2.self, Basic.IsP3.self)
+basic_double_generic_concrete(Basic.IsP2.self)
+basic_double_concrete_concrete()
+
+
+with_assoc_generic_generic(WithAssoc.IsAlsoP2.self, WithAssoc.IsP3.self)
+with_assoc_generic_concrete(WithAssoc.IsAlsoP2.self)
+with_assoc_concrete_generic(WithAssoc.IsP3.self)
+with_assoc_concrete_concrete()
+
+
+/*
+FIXME: see above
+subclass_subclassgeneric_generic(Subclass.IsP2.self)
+subclass_subclassgeneric_concrete()
+subclass_subclassconcrete()
+subclass_subclassgenericconcrete()
+*/
diff --git a/test/Interpreter/conditional_conformances_smoke.swift b/test/Interpreter/conditional_conformances_smoke.swift
new file mode 100644
index 0000000..0943d8b
--- /dev/null
+++ b/test/Interpreter/conditional_conformances_smoke.swift
@@ -0,0 +1,89 @@
+// RUN: %target-run-simple-swift | %FileCheck %s
+
+// REQUIRES: executable_test
+
+// Test fails in optimized mode. rdar://35492657
+// REQUIRES: swift_test_mode_optimize_none
+
+// Smoke test to see that various conditional conformances correctly execute
+
+protocol P1 {
+ func method1()
+}
+var isp1_count = 0
+struct IsP1: P1 {
+ var id: Int
+ init() {
+ id = isp1_count
+ isp1_count += 1
+ }
+ func method1() {
+ print("IsP1", id)
+ }
+}
+protocol P2 {
+ func method2()
+}
+protocol P3 {
+ func method3()
+}
+protocol P4: P1 {
+ func method4()
+}
+
+protocol Assoc { associatedtype AT }
+
+func takes_P2<X: P2>(_ x: X) {
+ x.method2()
+}
+
+struct NoRecur<T> {
+ var x: T
+}
+extension NoRecur: P2 where T: P1 {
+ func method2() {
+ print("NoRecur")
+ x.method1()
+ }
+}
+
+var noRecur = NoRecur(x: IsP1())
+print("noRecur.method2()")
+noRecur.method2()
+// CHECK-LABEL: noRecur.method2()
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 0
+
+print("takes_P2(NoRecur(...))")
+takes_P2(NoRecur(x: IsP1()))
+// CHECK-LABEL: takes_P2(NoRecur(...))
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 1
+
+struct Recur<T> {
+ var id: Int
+ var x: T
+}
+extension Recur: P2 where T: P2 {
+ func method2() {
+ print("Recur", id)
+ x.method2()
+ }
+}
+
+var recur = Recur(id: 0, x: Recur(id: 1, x: NoRecur(x: IsP1())))
+print("recur.method2()")
+recur.method2()
+// CHECK-LABEL: recur.method2()
+// CHECK-NEXT: Recur 0
+// CHECK-NEXT: Recur 1
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 2
+
+print("takes_P2(Recur(...))")
+takes_P2(Recur(id: 2, x: Recur(id: 3, x: NoRecur(x: IsP1()))))
+// CHECK-LABEL: takes_P2(Recur(...))
+// CHECK-NEXT: Recur 2
+// CHECK-NEXT: Recur 3
+// CHECK-NEXT: NoRecur
+// CHECK-NEXT: IsP1 3
diff --git a/test/Misc/stats_dir_failure_count.swift b/test/Misc/stats_dir_failure_count.swift
new file mode 100644
index 0000000..dbbfb58
--- /dev/null
+++ b/test/Misc/stats_dir_failure_count.swift
@@ -0,0 +1,25 @@
+// Check that a failed process-tree emits nonzero failure counters
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: echo zzz >%t/other.swift
+// RUN: not %target-swiftc_driver -D BROKEN -j 2 -typecheck -stats-output-dir %t %s %t/other.swift
+// RUN: %utils/process-stats-dir.py --set-csv-baseline %t/stats.csv %t
+// RUN: %FileCheck -input-file %t/stats.csv -check-prefix=FAILURE %s
+// FAILURE: {{"Driver.NumProcessFailures" 1$}}
+// FAILURE: {{"Frontend.NumProcessFailures" 2$}}
+
+// Check that a successful process-tree emits no failure counters
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: echo 'let x : Int = 1' >%t/other.swift
+// RUN: %target-swiftc_driver -j 2 -typecheck -stats-output-dir %t %s %t/other.swift
+// RUN: %utils/process-stats-dir.py --set-csv-baseline %t/stats.csv %t
+// RUN: %FileCheck -input-file %t/stats.csv -check-prefix=SUCCESS %s
+// SUCCESS-NOT: {{"Driver.NumProcessFailures"}}
+// SUCCESS-NOT: {{"Frontend.NumProcessFailures"}}
+
+func foo() {
+#if BROKEN
+ print(bar)
+#else
+ print(1)
+#endif
+}
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index 6bc6a0d..dd3f35f 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -144,7 +144,7 @@
}
enum ExpressibleByRawTypeNotLiteral : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
- // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}} expected-error@-1 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
+ // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
case Ladd, Elliott, Sixteenth, Harrison
}
diff --git a/test/Parse/pointer_conversion.swift.gyb b/test/Parse/pointer_conversion.swift.gyb
index dae6ff8..69741eb 100644
--- a/test/Parse/pointer_conversion.swift.gyb
+++ b/test/Parse/pointer_conversion.swift.gyb
@@ -291,8 +291,10 @@
func arrayComparison(_ x: [NotEquatable], y: [NotEquatable], p: UnsafeMutablePointer<NotEquatable>) {
var x = x
// Don't allow implicit array-to-pointer conversions in operators.
- let a: Bool = x == y // expected-error{{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists:}}
+ // FIXME: The use of <Self: Equatable> in this diagnostic is awful.
+ let a: Bool = x == y // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+ // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+ // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
let _: Bool = p == &x // Allowed!
}
diff --git a/test/RemoteAST/structural_types.swift b/test/RemoteAST/structural_types.swift
index 3d0407a..dad61d1 100644
--- a/test/RemoteAST/structural_types.swift
+++ b/test/RemoteAST/structural_types.swift
@@ -54,3 +54,11 @@
typealias Tuple3 = (x: Int, Float, y: Int.Type)
printType(Tuple3.self)
// CHECK: found type: (x: Int, Float, y: Int.Type)
+
+func foo<T>(_: T) {
+ var f = T.self
+ printType(f)
+}
+
+foo() { (x: Int) -> Int in return x }
+// CHECK: found type: (Int) -> Int
diff --git a/test/SIL/Parser/coroutines.sil b/test/SIL/Parser/coroutines.sil
new file mode 100644
index 0000000..9d5bd6b
--- /dev/null
+++ b/test/SIL/Parser/coroutines.sil
@@ -0,0 +1,60 @@
+// RUN: %target-swift-frontend %s -emit-silgen -verify
+
+sil_stage raw
+
+import Swift
+
+sil @use_int : $@convention(thin) (Int) -> ()
+sil @use_float : $@convention(thin) (Float) -> ()
+
+sil @once_signature : $@yield_once () -> (@yields Int, @yields Float) {
+bb0:
+ %0 = tuple ()
+ return %0 : $()
+}
+
+sil @many_signature : $@yield_many () -> (@yields Int, @yields Float) {
+bb0:
+ %0 = tuple ()
+ return %0 : $()
+}
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+ %r = tuple ()
+ return %r : $()
+
+bb2:
+ unwind
+}
+
+sil @yield_many : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+ yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb4
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+
+bb3:
+ unwind
+
+bb4:
+ unwind
+}
+
+sil @begin_apply : $(Int, Float) -> () {
+bb0(%0 : $Int, %1 : $Float):
+ %coro = function_ref @yield : $@convention(thin) @yield_once (Int, Float) -> (@yields Int, @yields Float)
+ (%int, %float, %token) = begin_apply %coro(%0, %1) : $@convention(thin) @yield_once (Int, Float) -> (@yields Int, @yields Float)
+
+ end_apply %token
+ %r = tuple ()
+ return %r : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_merge.sil b/test/SIL/Parser/coroutines_failure_merge.sil
new file mode 100644
index 0000000..e95cc0d
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_merge.sil
@@ -0,0 +1,21 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+ br bb3
+
+bb2:
+ br bb3
+
+bb3:
+ unreachable
+}
+
diff --git a/test/SIL/Parser/coroutines_failure_unwind_return.sil b/test/SIL/Parser/coroutines_failure_unwind_return.sil
new file mode 100644
index 0000000..c79c645
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_unwind_return.sil
@@ -0,0 +1,19 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb2
+
+bb1:
+ %r = tuple ()
+ return %r : $()
+
+bb2:
+ %r2 = tuple ()
+ return %r2 : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_unwind_reuse.sil b/test/SIL/Parser/coroutines_failure_unwind_reuse.sil
new file mode 100644
index 0000000..adfe6d6
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_unwind_reuse.sil
@@ -0,0 +1,25 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage raw
+
+import Swift
+
+sil @yield : $@yield_many (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+ yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb3
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+
+bb3:
+ unwind
+
+bb4:
+ unwind
+}
+
diff --git a/test/SIL/Parser/coroutines_failure_yieldonce_return.sil b/test/SIL/Parser/coroutines_failure_yieldonce_return.sil
new file mode 100644
index 0000000..378e443
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_yieldonce_return.sil
@@ -0,0 +1,12 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage canonical
+
+import Swift
+
+sil @once_signature : $@yield_once () -> (@yields Int, @yields Float) {
+bb0:
+ %0 = tuple ()
+ return %0 : $()
+}
diff --git a/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil b/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil
new file mode 100644
index 0000000..e14b74f
--- /dev/null
+++ b/test/SIL/Parser/coroutines_failure_yieldonce_twice.sil
@@ -0,0 +1,25 @@
+// RUN: not --crash %target-swift-frontend %s -emit-silgen -verify
+// REQUIRES: asserts
+
+sil_stage canonical
+
+import Swift
+
+sil @yield : $@yield_once (Int, Float) -> (@yields Int, @yields Float) {
+bb0(%0 : $Int, %1 : $Float):
+ yield (%0 : $Int, %1 : $Float), resume bb1, unwind bb3
+
+bb1:
+ yield (%0 : $Int, %1 : $Float), resume bb2, unwind bb4
+
+bb2:
+ %r = tuple ()
+ return %r : $()
+
+bb3:
+ unwind
+
+bb4:
+ unwind
+}
+
diff --git a/test/SIL/Parser/witness_method.sil b/test/SIL/Parser/witness_method.sil
new file mode 100644
index 0000000..51e1ce8
--- /dev/null
+++ b/test/SIL/Parser/witness_method.sil
@@ -0,0 +1,43 @@
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil %s -module-name=witness_tables | %target-sil-opt -assume-parsing-unqualified-ownership-sil -module-name=witness_tables | %FileCheck %s
+
+protocol AssocReqt {
+ func requiredMethod()
+}
+
+struct ConformingAssoc : AssocReqt {
+ func requiredMethod()
+}
+
+// CHECK-LABEL: sil @witness_method : $@convention(witness_method: AssocReqt) (@inout ConformingAssoc) -> () {
+sil @witness_method : $@convention(witness_method: AssocReqt) (@inout ConformingAssoc) -> () {
+bb0(%0 : $*ConformingAssoc):
+ %1 = tuple ()
+ return %1 : $()
+}
+
+// CHECK-LABEL: sil hidden @existential
+sil hidden @existential : $@convention(thin) (@in AssocReqt) -> () {
+bb0(%0 : $*AssocReqt):
+ // CHECK: open_existential_addr
+ %2 = open_existential_addr immutable_access %0 : $*AssocReqt to $*@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt
+ // CHECK: witness_method $@opened({{.*}}) AssocReqt, #AssocReqt.requiredMethod!1 {{.*}} $@convention(witness_method: AssocReqt)
+ %3 = witness_method $@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt, #AssocReqt.requiredMethod!1 : <Self where Self : AssocReqt> (Self) -> () -> (), %2 : $*@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+ // CHECK: apply {{.*}} $@convention(witness_method: AssocReqt)
+ %4 = apply %3<@opened("B2FFFC12-C4BD-11E7-A4BB-38C98616C0EA") AssocReqt>(%2) : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+ destroy_addr %0 : $*AssocReqt
+ %6 = tuple ()
+ return %6 : $()
+}
+
+// CHECK-LABEL: sil hidden @generic
+sil hidden @generic : $@convention(thin) <T where T : AssocReqt> (@in T) -> () {
+bb0(%0 : $*T):
+ // CHECK: witness_method $T, #AssocReqt.requiredMethod!1 {{.*}} $@convention(witness_method: AssocReqt)
+ %2 = witness_method $T, #AssocReqt.requiredMethod!1 : <Self where Self : AssocReqt> (Self) -> () -> () : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+ // CHECK: apply {{.*}} $@convention(witness_method: AssocReqt)
+ %3 = apply %2<T>(%0) : $@convention(witness_method: AssocReqt) <τ_0_0 where τ_0_0 : AssocReqt> (@in_guaranteed τ_0_0) -> ()
+ destroy_addr %0 : $*T
+ %5 = tuple ()
+ return %5 : $()
+}
+
diff --git a/test/SIL/whole_module_optimization.swift b/test/SIL/whole_module_optimization.swift
index 01326af..16d24cb 100644
--- a/test/SIL/whole_module_optimization.swift
+++ b/test/SIL/whole_module_optimization.swift
@@ -20,11 +20,11 @@
// CHECK-NEXT: %1 = struct $Int32 (%0 : $Builtin.Int32)
// CHECK-NEXT: return %1 : $Int32
- // CHECK-SINGLE-FILE: %0 = function_ref @_T04main7computes5Int32VADycF
- // CHECK-SINGLE-FILE: %1 = function_ref @_T04main9privateFn33_4704C82F83811927370AA02DFDC75B5ALLs5Int32VyF
- // CHECK-SINGLE-FILE: %2 = thin_to_thick_function %1
- // CHECK-SINGLE-FILE: %3 = convert_function %2
- // CHECK-SINGLE-FILE: %4 = apply %0(%3)
+ // CHECK-SINGLE-FILE: %0 = function_ref @_T04main9privateFn33_4704C82F83811927370AA02DFDC75B5ALLs5Int32VyF
+ // CHECK-SINGLE-FILE: %1 = thin_to_thick_function %0
+ // CHECK-SINGLE-FILE: %2 = convert_function %1
+ // CHECK-SINGLE-FILE: %3 = function_ref @_T04main7computes5Int32VADycF
+ // CHECK-SINGLE-FILE: %4 = apply %3(%2)
// CHECK-SINGLE-FILE: return %4 : $Int
return compute(privateFn)
diff --git a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
index 2d59069..456b446 100644
--- a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
+++ b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
@@ -93,3 +93,5 @@
@interface ObjectWithSplitProperty : NSObject
@property (nonatomic, setter=private_setFlagForSomething:) BOOL flagForSomething;
@end
+
+extern NSString * __nonnull (^ const __nonnull GlobalBlock)(NSString * __nonnull);
diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift
index 81ed0ab..c81d367 100644
--- a/test/SILGen/accessors.swift
+++ b/test/SILGen/accessors.swift
@@ -50,8 +50,6 @@
// CHECK-NEXT: end_borrow [[T0]] from [[TEMP]]
// CHECK-NEXT: destroy_addr [[TEMP]]
// Formal access to LHS.
-// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
-// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11OrdinarySubVS2icis
// CHECK-NEXT: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[BUFFER:%.*]] = alloc_stack $OrdinarySub
// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER]]
@@ -61,6 +59,8 @@
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on [[BORROWED_ARG_LHS]] : $A
+// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11OrdinarySubVS2icis
// 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]+]]
@@ -139,8 +139,6 @@
//
// CHECK: [[CONT]]:
// Formal access to LHS.
-// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
-// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11MutatingSubVS2icis : $@convention(method) (Int, Int, @inout MutatingSub) -> ()
// CHECK-NEXT: [[STORAGE2:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[BUFFER2:%.*]] = alloc_stack $MutatingSub
// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER2]]
@@ -150,6 +148,8 @@
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[BORROWED_ARG_LHS]] : $B
+// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
+// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T09accessors11MutatingSubVS2icis : $@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]+]]
//
diff --git a/test/SILGen/address_only_types.swift b/test/SILGen/address_only_types.swift
index b1d19c2..ae8077d 100644
--- a/test/SILGen/address_only_types.swift
+++ b/test/SILGen/address_only_types.swift
@@ -107,8 +107,8 @@
func address_only_call_1_ignore_return() {
// CHECK: bb0:
some_address_only_function_1()
- // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1AA10Unloadable_pyF
// CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1AA10Unloadable_pyF
// CHECK: apply [[FUNC]]([[TEMP]])
// CHECK: destroy_addr [[TEMP]]
// CHECK: dealloc_stack [[TEMP]]
@@ -120,9 +120,9 @@
// 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 @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
// CHECK: [[X_CALL_ARG:%[0-9]+]] = alloc_stack $Unloadable
// CHECK: copy_addr [[XARG]] to [initialization] [[X_CALL_ARG]]
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FUNC]]([[X_CALL_ARG]])
// CHECK: dealloc_stack [[X_CALL_ARG]]
// CHECK: return
@@ -132,10 +132,10 @@
func address_only_call_1_in_2() {
// CHECK: bb0:
some_address_only_function_2(some_address_only_function_1())
- // CHECK: [[FUNC2:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
- // CHECK: [[FUNC1:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
// CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[FUNC1:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FUNC1]]([[TEMP]])
+ // CHECK: [[FUNC2:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_2{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FUNC2]]([[TEMP]])
// CHECK: dealloc_stack [[TEMP]]
// CHECK: return
@@ -145,8 +145,8 @@
func address_only_materialize() -> Int {
// CHECK: bb0:
return some_address_only_function_1().foo()
- // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_only_types05some_a1_B11_function_1{{[_0-9a-zA-Z]*}}F
// CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T018address_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
@@ -194,8 +194,8 @@
func address_only_assignment_from_temp_to_property() {
// CHECK: bb0:
global_prop = some_address_only_function_1()
- // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
// CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
+ // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
// CHECK: apply [[SETTER]]([[TEMP]])
// CHECK: dealloc_stack [[TEMP]]
}
@@ -204,9 +204,9 @@
func address_only_assignment_from_lv_to_property(_ v: Unloadable) {
// CHECK: bb0([[VARG:%[0-9]+]] : @trivial $*Unloadable):
// CHECK: debug_value_addr [[VARG]] : $*Unloadable
- // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
// CHECK: [[TEMP:%[0-9]+]] = alloc_stack $Unloadable
// CHECK: copy_addr [[VARG]] to [initialization] [[TEMP]]
+ // CHECK: [[SETTER:%[0-9]+]] = function_ref @_T018address_only_types11global_propAA10Unloadable_pvs
// CHECK: apply [[SETTER]]([[TEMP]])
// CHECK: dealloc_stack [[TEMP]]
global_prop = v
diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift
index 247e6c9..98f4d4e 100644
--- a/test/SILGen/addressors.swift
+++ b/test/SILGen/addressors.swift
@@ -48,8 +48,8 @@
// CHECK-LABEL: sil hidden @_T010addressors5test0yyF : $@convention(thin) () -> () {
func test0() {
// CHECK: [[A:%.*]] = alloc_stack $A
-// CHECK: [[T0:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
// CHECK: [[T1:%.*]] = metatype $@thin A.Type
+// CHECK: [[T0:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
// CHECK: [[AVAL:%.*]] = apply [[T0]]([[T1]])
// CHECK: store [[AVAL]] to [[A]]
var a = A()
@@ -82,8 +82,8 @@
// CHECK-LABEL: sil hidden @_T010addressors5test1s5Int32VyF : $@convention(thin) () -> Int32
func test1() -> Int32 {
-// CHECK: [[CTOR:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
// CHECK: [[T0:%.*]] = metatype $@thin A.Type
+// CHECK: [[CTOR:%.*]] = function_ref @_T010addressors1AV{{[_0-9a-zA-Z]*}}fC
// CHECK: [[A:%.*]] = apply [[CTOR]]([[T0]]) : $@convention(method) (@thin A.Type) -> A
// CHECK: [[ACCESSOR:%.*]] = function_ref @_T010addressors1AVs5Int32VAEcilu : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
// CHECK: [[PTR:%.*]] = apply [[ACCESSOR]]({{%.*}}, [[A]]) : $@convention(method) (Int32, A) -> UnsafePointer<Int32>
@@ -230,12 +230,12 @@
// CHECK: store [[V]] to [[ADDR]] : $*Int32
array[0] = make_int()
-// CHECK: [[FN:%.*]] = function_ref @_T010addressors14take_int_inoutys5Int32VzF
// CHECK: [[WRITE:%.*]] = begin_access [modify] [static] [[ARRAY]] : $*D
// CHECK: [[T0:%.*]] = function_ref @_T010addressors1DVs5Int32VAEciau
// 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 @_T010addressors14take_int_inoutys5Int32VzF
// CHECK: apply [[FN]]([[ADDR]])
take_int_inout(&array[1])
diff --git a/test/SILGen/assignment.swift b/test/SILGen/assignment.swift
index 6418ee4..722c1bf 100644
--- a/test/SILGen/assignment.swift
+++ b/test/SILGen/assignment.swift
@@ -18,15 +18,14 @@
// Verify that the LHS is formally evaluated before the RHS.
// CHECK-LABEL: sil hidden @_T010assignment5test1yyF : $@convention(thin) () -> () {
func test1() {
- // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1DC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[T0:%.*]] = metatype $@thick D.Type
+ // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1DC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[D:%.*]] = apply [[CTOR]]([[T0]])
// CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
- // CHECK: [[SETTER:%.*]] = class_method [[BORROWED_D]] : $D, #D.child!setter.1
- // CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
- // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1CC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[T0:%.*]] = metatype $@thick C.Type
+ // CHECK: [[CTOR:%.*]] = function_ref @_T010assignment1CC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[C:%.*]] = apply [[CTOR]]([[T0]]) : $@convention(method) (@thick C.Type) -> @owned C
+ // CHECK: [[SETTER:%.*]] = class_method [[BORROWED_D]] : $D, #D.child!setter.1
// CHECK: apply [[SETTER]]([[C]], [[BORROWED_D]])
// CHECK: end_borrow [[BORROWED_D]] from [[D]]
// CHECK: destroy_value [[D]]
diff --git a/test/SILGen/auto_closures.swift b/test/SILGen/auto_closures.swift
index ddccafe..91e780a 100644
--- a/test/SILGen/auto_closures.swift
+++ b/test/SILGen/auto_closures.swift
@@ -42,11 +42,11 @@
public class Sub : Base {
// CHECK-LABEL: sil hidden @_T013auto_closures3SubC1xAA4BoolVvg : $@convention(method) (@guaranteed Sub) -> Bool {
// CHECK: bb0([[SELF:%.*]] : $Sub):
- // CHECK: [[AUTOCLOSURE_CONSUMER:%.*]] = function_ref @_T013auto_closures05call_A8_closureAA4BoolVADyXKF : $@convention(thin)
// CHECK: [[AUTOCLOSURE_FUNC:%.*]] = function_ref @_T013auto_closures3SubC1xAA4BoolVvgAFyXKfu_ : $@convention(thin) (@owned Sub) -> Bool
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[AUTOCLOSURE:%.*]] = partial_apply [[AUTOCLOSURE_FUNC]]([[SELF_COPY]])
// CHECK: [[CVT:%.*]] = convert_function [[AUTOCLOSURE]]
+ // CHECK: [[AUTOCLOSURE_CONSUMER:%.*]] = function_ref @_T013auto_closures05call_A8_closureAA4BoolVADyXKF : $@convention(thin)
// CHECK: [[RET:%.*]] = apply [[AUTOCLOSURE_CONSUMER]]([[CVT]])
// CHECK: return [[RET]] : $Bool
// CHECK: }
diff --git a/test/SILGen/borrow.swift b/test/SILGen/borrow.swift
index ee208cc..9d6aa8c 100644
--- a/test/SILGen/borrow.swift
+++ b/test/SILGen/borrow.swift
@@ -16,7 +16,6 @@
// CHECK: bb0:
// CHECK: [[BOX:%.*]] = alloc_box ${ var C }, var, name "c"
// CHECK: [[PB_BOX:%.*]] = project_box [[BOX]]
-// CHECK: [[FUNC:%.*]] = function_ref @_T06borrow4useD{{.*}} : $@convention(thin) (@owned D) -> ()
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[PB_BOX]] : $*C
// CHECK: [[CLASS:%.*]] = load [copy] [[ACCESS]]
// CHECK: [[BORROWED_CLASS:%.*]] = begin_borrow [[CLASS]]
@@ -24,6 +23,7 @@
// CHECK: [[ACCESS:%.*]] = begin_access [read] [dynamic] [[OFFSET]] : $*D
// CHECK: [[LOADED_VALUE:%.*]] = load [copy] [[ACCESS]]
// CHECK: end_borrow [[BORROWED_CLASS]] from [[CLASS]]
+// CHECK: [[FUNC:%.*]] = function_ref @_T06borrow4useD{{.*}} : $@convention(thin) (@owned D) -> ()
// CHECK: apply [[FUNC]]([[LOADED_VALUE]])
// CHECK: destroy_value [[CLASS]]
// CHECK: destroy_value [[BOX]]
diff --git a/test/SILGen/cf_members.swift b/test/SILGen/cf_members.swift
index fbbacd8..0f93faa 100644
--- a/test/SILGen/cf_members.swift
+++ b/test/SILGen/cf_members.swift
@@ -32,14 +32,14 @@
var z = Struct1(value: x)
// The metatype expression should still be evaluated even if it isn't
// used.
- // CHECK: [[FN:%.*]] = function_ref @IAMStruct1CreateSimple
// CHECK: [[MAKE_METATYPE:%.*]] = function_ref @_T010cf_members12makeMetatype{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[MAKE_METATYPE]]()
+ // CHECK: [[FN:%.*]] = function_ref @IAMStruct1CreateSimple
// CHECK: apply [[FN]]([[X]])
z = makeMetatype().init(value: x)
- // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1VABSd5value_tcfCTcTO
// CHECK: [[SELF_META:%.*]] = metatype $@thin Struct1.Type
+ // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1VABSd5value_tcfCTcTO
// CHECK: [[A:%.*]] = apply [[THUNK]]([[SELF_META]])
// CHECK: [[BORROWED_A:%.*]] = begin_borrow [[A]]
// CHECK: [[A_COPY:%.*]] = copy_value [[BORROWED_A]]
@@ -52,21 +52,21 @@
// let b: @convention(c) (Double) -> Struct1 = Struct1.init(value:)
// z = b(x)
- // CHECK: [[FN:%.*]] = function_ref @IAMStruct1InvertInPlace
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[Z]] : $*Struct1
+ // CHECK: [[FN:%.*]] = function_ref @IAMStruct1InvertInPlace
// CHECK: apply [[FN]]([[WRITE]])
z.invert()
- // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Rotate : $@convention(c) (@in Struct1, Double) -> Struct1
// CHECK: [[WRITE:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
// CHECK: [[ZVAL:%.*]] = load [trivial] [[WRITE]]
// CHECK: store [[ZVAL]] to [trivial] [[ZTMP:%.*]] :
+ // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Rotate : $@convention(c) (@in Struct1, Double) -> Struct1
// CHECK: apply [[FN]]([[ZTMP]], [[X]])
z = z.translate(radians: x)
- // CHECK: [[THUNK:%.*]] = function_ref [[THUNK_NAME:@_T0SC7Struct1V9translateABSd7radians_tFTcTO]]
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
// CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+ // CHECK: [[THUNK:%.*]] = function_ref [[THUNK_NAME:@_T0SC7Struct1V9translateABSd7radians_tFTcTO]]
// CHECK: [[C:%.*]] = apply [[THUNK]]([[ZVAL]])
// CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
// CHECK: [[C_COPY:%.*]] = copy_value [[BORROWED_C]]
@@ -75,8 +75,13 @@
// CHECK: end_borrow [[BORROWED_C]] from [[C]]
z = c(x)
// CHECK: [[THUNK:%.*]] = function_ref [[THUNK_NAME]]
- // CHECK: thin_to_thick_function [[THUNK]]
+ // CHECK: [[THICK:%.*]] = thin_to_thick_function [[THUNK]]
+ // CHECK: [[BORROW:%.*]] = begin_borrow [[THICK]]
+ // CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
let d: (Struct1) -> (Double) -> Struct1 = Struct1.translate(radians:)
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
+ // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+ // CHECK: apply [[COPY]]([[ZVAL]])
z = d(z)(x)
// TODO: If we implement SE-0042, this should thunk the value Struct1 param
@@ -86,15 +91,15 @@
// = Struct1.translate(radians:)
// z = e(z, x)
- // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Scale
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
// CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+ // CHECK: [[FN:%.*]] = function_ref @IAMStruct1Scale
// CHECK: apply [[FN]]([[ZVAL]], [[X]])
z = z.scale(x)
- // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V5scaleABSdFTcTO
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
// CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+ // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V5scaleABSdFTcTO
// CHECK: [[F:%.*]] = apply [[THUNK]]([[ZVAL]])
// CHECK: [[BORROWED_F:%.*]] = begin_borrow [[F]]
// CHECK: [[F_COPY:%.*]] = copy_value [[BORROWED_F]]
@@ -118,8 +123,8 @@
// CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
// CHECK: store [[ZVAL]] to [trivial] [[ZTMP:%.*]] :
// CHECK: [[ZVAL_2:%.*]] = load [trivial] [[ZTMP]]
- // CHECK: [[GET:%.*]] = function_ref @IAMStruct1GetRadius : $@convention(c) (@in Struct1) -> Double
// CHECK: store [[ZVAL_2]] to [trivial] [[ZTMP_2:%.*]] :
+ // CHECK: [[GET:%.*]] = function_ref @IAMStruct1GetRadius : $@convention(c) (@in Struct1) -> Double
// CHECK: apply [[GET]]([[ZTMP_2]])
_ = z.radius
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
@@ -133,8 +138,8 @@
// CHECK: [[GET:%.*]] = function_ref @IAMStruct1GetAltitude : $@convention(c) (Struct1) -> Double
// CHECK: apply [[GET]]([[ZVAL]])
_ = z.altitude
- // CHECK: [[SET:%.*]] = function_ref @IAMStruct1SetAltitude : $@convention(c) (@inout Struct1, Double) -> ()
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[Z]] : $*Struct1
+ // CHECK: [[SET:%.*]] = function_ref @IAMStruct1SetAltitude : $@convention(c) (@inout Struct1, Double) -> ()
// CHECK: apply [[SET]]([[WRITE]], [[X]])
z.altitude = x
@@ -147,8 +152,8 @@
// CHECK: [[FN:%.*]] = function_ref @IAMStruct1StaticMethod
// CHECK: apply [[FN]]()
var y = Struct1.staticMethod()
- // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V12staticMethods5Int32VyFZTcTO
// CHECK: [[SELF:%.*]] = metatype
+ // CHECK: [[THUNK:%.*]] = function_ref @_T0SC7Struct1V12staticMethods5Int32VyFZTcTO
// CHECK: [[I:%.*]] = apply [[THUNK]]([[SELF]])
// CHECK: [[BORROWED_I:%.*]] = begin_borrow [[I]]
// CHECK: [[I_COPY:%.*]] = copy_value [[BORROWED_I]]
@@ -187,23 +192,27 @@
// CHECK: apply [[GET]]()
_ = makeMetatype().getOnlyProperty
- // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesLast : $@convention(c) (Double, Struct1) -> ()
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
// CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+ // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesLast : $@convention(c) (Double, Struct1) -> ()
// CHECK: apply [[FN]]([[X]], [[ZVAL]])
z.selfComesLast(x: x)
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
+ // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
let k: (Double) -> () = z.selfComesLast(x:)
k(x)
let l: (Struct1) -> (Double) -> () = Struct1.selfComesLast(x:)
+ // CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
+ // CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
l(z)(x)
// TODO: If we implement SE-0042, this should thunk to reorder the arguments.
// let m: @convention(c) (Struct1, Double) -> () = Struct1.selfComesLast(x:)
// m(z, x)
- // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesThird : $@convention(c) (Int32, Float, Struct1, Double) -> ()
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]] : $*Struct1
// CHECK: [[ZVAL:%.*]] = load [trivial] [[READ]]
+ // CHECK: [[FN:%.*]] = function_ref @IAMStruct1SelfComesThird : $@convention(c) (Int32, Float, Struct1, Double) -> ()
// CHECK: apply [[FN]]({{.*}}, {{.*}}, [[ZVAL]], [[X]])
z.selfComesThird(a: y, b: 0, x: x)
let n: (Int32, Float, Double) -> () = z.selfComesThird(a:b:x:)
diff --git a/test/SILGen/class_bound_protocols.swift b/test/SILGen/class_bound_protocols.swift
index e2feaab..7048696 100644
--- a/test/SILGen/class_bound_protocols.swift
+++ b/test/SILGen/class_bound_protocols.swift
@@ -193,7 +193,6 @@
// CHECK-NEXT: [[TEMPORARY:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
// CHECK-NEXT: store [[X_PAYLOAD]] to [init] [[TEMPORARY]] : $*@opened("{{.*}}") InheritsMutatingMethod
// CHECK-NEXT: [[X_PAYLOAD_RELOADED:%.*]] = load [take] [[TEMPORARY]]
- // 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
//
// ** *NOTE* This extra copy is here since RValue invariants enforce that all
// ** loadable objects are actually loaded. So we form the RValue and
@@ -203,6 +202,7 @@
// CHECK-NEXT: [[TEMPORARY_2:%.*]] = alloc_stack $@opened("{{.*}}") InheritsMutatingMethod
// CHECK-NEXT: store [[X_PAYLOAD_RELOADED:%.*]] to [init] [[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: [[X_VALUE:%.*]] = load [take] [[TEMPORARY_2]] : $*@opened("{{.*}}") InheritsMutatingMethod
// CHECK-NEXT: destroy_value [[X_VALUE]] : $@opened("{{.*}}") InheritsMutatingMethod
diff --git a/test/SILGen/class_resilience.swift b/test/SILGen/class_resilience.swift
index c9442fe..5db4d2d 100644
--- a/test/SILGen/class_resilience.swift
+++ b/test/SILGen/class_resilience.swift
@@ -17,6 +17,26 @@
public class MyResilientClass {
public final var finalProperty: String = "MyResilientClass.finalProperty"
+
+ // CHECK-LABEL: sil [thunk] @_T016class_resilience16MyResilientClassC17publicMethodFirstSiSgyFTj : $@convention(method) (@guaranteed MyResilientClass) -> Optional<Int>
+ // CHECK: class_method %0 : $MyResilientClass, #MyResilientClass.publicMethodFirst!1 : (MyResilientClass) -> () -> Int?, $@convention(method) (@guaranteed MyResilientClass) -> Optional<Int>
+ // CHECK: return
+ public func publicMethodFirst() -> Int? { return nil }
+
+ // CHECK-LABEL: sil [thunk] @_T016class_resilience16MyResilientClassC18publicMethodSecondyyXlFTj : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+ // CHECK: class_method %1 : $MyResilientClass, #MyResilientClass.publicMethodSecond!1 : (MyResilientClass) -> (AnyObject) -> (), $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+ // CHECK: return
+ public func publicMethodSecond(_ a: AnyObject) {}
+}
+
+public class MyResilientSubclass : MyResilientClass {
+ // This override changes ABI so it gets its own dispatch thunk
+ // CHECK-LABEL: sil [thunk] @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTj : $@convention(method) (@guaranteed MyResilientSubclass) -> Int
+ // CHECK: class_method %0 : $MyResilientSubclass, #MyResilientSubclass.publicMethodFirst!1 : (MyResilientSubclass) -> () -> Int, $@convention(method) (@guaranteed MyResilientSubclass) -> Int
+ // CHECK: return
+ public override func publicMethodFirst() -> Int { return 0 }
+
+ public override func publicMethodSecond(_ a: AnyObject?) {}
}
// Accessing final property of resilient class from my resilience domain
@@ -38,6 +58,39 @@
func newMethod() {}
}
+// CHECK-LABEL: sil @_T016class_resilience19callResilientMethodyAA02MyD8SubclassCF : $@convention(thin) (@owned MyResilientSubclass) -> ()
+public func callResilientMethod(_ s: MyResilientSubclass) {
+// CHECK: class_method {{.*}} : $MyResilientSubclass, #MyResilientSubclass.publicMethodFirst!1
+ _ = s.publicMethodFirst()
+// CHECK: class_method {{.*}} : $MyResilientSubclass, #MyResilientSubclass.publicMethodSecond!1
+ s.publicMethodSecond(nil)
+// CHECK: return
+}
+
+// CHECK-LABEL: sil [serialized] @_T016class_resilience29callResilientMethodInlineableyAA02MyD8SubclassCF : $@convention(thin) (@owned MyResilientSubclass) -> ()
+@_inlineable public func callResilientMethodInlineable(_ s: MyResilientSubclass) {
+// CHECK: [[FN:%.*]] = function_ref @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTj : $@convention(method) (@guaranteed MyResilientSubclass) -> Int
+ _ = s.publicMethodFirst()
+ // CHECK: [[FN:%.*]] = function_ref @_T016class_resilience16MyResilientClassC18publicMethodSecondyyXlFTj : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+ // CHECK: [[CONVERTED:%.*]] = convert_function [[FN]] : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> () to $@convention(method) (@owned Optional<AnyObject>, @guaranteed MyResilientSubclass) -> ()
+ s.publicMethodSecond(nil)
+
+ // CHECK: function_ref @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTc
+ _ = s.publicMethodFirst
+
+ // CHECK: function_ref @_T016class_resilience19MyResilientSubclassC18publicMethodSecondyyXlSgFTc
+ _ = s.publicMethodSecond
+// CHECK: return
+}
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTc : $@convention(thin) (@owned MyResilientSubclass) -> @owned @callee_owned () -> Int
+// CHECK: function_ref @_T016class_resilience19MyResilientSubclassC17publicMethodFirstSiyFTj
+// CHECK: return
+
+// CHECK-LABEL: sil shared [serializable] [thunk] @_T016class_resilience19MyResilientSubclassC18publicMethodSecondyyXlSgFTc : $@convention(thin) (@owned MyResilientSubclass) -> @owned @callee_owned (@owned Optional<AnyObject>) -> ()
+// CHECK: function_ref @_T016class_resilience16MyResilientClassC18publicMethodSecondyyXlFTj : $@convention(method) (@owned AnyObject, @guaranteed MyResilientClass) -> ()
+// CHECK: return
+
// Note: no entries for [inherited] methods
// CHECK-LABEL: sil_vtable SubclassOfOutsideChild {
diff --git a/test/SILGen/closures.swift b/test/SILGen/closures.swift
index 3ed9217..6c28e80 100644
--- a/test/SILGen/closures.swift
+++ b/test/SILGen/closures.swift
@@ -1,4 +1,5 @@
// 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 -enable-guaranteed-closure-contexts %s | %FileCheck %s --check-prefix=GUARANTEED
import Swift
@@ -394,6 +395,17 @@
// CHECK: return [[INT_IN_CLASS]]
// CHECK: } // end sil function '_T08closures18closeOverLetLValueyyFSiycfU_'
+// GUARANTEED-LABEL: sil private @_T08closures18closeOverLetLValueyyFSiycfU_ : $@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 '_T08closures18closeOverLetLValueyyFSiycfU_'
// Use an external function so inout deshadowing cannot see its body.
@@ -442,8 +454,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -480,8 +492,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase)
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -517,8 +529,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -556,8 +568,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -596,8 +608,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPERCAST:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPERCAST:%.*]] = begin_borrow [[ARG_COPY_SUPERCAST]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPERCAST]])
// CHECK: destroy_value [[ARG_COPY_SUPERCAST]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -622,13 +634,13 @@
func f() {
// CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@owned SuperSub) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $SuperSub):
- // CHECK: [[TRY_APPLY_AUTOCLOSURE:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
// CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:_T08closures8SuperSubC1fyyFyycfU_yyKXKfu_]] : $@convention(thin) (@owned SuperSub) -> @error Error
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[PA:%.*]] = partial_apply [[INNER]]([[ARG_COPY]])
// CHECK: [[CVT:%.*]] = convert_function [[PA]]
// CHECK: [[REABSTRACT_PA:%.*]] = partial_apply {{.*}}([[CVT]])
// CHECK: [[REABSTRACT_CVT:%.*]] = convert_function [[REABSTRACT_PA]]
+ // CHECK: [[TRY_APPLY_AUTOCLOSURE:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
// CHECK: try_apply [[TRY_APPLY_AUTOCLOSURE]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
// CHECK: [[NORMAL_BB]]{{.*}}
// CHECK: destroy_value [[ARG]]
@@ -639,8 +651,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -659,13 +671,13 @@
func g() {
// CHECK: sil private @[[INNER_FUNC_1]] : $@convention(thin) (@owned SuperSub) -> ()
// CHECK: bb0([[ARG:%.*]] : @owned $SuperSub):
- // CHECK: [[TRY_APPLY_FUNC:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
// CHECK: [[INNER:%.*]] = function_ref @[[INNER_FUNC_2:_T08closures8SuperSubC1g.*]] : $@convention(thin) (@owned SuperSub) -> @error Error
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[PA:%.*]] = partial_apply [[INNER]]([[ARG_COPY]])
// CHECK: [[CVT:%.*]] = convert_function [[PA]] : $@callee_owned () -> @error Error to $@noescape @callee_owned () -> @error Error
// CHECK: [[REABSTRACT_PA:%.*]] = partial_apply {{%.*}}([[CVT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> @error Error) -> (@out (), @error Error)
// CHECK: [[REABSTRACT_CVT:%.*]] = convert_function [[REABSTRACT_PA]]
+ // CHECK: [[TRY_APPLY_FUNC:%.*]] = function_ref @_T0s2qqoixxSg_xyKXKtKlF : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error)
// CHECK: try_apply [[TRY_APPLY_FUNC]]<()>({{.*}}, {{.*}}, [[REABSTRACT_CVT]]) : $@convention(thin) <τ_0_0> (@in Optional<τ_0_0>, @owned @noescape @callee_owned () -> (@out τ_0_0, @error Error)) -> (@out τ_0_0, @error Error), normal [[NORMAL_BB:bb1]], error [[ERROR_BB:bb2]]
// CHECK: [[NORMAL_BB]]{{.*}}
// CHECK: destroy_value [[ARG]]
@@ -676,8 +688,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $SuperSub to $SuperBase
- // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+ // CHECK: [[SUPER_METHOD:%.*]] = function_ref @_T08closures9SuperBaseC4boomyyF : $@convention(method) (@guaranteed SuperBase) -> ()
// CHECK: = apply [[SUPER_METHOD]]([[BORROWED_ARG_COPY_SUPER]])
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -767,8 +779,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: [[ARG_COPY_SUPER:%.*]] = upcast [[ARG_COPY]] : $GenericDerived<Ocean> to $ConcreteBase
-// CHECK: [[METHOD:%.*]] = function_ref @_T08closures12ConcreteBaseC4swimyyF
// CHECK: [[BORROWED_ARG_COPY_SUPER:%.*]] = begin_borrow [[ARG_COPY_SUPER]]
+// CHECK: [[METHOD:%.*]] = function_ref @_T08closures12ConcreteBaseC4swimyyF
// CHECK: apply [[METHOD]]([[BORROWED_ARG_COPY_SUPER]]) : $@convention(method) (@guaranteed ConcreteBase) -> ()
// CHECK: destroy_value [[ARG_COPY_SUPER]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
diff --git a/test/SILGen/closures_callee_guaranteed.swift b/test/SILGen/closures_callee_guaranteed.swift
index a71221e..bc716f9 100644
--- a/test/SILGen/closures_callee_guaranteed.swift
+++ b/test/SILGen/closures_callee_guaranteed.swift
@@ -21,10 +21,10 @@
}
// CHECK-LABEL: sil @{{.*}}test{{.*}} : $@convention(thin) () -> ()
-// CHECK: [[A:%.*]] = function_ref @{{.*}}apply{{.*}} : $@convention(thin) (@owned @noescape @callee_guaranteed () -> Int) -> Int
// CHECK: [[C1:%.*]] = function_ref @{{.*}}test{{.*}} : $@convention(thin) () -> Int
// CHECK: [[C2:%.*]] = convert_function [[C1]] : $@convention(thin) () -> Int to $@convention(thin) @noescape () -> Int
// CHECK: [[C3:%.*]] = thin_to_thick_function [[C2]] : $@convention(thin) @noescape () -> Int to $@noescape @callee_guaranteed () -> Int
+// CHECK: [[A:%.*]] = function_ref @{{.*}}apply{{.*}} : $@convention(thin) (@owned @noescape @callee_guaranteed () -> Int) -> Int
// CHECK: apply [[A]]([[C3]]) : $@convention(thin) (@owned @noescape @callee_guaranteed () -> Int) -> Int
public func test() {
let res = apply({ return 1 })
diff --git a/test/SILGen/complete_object_init.swift b/test/SILGen/complete_object_init.swift
index 8363f9c..0c826ac 100644
--- a/test/SILGen/complete_object_init.swift
+++ b/test/SILGen/complete_object_init.swift
@@ -17,11 +17,10 @@
// CHECK: [[PB:%.*]] = project_box [[UNINIT_SELF]]
// CHECK: store [[SELF_PARAM]] to [init] [[PB]] : $*A
// CHECK: [[SELFP:%[0-9]+]] = load [take] [[PB]] : $*A
-// CHECK: [[BORROWED_SELFP:%.*]] = begin_borrow [[SELFP]]
-// CHECK: [[INIT:%[0-9]+]] = class_method [[BORROWED_SELFP]] : $A, #A.init!initializer.1 : (A.Type) -> (X) -> A, $@convention(method) (X, @owned A) -> @owned A
-// CHECK: [[X_INIT:%[0-9]+]] = function_ref @_T020complete_object_init1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X_META:%[0-9]+]] = metatype $@thin X.Type
+// CHECK: [[X_INIT:%[0-9]+]] = function_ref @_T020complete_object_init1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X:%[0-9]+]] = apply [[X_INIT]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
+// CHECK: [[INIT:%[0-9]+]] = class_method [[SELFP]] : $A, #A.init!initializer.1 : (A.Type) -> (X) -> A, $@convention(method) (X, @owned A) -> @owned A
// CHECK: [[INIT_RESULT:%[0-9]+]] = apply [[INIT]]([[X]], [[SELFP]]) : $@convention(method) (X, @owned A) -> @owned A
// CHECK: store [[INIT_RESULT]] to [init] [[PB]] : $*A
// CHECK: [[RESULT:%[0-9]+]] = load [copy] [[PB]] : $*A
diff --git a/test/SILGen/conditional_conformance.swift b/test/SILGen/conditional_conformance.swift
new file mode 100644
index 0000000..a43dc60
--- /dev/null
+++ b/test/SILGen/conditional_conformance.swift
@@ -0,0 +1,80 @@
+// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+
+protocol P1 {
+ func normal()
+ func generic<T: P3>(_: T)
+}
+protocol P2 {}
+protocol P3 {}
+
+protocol P4 {
+ associatedtype AT
+}
+
+struct Conformance<A> {}
+extension Conformance: P1 where A: P2 {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+// CHECK-LABEL: sil_witness_table hidden <A where A : P2> Conformance<A>: P1 module conditional_conformance {
+// CHECK-NEXT: method #P1.normal!1: <Self where Self : P1> (Self) -> () -> () : @_T023conditional_conformance11ConformanceVyxGAA2P1A2A2P2RzlAaEP6normalyyFTW // protocol witness for P1.normal() in conformance <A> Conformance<A>
+// CHECK-NEXT: method #P1.generic!1: <Self where Self : P1><T where T : P3> (Self) -> (T) -> () : @_T023conditional_conformance11ConformanceVyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW // protocol witness for P1.generic<A>(_:) in conformance <A> Conformance<A>
+// CHECK-NEXT: conditional_conformance (τ_0_0: P2): dependent
+// CHECK-NEXT: }
+
+struct ConformanceAssoc<A> {}
+extension ConformanceAssoc: P1 where A: P4, A.AT: P2 {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+// CHECK-LABEL: sil_witness_table hidden <A where A : P4, A.AT : P2> ConformanceAssoc<A>: P1 module conditional_conformance {
+// CHECK-NEXT: method #P1.normal!1: <Self where Self : P1> (Self) -> () -> () : @_T023conditional_conformance16ConformanceAssocVyxGAA2P1A2A2P4RzAA2P22ATRpzlAaEP6normalyyFTW // protocol witness for P1.normal() in conformance <A> ConformanceAssoc<A>
+// CHECK-NEXT: method #P1.generic!1: <Self where Self : P1><T where T : P3> (Self) -> (T) -> () : @_T023conditional_conformance16ConformanceAssocVyxGAA2P1A2A2P4RzAA2P22ATRpzlAaEP7genericyqd__AA2P3Rd__lFTW // protocol witness for P1.generic<A>(_:) in conformance <A> ConformanceAssoc<A>
+// CHECK-NEXT: conditional_conformance (τ_0_0: P4): dependent
+// CHECK-NEXT: conditional_conformance (τ_0_0.AT: P2): dependent
+// CHECK-NEXT: }
+
+/*
+FIXME: same type constraints are modelled incorrectly.
+struct SameTypeConcrete<B> {}
+extension SameTypeConcrete: P1 where B == Int {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+
+struct SameTypeGeneric<C, D> {}
+extension SameTypeGeneric: P1 where C == D {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+
+struct SameTypeGenericConcrete<E, F> {}
+extension SameTypeGenericConcrete: P1 where E == [F] {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+
+struct Everything<G, H, I, J, K, L> {}
+extension Everything: P1 where G: P2, H == Int, I == J, K == [L] {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+*/
+
+struct IsP2: P2 {}
+struct IsNotP2 {}
+
+class Base<A> {}
+extension Base: P1 where A: P2 {
+ func normal() {}
+ func generic<T: P3>(_: T) {}
+}
+// CHECK-LABEL: sil_witness_table hidden <A where A : P2> Base<A>: P1 module conditional_conformance {
+// CHECK-NEXT: method #P1.normal!1: <Self where Self : P1> (Self) -> () -> () : @_T023conditional_conformance4BaseCyxGAA2P1A2A2P2RzlAaEP6normalyyFTW // protocol witness for P1.normal() in conformance <A> Base<A>
+// CHECK-NEXT: method #P1.generic!1: <Self where Self : P1><T where T : P3> (Self) -> (T) -> () : @_T023conditional_conformance4BaseCyxGAA2P1A2A2P2RzlAaEP7genericyqd__AA2P3Rd__lFTW // protocol witness for P1.generic<A>(_:) in conformance <A> Base<A>
+// CHECK-NEXT: conditional_conformance (τ_0_0: P2): dependent
+// CHECK-NEXT: }
+
+// These don't get separate witness tables, but shouldn't crash anything.
+class SubclassGood: Base<IsP2> {}
+class SubclassBad: Base<IsNotP2> {}
diff --git a/test/SILGen/default_arguments.swift b/test/SILGen/default_arguments.swift
index d526ac7..e0f2fac 100644
--- a/test/SILGen/default_arguments.swift
+++ b/test/SILGen/default_arguments.swift
@@ -10,9 +10,9 @@
// Default argument for first parameter.
// CHECK-LABEL: sil hidden @_T017default_arguments7defarg1ySi1i_Sd1dSS1stFfA_ : $@convention(thin) () -> Int
-// CHECK: [[CVT:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
// CHECK: [[INT:%[0-9]+]] = metatype $@thin Int.Type
// CHECK: [[LIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 17
+// CHECK: [[CVT:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
// CHECK: [[RESULT:%[0-9]+]] = apply [[CVT]]([[LIT]], [[INT]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
// CHECK: return [[RESULT]] : $Int
@@ -28,15 +28,15 @@
// CHECK-LABEL: sil hidden @_T017default_arguments15testDefaultArg1yyF
func testDefaultArg1() {
- // CHECK: [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{[_0-9a-zA-Z]*}}F
- // CHECK: [[LITFN:%[0-9]+]] = function_ref @_T0S2d{{[_0-9a-zA-Z]*}}fC
// 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 @_T0S2d{{[_0-9a-zA-Z]*}}fC
// CHECK: [[FLOATVAL:%[0-9]+]] = apply [[LITFN]]([[FLOATLIT]], [[FLOAT64]])
// CHECK: [[DEF0FN:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{.*}}A_
// CHECK: [[DEF0:%[0-9]+]] = apply [[DEF0FN]]()
// CHECK: [[DEF2FN:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{.*}}A1_
// CHECK: [[DEF2:%[0-9]+]] = apply [[DEF2FN]]()
+ // CHECK: [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg1{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FNREF]]([[DEF0]], [[FLOATVAL]], [[DEF2]])
defarg1(d:3.125)
}
@@ -45,15 +45,15 @@
// CHECK-LABEL: sil hidden @_T017default_arguments15testDefaultArg2{{[_0-9a-zA-Z]*}}F
func testDefaultArg2() {
-// CHECK: [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Double, @owned String) -> ()
-// CHECK: [[LITFN:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
// CHECK: [[INT64:%[0-9]+]] = metatype $@thin Int.Type
// CHECK: [[INTLIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 5
+// CHECK: [[LITFN:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
// CHECK: [[I:%[0-9]+]] = apply [[LITFN]]([[INTLIT]], [[INT64]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
// CHECK: [[DFN:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{.*}}A0_ : $@convention(thin) () -> Double
// CHECK: [[D:%[0-9]+]] = apply [[DFN]]() : $@convention(thin) () -> Double
// CHECK: [[SFN:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{.*}}A1_ : $@convention(thin) () -> @owned String
// CHECK: [[S:%[0-9]+]] = apply [[SFN]]() : $@convention(thin) () -> @owned String
+// CHECK: [[FNREF:%[0-9]+]] = function_ref @_T017default_arguments7defarg2{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Double, @owned String) -> ()
// CHECK: apply [[FNREF]]([[I]], [[D]], [[S]]) : $@convention(thin) (Int, Double, @owned String) -> ()
defarg2(5)
}
@@ -178,8 +178,8 @@
// CHECK: sil hidden @_T017default_arguments13testSubDefArgAA0deF0CyF : $@convention(thin) () -> @owned SubDefArg
func testSubDefArg() -> SubDefArg {
- // CHECK: function_ref @_T017default_arguments9SubDefArgC{{[_0-9a-zA-Z]*}}fC
// CHECK: function_ref @_T017default_arguments11SuperDefArgCACSi3int_tcfcfA_
+ // CHECK: function_ref @_T017default_arguments9SubDefArgC{{[_0-9a-zA-Z]*}}fC
// CHECK: return
return SubDefArg()
}
@@ -219,20 +219,18 @@
// CHECK-LABEL: sil hidden @_T017default_arguments32testDefaultArgumentReabstractionyyF
// function_ref default_arguments.ReabstractDefaultArgument.__allocating_init <A>(default_arguments.ReabstractDefaultArgument<A>.Type)(a : (A, A) -> Swift.Bool) -> default_arguments.ReabstractDefaultArgument<A>
-// CHECK: [[INITFN:%[0-9]+]] = function_ref @_T017default_arguments25ReabstractDefaultArgumentC{{[_0-9a-zA-Z]*}}fC
-// %1 = metatype $@thick ReabstractDefaultArgument<Int>.Type
-// function_ref default_arguments.ReabstractDefaultArgument.(init <A>(default_arguments.ReabstractDefaultArgument<A>.Type) -> (a : (A, A) -> Swift.Bool) -> default_arguments.ReabstractDefaultArgument<A>).(default argument 0)
-// CHECK: %2 = function_ref @_T017default_arguments25ReabstractDefaultArgument{{.*}} : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
-// CHECK-NEXT: %3 = apply %2<Int>() : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
+// CHECK: [[FN:%.*]] = function_ref @_T017default_arguments25ReabstractDefaultArgument{{.*}} : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
+// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Int>() : $@convention(thin) <τ_0_0> () -> @owned @noescape @callee_owned (@in τ_0_0, @in τ_0_0) -> Bool
// CHECK-NEXT: function_ref reabstraction thunk helper from @callee_owned (@in Swift.Int, @in Swift.Int) -> (@unowned Swift.Bool) to @callee_owned (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool)
-// CHECK-NEXT: %4 = function_ref @_T0S2iSbIxiid_S2iSbIxyyd_TR : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
-// CHECK-NEXT: %5 = partial_apply %4(%3) : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
-// CHECK-NEXT: %6 = convert_function %5
+// CHECK-NEXT: [[THUNK:%.*]] = function_ref @_T0S2iSbIxiid_S2iSbIxyyd_TR : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [[THUNK]]([[RESULT]]) : $@convention(thin) (Int, Int, @owned @noescape @callee_owned (@in Int, @in Int) -> Bool) -> Bool
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_function [[FN]]
// function_ref reabstraction thunk helper from @callee_owned (@unowned Swift.Int, @unowned Swift.Int) -> (@unowned Swift.Bool) to @callee_owned (@in Swift.Int, @in Swift.Int) -> (@unowned Swift.Bool)
-// CHECK: %7 = function_ref @_T0S2iSbIxyyd_S2iSbIxiid_TR : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
-// CHECK-NEXT: %8 = partial_apply %7(%6) : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
-// CHECK-NEXT: %9 = convert_function %8
-// CHECK-NEXT: apply [[INITFN]]<Int>(%9,
+// CHECK: [[THUNK:%.*]] = function_ref @_T0S2iSbIxyyd_S2iSbIxiid_TR : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
+// CHECK-NEXT: [[FN:%.*]] = partial_apply [[THUNK]]([[CONV_FN]]) : $@convention(thin) (@in Int, @in Int, @owned @noescape @callee_owned (Int, Int) -> Bool) -> Bool
+// CHECK-NEXT: [[CONV_FN:%.*]] = convert_function [[FN]]
+// CHECK: [[INITFN:%[0-9]+]] = function_ref @_T017default_arguments25ReabstractDefaultArgumentC{{[_0-9a-zA-Z]*}}fC
+// CHECK-NEXT: apply [[INITFN]]<Int>([[CONV_FN]],
func testDefaultArgumentReabstraction() {
_ = ReabstractDefaultArgument<Int>()
@@ -256,9 +254,9 @@
// CHECK: integer_literal $Builtin.Int2048, 97
// CHECK-LABEL: sil hidden @_T017default_arguments14test_r18400194yyF
-// CHECK: function_ref @_T017default_arguments9r18400194ySi_Si1xtF : $@convention(thin) (Int, Int) -> (){{.*}} // user: %7
// CHECK: integer_literal $Builtin.Int2048, 1
// CHECK: function_ref @_T017default_arguments9r18400194ySi_Si1xtFfA0_ : $@convention(thin) () -> Int
+// CHECK: function_ref @_T017default_arguments9r18400194ySi_Si1xtF : $@convention(thin) (Int, Int) -> (){{.*}}
func test_r18400194() {
(r18400194)(1)
}
diff --git a/test/SILGen/default_arguments_generic.swift b/test/SILGen/default_arguments_generic.swift
index 93ed6c0..a825808 100644
--- a/test/SILGen/default_arguments_generic.swift
+++ b/test/SILGen/default_arguments_generic.swift
@@ -42,8 +42,8 @@
func testInitializable() {
// The ".init" is required to trigger the crash that used to happen.
_ = Generic<InitializableImpl>.init()
- // CHECK: [[INIT:%.+]] = function_ref @_T025default_arguments_generic7GenericVACyxGxcfC
// CHECK: function_ref @_T025default_arguments_generic7GenericVACyxGxcfcfA_ : $@convention(thin) <τ_0_0 where τ_0_0 : Initializable> () -> @out τ_0_0
+ // CHECK: [[INIT:%.+]] = function_ref @_T025default_arguments_generic7GenericVACyxGxcfC
// 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 '_T025default_arguments_generic17testInitializableyyF'
diff --git a/test/SILGen/default_arguments_imported.swift b/test/SILGen/default_arguments_imported.swift
index f951038..95ad609 100644
--- a/test/SILGen/default_arguments_imported.swift
+++ b/test/SILGen/default_arguments_imported.swift
@@ -8,23 +8,23 @@
// CHECK-LABEL: sil hidden @_T026default_arguments_imported9testGizmo{{[_0-9a-zA-Z]*}}F
func testGizmo(gizmo: Gizmo) {
- // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.enumerateSubGizmos!1.foreign
// CHECK: function_ref @_T0SqxSgyt10nilLiteral_tcfC
+ // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.enumerateSubGizmos!1.foreign
gizmo.enumerateSubGizmos()
} // CHECK: } // end sil function '_T026default_arguments_imported9testGizmoySo0E0C5gizmo_tF'
// CHECK-LABEL: sil hidden @_T026default_arguments_imported21testNonnullDictionaryySo5GizmoC5gizmo_tF
func testNonnullDictionary(gizmo: Gizmo) {
- // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheThing!1.foreign
// CHECK-NOT: nilLiteral
// CHECK: function_ref @_T0s10DictionaryVAByxq_Gx_q_t17dictionaryLiterald_tcfC
+ // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheThing!1.foreign
gizmo.doTheThing()
} // CHECK: } // end sil function '_T026default_arguments_imported21testNonnullDictionaryySo5GizmoC5gizmo_tF'
// CHECK-LABEL: sil hidden @_T026default_arguments_imported22testNullableDictionaryySo5GizmoC5gizmo_tF
func testNullableDictionary(gizmo: Gizmo) {
- // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheOtherThing!1.foreign
// CHECK-NOT: dictionaryLiteral
// CHECK: function_ref @_T0SqxSgyt10nilLiteral_tcfC
+ // CHECK: objc_method [[SELF:%[0-9]+]] : $Gizmo, #Gizmo.doTheOtherThing!1.foreign
gizmo.doTheOtherThing()
} // CHECK: } // end sil function '_T026default_arguments_imported22testNullableDictionaryySo5GizmoC5gizmo_tF'
diff --git a/test/SILGen/default_arguments_serialized.swift b/test/SILGen/default_arguments_serialized.swift
index 3391474..d264736 100644
--- a/test/SILGen/default_arguments_serialized.swift
+++ b/test/SILGen/default_arguments_serialized.swift
@@ -23,9 +23,9 @@
public func hasDefaultArguments(x: Int = 0, y: String = defaultString()) {}
// CHECK-LABEL: sil @_T028default_arguments_serialized21callsDefaultArgumentsyyF : $@convention(thin) () -> ()
-// CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytF : $@convention(thin) (Int, @owned String) -> ()
// CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytFfA_ : $@convention(thin) () -> Int
// CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytFfA0_ : $@convention(thin) () -> @owned String
+// CHECK: function_ref @_T028default_arguments_serialized19hasDefaultArgumentsySi1x_SS1ytF : $@convention(thin) (Int, @owned String) -> ()
// CHECK: apply
// CHECK: return
public func callsDefaultArguments() {
@@ -37,8 +37,8 @@
// even if *this* module is built in Swift 3 mode.
// CHECK-LABEL: sil @_T028default_arguments_serialized26callsOtherDefaultArgumentsyyF : $@convention(thin) () -> ()
-// CHECK: function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
// CHECK: function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tFfA_ : $@convention(thin) () -> Int
+// CHECK: function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
// CHECK: apply
// CHECK: return
@@ -46,15 +46,16 @@
// other module.
// OPT-LABEL: sil @_T028default_arguments_serialized26callsOtherDefaultArgumentsyyF : $@convention(thin) () -> ()
-// OPT: [[FN:%.*]] = function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> () // user: %3
// OPT: [[INT_VAL:%.*]] = integer_literal [[INT_TYPE:\$Builtin.Int(32|64)]], 0
// OPT: [[INT:%.*]] = struct $Int ([[INT_VAL]] : [[INT_TYPE]]
+// OPT: [[FN:%.*]] = function_ref @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
// OPT: apply [[FN]]([[INT]]) : $@convention(thin) (Int) -> ()
// OPT: return
public func callsOtherDefaultArguments() {
otherDefaultArguments()
}
+// CHECK-LABEL: sil [serialized] @_T023default_arguments_other0C16DefaultArgumentsySi1x_tFfA_ : $@convention(thin) () -> Int
+
// CHECK-LABEL: sil @_T023default_arguments_other0C16DefaultArgumentsySi1x_tF : $@convention(thin) (Int) -> ()
-// CHECK-LABEL: sil [serialized] @_T023default_arguments_other0C16DefaultArgumentsySi1x_tFfA_ : $@convention(thin) () -> Int
diff --git a/test/SILGen/default_constructor.swift b/test/SILGen/default_constructor.swift
index 7ffa02b..24f77ac 100644
--- a/test/SILGen/default_constructor.swift
+++ b/test/SILGen/default_constructor.swift
@@ -15,13 +15,13 @@
}
// CHECK-LABEL: sil hidden [transparent] @_T019default_constructor1DV1iSivpfi : $@convention(thin) () -> (Int, Double)
-// CHECK: [[FN:%.*]] = function_ref @_T0S2iBi2048_22_builtinIntegerLiteral_tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
-// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Int.Type
+// CHECK: [[METATYPE:%.*]] = metatype $@thin Int.Type
// CHECK-NEXT: [[VALUE:%.*]] = integer_literal $Builtin.Int2048, 2
+// CHECK: [[FN:%.*]] = function_ref @_T0S2iBi2048_22_builtinIntegerLiteral_tcfC : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
// CHECK-NEXT: [[LEFT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
-// CHECK: [[FN:%.*]] = function_ref @_T0S2dBf{{64|80}}_20_builtinFloatLiteral_tcfC : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Double.Type
// CHECK-NEXT: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x400C000000000000|0x4000E000000000000000}}
+// CHECK: [[FN:%.*]] = function_ref @_T0S2dBf{{64|80}}_20_builtinFloatLiteral_tcfC : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
// CHECK-NEXT: [[RIGHT:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE{{64|80}}, @thin Double.Type) -> Double
// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[LEFT]] : $Int, [[RIGHT]] : $Double)
// CHECK-NEXT: return [[RESULT]] : $(Int, Double)
diff --git a/test/SILGen/dynamic.swift b/test/SILGen/dynamic.swift
index 9cea33c..27414e3 100644
--- a/test/SILGen/dynamic.swift
+++ b/test/SILGen/dynamic.swift
@@ -334,13 +334,13 @@
}
// CHECK-LABEL: sil hidden @_T0So5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fC
- // CHECK: objc_method {{%.*}} : $@thick Gizmo.Type, #Gizmo.init!allocator.1.foreign
+ // 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 @_T0So5GizmoC7dynamicE{{[_0-9a-zA-Z]*}}fC
- // CHECK: objc_method {{%.*}} : $@thick Gizmo.Type, #Gizmo.init!allocator.1.foreign
+ // CHECK: objc_method {{%.*}} : $@objc_metatype Gizmo.Type, #Gizmo.init!allocator.1.foreign
convenience init(foreignClassExactFactory x: Int) {
self.init(exactlyStuff: x)
}
@@ -424,8 +424,8 @@
// CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.extensionProp!getter.1.foreign
_ = obj.extensionProp
- // CHECK: objc_method {{%.*}} : $@thick ObjCOtherFile.Type, #ObjCOtherFile.extensionClassProp!getter.1.foreign
- // CHECK-NEXT: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+ // 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
@@ -433,8 +433,8 @@
// CHECK: objc_method {{%.*}} : $ObjCOtherFile, #ObjCOtherFile.dynExtensionProp!getter.1.foreign
_ = obj.dynExtensionProp
- // CHECK: objc_method {{%.*}} : $@thick ObjCOtherFile.Type, #ObjCOtherFile.dynExtensionClassProp!getter.1.foreign
- // CHECK-NEXT: thick_to_objc_metatype {{%.*}} : $@thick ObjCOtherFile.Type to $@objc_metatype ObjCOtherFile.Type
+ // 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
}
diff --git a/test/SILGen/dynamic_lookup.swift b/test/SILGen/dynamic_lookup.swift
index 978a27c..92d9786 100644
--- a/test/SILGen/dynamic_lookup.swift
+++ b/test/SILGen/dynamic_lookup.swift
@@ -1,4 +1,5 @@
// 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 -enable-guaranteed-closure-contexts %s | %FileCheck %s --check-prefix=GUARANTEED
// REQUIRES: objc_interop
@@ -27,8 +28,7 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[OPENED_ARG:%[0-9]+]] = open_existential_ref [[BORROWED_ARG]] : $AnyObject to $@opened({{.*}}) AnyObject
// CHECK: [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
- // CHECK: [[BORROWED_OPENED_ARG_COPY:%.*]] = begin_borrow [[OPENED_ARG_COPY]]
- // CHECK: [[METHOD:%[0-9]+]] = objc_method [[BORROWED_OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #X.f!1.foreign : (X) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // 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]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -43,8 +43,7 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[OPENED_ARG:%[0-9]+]] = open_existential_ref [[BORROWED_ARG]] : $AnyObject to $@opened({{.*}}) AnyObject
// CHECK: [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
- // CHECK: [[BORROWED_OPENED_ARG_COPY:%.*]] = begin_borrow [[OPENED_ARG_COPY]]
- // CHECK: [[METHOD:%[0-9]+]] = objc_method [[BORROWED_OPENED_ARG_COPY]] : $@opened({{.*}}) AnyObject, #P.g!1.foreign : <Self where Self : P> (Self) -> () -> (), $@convention(objc_method) (@opened({{.*}}) AnyObject) -> ()
+ // 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]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -182,6 +181,34 @@
}
// CHECK: } // end sil function '_T014dynamic_lookup15opt_to_property{{[_0-9a-zA-Z]*}}F'
+// GUARANTEED-LABEL: sil hidden @_T014dynamic_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: [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
+ // GUARANTEED: [[OBJ_COPY:%.*]] = copy_value [[BORROWED_OBJ]]
+ // GUARANTEED: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // GUARANTEED: end_borrow [[BORROWED_OBJ]] from [[OBJ]]
+ // 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 @_T014dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F
func direct_to_subscript(_ obj: AnyObject, i: Int) {
var obj = obj
@@ -218,6 +245,39 @@
}
// CHECK: } // end sil function '_T014dynamic_lookup19direct_to_subscript{{[_0-9a-zA-Z]*}}F'
+// GUARANTEED-LABEL: sil hidden @_T014dynamic_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: [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
+ // GUARANTEED: [[OBJ_COPY:%.*]] = copy_value [[BORROWED_OBJ]]
+ // GUARANTEED: store [[OBJ_COPY]] to [init] [[PBOBJ]] : $*AnyObject
+ // GUARANTEED: end_borrow [[BORROWED_OBJ]] from [[OBJ]]
+ // 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 @_T014dynamic_lookup16opt_to_subscript{{[_0-9a-zA-Z]*}}F
func opt_to_subscript(_ obj: AnyObject, i: Int) {
var obj = obj
diff --git a/test/SILGen/dynamic_lookup_throws.swift b/test/SILGen/dynamic_lookup_throws.swift
index af96fda..29780ae 100644
--- a/test/SILGen/dynamic_lookup_throws.swift
+++ b/test/SILGen/dynamic_lookup_throws.swift
@@ -17,8 +17,7 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ANYOBJECT_REF:%.*]] = open_existential_ref [[BORROWED_ARG]] : $AnyObject to $@opened("[[OPENED:.*]]") AnyObject
// CHECK: [[ANYOBJECT_REF_COPY:%.*]] = copy_value [[ANYOBJECT_REF]]
- // CHECK: [[BORROWED_ANYOBJECT_REF_COPY:%.*]] = begin_borrow [[ANYOBJECT_REF_COPY]]
- // CHECK: objc_method [[BORROWED_ANYOBJECT_REF_COPY]] : $@opened("[[OPENED]]") AnyObject, #Blub.blub!1.foreign : (Blub) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @opened("[[OPENED]]") AnyObject) -> ObjCBool
+ // 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
diff --git a/test/SILGen/dynamic_self.swift b/test/SILGen/dynamic_self.swift
index 078fba2..0186d2b 100644
--- a/test/SILGen/dynamic_self.swift
+++ b/test/SILGen/dynamic_self.swift
@@ -43,9 +43,9 @@
// CHECK: [[BORROWED_Y_AS_X:%[0-9]+]] = upcast [[BORROWED_Y]] : $Y to $X
// CHECK: [[X_F:%[0-9]+]] = class_method [[BORROWED_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]]([[BORROWED_Y_AS_X]]) : $@convention(method) (@guaranteed X) -> @owned X
+// CHECK: end_borrow [[BORROWED_Y]] from [[Y]]
// CHECK: [[Y_RESULT:%[0-9]+]] = unchecked_ref_cast [[X_RESULT]] : $X to $Y
// CHECK: destroy_value [[Y_RESULT]] : $Y
-// CHECK: end_borrow [[BORROWED_Y]] from [[Y]]
// CHECK: destroy_value [[Y]] : $Y
func testDynamicSelfDispatch(y: Y) {
_ = y.f()
@@ -58,9 +58,9 @@
// CHECK: [[BORROWED_GY_AS_GX:%[0-9]+]] = upcast [[BORROWED_GY]] : $GY<Int> to $GX<Array<Int>>
// CHECK: [[GX_F:%[0-9]+]] = class_method [[BORROWED_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]>([[BORROWED_GY_AS_GX]]) : $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
+ // CHECK: end_borrow [[BORROWED_GY]] from [[GY]]
// CHECK: [[GY_RESULT:%[0-9]+]] = unchecked_ref_cast [[GX_RESULT]] : $GX<Array<Int>> to $GY<Int>
// CHECK: destroy_value [[GY_RESULT]] : $GY<Int>
- // CHECK: end_borrow [[BORROWED_GY]] from [[GY]]
// CHECK: destroy_value [[GY]]
_ = gy.f()
}
@@ -68,8 +68,8 @@
// CHECK-LABEL: sil hidden @_T012dynamic_self21testArchetypeDispatch{{[_0-9a-zA-Z]*}}F : $@convention(thin) <T where T : P> (@in T) -> ()
func testArchetypeDispatch<T: P>(t: T) {
// CHECK: bb0([[T:%[0-9]+]] : $*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: [[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()
}
@@ -128,8 +128,7 @@
// CHECK: bb0([[THICK_META:%[0-9]+]] : $@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: [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
-// CHECK: [[INIT:%[0-9]+]] = objc_method [[BORROWED_OBJ]] : $ObjCInit, #ObjCInit.init!initializer.1.foreign : (ObjCInit.Type) -> () -> ObjCInit, $@convention(objc_method) (@owned ObjCInit) -> @owned 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]] : $()
@@ -162,6 +161,7 @@
// CHECK: [[CAST_BORROWED_ARG:%.*]] = upcast [[BORROWED_ARG]]
// CHECK: [[T0:%.*]] = class_method [[CAST_BORROWED_ARG]] : $OptionalResult, #OptionalResult.foo!1 : (OptionalResult) -> () -> @dynamic_self OptionalResult?, $@convention(method) (@guaranteed OptionalResult) -> @owned Optional<OptionalResult>
// CHECK-NEXT: [[RES:%.*]] = apply [[T0]]([[CAST_BORROWED_ARG]])
+// CHECK-NEXT: end_borrow [[BORROWED_ARG]]
// CHECK-NEXT: [[T4:%.*]] = unchecked_ref_cast [[RES]] : $Optional<OptionalResult> to $Optional<OptionalResultInheritor>
func id<T>(_ t: T) -> T { return t }
diff --git a/test/SILGen/enum.swift b/test/SILGen/enum.swift
index 85fa5cb..1ffc32e 100644
--- a/test/SILGen/enum.swift
+++ b/test/SILGen/enum.swift
@@ -33,8 +33,8 @@
// CHECK-LABEL: sil hidden @_T0s16Optionable_casesySiF
func Optionable_cases(_ x: Int) {
+ // CHECK: [[METATYPE:%.*]] = metatype $@thin Optionable.Type
// CHECK: [[FN:%.*]] = function_ref @_T0s10OptionableO4mereABSicABmF
- // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Optionable.Type
// CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
// CHECK-NEXT: destroy_value [[CTOR]]
_ = Optionable.mere
@@ -67,8 +67,8 @@
// CHECK-LABEL: sil hidden @_T0s17AddressOnly_casesys1SVF
func AddressOnly_cases(_ s: S) {
+ // CHECK: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
// CHECK: [[FN:%.*]] = function_ref @_T0s11AddressOnlyO4mereABs1P_pcABmF
- // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin AddressOnly.Type
// CHECK-NEXT: [[CTOR:%.*]] = apply [[FN]]([[METATYPE]])
// CHECK-NEXT: destroy_value [[CTOR]]
_ = AddressOnly.mere
diff --git a/test/SILGen/enum_resilience.swift b/test/SILGen/enum_resilience.swift
index d586136..41a265e 100644
--- a/test/SILGen/enum_resilience.swift
+++ b/test/SILGen/enum_resilience.swift
@@ -52,3 +52,30 @@
// CHECK-LABEL: sil hidden @_T015enum_resilience21indirectResilientEnumy010resilient_A016IndirectApproachOF : $@convention(thin) (@in IndirectApproach) -> ()
func indirectResilientEnum(_ ia: IndirectApproach) {}
+
+public enum MyResilientEnum {
+ case kevin
+ case loki
+}
+
+// CHECK-LABEL: sil @_T015enum_resilience15resilientSwitchyAA15MyResilientEnumOF : $@convention(thin) (@in 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] @_T015enum_resilience16inlineableSwitchyAA15MyResilientEnumOF : $@convention(thin) (@in 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/errors.swift b/test/SILGen/errors.swift
index 3855c28..ff2ae57 100644
--- a/test/SILGen/errors.swift
+++ b/test/SILGen/errors.swift
@@ -14,8 +14,8 @@
func someValidPointer<T>() -> UnsafeMutablePointer<T> { fatalError() }
// CHECK: sil hidden @_T06errors10make_a_cat{{.*}}F : $@convention(thin) () -> (@owned Cat, @error Error) {
+// CHECK: [[T1:%.*]] = metatype $@thick Cat.Type
// CHECK: [[T0:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
-// CHECK-NEXT: [[T1:%.*]] = metatype $@thick Cat.Type
// CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]])
// CHECK-NEXT: return [[T2]] : $Cat
func make_a_cat() throws -> Cat {
@@ -49,8 +49,7 @@
// CHECK: sil hidden @_T06errors16all_together_nowAA3CatCSbF : $@convention(thin) (Bool) -> @owned Cat {
// CHECK: bb0(%0 : @trivial $Bool):
-// CHECK: [[DR_FN:%.*]] = function_ref @_T06errors11dont_return{{.*}} :
-// CHECK-NEXT: [[RET_TEMP:%.*]] = alloc_stack $Cat
+// CHECK: [[RET_TEMP:%.*]] = alloc_stack $Cat
// Branch on the flag.
// CHECK: cond_br {{%.*}}, [[FLAG_TRUE:bb[0-9]+]], [[FLAG_FALSE:bb[0-9]+]]
@@ -73,6 +72,7 @@
// CHECK: [[TERNARY_CONT]]([[T0:%.*]] : @owned $Cat):
// CHECK-NEXT: [[ARG_TEMP:%.*]] = alloc_stack $Cat
// CHECK-NEXT: store [[T0]] to [init] [[ARG_TEMP]]
+// CHECK: [[DR_FN:%.*]] = function_ref @_T06errors11dont_return{{.*}} :
// CHECK-NEXT: try_apply [[DR_FN]]<Cat>([[RET_TEMP]], [[ARG_TEMP]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[DR_NORMAL:bb[0-9]+]], error [[DR_ERROR:bb[0-9]+]]
// CHECK: [[DR_NORMAL]]({{%.*}} : @trivial $()):
// CHECK-NEXT: dealloc_stack [[ARG_TEMP]]
@@ -132,8 +132,8 @@
// Catch all.
// CHECK: [[CATCHALL]]:
-// CHECK: [[T0:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
// CHECK-NEXT: [[T1:%.*]] = metatype $@thick Cat.Type
+// CHECK: [[T0:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
// CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]])
// CHECK-NEXT: end_borrow [[BORROWED_ERROR]] from [[ERROR]]
// CHECK-NEXT: destroy_value [[ERROR]] : $Error
@@ -163,8 +163,8 @@
// Catch in non-throwing context.
// CHECK-LABEL: sil hidden @_T06errors11catch_a_catAA3CatCyF : $@convention(thin) () -> @owned Cat
// CHECK-NEXT: bb0:
-// CHECK: [[F:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
// CHECK-NEXT: [[M:%.*]] = metatype $@thick Cat.Type
+// CHECK: [[F:%.*]] = function_ref @_T06errors3Cat{{.*}} : $@convention(method) (@thick Cat.Type) -> @owned Cat
// CHECK-NEXT: [[V:%.*]] = apply [[F]]([[M]])
// CHECK-NEXT: return [[V]] : $Cat
func catch_a_cat() -> Cat {
@@ -323,9 +323,9 @@
}
// CHECK-LABEL: sil hidden @_T06errors12testForceTryySiycF : $@convention(thin) (@owned @noescape @callee_owned () -> Int) -> ()
// CHECK: bb0([[ARG:%.*]] : @owned $@noescape @callee_owned () -> Int):
-// CHECK: [[FUNC:%.*]] = function_ref @_T06errors9createIntySiycKF : $@convention(thin) (@owned @noescape @callee_owned () -> Int) -> @error Error
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+// CHECK: [[FUNC:%.*]] = function_ref @_T06errors9createIntySiycKF : $@convention(thin) (@owned @noescape @callee_owned () -> Int) -> @error Error
// CHECK: try_apply [[FUNC]]([[ARG_COPY]])
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: destroy_value [[ARG]]
@@ -423,7 +423,6 @@
// CHECK-LABEL: sil hidden @_T06errors13test_variadicyAA3CatCKF : $@convention(thin) (@owned Cat) -> @error Error {
// CHECK: bb0([[ARG:%.*]] : @owned $Cat):
// CHECK: debug_value undef : $Error, var, name "$error", argno 2
-// CHECK: [[TAKE_FN:%.*]] = function_ref @_T06errors14take_many_catsyAA3CatCd_tKF : $@convention(thin) (@owned Array<Cat>) -> @error Error
// CHECK: [[N:%.*]] = integer_literal $Builtin.Word, 4
// CHECK: [[T0:%.*]] = function_ref @_T0s27_allocateUninitializedArray{{.*}}F
// CHECK: [[T1:%.*]] = apply [[T0]]<Cat>([[N]])
@@ -462,6 +461,7 @@
// CHECK: [[NORM_3]]([[CAT3:%.*]] : @owned $Cat):
// CHECK-NEXT: store [[CAT3]] to [init] [[ELT3]]
// Complete the call and return.
+// CHECK: [[TAKE_FN:%.*]] = function_ref @_T06errors14take_many_catsyAA3CatCd_tKF : $@convention(thin) (@owned Array<Cat>) -> @error Error
// CHECK-NEXT: try_apply [[TAKE_FN]]([[ARRAY]]) : $@convention(thin) (@owned Array<Cat>) -> @error Error, normal [[NORM_CALL:bb[0-9]+]], error [[ERR_CALL:bb[0-9]+]]
// CHECK: [[NORM_CALL]]([[T0:%.*]] : @trivial $()):
// CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -544,7 +544,6 @@
try b.firstStructure.support()
}
// CHECK-LABEL: sil hidden @_T06errors21supportFirstStructure{{.*}}F : $@convention(thin) <B where B : Buildable> (@inout B) -> @error Error {
-// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
// CHECK: [[MATBUFFER:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK: [[BUFFER:%.*]] = alloc_stack $B.Structure
// CHECK: [[BUFFER_CAST:%.*]] = address_to_pointer [[BUFFER]] : $*B.Structure to $Builtin.RawPointer
@@ -554,6 +553,7 @@
// CHECK: [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
// CHECK: [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T4]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
@@ -575,7 +575,6 @@
}
// CHECK-LABEL: sil hidden @_T06errors16supportStructure{{.*}}F
// CHECK: bb0({{.*}}, [[INDEX:%.*]] : @owned $String):
-// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
// CHECK: [[BORROWED_INDEX:%.*]] = begin_borrow [[INDEX]]
// CHECK: [[INDEX_COPY:%.*]] = copy_value [[BORROWED_INDEX]] : $String
// CHECK: [[MATBUFFER:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
@@ -587,6 +586,7 @@
// CHECK: [[CALLBACK:%.*]] = tuple_extract [[T1]] : {{.*}}, 1
// CHECK: [[T3:%.*]] = pointer_to_address [[T2]] : $Builtin.RawPointer to [strict] $*B.Structure
// CHECK: [[T4:%.*]] = mark_dependence [[T3]] : $*B.Structure on [[BASE]] : $*B
+// CHECK: [[SUPPORT:%.*]] = witness_method $B.Structure, #Supportable.support!1 :
// CHECK: try_apply [[SUPPORT]]<B.Structure>([[T4]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
@@ -625,8 +625,7 @@
}
// CHECK: sil hidden @_T06errors16supportStructureyAA6BridgeVz_SS4nametKF : $@convention(thin) (@inout Bridge, @owned String) -> @error Error {
// CHECK: bb0([[ARG1:%.*]] : @trivial $*Bridge, [[ARG2:%.*]] : @owned $String):
-// CHECK: [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
-// CHECK-NEXT: [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
+// CHECK: [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
// CHECK-NEXT: [[INDEX_COPY_1:%.*]] = copy_value [[BORROWED_ARG2]] : $String
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*Bridge
// CHECK-NEXT: [[INDEX_COPY_2:%.*]] = copy_value [[INDEX_COPY_1]] : $String
@@ -637,6 +636,7 @@
// CHECK-NEXT: [[T0:%.*]] = apply [[GETTER]]([[INDEX_COPY_1]], [[BASE]])
// CHECK-NEXT: store [[T0]] to [init] [[TEMP]]
// CHECK-NEXT: end_borrow [[BASE]] from [[WRITE]]
+// CHECK: [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
// CHECK-NEXT: try_apply [[SUPPORT]]([[TEMP]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
@@ -681,7 +681,6 @@
}
// CHECK: sil hidden @_T06errors16supportStructureyAA11OwnedBridgeVz_SS4nametKF :
// CHECK: bb0([[ARG1:%.*]] : @trivial $*OwnedBridge, [[ARG2:%.*]] : @owned $String):
-// CHECK: [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
// CHECK: [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
// CHECK: [[ARG2_COPY:%.*]] = copy_value [[BORROWED_ARG2]] : $String
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*OwnedBridge
@@ -697,6 +696,7 @@
// CHECK-NEXT: [[T3:%.*]] = struct_extract [[T1]]
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK: [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
// CHECK-NEXT: try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
// CHECK-NEXT: end_access [[WRITE]]
@@ -725,7 +725,6 @@
}
// CHECK: sil hidden @_T06errors16supportStructureyAA12PinnedBridgeVz_SS4nametKF :
// CHECK: bb0([[ARG1:%.*]] : @trivial $*PinnedBridge, [[ARG2:%.*]] : @owned $String):
-// CHECK: [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
// CHECK: [[BORROWED_ARG2:%.*]] = begin_borrow [[ARG2]]
// CHECK: [[ARG2_COPY:%.*]] = copy_value [[BORROWED_ARG2]] : $String
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] [[ARG1]] : $*PinnedBridge
@@ -741,6 +740,7 @@
// CHECK-NEXT: [[T3:%.*]] = struct_extract [[T1]]
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[T5:%.*]] = mark_dependence [[T4]] : $*Pylon on [[OWNER]]
+// CHECK: [[SUPPORT:%.*]] = function_ref @_T06errors5PylonV7supportyyKF
// CHECK-NEXT: try_apply [[SUPPORT]]([[T5]]) : {{.*}}, normal [[BB_NORMAL:bb[0-9]+]], error [[BB_ERROR:bb[0-9]+]]
// CHECK: [[BB_NORMAL]]
// CHECK-NEXT: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>
@@ -828,9 +828,9 @@
// CHECK: bb0(%0 : @trivial $*T):
// CHECK: [[BOX:%.+]] = alloc_stack $Optional<T>
// CHECK-NEXT: [[BOX_DATA:%.+]] = init_enum_data_addr [[BOX]] : $*Optional<T>, #Optional.some!enumelt.1
-// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
// CHECK-NEXT: [[ARG_BOX:%.+]] = alloc_stack $T
// CHECK-NEXT: copy_addr %0 to [initialization] [[ARG_BOX]] : $*T
+// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
// CHECK-NEXT: try_apply [[FN]]<T>([[BOX_DATA]], [[ARG_BOX]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]],
// CHECK: [[SUCCESS]]({{%.+}} : @trivial $()):
// CHECK-NEXT: dealloc_stack [[ARG_BOX]] : $*T
@@ -859,9 +859,9 @@
// CHECK: [[BOX:%.+]] = alloc_box $<τ_0_0> { var Optional<τ_0_0> } <T>
// CHECK-NEXT: [[PB:%.*]] = project_box [[BOX]]
// CHECK-NEXT: [[BOX_DATA:%.+]] = init_enum_data_addr [[PB]] : $*Optional<T>, #Optional.some!enumelt.1
-// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
// CHECK-NEXT: [[ARG_BOX:%.+]] = alloc_stack $T
// CHECK-NEXT: copy_addr %0 to [initialization] [[ARG_BOX]] : $*T
+// CHECK: [[FN:%.+]] = function_ref @_T06errors11dont_return{{.*}}F
// CHECK-NEXT: try_apply [[FN]]<T>([[BOX_DATA]], [[ARG_BOX]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @error Error), normal [[SUCCESS:[^ ]+]], error [[CLEANUPS:[^ ]+]],
// CHECK: [[SUCCESS]]({{%.+}} : @trivial $()):
// CHECK-NEXT: dealloc_stack [[ARG_BOX]] : $*T
diff --git a/test/SILGen/existential_erasure.swift b/test/SILGen/existential_erasure.swift
index 0f3cba1..3b2eebb 100644
--- a/test/SILGen/existential_erasure.swift
+++ b/test/SILGen/existential_erasure.swift
@@ -44,11 +44,11 @@
// 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.downgrade!1 : {{.*}}, [[OPEN]]
// CHECK: [[FUNC:%.*]] = function_ref @_T019existential_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: destroy_addr %0
diff --git a/test/SILGen/expressions.swift b/test/SILGen/expressions.swift
index a6934c6..89ca6d4 100644
--- a/test/SILGen/expressions.swift
+++ b/test/SILGen/expressions.swift
@@ -108,9 +108,9 @@
}
// CHECK-LABEL: sil hidden @_T011expressions8call_oneyyF
-// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int) -> ()
// CHECK: [[FORTYTWO:%[0-9]+]] = integer_literal {{.*}} 42
// CHECK: [[FORTYTWO_CONVERTED:%[0-9]+]] = apply {{.*}}([[FORTYTWO]], {{.*}})
+// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int) -> ()
// CHECK: apply [[BAR]]([[FORTYTWO_CONVERTED]])
func call_two() {
@@ -118,11 +118,11 @@
}
// CHECK-LABEL: sil hidden @_T011expressions8call_twoyyF
-// CHECK: [[BAR:%[0-9]+]] = function_ref @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Int) -> ()
// 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 @_T011expressions3bar{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Int, Int) -> ()
// CHECK: apply [[BAR]]([[FORTYTWO_CONVERTED]], [[TWONINETEEN_CONVERTED]])
func tuples() {
@@ -206,21 +206,21 @@
// CHECK-LABEL: sil hidden @_T011expressions19call_default_args_1{{[_0-9a-zA-Z]*}}F
func call_default_args_1(_ x: Int) {
default_args(x)
- // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
// CHECK: [[YFUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}A0_
// CHECK: [[Y:%[0-9]+]] = apply [[YFUNC]]()
// CHECK: [[ZFUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}A1_
// CHECK: [[Z:%[0-9]+]] = apply [[ZFUNC]]()
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FUNC]]({{.*}}, [[Y]], [[Z]])
}
// CHECK-LABEL: sil hidden @_T011expressions19call_default_args_2{{[_0-9a-zA-Z]*}}F
func call_default_args_2(_ x: Int, z: Int) {
default_args(x, z:z)
- // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
// CHECK: [[DEFFN:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}A0_
// CHECK-NEXT: [[C219:%[0-9]+]] = apply [[DEFFN]]()
- // CHECK: apply [[FUNC]]({{.*}}, [[C219]], {{.*}})
+ // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T011expressions12default_args{{[_0-9a-zA-Z]*}}F
+ // CHECK-NEXT: apply [[FUNC]]({{.*}}, [[C219]], {{.*}})
}
struct Generic<T> {
@@ -336,20 +336,20 @@
func archetype_member_ref<T : Runcible>(_ x: T) {
var x = x
x.free_method()
- // CHECK: witness_method $T, #Runcible.free_method!1
- // CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[X:%.*]]
+ // 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: witness_method $T, #Runcible.associated_method!1
- // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown]
+ // CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown]
+ // CHECK-NEXT: witness_method $T, #Runcible.associated_method!1
// CHECK-NEXT: apply
T.static_method()
- // CHECK: witness_method $T, #Runcible.static_method!1
- // CHECK-NEXT: metatype $@thick T.Type
+ // CHECK: metatype $@thick T.Type
+ // CHECK-NEXT: witness_method $T, #Runcible.static_method!1
// CHECK-NEXT: apply
}
diff --git a/test/SILGen/extensions.swift b/test/SILGen/extensions.swift
index 190c8eb..aa1fe8f 100644
--- a/test/SILGen/extensions.swift
+++ b/test/SILGen/extensions.swift
@@ -44,8 +44,8 @@
// CHECK-LABEL: sil hidden [transparent] @_T010extensions3BoxV1txSgvpfi : $@convention(thin) <T> () -> @out Optional<T>
// CHECK: bb0(%0 : @trivial $*Optional<T>):
-// CHECK: [[FN:%.*]] = function_ref @_T0SqxSgyt10nilLiteral_tcfC : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Optional<T>.Type
+// CHECK: [[FN:%.*]] = function_ref @_T0SqxSgyt10nilLiteral_tcfC : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
// CHECK-NEXT: apply [[FN]]<T>(%0, [[METATYPE]]) : $@convention(method) <τ_0_0> (@thin Optional<τ_0_0>.Type) -> @out Optional<τ_0_0>
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
// CHECK-NEXT: return [[RESULT]] : $()
diff --git a/test/SILGen/external_definitions.swift b/test/SILGen/external_definitions.swift
index 954b796..fb679f1 100644
--- a/test/SILGen/external_definitions.swift
+++ b/test/SILGen/external_definitions.swift
@@ -12,10 +12,10 @@
// CHECK-LABEL: sil @main
// -- Foreign function is referenced with C calling conv and ownership semantics
-// CHECK: [[NSANSE:%.*]] = function_ref @NSAnse : $@convention(c) (Optional<Ansible>) -> @autoreleased Optional<Ansible>
-// CHECK: [[ANSIBLE_CTOR:%.*]] = function_ref @_T0So7AnsibleC{{[_0-9a-zA-Z]*}}fC
// CHECK: [[NSOBJECT_CTOR:%.*]] = function_ref @_T0So8NSObjectC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick NSObject.Type) -> @owned NSObject
+// CHECK: [[ANSIBLE_CTOR:%.*]] = function_ref @_T0So7AnsibleC{{[_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
@@ -24,13 +24,12 @@
// CHECK: [[NOPROTO:%.*]] = function_ref @hasNoPrototype : $@convention(c) () -> ()
// CHECK: apply [[NOPROTO]]()
-// -- Constructors for imported Ansible
-// CHECK-LABEL: sil shared [serializable] @_T0So7AnsibleC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@in Optional<Any>, @thick Ansible.Type) -> @owned Optional<Ansible>
-
-
// -- Constructors for imported NSObject
// CHECK-LABEL: sil shared [serializable] @_T0So8NSObjectC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick NSObject.Type) -> @owned NSObject
+// -- Constructors for imported Ansible
+// CHECK-LABEL: sil shared [serializable] @_T0So7AnsibleC{{[_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] @_T0SC6NSAnseSQySo7AnsibleCGADFTO : $@convention(thin) (@owned Optional<Ansible>) -> @owned Optional<Ansible> {
// CHECK: bb0(%0 : @owned $Optional<Ansible>):
diff --git a/test/SILGen/final.swift b/test/SILGen/final.swift
index a6c6618..a25edc7 100644
--- a/test/SILGen/final.swift
+++ b/test/SILGen/final.swift
@@ -20,8 +20,8 @@
// CHECK-LABEL: sil hidden @{{.*}}testDirectDispatch{{.*}} : $@convention(thin) (@owned TestClass) -> Int {
// CHECK: bb0([[ARG:%.*]] : @owned $TestClass):
-// CHECK: [[FINALMETH:%[0-9]+]] = function_ref @_T05final9TestClassC0A6Method{{[_0-9a-zA-Z]*}}F
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+// CHECK: [[FINALMETH:%[0-9]+]] = function_ref @_T05final9TestClassC0A6Method{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FINALMETH]]([[BORROWED_ARG]])
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
diff --git a/test/SILGen/force_cast_chained_optional.swift b/test/SILGen/force_cast_chained_optional.swift
index 29cff95..c5ae257 100644
--- a/test/SILGen/force_cast_chained_optional.swift
+++ b/test/SILGen/force_cast_chained_optional.swift
@@ -26,7 +26,6 @@
// 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: [[BORROWED_BAR:%.*]] = begin_borrow [[BAR]]
// CHECK: apply [[METHOD]]([[BORROWED_BAR]])
// CHECK: end_borrow [[BORROWED_BAR]] from [[BAR]]
// CHECK: unconditional_checked_cast {{%.*}} : $C to $D
diff --git a/test/SILGen/foreach.swift b/test/SILGen/foreach.swift
index 10a096d..bcbdbc9 100644
--- a/test/SILGen/foreach.swift
+++ b/test/SILGen/foreach.swift
@@ -109,17 +109,17 @@
// CHECK: bb0([[ARRAY:%.*]] : @owned $Array<Int>):
// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<Int>> }, var, name "$x$generator"
// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
-// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
// CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<Int>
// CHECK: store_borrow [[BORROWED_ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@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: [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
// 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 @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@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]+]]
@@ -214,17 +214,17 @@
// CHECK: bb0([[ARRAY:%.*]] : @owned $Array<P>):
// CHECK: [[ITERATOR_BOX:%.*]] = alloc_box ${ var IndexingIterator<Array<P>> }, var, name "$x$generator"
// CHECK: [[PROJECT_ITERATOR_BOX:%.*]] = project_box [[ITERATOR_BOX]]
-// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
// CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<P>
// CHECK: store_borrow [[BORROWED_ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@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: [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<P>> // users: %16, %15
+// CHECK: [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@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]+]]
//
@@ -379,17 +379,17 @@
// CHECK: bb0([[ARRAY:%.*]] : @owned $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: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in_guaranteed τ_0_0) -> @out IndexingIterator<τ_0_0>
// CHECK: [[BORROWED_ARRAY:%.*]] = begin_borrow [[ARRAY]]
// CHECK: [[BORROWED_ARRAY_STACK:%.*]] = alloc_stack $Array<GenericStruct<T>>
// CHECK: store_borrow [[BORROWED_ARRAY]] to [[BORROWED_ARRAY_STACK]]
+// CHECK: [[MAKE_ITERATOR_FUNC:%.*]] = function_ref @_T0s10CollectionPss16IndexingIteratorVyxG0C0RtzrlE04makeC0AEyF : $@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: [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@convention(method)
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PROJECT_ITERATOR_BOX]] : $*IndexingIterator<Array<GenericStruct<T>>>
+// CHECK: [[FUNC_REF:%.*]] = function_ref @_T0s16IndexingIteratorV4next7ElementQzSgyF : $@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]+]]
//
@@ -498,8 +498,8 @@
// CHECK: br [[LOOP_DEST:bb[0-9]+]]
//
// CHECK: [[LOOP_DEST]]:
-// 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: [[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]+]]
//
diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift
index a3ed901..5b01bef 100644
--- a/test/SILGen/foreign_errors.swift
+++ b/test/SILGen/foreign_errors.swift
@@ -7,16 +7,14 @@
import Foundation
import errors
-// CHECK: sil hidden @_T014foreign_errors5test0yyKF : $@convention(thin) () -> @error Error
+// CHECK-LABEL: sil hidden @_T014foreign_errors5test0yyKF : $@convention(thin) () -> @error Error
func test0() throws {
- // CHECK: [[SELF:%.*]] = metatype $@thick ErrorProne.Type
- // CHECK: [[METHOD:%.*]] = objc_method [[SELF]] : $@thick ErrorProne.Type, #ErrorProne.fail!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
-
// 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: [[OBJC_SELF:%.*]] = thick_to_objc_metatype [[SELF]]
+ // 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>
@@ -26,7 +24,7 @@
// CHECK: address_to_pointer [[ERR_TEMP1]]
// Call the method.
- // CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{.*}}, [[OBJC_SELF]])
+ // CHECK: [[RESULT:%.*]] = apply [[METHOD]]({{.*}}, [[SELF]])
// Writeback to the first temporary.
// CHECK: [[T0:%.*]] = load [trivial] [[ERR_TEMP1]]
@@ -73,9 +71,9 @@
// CHECK: [[T0:%.*]] = function_ref @swift_convertErrorToNSError : $@convention(thin) (@owned Error) -> @owned NSError
// CHECK: [[T1:%.*]] = apply [[T0]]([[ERR]])
// CHECK: [[OBJCERR:%.*]] = enum $Optional<NSError>, #Optional.some!enumelt.1, [[T1]] : $NSError
-// CHECK: [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
// CHECK: [[TEMP:%.*]] = alloc_stack $Optional<NSError>
// CHECK: store [[OBJCERR]] to [init] [[TEMP]]
+// CHECK: [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
// CHECK: apply [[SETTER]]<Optional<NSError>>([[TEMP]], [[UNWRAPPED_OUT]])
// CHECK: dealloc_stack [[TEMP]]
// CHECK: br bb5
@@ -116,9 +114,9 @@
// CHECK: [[T0:%.*]] = function_ref @swift_convertErrorToNSError : $@convention(thin) (@owned Error) -> @owned NSError
// CHECK: [[T1:%.*]] = apply [[T0]]([[ERR]])
// CHECK: [[OBJCERR:%.*]] = enum $Optional<NSError>, #Optional.some!enumelt.1, [[T1]] : $NSError
-// CHECK: [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
// CHECK: [[TEMP:%.*]] = alloc_stack $Optional<NSError>
// CHECK: store [[OBJCERR]] to [init] [[TEMP]]
+// CHECK: [[SETTER:%.*]] = function_ref @_T0s33AutoreleasingUnsafeMutablePointerV7pointeexvs :
// CHECK: apply [[SETTER]]<Optional<NSError>>([[TEMP]], [[UNWRAPPED_OUT]])
// CHECK: dealloc_stack [[TEMP]]
// CHECK: br bb5
@@ -167,16 +165,16 @@
func testArgs() throws {
try ErrorProne.consume(nil)
}
-// CHECK: sil hidden @_T014foreign_errors8testArgsyyKF : $@convention(thin) () -> @error Error
+// CHECK-LABEL: sil hidden @_T014foreign_errors8testArgsyyKF : $@convention(thin) () -> @error Error
// CHECK: debug_value undef : $Error, var, name "$error", argno 1
-// CHECK: objc_method %1 : $@thick ErrorProne.Type, #ErrorProne.consume!1.foreign : (ErrorProne.Type) -> (Any!) throws -> (), $@convention(objc_method) (Optional<AnyObject>, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> ObjCBool
+// 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 @_T014foreign_errors17testBridgedResultyyKF : $@convention(thin) () -> @error Error {
// CHECK: debug_value undef : $Error, var, name "$error", argno 1
-// CHECK: objc_method %1 : $@thick 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>
+// 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.
@@ -198,14 +196,14 @@
// CHECK: store [[ARG2]] to [init] [[PB]]
// CHECK: [[T0:%.*]] = load [take] [[PB]]
// CHECK-NEXT: [[T1:%.*]] = upcast [[T0]] : $VeryErrorProne to $ErrorProne
-// CHECK-NEXT: [[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: [[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
@@ -229,17 +227,17 @@
class ExtremelyErrorProne : ErrorProne {
override func conflict3(_ obj: Any, error: ()) throws {}
}
-// CHECK: sil hidden @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKF
-// CHECK: sil hidden [thunk] @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKFTo : $@convention(objc_method) (AnyObject, Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, ExtremelyErrorProne) -> ObjCBool
+// CHECK-LABEL: sil hidden @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKF
+// CHECK-LABEL: sil hidden [thunk] @_T014foreign_errors19ExtremelyErrorProneC9conflict3yyp_yt5errortKFTo : $@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: sil hidden @_T014foreign_errors15testNonNilErrorSfyKF :
-// CHECK: [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.bounce!1.foreign : (ErrorProne.Type) -> () throws -> Float, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Float
+// CHECK-LABEL: sil hidden @_T014foreign_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]]
@@ -252,10 +250,10 @@
func testPreservedResult() throws -> CInt {
return try ErrorProne.ounce()
}
-// CHECK: sil hidden @_T014foreign_errors19testPreservedResults5Int32VyKF
-// CHECK: [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.ounce!1.foreign : (ErrorProne.Type) -> () throws -> Int32, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
+// CHECK-LABEL: sil hidden @_T014foreign_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
@@ -271,9 +269,9 @@
}
// CHECK-LABEL: sil hidden @_T014foreign_errors26testPreservedResultBridgedSiyKF
-// CHECK: [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.ounceWord!1.foreign : (ErrorProne.Type) -> () throws -> Int, $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int
// 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
@@ -289,9 +287,9 @@
}
// CHECK-LABEL: sil hidden @_T014foreign_errors27testPreservedResultInvertedyyKF
-// CHECK: [[T0:%.*]] = metatype $@thick ErrorProne.Type
-// CHECK: [[T1:%.*]] = objc_method [[T0]] : $@thick ErrorProne.Type, #ErrorProne.once!1.foreign : (ErrorProne.Type) -> () throws -> (), $@convention(objc_method) (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, @objc_metatype ErrorProne.Type) -> Int32
// 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
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index d510fe5..d8d9294 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -109,23 +109,23 @@
// CHECK: [[KBOX:%[0-9]+]] = alloc_box ${ var Builtin.Int64 }
// CHECK: [[KADDR:%.*]] = project_box [[KBOX]]
- // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T09functions19standalone_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) (Builtin.Int64, Builtin.Int64) -> Builtin.Int64
// 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 @_T09functions19standalone_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: [[CTOR:%.*]] = function_ref @_T09functions10SomeStructV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thin SomeStruct.Type) -> 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 @_T09functions10SomeStructV{{[_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)
@@ -140,22 +140,21 @@
// CHECK: [[CBOX:%[0-9]+]] = alloc_box ${ var SomeClass }
// CHECK: [[CADDR:%.*]] = project_box [[CBOX]]
- // CHECK: [[FUNC:%[0-9]+]] = function_ref @_T09functions9SomeClassC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (Builtin.Int64, Builtin.Int64, @thick SomeClass.Type) -> @owned SomeClass
// 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 @_T09functions9SomeClassC{{[_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: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
- // 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]]
@@ -170,10 +169,9 @@
// CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
// CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
// CHECK: [[BORROWED_C:%.*]] = begin_borrow [[C]]
- // CHECK: [[METHOD:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.method!1
- // 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]]
@@ -184,9 +182,9 @@
// CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
// CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
// CHECK: [[META:%.*]] = value_metatype $@thick SomeClass.Type, [[C]]
- // CHECK: [[METHOD:%[0-9]+]] = class_method [[META]] : {{.*}}, #SomeClass.static_method!1
// 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)
@@ -195,8 +193,8 @@
// -- FIXME: class_method-ify class getters.
// CHECK: [[READC:%.*]] = begin_access [read] [unknown] [[CADDR]]
// CHECK: [[C:%[0-9]+]] = load [copy] [[READC]]
- // CHECK: [[GETTER:%[0-9]+]] = class_method {{.*}} : $SomeClass, #SomeClass.someProperty!getter.1
// 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]]
@@ -208,7 +206,6 @@
// 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: [[BORROWED_C:%.*]] = begin_borrow [[C]]
// CHECK: apply [[SETTER]]([[I]], [[BORROWED_C]])
// CHECK: end_borrow [[BORROWED_C]] from [[C]]
// CHECK: destroy_value [[C]]
@@ -222,7 +219,6 @@
// 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: [[BORROWED_C:%.*]] = begin_borrow [[C]]
// CHECK: apply [[GETTER]]([[J]], [[K]], [[BORROWED_C]])
// CHECK: end_borrow [[BORROWED_C]] from [[C]]
// CHECK: destroy_value [[C]]
@@ -238,7 +234,6 @@
// 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: [[BORROWED_C:%.*]] = begin_borrow [[C]]
// CHECK: apply [[SETTER]]([[K]], [[I]], [[J]], [[BORROWED_C]])
// CHECK: end_borrow [[BORROWED_C]] from [[C]]
// CHECK: destroy_value [[C]]
@@ -255,18 +250,18 @@
// 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: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
// 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: [[PMETHOD:%[0-9]+]] = witness_method $[[OPENED]], #SomeProtocol.method!1
// 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)
@@ -281,42 +276,39 @@
// CHECK: [[GBOX:%[0-9]+]] = alloc_box ${ var SomeGeneric<Builtin.Int64> }
// CHECK: [[GADDR:%.*]] = project_box [[GBOX]]
- // CHECK: [[CTOR_GEN:%[0-9]+]] = function_ref @_T09functions11SomeGenericC{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@thick SomeGeneric<τ_0_0>.Type) -> @owned SomeGeneric<τ_0_0>
// CHECK: [[META:%[0-9]+]] = metatype $@thick SomeGeneric<Builtin.Int64>.Type
+ // CHECK: [[CTOR_GEN:%[0-9]+]] = function_ref @_T09functions11SomeGenericC{{[_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: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.method!1
- // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
- // 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: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_G]] : {{.*}}, #SomeGeneric.generic!1
- // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
- // 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: [[METHOD_GEN:%[0-9]+]] = class_method [[BORROWED_C]] : {{.*}}, #SomeClass.generic!1
- // CHECK: [[TMPR:%.*]] = alloc_stack $Builtin.Int64
- // 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]]
@@ -350,7 +342,6 @@
// CHECK: apply [[F]]([[I]], [[J]])
f(i, j)
- // CHECK: [[HOF:%[0-9]+]] = function_ref @_T09functions21higher_order_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_T09functions19standalone_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_function [[FUNC_THICK]]
@@ -358,10 +349,10 @@
// 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 @_T09functions21higher_order_function{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
// CHECK: apply [[HOF]]([[CONVERT]], [[I]], [[J]])
higher_order_function(standalone_function, i, j)
- // CHECK: [[HOF2:%[0-9]+]] = function_ref @_T09functions22higher_order_function2{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
// CHECK: [[FUNC_THIN:%[0-9]+]] = function_ref @_T09functions19standalone_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_function [[FUNC_THICK]]
@@ -369,6 +360,7 @@
// 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 @_T09functions22higher_order_function2{{[_0-9a-zA-Z]*}}F : $@convention(thin) {{.*}}
// CHECK: apply [[HOF2]]([[CONVERT]], [[I]], [[J]])
higher_order_function2(standalone_function, i, j)
}
@@ -460,6 +452,37 @@
func alwaysInlined() {}
}
+// CHECK-LABEL: sil hidden [Onone] @_T09functions10onone_funcyyF : $@convention(thin) () -> ()
+@_optimize(none)
+func onone_func() {}
+
+// CHECK-LABEL: sil hidden [Ospeed] @_T09functions11ospeed_funcyyF : $@convention(thin) () -> ()
+@_optimize(speed)
+func ospeed_func() {}
+
+// CHECK-LABEL: sil hidden [Osize] @_T09functions10osize_funcyyF : $@convention(thin) () -> ()
+@_optimize(size)
+func osize_func() {}
+
+struct OptmodeTestStruct {
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructV3fooyyF :
+ @_optimize(speed)
+ func foo() { }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructVACycfC :
+ @_optimize(speed)
+ init() { }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructV1xBi64_vg :
+ @_optimize(speed)
+ var x: Int { return getInt() }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructVBi64_Bi64_cig :
+ @_optimize(speed)
+ subscript(l: Int) -> Int { return getInt() }
+}
+
// CHECK-LABEL: sil hidden [_semantics "foo"] @_T09functions9semanticsyyF : $@convention(thin) () -> ()
@_semantics("foo")
func semantics() {}
diff --git a/test/SILGen/generic_literals.swift b/test/SILGen/generic_literals.swift
index 5607de8..d0af2f4 100644
--- a/test/SILGen/generic_literals.swift
+++ b/test/SILGen/generic_literals.swift
@@ -3,14 +3,14 @@
// CHECK-LABEL: sil hidden @_T016generic_literals0A14IntegerLiteralyx1x_ts013ExpressibleBycD0RzlF
func genericIntegerLiteral<T : ExpressibleByIntegerLiteral>(x: T) {
var x = x
- // CHECK: [[TCONV:%.*]] = witness_method $T, #ExpressibleByIntegerLiteral.init!allocator.1
// CHECK: [[ADDR:%.*]] = alloc_stack $T
// CHECK: [[TMETA:%.*]] = metatype $@thick T.Type
- // CHECK: [[BUILTINCONV:%.*]] = witness_method $T.IntegerLiteralType, #_ExpressibleByBuiltinIntegerLiteral.init!allocator.1
// CHECK: [[LITVAR:%.*]] = alloc_stack $T.IntegerLiteralType
// CHECK: [[LITMETA:%.*]] = metatype $@thick T.IntegerLiteralType.Type
// CHECK: [[INTLIT:%.*]] = integer_literal $Builtin.Int2048, 17
+ // CHECK: [[BUILTINCONV:%.*]] = witness_method $T.IntegerLiteralType, #_ExpressibleByBuiltinIntegerLiteral.init!allocator.1
// CHECK: [[LIT:%.*]] = apply [[BUILTINCONV]]<T.IntegerLiteralType>([[LITVAR]], [[INTLIT]], [[LITMETA]]) : $@convention(witness_method: _ExpressibleByBuiltinIntegerLiteral) <τ_0_0 where τ_0_0 : _ExpressibleByBuiltinIntegerLiteral> (Builtin.Int2048, @thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK: [[TCONV:%.*]] = witness_method $T, #ExpressibleByIntegerLiteral.init!allocator.1
// CHECK: apply [[TCONV]]<T>([[ADDR]], [[LITVAR]], [[TMETA]]) : $@convention(witness_method: ExpressibleByIntegerLiteral) <τ_0_0 where τ_0_0 : ExpressibleByIntegerLiteral> (@in τ_0_0.IntegerLiteralType, @thick τ_0_0.Type) -> @out τ_0_0
x = 17
@@ -19,14 +19,14 @@
// CHECK-LABEL: sil hidden @_T016generic_literals0A15FloatingLiteral{{[_0-9a-zA-Z]*}}F
func genericFloatingLiteral<T : ExpressibleByFloatLiteral>(x: T) {
var x = x
- // CHECK: [[CONV:%.*]] = witness_method $T, #ExpressibleByFloatLiteral.init!allocator.1
// CHECK: [[TVAL:%.*]] = alloc_stack $T
// CHECK: [[TMETA:%.*]] = metatype $@thick T.Type
- // CHECK: [[BUILTIN_CONV:%.*]] = witness_method $T.FloatLiteralType, #_ExpressibleByBuiltinFloatLiteral.init!allocator.1
// CHECK: [[FLT_VAL:%.*]] = alloc_stack $T.FloatLiteralType
// CHECK: [[TFLT_META:%.*]] = metatype $@thick T.FloatLiteralType.Type
// CHECK: [[LIT_VALUE:%.*]] = float_literal $Builtin.FPIEEE{{64|80}}, {{0x4004000000000000|0x4000A000000000000000}}
+ // CHECK: [[BUILTIN_CONV:%.*]] = witness_method $T.FloatLiteralType, #_ExpressibleByBuiltinFloatLiteral.init!allocator.1
// CHECK: apply [[BUILTIN_CONV]]<T.FloatLiteralType>([[FLT_VAL]], [[LIT_VALUE]], [[TFLT_META]]) : $@convention(witness_method: _ExpressibleByBuiltinFloatLiteral) <τ_0_0 where τ_0_0 : _ExpressibleByBuiltinFloatLiteral> (Builtin.FPIEEE{{64|80}}, @thick τ_0_0.Type) -> @out τ_0_0
+ // CHECK: [[CONV:%.*]] = witness_method $T, #ExpressibleByFloatLiteral.init!allocator.1
// CHECK: apply [[CONV]]<T>([[TVAL]], [[FLT_VAL]], [[TMETA]]) : $@convention(witness_method: ExpressibleByFloatLiteral) <τ_0_0 where τ_0_0 : ExpressibleByFloatLiteral> (@in τ_0_0.FloatLiteralType, @thick τ_0_0.Type) -> @out τ_0_0
x = 2.5
diff --git a/test/SILGen/generic_property_base_lifetime.swift b/test/SILGen/generic_property_base_lifetime.swift
index 016fb43..6ea050c 100644
--- a/test/SILGen/generic_property_base_lifetime.swift
+++ b/test/SILGen/generic_property_base_lifetime.swift
@@ -18,8 +18,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[PROJECTION:%.*]] = open_existential_ref [[BORROWED_ARG]]
// CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
-// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!getter.1 : {{.*}}, [[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]]
@@ -36,8 +36,8 @@
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[PROJECTION:%.*]] = open_existential_ref [[BORROWED_ARG]]
// CHECK: [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
-// CHECK: [[WITNESS_METHOD:%.*]] = witness_method $@opened({{.*}}) ProtocolA, #ProtocolA.intProp!setter.1 : {{.*}}, [[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]]
diff --git a/test/SILGen/guaranteed_self.swift b/test/SILGen/guaranteed_self.swift
index d9c33c9..db83215 100644
--- a/test/SILGen/guaranteed_self.swift
+++ b/test/SILGen/guaranteed_self.swift
@@ -492,9 +492,9 @@
// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[KRAKEN_ADDR]] : $*Kraken
// CHECK-NEXT: [[KRAKEN:%.*]] = load [copy] [[READ]]
// CHECK-NEXT: end_access [[READ]] : $*Kraken
- // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
- // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+ // CHECK: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
// CHECK-NEXT: [[KRAKEN_COPY:%.*]] = copy_value [[BORROWED_KRAKEN]]
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
// CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
// CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
// CHECK-NEXT: [[KRAKEN_BOX:%.*]] = alloc_box ${ var Kraken }
@@ -504,10 +504,10 @@
// CHECK-NEXT: [[KRAKEN2:%.*]] = load [copy] [[READ]]
// CHECK-NEXT: end_access [[READ]] : $*Kraken
// CHECK-NEXT: store [[KRAKEN2]] to [init] [[PB]]
- // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
// CHECK-NEXT: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*Kraken
// CHECK-NEXT: [[KRAKEN_COPY:%.*]] = load [copy] [[READ]]
// CHECK-NEXT: end_access [[READ]] : $*Kraken
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
// CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
// CHECK-NEXT: destroy_value [[KRAKEN_BOX]]
// CHECK-NEXT: destroy_value [[KRAKEN]]
@@ -527,16 +527,14 @@
// 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: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
- // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[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: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
- // CHECK-NEXT: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
+ // CHECK: [[BORROWED_KRAKEN:%.*]] = begin_borrow [[KRAKEN]]
// CHECK-NEXT: [[KRAKEN_COPY:%.*]] = copy_value [[BORROWED_KRAKEN]]
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
// CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
// CHECK-NEXT: end_borrow [[BORROWED_KRAKEN]] from [[KRAKEN]]
// CHECK-NEXT: [[KRAKEN_BOX:%.*]] = alloc_box ${ var Kraken }
@@ -544,10 +542,10 @@
// 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: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [read] [unknown] [[PB]] : $*Kraken
// CHECK-NEXT: [[KRAKEN_COPY:%.*]] = load [copy] [[WRITE]]
// CHECK-NEXT: end_access [[WRITE]] : $*Kraken
+ // CHECK: [[DESTROY_SHIP_FUN:%.*]] = function_ref @_T015guaranteed_self11destroyShipyAA6KrakenCF : $@convention(thin) (@owned Kraken) -> ()
// CHECK-NEXT: apply [[DESTROY_SHIP_FUN]]([[KRAKEN_COPY]])
// CHECK-NEXT: destroy_value [[KRAKEN_BOX]]
// CHECK-NEXT: destroy_value [[KRAKEN]]
diff --git a/test/SILGen/if_while_binding.swift b/test/SILGen/if_while_binding.swift
index c2d6a33..2df545e 100644
--- a/test/SILGen/if_while_binding.swift
+++ b/test/SILGen/if_while_binding.swift
@@ -22,9 +22,9 @@
// CHECK: br [[CONT:bb[0-9]+]]
if let x = foo() {
// CHECK: [[YES]]([[VAL:%[0-9]+]] : @owned $String):
- // CHECK: [[A:%.*]] = function_ref @_T016if_while_binding1a
// CHECK: [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]]
// CHECK: [[VAL_COPY:%.*]] = copy_value [[BORROWED_VAL]]
+ // CHECK: [[A:%.*]] = function_ref @_T016if_while_binding1a
// CHECK: apply [[A]]([[VAL_COPY]])
// CHECK: end_borrow [[BORROWED_VAL]] from [[VAL]]
// CHECK: destroy_value [[VAL]]
@@ -47,9 +47,9 @@
//
// CHECK: [[YESX]]([[VAL:%[0-9]+]] : @owned $String):
// CHECK: debug_value [[VAL]] : $String, let, name "x"
- // CHECK: [[A:%.*]] = function_ref @_T016if_while_binding1a
// CHECK: [[BORROWED_VAL:%.*]] = begin_borrow [[VAL]]
// CHECK: [[VAL_COPY:%.*]] = copy_value [[BORROWED_VAL]]
+ // CHECK: [[A:%.*]] = function_ref @_T016if_while_binding1a
// CHECK: apply [[A]]([[VAL_COPY]])
// CHECK: end_borrow [[BORROWED_VAL]] from [[VAL]]
// CHECK: destroy_value [[VAL]]
@@ -286,7 +286,8 @@
// CHECK: debug_value %0 : $Int, let, name "a"
// CHECK: [[EQRESULT:%[0-9]+]] = apply {{.*}}(%0, %0{{.*}}) : $@convention({{.*}}) (Int, Int{{.*}}) -> Bool
- // CHECK-NEXT: [[EQRESULTI1:%[0-9]+]] = apply %2([[EQRESULT]]) : $@convention(method) (Bool) -> Builtin.Int1
+ // 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.
diff --git a/test/SILGen/import_as_member.swift b/test/SILGen/import_as_member.swift
index 868d379..6d4154a 100644
--- a/test/SILGen/import_as_member.swift
+++ b/test/SILGen/import_as_member.swift
@@ -45,8 +45,8 @@
// CHECK: [[OBJ:%[0-9]+]] = apply [[CTOR]]([[D]])
let o = SomeClass(value: d)
- // CHECK: [[APPLY_FN:%[0-9]+]] = function_ref @IAMSomeClassApplyOptions : $@convention(c) (SomeClass, SomeClass.Options) -> ()
// CHECK: [[BORROWED_OBJ:%.*]] = begin_borrow [[OBJ]]
+ // CHECK: [[APPLY_FN:%[0-9]+]] = function_ref @IAMSomeClassApplyOptions : $@convention(c) (SomeClass, SomeClass.Options) -> ()
// CHECK: apply [[APPLY_FN]]([[BORROWED_OBJ]], [[OPTS]])
// CHECK: end_borrow [[BORROWED_OBJ]] from [[OBJ]]
// CHECK: destroy_value [[OBJ]]
diff --git a/test/SILGen/init_ref_delegation.swift b/test/SILGen/init_ref_delegation.swift
index 1059dd2..758a58c 100644
--- a/test/SILGen/init_ref_delegation.swift
+++ b/test/SILGen/init_ref_delegation.swift
@@ -10,11 +10,11 @@
// CHECK-NEXT: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var S }
// CHECK-NEXT: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
// CHECK-NEXT: [[PB:%.*]] = project_box [[MARKED_SELF_BOX]]
- // CHECK: [[S_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin S.Type) -> S
- // CHECK: [[X_CTOR:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK-NEXT: [[X_META:%[0-9]+]] = metatype $@thin X.Type
+ // CHECK: [[X_CTOR:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK-NEXT: [[X:%[0-9]+]] = apply [[X_CTOR]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
+ // CHECK: [[S_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1SV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin S.Type) -> S
// CHECK-NEXT: [[REPLACEMENT_SELF:%[0-9]+]] = apply [[S_DELEG_INIT]]([[X]], [[SELF_META]]) : $@convention(method) (X, @thin S.Type) -> S
self.init(x: X())
// CHECK-NEXT: assign [[REPLACEMENT_SELF]] to [[PB]] : $*S
@@ -38,11 +38,10 @@
// CHECK: [[MARKED_E_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[E_BOX]]
// CHECK: [[PB:%.*]] = project_box [[MARKED_E_BOX]]
- // CHECK: [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1EO{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin E.Type) -> E
-
- // CHECK: [[E_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X_META:%[0-9]+]] = metatype $@thin X.Type
+ // CHECK: [[E_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X:%[0-9]+]] = apply [[E_DELEG_INIT]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
+ // CHECK: [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1EO{{[_0-9a-zA-Z]*}}fC : $@convention(method) (X, @thin E.Type) -> E
// CHECK: [[S:%[0-9]+]] = apply [[X_INIT]]([[X]], [[E_META]]) : $@convention(method) (X, @thin E.Type) -> E
// CHECK: assign [[S:%[0-9]+]] to [[PB]] : $*E
// CHECK: [[E_BOX1:%[0-9]+]] = load [trivial] [[PB]] : $*E
@@ -62,13 +61,13 @@
// CHECK: [[SELF_BOX:%[0-9]+]] = alloc_box ${ var S2 }
// CHECK: [[MARKED_SELF_BOX:%[0-9]+]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
// CHECK: [[PB:%.*]] = project_box [[MARKED_SELF_BOX]]
- // CHECK: [[S2_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation2S2V{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S2.Type) -> S2
- // CHECK: [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X_META:%[0-9]+]] = metatype $@thin X.Type
+ // CHECK: [[X_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation1XV{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X:%[0-9]+]] = apply [[X_INIT]]([[X_META]]) : $@convention(method) (@thin X.Type) -> X
// CHECK: [[X_BOX:%[0-9]+]] = alloc_stack $X
// CHECK: store [[X]] to [trivial] [[X_BOX]] : $*X
+ // CHECK: [[S2_DELEG_INIT:%[0-9]+]] = function_ref @_T019init_ref_delegation2S2V{{[_0-9a-zA-Z]*}}fC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S2.Type) -> S2
// CHECK: [[SELF_BOX1:%[0-9]+]] = apply [[S2_DELEG_INIT]]<X>([[X_BOX]], [[S2_META]]) : $@convention(method) <τ_0_0> (@in τ_0_0, @thin S2.Type) -> S2
// CHECK: dealloc_stack [[X_BOX]] : $*X
// CHECK: assign [[SELF_BOX1]] to [[PB]] : $*S2
@@ -95,8 +94,7 @@
// CHECK: store [[ORIG_SELF]] to [init] [[PB]] : $*C1
// CHECK: [[SELF_FROM_BOX:%[0-9]+]] = load [take] [[PB]] : $*C1
- // CHECK: [[BORROWED_SELF_FROM_BOX:%.*]] = begin_borrow [[SELF_FROM_BOX]]
- // CHECK: [[DELEG_INIT:%[0-9]+]] = class_method [[BORROWED_SELF_FROM_BOX]] : $C1, #C1.init!initializer.1 : (C1.Type) -> (X, X) -> C1, $@convention(method) (X, X, @owned C1) -> @owned C1
+ // CHECK: [[DELEG_INIT:%[0-9]+]] = class_method [[SELF_FROM_BOX]] : $C1, #C1.init!initializer.1 : (C1.Type) -> (X, X) -> C1, $@convention(method) (X, X, @owned C1) -> @owned C1
// CHECK: [[SELFP:%[0-9]+]] = apply [[DELEG_INIT]]([[X]], [[X]], [[SELF_FROM_BOX]]) : $@convention(method) (X, X, @owned C1) -> @owned C1
// CHECK: store [[SELFP]] to [init] [[PB]] : $*C1
// CHECK: [[SELFP:%[0-9]+]] = load [copy] [[PB]] : $*C1
@@ -119,8 +117,7 @@
// CHECK: [[PB_SELF:%.*]] = project_box [[MARKED_SELF_BOX]]
// CHECK: store [[ORIG_SELF]] to [init] [[PB_SELF]] : $*C2
// CHECK: [[SELF:%[0-9]+]] = load [take] [[PB_SELF]] : $*C2
- // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[DELEG_INIT:%[0-9]+]] = class_method [[BORROWED_SELF]] : $C2, #C2.init!initializer.1 : (C2.Type) -> (X, X) -> C2, $@convention(method) (X, X, @owned C2) -> @owned C2
+ // CHECK: [[DELEG_INIT:%[0-9]+]] = class_method [[SELF]] : $C2, #C2.init!initializer.1 : (C2.Type) -> (X, X) -> C2, $@convention(method) (X, X, @owned C2) -> @owned C2
// CHECK: [[REPLACE_SELF:%[0-9]+]] = apply [[DELEG_INIT]]([[X]], [[X]], [[SELF]]) : $@convention(method) (X, X, @owned C2) -> @owned C2
// CHECK: store [[REPLACE_SELF]] to [init] [[PB_SELF]] : $*C2
// CHECK: [[VAR_15:%[0-9]+]] = load [copy] [[PB_SELF]] : $*C2
diff --git a/test/SILGen/initializers.swift b/test/SILGen/initializers.swift
index e438fc8..44a1999 100644
--- a/test/SILGen/initializers.swift
+++ b/test/SILGen/initializers.swift
@@ -644,13 +644,13 @@
// Now we begin argument emission where we perform the unwrap.
// CHECK: [[SELF:%.*]] = load [take] [[PROJ]]
// CHECK: [[BASE_SELF:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass
- // CHECK: [[INIT_FN:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method)
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T021failable_initializers6unwrapS2iKF : $@convention(thin)
// CHECK: try_apply [[UNWRAP_FN]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[NORMAL_BB:bb[0-9]+]], error [[ERROR_BB:bb[0-9]+]]
//
// Now we emit the call to the initializer. Notice how we return self back to
// its memory locatio nbefore any other work is done.
// CHECK: [[NORMAL_BB]](
+ // CHECK: [[INIT_FN:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method)
// CHECK: [[BASE_SELF_INIT:%.*]] = apply [[INIT_FN]]({{%.*}}, [[BASE_SELF]])
// CHECK: [[SELF:%.*]] = unchecked_ref_cast [[BASE_SELF_INIT]] : $ThrowBaseClass to $ThrowDerivedClass
// CHECK: store [[SELF]] to [init] [[PROJ]]
@@ -755,12 +755,12 @@
// CHECK: [[UNWRAP_NORMAL_BB]](
// CHECK: [[SELF:%.*]] = load [take] [[PROJ]]
// CHECK: [[SELF_CAST:%.*]] = upcast [[SELF]] : $ThrowDerivedClass to $ThrowBaseClass
- // CHECK: [[INIT_FN2:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method) (Int, @owned ThrowBaseClass) -> @owned ThrowBaseClass
// CHECK: [[UNWRAP_FN2:%.*]] = function_ref @_T021failable_initializers6unwrapS2iKF : $@convention(thin) (Int) -> (Int, @error Error)
// CHECK: try_apply [[UNWRAP_FN2]]({{%.*}}) : $@convention(thin) (Int) -> (Int, @error Error), normal [[UNWRAP_NORMAL_BB2:bb[0-9]+]], error [[UNWRAP_ERROR_BB2:bb[0-9]+]]
//
// Then since this example has a
// CHECK: [[UNWRAP_NORMAL_BB2]]([[INT:%.*]] : @trivial $Int):
+ // CHECK: [[INIT_FN2:%.*]] = function_ref @_T021failable_initializers14ThrowBaseClassCACSi6noFail_tcfc : $@convention(method) (Int, @owned ThrowBaseClass) -> @owned ThrowBaseClass
// CHECK: [[NEW_SELF_CAST:%.*]] = apply [[INIT_FN2]]([[INT]], [[SELF_CAST]]) : $@convention(method) (Int, @owned ThrowBaseClass) -> @owned ThrowBaseClass
// CHECK: [[NEW_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF_CAST]] : $ThrowBaseClass to $ThrowDerivedClass
// CHECK: store [[NEW_SELF]] to [init] [[PROJ]]
diff --git a/test/SILGen/let_decls.swift b/test/SILGen/let_decls.swift
index 46c5b64..8b75efd 100644
--- a/test/SILGen/let_decls.swift
+++ b/test/SILGen/let_decls.swift
@@ -73,9 +73,9 @@
// CHECK-NOT: destroy_value
- // CHECK: [[USEFN:%[0-9]+]] = function_ref{{.*}}useAString
- // CHECK-NEXT: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
+ // CHECK: [[BORROWED_STR:%.*]] = begin_borrow [[STR]]
// CHECK-NEXT: [[STR_COPY:%.*]] = copy_value [[BORROWED_STR]]
+ // CHECK: [[USEFN:%[0-9]+]] = function_ref{{.*}}useAString
// CHECK-NEXT: [[USE:%[0-9]+]] = apply [[USEFN]]([[STR_COPY]])
// CHECK-NEXT: end_borrow [[BORROWED_STR]] from [[STR]]
useAString(o)
@@ -98,10 +98,10 @@
func testAddressOnlyStructString<T>(_ a : T) -> String {
return produceAddressOnlyStruct(a).str
- // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
// CHECK: [[TMPSTRUCT:%[0-9]+]] = alloc_stack $AddressOnlyStruct<T>
// CHECK: [[ARG:%.*]] = alloc_stack $T
// CHECK: copy_addr [[FUNC_ARG]] to [initialization] [[ARG]]
+ // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
// CHECK: apply [[PRODFN]]<T>([[TMPSTRUCT]], [[ARG]])
// CHECK-NEXT: dealloc_stack [[ARG]]
// CHECK-NEXT: [[STRADDR:%[0-9]+]] = struct_element_addr [[TMPSTRUCT]] : $*AddressOnlyStruct<T>, #AddressOnlyStruct.str
@@ -115,9 +115,9 @@
func testAddressOnlyStructElt<T>(_ a : T) -> T {
return produceAddressOnlyStruct(a).elt
- // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
// CHECK: [[TMPSTRUCT:%[0-9]+]] = alloc_stack $AddressOnlyStruct<T>
// CHECK: [[ARG:%.*]] = alloc_stack $T
+ // CHECK: [[PRODFN:%[0-9]+]] = function_ref @{{.*}}produceAddressOnlyStruct
// CHECK: apply [[PRODFN]]<T>([[TMPSTRUCT]], [[ARG]])
// CHECK-NEXT: dealloc_stack [[ARG]]
// CHECK-NEXT: [[ELTADDR:%[0-9]+]] = struct_element_addr [[TMPSTRUCT]] : $*AddressOnlyStruct<T>, #AddressOnlyStruct.elt
diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift
index dfe57aa..8f13ad0 100644
--- a/test/SILGen/lifetime.swift
+++ b/test/SILGen/lifetime.swift
@@ -172,9 +172,9 @@
// CHECK-LABEL: sil hidden @_T08lifetime16reftype_call_argyyF
func reftype_call_arg() {
reftype_func_with_arg(reftype_func())
- // CHECK: [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
// CHECK: [[RF:%[0-9]+]] = function_ref @_T08lifetime12reftype_func{{[_0-9a-zA-Z]*}}F
// CHECK: [[R1:%[0-9]+]] = apply [[RF]]
+ // CHECK: [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
// CHECK: [[R2:%[0-9]+]] = apply [[RFWA]]([[R1]])
// CHECK: destroy_value [[R2]]
// CHECK: return
@@ -188,9 +188,9 @@
// CHECK: [[A1_COPY:%.*]] = copy_value [[BORROWED_A1]]
// CHECK: store [[A1_COPY]] to [init] [[PB]]
// CHECK: end_borrow [[BORROWED_A1]] from [[A1]]
-// CHECK: [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]]
// CHECK: [[A2:%[0-9]+]] = load [copy] [[READ]]
+// CHECK: [[RFWA:%[0-9]+]] = function_ref @_T08lifetime21reftype_func_with_arg{{[_0-9a-zA-Z]*}}F
// CHECK: [[RESULT:%.*]] = apply [[RFWA]]([[A2]])
// CHECK: destroy_value [[RESULT]]
// CHECK: destroy_value [[AADDR]]
@@ -343,9 +343,9 @@
// CHECK-LABEL: sil hidden @_T08lifetime28struct_with_ref_materializedyyF
func struct_with_ref_materialized() {
fragile_struct_with_ref_elements().gimel()
- // CHECK: [[METHOD:%[0-9]+]] = function_ref @_T08lifetime4BethV5gimel{{[_0-9a-zA-Z]*}}F
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_T08lifetime32fragile_struct_with_ref_elementsAA4BethVyF
// CHECK: [[STRUCT:%[0-9]+]] = apply [[FUNC]]
+ // CHECK: [[METHOD:%[0-9]+]] = function_ref @_T08lifetime4BethV5gimel{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[METHOD]]([[STRUCT]])
}
@@ -744,9 +744,9 @@
super.init(y: y)
// CHECK: [[THIS1:%[0-9]+]] = load [take] [[PB_BOX]]
// CHECK: [[THIS1_SUP:%[0-9]+]] = upcast [[THIS1]] : ${{.*}} to $B
- // CHECK: [[SUPER_CTOR:%[0-9]+]] = function_ref @_T08lifetime1BCACSi1y_tcfc : $@convention(method) (Int, @owned B) -> @owned B
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PY]]
// CHECK: [[Y:%[0-9]+]] = load [trivial] [[READ]]
+ // CHECK: [[SUPER_CTOR:%[0-9]+]] = function_ref @_T08lifetime1BCACSi1y_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]]
diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift
index 99232f0..80f2426 100644
--- a/test/SILGen/materializeForSet.swift
+++ b/test/SILGen/materializeForSet.swift
@@ -364,23 +364,21 @@
improve(&wizard.hocus)
}
// CHECK-LABEL: sil hidden @_T017materializeForSet13improveWizardyAA0E0VzF
-// CHECK: [[IMPROVE:%.*]] = function_ref @_T017materializeForSet7improveySizF :
-// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*Wizard
+// 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-NEXT: function_ref
-// CHECK-NEXT: [[GETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivg
-// CHECK-NEXT: [[WTEMP:%.*]] = alloc_stack $Wizard
+// CHECK: [[WTEMP:%.*]] = alloc_stack $Wizard
// CHECK-NEXT: store [[T0]] to [trivial] [[WTEMP]]
+// CHECK: [[GETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivg
// 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 @_T017materializeForSet7improveySizF :
// CHECK-NEXT: apply [[IMPROVE]]([[TEMP]])
// CHECK-NEXT: [[T0:%.*]] = load [trivial] [[TEMP]]
-// CHECK-NEXT: function_ref
-// CHECK-NEXT: [[SETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivs
+// CHECK: [[SETTER:%.*]] = function_ref @_T017materializeForSet5MagicPAAE5hocusSivs
// CHECK-NEXT: apply [[SETTER]]<Wizard>([[T0]], [[WRITE]])
// CHECK-NEXT: end_access [[WRITE]] : $*Wizard
// CHECK-NEXT: dealloc_stack [[TEMP]]
@@ -574,10 +572,10 @@
// CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIexir_A2CIexyd_TR : $@convention(thin) (TuxedoPanda, @owned @callee_owned (@in TuxedoPanda) -> @out TuxedoPanda) -> TuxedoPanda
- // CHECK: function_ref @_T017materializeForSet5PandaPAAE1xxxcvs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_owned (@in τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
-
// CHECK: function_ref @_T017materializeForSet11TuxedoPandaVACIexyd_A2CIexir_TR : $@convention(thin) (@in TuxedoPanda, @owned @callee_owned (TuxedoPanda) -> TuxedoPanda) -> @out TuxedoPanda
+ // CHECK: function_ref @_T017materializeForSet5PandaPAAE1xxxcvs : $@convention(method) <τ_0_0 where τ_0_0 : Panda> (@owned @callee_owned (@in τ_0_0) -> @out τ_0_0, @inout τ_0_0) -> ()
+
// CHECK: }
// CHECK-LABEL: sil private [transparent] [thunk] @_T017materializeForSet11TuxedoPandaVAA0E0A2aDP1xxxcvmTW
diff --git a/test/SILGen/metatypes.swift b/test/SILGen/metatypes.swift
index 8f9b41f..36b2588 100644
--- a/test/SILGen/metatypes.swift
+++ b/test/SILGen/metatypes.swift
@@ -89,8 +89,8 @@
}
// CHECK-LABEL: sil hidden @_T09metatypes36existential_metatype_from_thin_valueypXpyF : $@convention(thin) () -> @thick Any.Type
+// CHECK: [[T1:%.*]] = metatype $@thin SomeStruct.Type
// CHECK: [[T0:%.*]] = function_ref @_T09metatypes10SomeStructV{{[_0-9a-zA-Z]*}}fC
-// CHECK-NEXT: [[T1:%.*]] = metatype $@thin SomeStruct.Type
// CHECK-NEXT: [[T2:%.*]] = apply [[T0]]([[T1]])
// CHECK-NEXT: debug_value [[T2]] : $SomeStruct, let, name "s"
// CHECK-NEXT: [[T0:%.*]] = metatype $@thin SomeStruct.Type
diff --git a/test/SILGen/objc_attr_NSManaged.swift b/test/SILGen/objc_attr_NSManaged.swift
index 7d4553a..c264d2b 100644
--- a/test/SILGen/objc_attr_NSManaged.swift
+++ b/test/SILGen/objc_attr_NSManaged.swift
@@ -23,10 +23,10 @@
// Make sure that we're calling through the @objc entry points.
// CHECK-LABEL: sil hidden @_T019objc_attr_NSManaged10SwiftGizmoC7modifyX{{[_0-9a-zA-Z]*}}F : $@convention(method) (@guaranteed SwiftGizmo) -> () {
func modifyX() {
- // CHECK: [[SETTER:%[0-9]+]] = objc_method [[SELF:%.*]] : $SwiftGizmo, #SwiftGizmo.x!setter.1.foreign : (SwiftGizmo) -> (X) -> (), $@convention(objc_method) (X, SwiftGizmo) -> ()
- // CHECK: [[GETTER:%[0-9]+]] = objc_method [[SELF]] : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : (SwiftGizmo) -> () -> X, $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
+ // 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
diff --git a/test/SILGen/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift
index 89d3551..08b07c3 100644
--- a/test/SILGen/objc_blocks_bridging.swift
+++ b/test/SILGen/objc_blocks_bridging.swift
@@ -101,7 +101,6 @@
) -> (Int, String, String?, String?) {
// CHECK: bb0([[ARG0:%.*]] : @owned $Foo, [[ARG1:%.*]] : @owned $@callee_owned (Int) -> Int, [[ARG2:%.*]] : @owned $@callee_owned (@owned String) -> @owned String, [[ARG3:%.*]] : @owned $@callee_owned (@owned Optional<String>) -> @owned Optional<String>):
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
- // CHECK: [[FOO:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.foo!1.foreign
// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
// CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
// CHECK: [[CONVERT:%.*]] = convert_function [[CLOSURE_COPY]]
@@ -111,20 +110,21 @@
// CHECK: [[F_BLOCK_INVOKE:%.*]] = function_ref @_T0S2iIxyd_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 [[BORROWED_ARG0]] : $Foo, #Foo.foo!1.foreign
// CHECK: apply [[FOO]]([[F_BLOCK]]
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
- // CHECK: [[BAR:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.bar!1.foreign
// CHECK: [[G_BLOCK_INVOKE:%.*]] = function_ref @_T0S2SIxxo_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 [[BORROWED_ARG0]] : $Foo, #Foo.bar!1.foreign
// CHECK: apply [[BAR]]([[G_BLOCK]]
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
- // CHECK: [[BAS:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.bas!1.foreign
// CHECK: [[H_BLOCK_INVOKE:%.*]] = function_ref @_T0SSSgAAIxxo_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 [[BORROWED_ARG0]] : $Foo, #Foo.bas!1.foreign
// CHECK: apply [[BAS]]([[H_BLOCK]]
// CHECK: [[G_BLOCK:%.*]] = copy_block {{%.*}} : $@convention(block) (NSString) -> @autoreleased NSString
@@ -188,3 +188,11 @@
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ix_Ixx_IyB_IyBy_TR : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_owned (@owned @noescape @callee_owned () -> ()) -> (), @convention(block) @noescape () -> ()) -> ()
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0IyB_Ix_TR : $@convention(thin) (@owned @convention(block) @noescape () -> ()) -> ()
+// rdar://35402696
+func takeOptStringFunction(fn: (String) -> String?) {}
+func testGlobalBlock() {
+ takeOptStringFunction(fn: GlobalBlock)
+}
+// CHECK-LABEL: sil hidden @_T020objc_blocks_bridging15testGlobalBlockyyF
+// CHECK: global_addr @GlobalBlock : $*@convention(block) (NSString) -> @autoreleased Optional<NSString>
+// CHECK: function_ref @_T0So8NSStringCABSgIeyBya_S2SIexxo_TR : $@convention(thin) (@owned String, @owned @convention(block) (NSString) -> @autoreleased Optional<NSString>) -> @owned String
diff --git a/test/SILGen/objc_bridged_results.swift b/test/SILGen/objc_bridged_results.swift
index da859c8..d83c0c5 100644
--- a/test/SILGen/objc_bridged_results.swift
+++ b/test/SILGen/objc_bridged_results.swift
@@ -125,10 +125,9 @@
// CHECK-LABEL: sil hidden @_T020objc_bridged_results13testClassPropSSyF
func testClassProp() -> String {
- // CHECK: [[CLASS:%.+]] = metatype $@thick Test.Type
- // CHECK: [[METHOD:%.+]] = objc_method [[CLASS]] : $@thick Test.Type, #Test.nonnullSharedString!getter.1.foreign : (Test.Type) -> () -> String, $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
- // CHECK: [[OBJC_CLASS:%.+]] = thick_to_objc_metatype [[CLASS]] : $@thick Test.Type to $@objc_metatype Test.Type
- // CHECK: [[COCOA_VAL:%[0-9]+]] = apply [[METHOD]]([[OBJC_CLASS]]) : $@convention(objc_method) (@objc_metatype Test.Type) -> @autoreleased Optional<NSString>
+ // 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 @_T0SS10FoundationE36_unconditionallyBridgeFromObjectiveCSSSo8NSStringCSgFZ
// CHECK: [[STRING_META:%[0-9]+]] = metatype $@thin String.Type
// CHECK: [[RESULT:%[0-9]+]] = apply [[CONVERT]]([[COCOA_VAL]], [[STRING_META]]) : $@convention(method) (@owned Optional<NSString>, @thin String.Type) -> @owned String
diff --git a/test/SILGen/objc_bridging.swift b/test/SILGen/objc_bridging.swift
index 7aef8ed..644e1ad 100644
--- a/test/SILGen/objc_bridging.swift
+++ b/test/SILGen/objc_bridging.swift
@@ -87,12 +87,12 @@
// CHECK-LABEL: sil hidden @_T013objc_bridging6setFoo{{.*}}F
// CHECK: bb0([[ARG0:%.*]] : @owned $Foo, {{%.*}} : @owned $String):
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-// CHECK: [[SET_FOO:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setFoo!1.foreign
// CHECK: [[NATIVE:%.*]] = load
// CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @_T0SS10FoundationE19_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 [[BORROWED_ARG0]] : $Foo, #Foo.setFoo!1.foreign
// CHECK: apply [[SET_FOO]]([[OPT_BRIDGED]], [[BORROWED_ARG0]]) : $@convention(objc_method) (Optional<NSString>, Foo) -> ()
// CHECK: destroy_value [[OPT_BRIDGED]]
// CHECK: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
@@ -109,9 +109,9 @@
// 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: end_borrow [[BORROWED_SELF]] from [[SELF]]
// CHECK-ios-i386: return [[SWIFT_BOOL]] : $Bool
// CHECK-ios-i386: }
@@ -129,9 +129,9 @@
// CHECK-macosx-x86_64: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
// CHECK-macosx-x86_64: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $Foo, #Foo.zim!1.foreign : (Foo) -> () -> Bool
// CHECK-macosx-x86_64: [[OBJC_BOOL:%.*]] = apply [[METHOD]]([[BORROWED_SELF]]) : $@convention(objc_method) (Foo) -> ObjCBool
+// CHECK-macosx-x86_64: end_borrow [[BORROWED_SELF]] from [[SELF]]
// 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: end_borrow [[BORROWED_SELF]] from [[SELF]]
// CHECK-macosx-x86_64: return [[SWIFT_BOOL]] : $Bool
// CHECK-macosx-x86_64: }
@@ -160,9 +160,9 @@
// CHECK-ios-i386-LABEL: sil hidden @_T013objc_bridging6setZim{{.*}}F
// CHECK-ios-i386: bb0([[ARG0:%.*]] : @owned $Foo, [[ARG1:%.*]] : @trivial $Bool):
// CHECK-ios-i386: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-// CHECK-ios-i386: [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
// 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 [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
// CHECK-ios-i386: apply [[METHOD]]([[OBJC_BOOL]], [[BORROWED_ARG0]]) : $@convention(objc_method) (ObjCBool, Foo) -> ()
// CHECK-ios-i386: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
// CHECK-ios-i386: destroy_value [[ARG0]]
@@ -171,9 +171,9 @@
// CHECK-macosx-x86_64-LABEL: sil hidden @_T013objc_bridging6setZim{{.*}}F
// CHECK-macosx-x86_64: bb0([[ARG0:%.*]] : @owned $Foo, [[ARG1:%.*]] : @trivial $Bool):
// CHECK-macosx-x86_64: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
-// CHECK-macosx-x86_64: [[METHOD:%.*]] = objc_method [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
// 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 [[BORROWED_ARG0]] : $Foo, #Foo.setZim!1.foreign
// CHECK-macosx-x86_64: apply [[METHOD]]([[OBJC_BOOL]], [[BORROWED_ARG0]]) : $@convention(objc_method) (ObjCBool, Foo) -> ()
// CHECK-macosx-x86_64: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
// CHECK-macosx-x86_64: destroy_value [[ARG0]]
@@ -258,13 +258,13 @@
}
// CHECK-LABEL: sil hidden @_T013objc_bridging10callSetBar{{.*}}F
// CHECK: bb0({{%.*}} : @owned $String):
-// CHECK: [[SET_BAR:%.*]] = function_ref @setBar
// CHECK: [[NATIVE:%.*]] = load
// CHECK: [[STRING_TO_NSSTRING:%.*]] = function_ref @_T0SS10FoundationE19_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: }
@@ -660,13 +660,13 @@
// CHECK-LABEL: sil hidden @_T013objc_bridging15castToCFunctionySV3ptr_tF : $@convention(thin) (UnsafeRawPointer) -> () {
func castToCFunction(ptr: UnsafeRawPointer) {
- // CHECK: [[CASTFN:%.*]] = function_ref @_T0s13unsafeBitCastq_x_q_m2totr0_lF
// 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 @_T0s13unsafeBitCastq_x_q_m2totr0_lF
// CHECK: apply [[CASTFN]]<UnsafeRawPointer, @convention(c) (AnyObject?) -> ()>([[OUT]], [[IN]], [[META]]) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @thick τ_0_1.Type) -> @out τ_0_1
- // CHECK: [[RESULT:%.*]] = load [trivial] %3 : $*@convention(c) (Optional<AnyObject>) -> ()
+ // 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/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift
index d32606b..4b1006a 100644
--- a/test/SILGen/objc_bridging_any.swift
+++ b/test/SILGen/objc_bridging_any.swift
@@ -40,7 +40,6 @@
// CHECK: debug_value_addr [[OPT_ANY:%.*]] : $*Optional<Any>
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: [[BORROWED_STRING:%.*]] = begin_borrow [[STRING]]
// CHECK: [[STRING_COPY:%.*]] = copy_value [[BORROWED_STRING]]
// CHECK: [[BRIDGE_STRING:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
@@ -50,50 +49,51 @@
// CHECK: end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
// CHECK: destroy_value [[STRING_COPY]]
// CHECK: end_borrow [[BORROWED_STRING]] from [[STRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(string)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_NSSTRING:%.*]] = begin_borrow [[NSSTRING]]
// CHECK: [[NSSTRING_COPY:%.*]] = copy_value [[BORROWED_NSSTRING]]
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING_COPY]] : $NSString : $NSString, $AnyObject
// CHECK: end_borrow [[BORROWED_NSSTRING]] from [[NSSTRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(nsString)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_CLASS_GENERIC:%.*]] = begin_borrow [[CLASS_GENERIC]]
// CHECK: [[CLASS_GENERIC_COPY:%.*]] = copy_value [[BORROWED_CLASS_GENERIC]]
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC_COPY]] : $T : $T, $AnyObject
// CHECK: end_borrow [[BORROWED_CLASS_GENERIC]] from [[CLASS_GENERIC]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(classGeneric)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_OBJECT:%.*]] = begin_borrow [[OBJECT]]
// CHECK: [[OBJECT_COPY:%.*]] = copy_value [[BORROWED_OBJECT]]
// CHECK: end_borrow [[BORROWED_OBJECT]] from [[OBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[OBJECT_COPY]], [[BORROWED_SELF]])
// CHECK: destroy_value [[OBJECT_COPY]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(object)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_CLASS_EXISTENTIAL:%.*]] = begin_borrow [[CLASS_EXISTENTIAL]]
// CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[BORROWED_CLASS_EXISTENTIAL]]
// CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
// CHECK: end_borrow [[BORROWED_CLASS_EXISTENTIAL]] from [[CLASS_EXISTENTIAL]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
@@ -102,20 +102,19 @@
// These cases perform a universal bridging conversion.
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// 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 [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(generic)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// 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]],
@@ -127,13 +126,13 @@
// CHECK: dealloc_stack [[TMP]]
// CHECK: destroy_addr [[COPY]]
// CHECK: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(existential)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
// CHECK: [[ERROR_COPY:%.*]] = copy_value [[BORROWED_ERROR]] : $Error
// CHECK: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
@@ -144,13 +143,13 @@
// CHECK: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
// CHECK: destroy_value [[ERROR_COPY]] : $Error
// CHECK: end_borrow [[BORROWED_ERROR]] from [[ERROR]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[BRIDGED_ERROR]], [[BORROWED_SELF]])
// CHECK: destroy_value [[BRIDGED_ERROR]] : $AnyObject
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(error)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// 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]],
@@ -161,17 +160,18 @@
// CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<[[OPENED_TYPE]]>([[TMP]])
// CHECK: destroy_addr [[COPY]]
// CHECK: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(any)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[TMP:%.*]] = alloc_stack $KnownUnbridged
// CHECK: store [[KNOWN_UNBRIDGED]] to [trivial] [[TMP]]
// CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveC{{.*}}F
// CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<KnownUnbridged>([[TMP]])
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(knownUnbridged)
@@ -179,7 +179,6 @@
// These cases bridge using Optional's _ObjectiveCBridgeable conformance.
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_OPT_STRING:%.*]] = begin_borrow [[OPT_STRING]]
// CHECK: [[OPT_STRING_COPY:%.*]] = copy_value [[BORROWED_OPT_STRING]]
// CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
@@ -188,12 +187,12 @@
// CHECK: store_borrow [[BORROWED_OPT_STRING_COPY]] to [[TMP]]
// CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<String>([[TMP]])
// CHECK: end_borrow [[BORROWED_OPT_STRING]] from [[OPT_STRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(optionalA)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_OPT_NSSTRING:%.*]] = begin_borrow [[OPT_NSSTRING]]
// CHECK: [[OPT_NSSTRING_COPY:%.*]] = copy_value [[BORROWED_OPT_NSSTRING]]
// CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
@@ -202,16 +201,17 @@
// CHECK: store_borrow [[BORROWED_OPT_NSSTRING_COPY]] to [[TMP]]
// CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<NSString>([[TMP]])
// CHECK: end_borrow [[BORROWED_OPT_NSSTRING]] from [[OPT_NSSTRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(optionalB)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[TMP:%.*]] = alloc_stack $Optional<Any>
// CHECK: copy_addr [[OPT_ANY]] to [initialization] [[TMP]]
// CHECK: [[BRIDGE_OPTIONAL:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
// CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_OPTIONAL]]<Any>([[TMP]])
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesId(optionalC)
@@ -287,7 +287,6 @@
// CHECK: [[OPT_OPT_C:%.*]] : $*Optional<Optional<Any>>
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: [[BORROWED_STRING:%.*]] = begin_borrow [[STRING]]
// CHECK: [[STRING_COPY:%.*]] = copy_value [[BORROWED_STRING]]
// CHECK: [[BRIDGE_STRING:%.*]] = function_ref @_T0SS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
@@ -297,57 +296,57 @@
// CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_STRING_COPY]] from [[STRING_COPY]]
// CHECK: destroy_value [[STRING_COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: destroy_value [[OPT_ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(string)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_NSSTRING:%.*]] = begin_borrow [[NSSTRING]]
// CHECK: [[NSSTRING_COPY:%.*]] = copy_value [[BORROWED_NSSTRING]]
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING_COPY]] : $NSString : $NSString, $AnyObject
// CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_NSSTRING]] from [[NSSTRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(nsString)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_OBJECT:%.*]] = begin_borrow [[OBJECT]]
// CHECK: [[OBJECT_COPY:%.*]] = copy_value [[BORROWED_OBJECT]]
// CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[OBJECT_COPY]]
// CHECK: end_borrow [[BORROWED_OBJECT]] from [[OBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(object)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_CLASS_GENERIC:%.*]] = begin_borrow [[CLASS_GENERIC]]
// CHECK: [[CLASS_GENERIC_COPY:%.*]] = copy_value [[BORROWED_CLASS_GENERIC]]
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC_COPY]] : $T : $T, $AnyObject
// CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_CLASS_GENERIC]] from [[CLASS_GENERIC]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(classGeneric)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_CLASS_EXISTENTIAL:%.*]] = begin_borrow [[CLASS_EXISTENTIAL]]
// CHECK: [[CLASS_EXISTENTIAL_COPY:%.*]] = copy_value [[BORROWED_CLASS_EXISTENTIAL]]
// CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL_COPY]] : $CP
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
// CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
// CHECK: end_borrow [[BORROWED_CLASS_EXISTENTIAL]] from [[CLASS_EXISTENTIAL]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(classExistential)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK-NEXT: [[COPY:%.*]] = alloc_stack $U
// CHECK-NEXT: copy_addr [[GENERIC]] to [initialization] [[COPY]]
// CHECK-NEXT: // function_ref _bridgeAnythingToObjectiveC
@@ -355,13 +354,13 @@
// CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<U>([[COPY]])
// CHECK-NEXT: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
// CHECK-NEXT: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
// CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(generic)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// 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]],
@@ -374,13 +373,13 @@
// CHECK-NEXT: dealloc_stack [[TMP]]
// CHECK-NEXT: destroy_addr [[COPY]]
// CHECK-NEXT: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
// CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(existential)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[BORROWED_ERROR:%.*]] = begin_borrow [[ERROR]]
// CHECK-NEXT: [[ERROR_COPY:%.*]] = copy_value [[BORROWED_ERROR]] : $Error
// CHECK-NEXT: [[ERROR_BOX:%[0-9]+]] = open_existential_box [[ERROR_COPY]] : $Error to $*@opened([[ERROR_ARCHETYPE:"[^"]*"]]) Error
@@ -392,13 +391,13 @@
// CHECK-NEXT: dealloc_stack [[ERROR_STACK]] : $*@opened([[ERROR_ARCHETYPE]]) Error
// CHECK-NEXT: destroy_value [[ERROR_COPY]] : $Error
// CHECK-NEXT: end_borrow [[BORROWED_ERROR]] from [[ERROR]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK-NEXT: apply [[METHOD]]([[BRIDGED_ERROR_OPT]], [[BORROWED_SELF]])
// CHECK-NEXT: destroy_value [[BRIDGED_ERROR_OPT]]
// CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(error)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// 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]],
@@ -411,24 +410,24 @@
// CHECK-NEXT: dealloc_stack [[TMP]]
// CHECK-NEXT: destroy_addr [[COPY]]
// CHECK-NEXT: dealloc_stack [[COPY]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK-NEXT: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK-NEXT: destroy_value [[OPT_ANYOBJECT]]
// CHECK-NEXT: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(any)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: [[TMP:%.*]] = alloc_stack $KnownUnbridged
// CHECK: store [[KNOWN_UNBRIDGED]] to [trivial] [[TMP]]
// CHECK: [[BRIDGE_ANYTHING:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveC{{.*}}F
// CHECK: [[ANYOBJECT:%.*]] = apply [[BRIDGE_ANYTHING]]<KnownUnbridged>([[TMP]])
// CHECK: [[OPT_ANYOBJECT:%.*]] = enum {{.*}} [[ANYOBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]] : $NSIdLover,
// CHECK: apply [[METHOD]]([[OPT_ANYOBJECT]], [[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
receiver.takesNullableId(knownUnbridged)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: [[BORROWED_OPT_STRING:%.*]] = begin_borrow [[OPT_STRING]]
// CHECK: [[OPT_STRING_COPY:%.*]] = copy_value [[BORROWED_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]+]]
@@ -449,6 +448,7 @@
//
// CHECK: [[JOIN]]([[PHI:%.*]] : @owned $Optional<AnyObject>):
// CHECK: end_borrow [[BORROWED_OPT_STRING]] from [[OPT_STRING]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: apply [[METHOD]]([[PHI]], [[BORROWED_SELF]])
// CHECK: destroy_value [[PHI]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
@@ -459,9 +459,9 @@
receiver.takesNullableId(optNSString)
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: [[BORROWED_OPT_OBJECT:%.*]] = begin_borrow [[OPT_OBJECT]]
// CHECK: [[OPT_OBJECT_COPY:%.*]] = copy_value [[BORROWED_OPT_OBJECT]]
+ // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_SELF]]
// CHECK: apply [[METHOD]]([[OPT_OBJECT_COPY]], [[BORROWED_SELF]])
receiver.takesNullableId(optObject)
receiver.takesNullableId(optClassGeneric)
@@ -738,6 +738,16 @@
}
}
+// CHECK-LABEL: sil hidden @_T017objc_bridging_any33bridgeOptionalFunctionToAnyObjectyXlyycSg2fn_tF : $@convention(thin) (@owned Optional<@callee_owned () -> ()>) -> @owned AnyObject
+// CHECK: [[BRIDGE:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
+// CHECK: [[FN:%.*]] = function_ref @_T0Iex_ytytIexir_TR
+// CHECK: partial_apply [[FN]]
+// CHECK: [[SELF:%.*]] = alloc_stack $Optional<@callee_owned (@in ()) -> @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: {{.*}} : @_T0SC13GenericOptionVs8Hashable13objc_genericssACP9hashValueSivgTW
diff --git a/test/SILGen/objc_bridging_peephole.swift b/test/SILGen/objc_bridging_peephole.swift
index 6697bd3..e8b23e2 100644
--- a/test/SILGen/objc_bridging_peephole.swift
+++ b/test/SILGen/objc_bridging_peephole.swift
@@ -17,55 +17,55 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole16testMethodResultySo10DummyClassC5dummy_tF
func testMethodResult(dummy: DummyClass) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
- // CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[RESULT]])
useOptNS(dummy.fetchNullableString() as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
- // CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[RESULT]])
useOptNS(dummy.fetchNullproneString() as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
- // CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
+ // CHECK-NEXT: apply [[USE]]([[RESULT]])
useOptNS(dummy.fetchNonnullString() as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
- // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
- // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+ // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
useOptAnyObject(dummy.fetchNullableString() as AnyObject?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
- // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
- // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+ // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
useOptAnyObject(dummy.fetchNullproneString() as AnyObject?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
- // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
- // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
+ // CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
+ // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
useOptAnyObject(dummy.fetchNonnullString() as AnyObject?)
// CHECK: return
@@ -73,29 +73,29 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonNullMethodResultySo10DummyClassC5dummy_tF
func testNonNullMethodResult(dummy: DummyClass) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: end_borrow [[SELF]] from %0
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb1:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
- // CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.fetchNonnullString() as NSString)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: end_borrow [[SELF]] from %0
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb3:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
- // CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.fetchNonnullString() as AnyObject)
// CHECK: return
@@ -103,29 +103,29 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole22testForcedMethodResultySo10DummyClassC5dummy_tF
func testForcedMethodResult(dummy: DummyClass) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: end_borrow [[SELF]] from %0
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb1:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
- // CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.fetchNullproneString() as NSString)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK-NEXT: end_borrow [[SELF]] from %0
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb3:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
- // CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.fetchNullproneString() as AnyObject)
// CHECK: return
@@ -135,53 +135,53 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole17testPropertyValueySo10DummyClassC5dummy_tF
func testPropertyValue(dummy: DummyClass) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptNS(dummy.nullableStringProperty as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptNS(dummy.nullproneStringProperty as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptNS(dummy.nonnullStringProperty as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.nullableStringProperty as AnyObject?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.nullproneStringProperty as AnyObject?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: [[ANYOBJECT:%.*]] = unchecked_ref_cast [[RESULT]] : $Optional<NSString> to $Optional<AnyObject>
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole15useOptAnyObjectyyXlSgF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useOptAnyObject(dummy.nonnullStringProperty as AnyObject?)
@@ -191,20 +191,19 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNonNullPropertyValueySo10DummyClassC5dummy_tF
func testNonNullPropertyValue(dummy: DummyClass) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb1:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.nonnullStringProperty as NSString)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
@@ -212,6 +211,7 @@
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.nonnullStringProperty as AnyObject)
@@ -221,19 +221,18 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testForcedPropertyValueySo10DummyClassC5dummy_tF
func testForcedPropertyValue(dummy: DummyClass) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
// CHECK-NEXT: switch_enum [[RESULT]]
// CHECK: bb1:
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb2([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useNS(dummy.nullproneStringProperty as NSString)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
// CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
@@ -242,6 +241,7 @@
// CHECK: function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
// CHECK: bb4([[RESULT:%.*]] : @owned $NSString):
// CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
// CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
// CHECK-NEXT: end_borrow [[SELF]] from %0
useAnyObject(dummy.nullproneStringProperty as AnyObject)
@@ -255,27 +255,27 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonnullSubscriptGetySo0eF0C6object_yXl5indextF
func testNonnullSubscriptGet(object: NonnullSubscript, index: AnyObject) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
// CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useOptNS(object[index] as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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 @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart
// CHECK: bb{{[0-9]+}}([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useNS(object[index] as NSString)
@@ -285,13 +285,13 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptGetySo0eF0C6object_yXl5indextF
func testNullableSubscriptGet(object: NullableSubscript, index: AnyObject) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
// CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useOptNS(object[index] as NSString?)
@@ -301,27 +301,27 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptGetySo0eF0C6object_yXl5indextF
func testNullproneSubscriptGet(object: NullproneSubscript, index: AnyObject) {
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
- // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
+ // CHECK: [[SELF:%.*]] = begin_borrow %0
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// CHECK-NEXT: [[INDEX:%.*]] = apply [[BRIDGE_TO_ID]]
+ // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]([[INDEX]], [[SELF]])
// CHECK-NEXT: destroy_value [[INDEX]] : $AnyObject
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole8useOptNSySo8NSStringCSgF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useOptNS(object[index] as NSString?)
- // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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 @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart
// CHECK: bb{{[0-9]+}}([[RESULT:%.*]] : @owned $NSString):
+ // CHECK: [[USE:%.*]] = function_ref @_T022objc_bridging_peephole5useNSySo8NSStringCF
// CHECK-NEXT: apply [[USE]]([[RESULT]])
// CHECK: end_borrow [[SELF]] from %0
useNS(object[index] as NSString)
@@ -334,32 +334,32 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole18testMethodArgumentySo10DummyClassC5dummy_tF
func testMethodArgument(dummy: DummyClass) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNonnullString(makeNS() as String)
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNullableString(makeNS() as String)
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -371,22 +371,22 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptMethodArgumentySo10DummyClassC5dummy_tF
func testValueToOptMethodArgument(dummy: DummyClass) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNullableString(makeNS() as String?)
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -398,20 +398,20 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14MethodArgumentySo10DummyClassC5dummy_tF
func testOptToOptMethodArgument(dummy: DummyClass) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.takeNullableString(makeOptNS() as String?)
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -425,32 +425,32 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole18testPropertySetterySo10DummyClassC5dummy_tF
func testPropertySetter(dummy: DummyClass) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nonnullStringProperty = makeNS() as String
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nullableStringProperty = makeNS() as String
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -462,22 +462,22 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole28testValueToOptPropertySetterySo10DummyClassC5dummy_tF
func testValueToOptPropertySetter(dummy: DummyClass) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nullableStringProperty = makeNS() as String?
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_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]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -489,20 +489,20 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole09testOptToE14PropertySetterySo10DummyClassC5dummy_tF
func testOptToOptPropertySetter(dummy: DummyClass) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
dummy.nullableStringProperty = makeOptNS() as String?
// CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
- // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
+ // CHECK-NEXT: [[METHOD:%.*]] = objc_method
// CHECK-NEXT: apply [[METHOD]]([[ARG]], [[SELF]])
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: end_borrow [[SELF]] from %0
@@ -518,11 +518,11 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole23testNonnullSubscriptSetySo0eF0C6object_yXl5indextF
func testNonnullSubscriptSet(object: NonnullSubscript, index: AnyObject) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
@@ -535,12 +535,12 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole24testNullableSubscriptSetySo0eF0C6object_yXl5indextF
func testNullableSubscriptSet(object: NullableSubscript, index: AnyObject) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
@@ -548,12 +548,12 @@
object[index] = makeNS() as String
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
@@ -561,11 +561,11 @@
object[index] = makeNS() as String?
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
@@ -578,12 +578,12 @@
// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole25testNullproneSubscriptSetySo0eF0C6object_yXl5indextF
func testNullproneSubscriptSet(object: NullproneSubscript, index: AnyObject) {
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
@@ -591,12 +591,12 @@
object[index] = makeNS() as String
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole6makeNSSo8NSStringCyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK-NEXT: [[OPTARG:%.*]] = enum $Optional<NSString>, #Optional.some!enumelt.1, [[ARG]]
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
@@ -604,11 +604,11 @@
object[index] = makeNS() as String?
// CHECK: [[SELF:%.*]] = begin_borrow %0
- // CHECK: [[METHOD:%.*]] = objc_method
// CHECK: [[MAKE:%.*]] = function_ref @_T022objc_bridging_peephole9makeOptNSSo8NSStringCSgyF
// CHECK-NEXT: [[ARG:%.*]] = apply [[MAKE]]()
// CHECK: [[BRIDGE_TO_ID:%.*]] = function_ref @_T0s27_bridgeAnythingToObjectiveCyXlxlF
// 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]]
diff --git a/test/SILGen/objc_currying.swift b/test/SILGen/objc_currying.swift
index 74c9e38..7818504 100644
--- a/test/SILGen/objc_currying.swift
+++ b/test/SILGen/objc_currying.swift
@@ -13,8 +13,8 @@
// CHECK-LABEL: sil hidden @_T013objc_currying9curry_podS2icSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
// CHECK: bb0([[ARG1:%.*]] : @owned $CurryTest):
// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
-// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_FOO_1:_T0So9CurryTestC3podS2iFTcTO]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
// CHECK: [[COPIED_ARG1:%.*]] = copy_value [[BORROWED_ARG1]]
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_FOO_1:_T0So9CurryTestC3podS2iFTcTO]] : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (Int) -> Int
// CHECK: [[FN:%.*]] = apply [[THUNK]]([[COPIED_ARG1]])
// CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
// CHECK: destroy_value [[ARG1]]
@@ -42,8 +42,8 @@
// CHECK-LABEL: sil hidden @_T013objc_currying13curry_bridgedSQySSGACcSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned (@owned Optional<String>) -> @owned Optional<String>
// CHECK: bb0([[ARG1:%.*]] : @owned $CurryTest):
// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
-// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_BAR_1:_T0So9CurryTestC7bridgedSQySSGADFTcTO]]
// CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]]
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_BAR_1:_T0So9CurryTestC7bridgedSQySSGADFTcTO]]
// CHECK: [[FN:%.*]] = apply [[THUNK]]([[ARG1_COPY]])
// CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
// CHECK: destroy_value [[ARG1]]
@@ -103,8 +103,8 @@
// CHECK-LABEL: sil hidden @_T013objc_currying25curry_returnsInnerPointerSQySvGycSo9CurryTestCF : $@convention(thin) (@owned CurryTest) -> @owned @callee_owned () -> Optional<UnsafeMutableRawPointer> {
// CHECK: bb0([[SELF:%.*]] : @owned $CurryTest):
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
-// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER:_T0So9CurryTestC19returnsInnerPointerSQySvGyFTcTO]]
// CHECK: [[SELF_COPY:%.*]] = copy_value [[BORROWED_SELF]]
+// CHECK: [[THUNK:%.*]] = function_ref @[[THUNK_RETURNSINNERPOINTER:_T0So9CurryTestC19returnsInnerPointerSQySvGyFTcTO]]
// CHECK: [[FN:%.*]] = apply [[THUNK]]([[SELF_COPY]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
// CHECK: destroy_value [[SELF]]
diff --git a/test/SILGen/objc_dealloc.swift b/test/SILGen/objc_dealloc.swift
index 3df7cad..e9bcfbf 100644
--- a/test/SILGen/objc_dealloc.swift
+++ b/test/SILGen/objc_dealloc.swift
@@ -12,8 +12,8 @@
var x = X()
// CHECK-LABEL: sil hidden [transparent] @_T012objc_dealloc10SwiftGizmoC1xAA1XCvpfi : $@convention(thin) () -> @owned X
+ // CHECK: [[METATYPE:%.*]] = metatype $@thick X.Type
// CHECK: [[FN:%.*]] = function_ref @_T012objc_dealloc1XCACycfC : $@convention(method) (@thick X.Type) -> @owned X
- // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick X.Type
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]([[METATYPE]]) : $@convention(method) (@thick X.Type) -> @owned X
// CHECK-NEXT: return [[RESULT]] : $X
diff --git a/test/SILGen/objc_extensions.swift b/test/SILGen/objc_extensions.swift
index df804d8..1d5ddfc 100644
--- a/test/SILGen/objc_extensions.swift
+++ b/test/SILGen/objc_extensions.swift
@@ -75,10 +75,6 @@
// CHECK: destroy_value [[UPCAST_SELF_COPY]]
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[UPCAST_SELF_COPY:%.*]] = upcast [[SELF_COPY]] : $Sub to $Base
- // 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: end_borrow [[BORROWED_UPCAST_SELF]]
// 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]+]]
@@ -86,14 +82,17 @@
// 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: [[DIDSET_NOTIFIER:%.*]] = function_ref @_T015objc_extensions3SubC4propSQySSGvW : $@convention(method) (@owned Optional<String>, @guaranteed Sub) -> ()
// CHECK: [[BORROWED_OLD_NSSTRING_BRIDGED:%.*]] = begin_borrow [[OLD_NSSTRING_BRIDGED]]
// CHECK: [[COPIED_OLD_NSSTRING_BRIDGED:%.*]] = copy_value [[BORROWED_OLD_NSSTRING_BRIDGED]]
// CHECK: end_borrow [[BORROWED_OLD_NSSTRING_BRIDGED]] from [[OLD_NSSTRING_BRIDGED]]
// This is an identity cast that should be eliminated by SILGen peepholes.
+ // CHECK: [[DIDSET_NOTIFIER:%.*]] = function_ref @_T015objc_extensions3SubC4propSQySSGvW : $@convention(method) (@owned Optional<String>, @guaranteed Sub) -> ()
// CHECK: apply [[DIDSET_NOTIFIER]]([[COPIED_OLD_NSSTRING_BRIDGED]], [[SELF]])
// CHECK: destroy_value [[OLD_NSSTRING_BRIDGED]]
// CHECK: destroy_value [[NEW_VALUE]]
diff --git a/test/SILGen/objc_factory_init.swift b/test/SILGen/objc_factory_init.swift
index f0e6ed4..8825e70 100644
--- a/test/SILGen/objc_factory_init.swift
+++ b/test/SILGen/objc_factory_init.swift
@@ -30,11 +30,11 @@
// CHECK: [[BORROWED_SELF:%.*]] = load_borrow [[PB_BOX]]
// CHECK: [[META:%[0-9]+]] = value_metatype $@thick Hive.Type, [[BORROWED_SELF]] : $Hive
// CHECK: end_borrow [[BORROWED_SELF]] from [[PB_BOX]]
- // CHECK: [[FACTORY:%[0-9]+]] = objc_method [[META]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[META]] : $@thick Hive.Type to $@objc_metatype Hive.Type
// CHECK: [[BORROWED_QUEEN:%.*]] = begin_borrow [[QUEEN]]
// CHECK: [[COPIED_BORROWED_QUEEN:%.*]] = copy_value [[BORROWED_QUEEN]]
// CHECK: [[OPT_COPIED_BORROWED_QUEEN:%.*]] = enum $Optional<Bee>, #Optional.some!enumelt.1, [[COPIED_BORROWED_QUEEN]]
+ // CHECK: [[FACTORY:%[0-9]+]] = objc_method [[OBJC_META]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: [[NEW_HIVE:%.*]] = apply [[FACTORY]]([[OPT_COPIED_BORROWED_QUEEN]], [[OBJC_META]]) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: destroy_value [[OPT_COPIED_BORROWED_QUEEN]]
// CHECK: end_borrow [[BORROWED_QUEEN]] from [[QUEEN]]
@@ -88,9 +88,9 @@
// CHECK: [[UPCAST_BORROWED_SELF:%.*]] = upcast [[BORROWED_SELF]] : $SubHive to $Hive
// CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[UPCAST_BORROWED_SELF:%.*]]
// CHECK: end_borrow [[BORROWED_SELF]] from [[PB_BOX]]
- // CHECK: [[HIVE_INIT_FN:%.*]] = objc_method [[METATYPE]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign
// CHECK: [[OBJC_METATYPE:%.*]] = thick_to_objc_metatype [[METATYPE]]
// CHECK: [[QUEEN:%.*]] = unchecked_ref_cast {{.*}} : $Bee to $Optional<Bee>
+ // CHECK: [[HIVE_INIT_FN:%.*]] = objc_method [[OBJC_METATYPE]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign
// CHECK: apply [[HIVE_INIT_FN]]([[QUEEN]], [[OBJC_METATYPE]]) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: destroy_value [[QUEEN]]
// CHECK: } // end sil function '_T017objc_factory_init7SubHiveCACyt20delegatesToInherited_tcfc'
diff --git a/test/SILGen/objc_imported_generic.swift b/test/SILGen/objc_imported_generic.swift
index 8029b99..bb6a747 100644
--- a/test/SILGen/objc_imported_generic.swift
+++ b/test/SILGen/objc_imported_generic.swift
@@ -107,8 +107,8 @@
}
// CHECK-LABEL: sil private @_T021objc_imported_generic0C4FuncyxmRlzClFyycfU_ : $@convention(thin) <V where V : AnyObject> () -> () {
-// CHECK: [[INIT:%.*]] = function_ref @_T0So12GenericClassCAByxGycfC : $@convention(method) <τ_0_0 where τ_0_0 : AnyObject> (@thick GenericClass<τ_0_0>.Type) -> @owned GenericClass<τ_0_0>
// CHECK: [[META:%.*]] = metatype $@thick GenericClass<V>.Type
+// CHECK: [[INIT:%.*]] = function_ref @_T0So12GenericClassCAByxGycfC : $@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) {
diff --git a/test/SILGen/objc_init_ref_delegation.swift b/test/SILGen/objc_init_ref_delegation.swift
index 078e725..f397306b2 100644
--- a/test/SILGen/objc_init_ref_delegation.swift
+++ b/test/SILGen/objc_init_ref_delegation.swift
@@ -13,8 +13,7 @@
// CHECK: [[PB_BOX:%.*]] = project_box [[MARKED_SELF_BOX]]
// CHECK: store [[ORIG_SELF]] to [init] [[PB_BOX]] : $*Gizmo
// CHECK: [[SELF:%[0-9]+]] = load [take] [[PB_BOX]] : $*Gizmo
- // CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
- // CHECK: [[INIT_DELEG:%[0-9]+]] = objc_method [[BORROWED_SELF]] : $Gizmo, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo!, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
+ // CHECK: [[INIT_DELEG:%[0-9]+]] = objc_method [[SELF]] : $Gizmo, #Gizmo.init!initializer.1.foreign : (Gizmo.Type) -> (Int) -> Gizmo!, $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
// CHECK: [[SELF_RET:%[0-9]+]] = apply [[INIT_DELEG]]([[I]], [[SELF]]) : $@convention(objc_method) (Int, @owned Gizmo) -> @owned Optional<Gizmo>
// CHECK: [[SELF4:%.*]] = load [copy] [[PB_BOX]]
// CHECK: destroy_value [[MARKED_SELF_BOX]]
diff --git a/test/SILGen/objc_ownership_conventions.swift b/test/SILGen/objc_ownership_conventions.swift
index 6b36fa4..d25a82f 100644
--- a/test/SILGen/objc_ownership_conventions.swift
+++ b/test/SILGen/objc_ownership_conventions.swift
@@ -8,8 +8,8 @@
func test3() -> NSObject {
// initializer returns at +1
return Gizmo()
+ // CHECK: [[GIZMO_META:%[0-9]+]] = metatype $@thick Gizmo.Type
// CHECK: [[CTOR:%[0-9]+]] = function_ref @_T0So5GizmoC{{[_0-9a-zA-Z]*}}fC : $@convention(method) (@thick Gizmo.Type) -> @owned Optional<Gizmo>
- // CHECK-NEXT: [[GIZMO_META:%[0-9]+]] = metatype $@thick Gizmo.Type
// 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
@@ -40,13 +40,12 @@
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
- // CHECK: [[CLASS:%.*]] = metatype $@thick Gizmo.Type
- // CHECK: [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.inspect!1.foreign
- // CHECK: [[OBJC_CLASS:%[0-9]+]] = thick_to_objc_metatype [[CLASS]] : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
+ // 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: apply [[METHOD]]([[G]], [[OBJC_CLASS]])
+ // CHECK: [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.inspect!1.foreign
+ // CHECK: apply [[METHOD]]([[G]], [[CLASS]])
// CHECK: destroy_value [[G]]
// CHECK: destroy_value [[GIZMO_BOX]]
// CHECK: destroy_value [[ARG]]
@@ -65,13 +64,12 @@
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: store [[ARG_COPY]] to [init] [[GIZMO_BOX_PB]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
- // CHECK: [[CLASS:%.*]] = metatype $@thick Gizmo.Type
- // CHECK: [[METHOD:%.*]] = objc_method [[CLASS]] : {{.*}}, #Gizmo.consume!1.foreign
- // CHECK: [[OBJC_CLASS:%.*]] = thick_to_objc_metatype [[CLASS]] : $@thick Gizmo.Type to $@objc_metatype Gizmo.Type
+ // 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: apply [[METHOD]]([[G]], [[OBJC_CLASS]])
+ // 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]]
@@ -94,8 +92,7 @@
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[GIZMO_BOX_PB]] : $*Gizmo
// CHECK: [[G:%.*]] = load [copy] [[READ]]
- // CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
- // CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_G]] : {{.*}}, #Gizmo.fork!1.foreign
+ // CHECK: [[METHOD:%.*]] = objc_method [[G]] : {{.*}}, #Gizmo.fork!1.foreign
// CHECK: apply [[METHOD]]([[G]])
// CHECK-NOT: destroy_value [[G]]
// CHECK: destroy_value [[GIZMO_BOX]]
@@ -113,10 +110,10 @@
// CHECK-NOT: copy_value
// CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
// CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_G]] : {{.*}}, #Gizmo.clone!1.foreign
+ // CHECK: end_borrow [[BORROWED_G]] from [[G]]
// CHECK-NOT: copy_value [[RESULT]]
// CHECK: bb2([[RESULT:%.*]] : @owned $Gizmo):
// CHECK-NOT: copy_value [[RESULT]]
- // CHECK: end_borrow [[BORROWED_G]] from [[G]]
// CHECK-NEXT: destroy_value [[G]]
// CHECK-NEXT: return [[RESULT]]
}
@@ -129,10 +126,10 @@
// CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
// CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_G]] : {{.*}}, #Gizmo.duplicate!1.foreign
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[BORROWED_G]])
+ // CHECK: end_borrow [[BORROWED_G]] from [[G]]
// CHECK-NOT: copy_value [[RESULT]]
// CHECK: bb2([[RESULT:%.*]] : @owned $Gizmo):
// CHECK-NOT: copy_value [[RESULT]]
- // CHECK: end_borrow [[BORROWED_G]] from [[G]]
// CHECK-NEXT: destroy_value [[G]]
// CHECK-NEXT: return [[RESULT]]
}
@@ -143,9 +140,7 @@
// CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
// CHECK: [[G_COPY:%.*]] = copy_value [[BORROWED_G]]
// CHECK-NEXT: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY]] : $Gizmo to $NSObject
- // CHECK-NEXT: [[BORROWED_NS_G_COPY:%.*]] = begin_borrow [[NS_G_COPY]]
- // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[BORROWED_NS_G_COPY]] : $NSObject, #NSObject.classProp!getter.1.foreign : (NSObject) -> () -> AnyObject.Type!, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype AnyObject.Type>
- // CHECK-NEXT: end_borrow [[BORROWED_NS_G_COPY]]
+ // 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]+]]
//
@@ -165,9 +160,7 @@
// CHECK: [[BORROWED_G:%.*]] = begin_borrow [[G]]
// CHECK: [[G_COPY:%.*]] = copy_value [[BORROWED_G]]
// CHECK: [[NS_G_COPY:%[0-9]+]] = upcast [[G_COPY:%[0-9]+]] : $Gizmo to $NSObject
- // CHECK: [[BORROWED_NS_G_COPY:%.*]] = begin_borrow [[NS_G_COPY]]
- // CHECK-NEXT: [[GETTER:%[0-9]+]] = objc_method [[BORROWED_NS_G_COPY]] : $NSObject, #NSObject.qualifiedClassProp!getter.1.foreign : (NSObject) -> () -> NSAnsing.Type!, $@convention(objc_method) (NSObject) -> Optional<@objc_metatype NSAnsing.Type>
- // CHECK-NEXT: end_borrow [[BORROWED_NS_G_COPY]]
+ // 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]+]]
//
@@ -215,7 +208,6 @@
// Handle inner-pointer methods by autoreleasing self after the call.
// CHECK-LABEL: sil hidden @_T026objc_ownership_conventions18innerPointerMethodySo5GizmoCF : $@convention(thin) (@owned Gizmo) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $Gizmo):
-// CHECK: [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_ARG]] : $Gizmo, #Gizmo.getBytes!1.foreign : (Gizmo) -> () -> UnsafeMutableRawPointer, $@convention(objc_method) (Gizmo) -> @unowned_inner_pointer UnsafeMutableRawPointer
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
@@ -223,6 +215,7 @@
// it is today though since we are using a reference type.
// CHECK: [[PTR:%.*]] = apply [[METHOD]]([[BORROWED_ARG]])
// CHECK: autorelease_value [[ARG_COPY]]
+// CHECK: [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[USE]]([[PTR]])
// CHECK: destroy_value [[ARG]]
func innerPointerMethod(_ g: Gizmo) {
@@ -231,13 +224,13 @@
// CHECK-LABEL: sil hidden @_T026objc_ownership_conventions20innerPointerPropertyySo5GizmoCF : $@convention(thin) (@owned Gizmo) -> () {
// CHECK: bb0([[ARG:%.*]] : @owned $Gizmo):
-// CHECK: [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_ARG]] : $Gizmo, #Gizmo.innerProperty!getter.1.foreign : (Gizmo) -> () -> UnsafeMutableRawPointer, $@convention(objc_method) (Gizmo) -> @unowned_inner_pointer UnsafeMutableRawPointer
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_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]]([[BORROWED_ARG]])
// CHECK: autorelease_value [[ARG_COPY]]
+// CHECK: [[USE:%.*]] = function_ref @_T026objc_ownership_conventions15useInnerPointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[USE]]([[PTR]])
// CHECK: destroy_value [[ARG]]
// CHECK: } // end sil function '_T026objc_ownership_conventions20innerPointerPropertyySo5GizmoCF'
diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift
index 6918532..7a3b8c1 100644
--- a/test/SILGen/objc_protocols.swift
+++ b/test/SILGen/objc_protocols.swift
@@ -27,14 +27,14 @@
// CHECK-LABEL: sil hidden @_T014objc_protocols0A8_generic{{[_0-9a-zA-Z]*}}F
// CHECK: bb0([[THIS:%.*]] : @owned $T):
// -- Result of runce is autoreleased according to default objc conv
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}}, #NSRuncing.runce!1.foreign
// CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}}, #NSRuncing.runce!1.foreign
// CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<T>([[BORROWED_THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @autoreleased NSObject
// CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
// -- Result of copyRuncing is received copy_valued according to -copy family
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}}, #NSRuncing.copyRuncing!1.foreign
// CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
+// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}}, #NSRuncing.copyRuncing!1.foreign
// CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<T>([[BORROWED_THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @owned NSObject
// CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
@@ -47,9 +47,9 @@
// CHECK-LABEL: sil hidden @_T014objc_protocols0A22_generic_partial_applyyxAA9NSRuncingRzlF : $@convention(thin) <T where T : NSRuncing> (@owned T) -> () {
func objc_generic_partial_apply<T : NSRuncing>(_ x: T) {
// CHECK: bb0([[ARG:%.*]] : @owned $T):
- // CHECK: [[FN:%.*]] = function_ref @[[THUNK1:_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO]] :
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
+ // CHECK: [[FN:%.*]] = function_ref @[[THUNK1:_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO]] :
// CHECK: [[METHOD:%.*]] = apply [[FN]]<T>([[ARG_COPY]])
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: destroy_value [[METHOD]]
@@ -60,8 +60,8 @@
// CHECK: destroy_value [[METHOD]]
_ = T.runce
- // CHECK: [[FN:%.*]] = function_ref @[[THUNK2:_T014objc_protocols9NSRuncingP5minceSo8NSObjectCyFZTcTO]]
// CHECK: [[METATYPE:%.*]] = metatype $@thick T.Type
+ // CHECK: [[FN:%.*]] = function_ref @[[THUNK2:_T014objc_protocols9NSRuncingP5minceSo8NSObjectCyFZTcTO]]
// CHECK: [[METHOD:%.*]] = apply [[FN]]<T>([[METATYPE]])
// CHECK: destroy_value [[METHOD:%.*]]
_ = T.mince
@@ -124,8 +124,8 @@
// CHECK: bb0([[ARG:%.*]] : @owned $NSRuncing):
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[OPENED_ARG:%.*]] = open_existential_ref [[BORROWED_ARG]] : $NSRuncing to $[[OPENED:@opened(.*) NSRuncing]]
- // CHECK: [[FN:%.*]] = function_ref @_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO
// CHECK: [[OPENED_ARG_COPY:%.*]] = copy_value [[OPENED_ARG]]
+ // CHECK: [[FN:%.*]] = function_ref @_T014objc_protocols9NSRuncingP5runceSo8NSObjectCyFTcTO
// CHECK: [[RESULT:%.*]] = apply [[FN]]<[[OPENED]]>([[OPENED_ARG_COPY]])
// CHECK: destroy_value [[RESULT]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
diff --git a/test/SILGen/objc_required_designated_init.swift b/test/SILGen/objc_required_designated_init.swift
index 546aa21..fad2ba2 100644
--- a/test/SILGen/objc_required_designated_init.swift
+++ b/test/SILGen/objc_required_designated_init.swift
@@ -1,19 +1,39 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -enable-sil-ownership %S/Inputs/objc_required_designated_init_2.swift -module-name Booms -o %t/Booms.swiftmodule -import-objc-header %S/Inputs/objc_required_designated_init.h
-// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -verify %s -import-objc-header %S/Inputs/objc_required_designated_init.h
+// RUN: %target-swift-frontend -I %t -emit-silgen -enable-sil-ownership -verify %s -import-objc-header %S/Inputs/objc_required_designated_init.h | %FileCheck %s
+// RUN: %target-swift-frontend -I %t -emit-ir %s -import-objc-header %S/Inputs/objc_required_designated_init.h
// REQUIRES: objc_interop
import Booms
-class Baboom: Boom {
+class Baboom : Boom {
+ @objc dynamic required init() {
+ super.init()
+ }
+}
+
+class BigBadaBoom<V> : Badaboom<V> {
required init() {
super.init()
}
}
-class BigBadaBoom<V>: Badaboom<V> {
- required init() {
- super.init()
- }
+class Root {
+ @objc dynamic required init() {}
}
+
+// CHECK-LABEL: sil_vtable Baboom {
+// CHECK: #Boom.init!allocator.1: (Boom.Type) -> () -> Boom : _T029objc_required_designated_init6BaboomCACycfC [override]
+// CHECK: #Baboom.deinit!deallocator: _T029objc_required_designated_init6BaboomCfD
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable BigBadaBoom {
+// CHECK: #Badaboom.init!allocator.1: <U> (Badaboom<U>.Type) -> () -> Badaboom<U> : _T029objc_required_designated_init11BigBadaBoomCACyxGycfC [override]
+// CHECK: #BigBadaBoom.deinit!deallocator: _T029objc_required_designated_init11BigBadaBoomCfD
+// CHECK: }
+
+// CHECK-LABEL: sil_vtable Root {
+// CHECK: #Root.init!allocator.1: (Root.Type) -> () -> Root : _T029objc_required_designated_init4RootCACycfC
+// CHECK: #Root.deinit!deallocator: _T029objc_required_designated_init4RootCfD
+// CHECK: }
diff --git a/test/SILGen/objc_thunks.swift b/test/SILGen/objc_thunks.swift
index 91ce7d3..7651ba2 100644
--- a/test/SILGen/objc_thunks.swift
+++ b/test/SILGen/objc_thunks.swift
@@ -106,7 +106,7 @@
// 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]] : $(), scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:13:auto_gen
+ // CHECK: return [[RES]] : $(), loc {{.*}}, scope {{.*}} // id: {{.*}} line:[[@LINE-34]]:13:auto_gen
// CHECK: } // end sil function '_T011objc_thunks6HoozitC15typicalPropertySo5GizmoCvsTo'
// CHECK-LABEL: sil hidden @_T011objc_thunks6HoozitC15typicalPropertySo5GizmoCvs
@@ -492,10 +492,10 @@
override init() { i = 5 }
// CHECK-LABEL: sil hidden @_T011objc_thunks15DesignatedStubsCSQyACGSi7bellsOn_tcfc
- // CHECK: function_ref @_T0s25_unimplementedInitializers5NeverOs12StaticStringV9className_AE04initG0AE4fileSu4lineSu6columntF
// CHECK: string_literal utf8 "objc_thunks.DesignatedStubs"
// CHECK: string_literal utf8 "init(bellsOn:)"
// CHECK: string_literal utf8 "{{.*}}objc_thunks.swift"
+ // CHECK: function_ref @_T0s25_unimplementedInitializers5NeverOs12StaticStringV9className_AE04initG0AE4fileSu4lineSu6columntF
// CHECK: return
// CHECK-NOT: sil hidden @_TFCSo15DesignatedStubsc{{.*}}
diff --git a/test/SILGen/opaque_ownership.swift b/test/SILGen/opaque_ownership.swift
index f1c6b63..4ff4926 100644
--- a/test/SILGen/opaque_ownership.swift
+++ b/test/SILGen/opaque_ownership.swift
@@ -242,15 +242,15 @@
// ---
// CHECK-LABEL: sil @_T0s7EnumSeqV12makeIterators0A4IterVy0D0QzGyF : $@convention(method) <Base where Base : Seq> (@in_guaranteed EnumSeq<Base>) -> @out EnumIter<Base.Iterator> {
// CHECK: bb0(%0 : @guaranteed $EnumSeq<Base>):
-// CHECK: [[FN:%.*]] = function_ref @_T0s8EnumIterVAByxGx5_base_tcfC : $@convention(method) <τ_0_0 where τ_0_0 : IP> (@in τ_0_0, @thin EnumIter<τ_0_0>.Type) -> @out EnumIter<τ_0_0>
// CHECK: [[MT:%.*]] = metatype $@thin EnumIter<Base.Iterator>.Type
-// 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: [[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 @_T0s8EnumIterVAByxGx5_base_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 '_T0s7EnumSeqV12makeIterators0A4IterVy0D0QzGyF'
diff --git a/test/SILGen/opaque_values_silgen.swift b/test/SILGen/opaque_values_silgen.swift
index 41815bc..d5a8939 100644
--- a/test/SILGen/opaque_values_silgen.swift
+++ b/test/SILGen/opaque_values_silgen.swift
@@ -255,8 +255,8 @@
// ---
// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s070__materializeSelfyx1t_tRlzCAA3FooRzlF : $@convention(thin) <T where T : AnyObject, T : Foo> (@owned 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: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
+// 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>([[BORROWED_ARG]]) : $@convention(witness_method: Foo) <τ_0_0 where τ_0_0 : Foo> (@in_guaranteed τ_0_0) -> ()
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: destroy_value [[ARG]] : $T
diff --git a/test/SILGen/optional-cast.swift b/test/SILGen/optional-cast.swift
index 221181b..a5a6e32 100644
--- a/test/SILGen/optional-cast.swift
+++ b/test/SILGen/optional-cast.swift
@@ -221,7 +221,7 @@
// CHECK: bb0(%0 : @trivial $*Optional<T>, %1 : @trivial $TestAddressOnlyStruct<T>):
// CHECK: [[TMPBUF:%.*]] = alloc_stack $Optional<T>
// CHECK-NEXT: copy_addr %0 to [initialization] [[TMPBUF]]
- // CHECK-NEXT: apply {{.*}}<T>([[TMPBUF]], %1)
+ // CHECK: apply {{.*}}<T>([[TMPBUF]], %1)
func testCall(_ a : T!) {
f(a)
}
diff --git a/test/SILGen/partial_apply_generic.swift b/test/SILGen/partial_apply_generic.swift
index 70dbbfc..e2fd33e 100644
--- a/test/SILGen/partial_apply_generic.swift
+++ b/test/SILGen/partial_apply_generic.swift
@@ -35,9 +35,9 @@
// CHECK-LABEL: sil hidden @_T021partial_apply_generic16getInstanceFunc1{{[_0-9a-zA-Z]*}}F
func getInstanceFunc1<T: Foo>(t: T) -> () -> () {
-// CHECK: [[REF:%.*]] = function_ref @_T021partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
-// CHECK-NEXT: alloc_stack $T
+// CHECK: alloc_stack $T
// CHECK-NEXT: copy_addr %0 to [initialization]
+// CHECK: [[REF:%.*]] = function_ref @_T021partial_apply_generic3FooP12instanceFunc{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: apply [[REF]]<T>
return t.instanceFunc
// CHECK-NEXT: dealloc_stack
diff --git a/test/SILGen/partial_apply_super.swift b/test/SILGen/partial_apply_super.swift
index cdc867f..512f820 100644
--- a/test/SILGen/partial_apply_super.swift
+++ b/test/SILGen/partial_apply_super.swift
@@ -31,12 +31,12 @@
class Child : Parent {
// CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC6methodyyF : $@convention(method) (@guaranteed Child) -> ()
// CHECK: bb0([[SELF:%.*]] : $Child):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// 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 @_T019partial_apply_super6ParentC6methodyyFTcTd : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super5ChildC6methodyyF'
override func method() {
@@ -44,11 +44,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC11classMethodyyFZ : $@convention(method) (@thick Child.Type) -> () {
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick Child.Type to $@thick Parent.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super6ParentC11classMethodyyFZTcTd : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
@@ -56,12 +56,12 @@
// CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC20callFinalSuperMethodyyF : $@convention(method) (@guaranteed Child) -> ()
// CHECK: bb0([[SELF:%.*]] : $Child):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// 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 @_T019partial_apply_super6ParentC11finalMethodyyFTc : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
// CHECK: [[APPLIED_SELF:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(thin) (@owned Parent) -> @owned @callee_owned () -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_SELF]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super5ChildC20callFinalSuperMethodyyF'
func callFinalSuperMethod() {
@@ -69,11 +69,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super5ChildC25callFinalSuperClassMethodyyFZ : $@convention(method) (@thick Child.Type) -> ()
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick Child.Type to $@thick Parent.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super6ParentC16finalClassMethodyyFZTc : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
// CHECK: [[APPLIED_SELF:%[0-9]+]] = apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(thin) (@thick Parent.Type) -> @owned @callee_owned () -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_SELF]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
class func callFinalSuperClassMethod() {
doFoo(super.finalClassMethod)
@@ -86,12 +86,12 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super12GenericChildC6methodyyF : $@convention(method) <A> (@guaranteed GenericChild<A>) -> ()
// CHECK: bb0([[SELF:%.*]] : $GenericChild<A>):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChild<A> to $GenericParent<A>
// CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super13GenericParentC6methodyyFTcTd : $@convention(thin) <τ_0_0> (@owned GenericParent<τ_0_0>) -> @owned @callee_owned () -> ()
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(thin) <τ_0_0> (@owned GenericParent<τ_0_0>) -> @owned @callee_owned () -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super12GenericChildC6methodyyF'
override func method() {
@@ -99,12 +99,12 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super12GenericChildC11classMethodyyFZ : $@convention(method) <A> (@thick GenericChild<A>.Type) -> ()
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GenericChild<A>.Type to $@thick GenericParent<A>.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = function_ref @_T019partial_apply_super13GenericParentC11classMethodyyFZTcTd : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_owned () -> ()
- // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply %4<A>(%3) : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_owned () -> ()
+ // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(thin) <τ_0_0> (@thick GenericParent<τ_0_0>.Type) -> @owned @callee_owned () -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
- // CHECK: apply %2([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
+ // CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
}
@@ -113,7 +113,6 @@
class ChildToFixedOutsideParent : OutsideParent {
// CHECK-LABEL: sil hidden @_T019partial_apply_super25ChildToFixedOutsideParentC6methodyyF
// CHECK: bb0([[SELF:%.*]] : $ChildToFixedOutsideParent):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $ChildToFixedOutsideParent to $OutsideParent
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -122,6 +121,7 @@
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideParent) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super25ChildToFixedOutsideParentC6methodyyF'
override func method() {
@@ -129,11 +129,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super25ChildToFixedOutsideParentC11classMethodyyFZ
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick ChildToFixedOutsideParent.Type to $@thick OutsideParent.Type
- // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick ChildToFixedOutsideParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> (){{.*}} // user: %5
+ // CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick ChildToFixedOutsideParent.Type, #OutsideParent.classMethod!1 : (OutsideParent.Type) -> () -> (), $@convention(method) (@thick OutsideParent.Type) -> (){{.*}}
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideParent.Type) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
@@ -143,7 +143,6 @@
class ChildToResilientOutsideParent : ResilientOutsideParent {
// CHECK-LABEL: sil hidden @_T019partial_apply_super29ChildToResilientOutsideParentC6methodyyF
// CHECK: bb0([[SELF:%.*]] : $ChildToResilientOutsideParent):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $ChildToResilientOutsideParent to $ResilientOutsideParent
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -152,6 +151,7 @@
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideParent) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super29ChildToResilientOutsideParentC6methodyyF'
override func method() {
@@ -159,11 +159,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super29ChildToResilientOutsideParentC11classMethodyyFZ
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick ChildToResilientOutsideParent.Type to $@thick ResilientOutsideParent.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick ChildToResilientOutsideParent.Type, #ResilientOutsideParent.classMethod!1 : (ResilientOutsideParent.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideParent.Type) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
@@ -173,7 +173,6 @@
class GrandchildToFixedOutsideChild : OutsideChild {
// CHECK-LABEL: sil hidden @_T019partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF
// CHECK: bb0([[SELF:%.*]] : $GrandchildToFixedOutsideChild):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GrandchildToFixedOutsideChild to $OutsideChild
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -182,6 +181,7 @@
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed OutsideChild) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super29GrandchildToFixedOutsideChildC6methodyyF'
override func method() {
@@ -189,11 +189,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super29GrandchildToFixedOutsideChildC11classMethodyyFZ
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GrandchildToFixedOutsideChild.Type to $@thick OutsideChild.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick GrandchildToFixedOutsideChild.Type, #OutsideChild.classMethod!1 : (OutsideChild.Type) -> () -> (), $@convention(method) (@thick OutsideChild.Type) -> ()
- // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply %4(%3) : $@convention(method) (@thick OutsideChild.Type) -> ()
+ // CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick OutsideChild.Type) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
@@ -203,7 +203,6 @@
class GrandchildToResilientOutsideChild : ResilientOutsideChild {
// CHECK-LABEL: sil hidden @_T019partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF
// CHECK: bb0([[SELF:%.*]] : $GrandchildToResilientOutsideChild):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GrandchildToResilientOutsideChild to $ResilientOutsideChild
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -212,6 +211,7 @@
// CHEC: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF_COPY]]) : $@convention(method) (@guaranteed ResilientOutsideChild) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super33GrandchildToResilientOutsideChildC6methodyyF'
override func method() {
@@ -219,11 +219,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super33GrandchildToResilientOutsideChildC11classMethodyyFZ
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GrandchildToResilientOutsideChild.Type to $@thick ResilientOutsideChild.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = super_method %0 : $@thick GrandchildToResilientOutsideChild.Type, #ResilientOutsideChild.classMethod!1 : (ResilientOutsideChild.Type) -> () -> (), $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]([[CASTED_SELF]]) : $@convention(method) (@thick ResilientOutsideChild.Type) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
@@ -233,7 +233,6 @@
class GenericChildToFixedGenericOutsideParent<A> : GenericOutsideParent<A> {
// CHECK-LABEL: sil hidden @_T019partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF
// CHECK: bb0([[SELF:%.*]] : $GenericChildToFixedGenericOutsideParent<A>):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChildToFixedGenericOutsideParent<A> to $GenericOutsideParent<A>
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -242,6 +241,7 @@
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed GenericOutsideParent<τ_0_0>) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super019GenericChildToFixedD13OutsideParentC6methodyyF'
override func method() {
@@ -249,11 +249,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super019GenericChildToFixedD13OutsideParentC11classMethodyyFZ
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GenericChildToFixedGenericOutsideParent<A>.Type to $@thick GenericOutsideParent<A>.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = 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:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick GenericOutsideParent<τ_0_0>.Type) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
@@ -263,7 +263,6 @@
class GenericChildToResilientGenericOutsideParent<A> : ResilientGenericOutsideParent<A> {
// CHECK-LABEL: sil hidden @_T019partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF
// CHECK: bb0([[SELF:%.*]] : $GenericChildToResilientGenericOutsideParent<A>):
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[SELF_COPY:%.*]] = copy_value [[SELF]]
// CHECK: [[CASTED_SELF_COPY:%[0-9]+]] = upcast [[SELF_COPY]] : $GenericChildToResilientGenericOutsideParent<A> to $ResilientGenericOutsideParent<A>
// CHECK: [[BORROWED_CASTED_SELF_COPY:%.*]] = begin_borrow [[CASTED_SELF_COPY]]
@@ -272,6 +271,7 @@
// CHECK: end_borrow [[BORROWED_CASTED_SELF_COPY]] from [[CASTED_SELF_COPY]]
// CHECK: [[PARTIAL_APPLY:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF_COPY]]) : $@convention(method) <τ_0_0> (@guaranteed ResilientGenericOutsideParent<τ_0_0>) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: } // end sil function '_T019partial_apply_super023GenericChildToResilientD13OutsideParentC6methodyyF'
override func method() {
@@ -279,11 +279,11 @@
}
// CHECK-LABEL: sil hidden @_T019partial_apply_super023GenericChildToResilientD13OutsideParentC11classMethodyyFZ
- // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: [[CASTED_SELF:%[0-9]+]] = upcast %0 : $@thick GenericChildToResilientGenericOutsideParent<A>.Type to $@thick ResilientGenericOutsideParent<A>.Type
// CHECK: [[SUPER_METHOD:%[0-9]+]] = 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:%[0-9]+]] = partial_apply [[SUPER_METHOD]]<A>([[CASTED_SELF]]) : $@convention(method) <τ_0_0> (@thick ResilientGenericOutsideParent<τ_0_0>.Type) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[PARTIAL_APPLY]]
+ // CHECK: [[DOFOO:%[0-9]+]] = function_ref @_T019partial_apply_super5doFooyyycF : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
// CHECK: apply [[DOFOO]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> ()) -> ()
override class func classMethod() {
doFoo(super.classMethod)
diff --git a/test/SILGen/pointer_conversion.swift b/test/SILGen/pointer_conversion.swift
index e8ab640..4e3a012 100644
--- a/test/SILGen/pointer_conversion.swift
+++ b/test/SILGen/pointer_conversion.swift
@@ -31,33 +31,33 @@
// CHECK: apply [[TAKES_MUTABLE_POINTER]]([[MP]])
takesMutableVoidPointer(mp)
- // CHECK: [[TAKES_MUTABLE_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesMutableVoidPointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeMutableRawPointer>
+ // CHECK: [[TAKES_MUTABLE_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesMutableVoidPointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_MUTABLE_VOID_POINTER]]
takesMutableRawPointer(mp)
- // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeMutableRawPointer>
+ // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
// CHECK: apply [[TAKES_MUTABLE_RAW_POINTER]]
takesConstPointer(mp)
- // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafePointer<Int>>
+ // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
// CHECK: apply [[TAKES_CONST_POINTER]]
takesConstVoidPointer(mp)
- // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
// CHECK: apply [[TAKES_CONST_VOID_POINTER]]
takesConstRawPointer(mp)
- // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
// CHECK: apply [[TAKES_CONST_RAW_POINTER]]
takesConstPointer(cp)
@@ -65,21 +65,21 @@
// CHECK: apply [[TAKES_CONST_POINTER]]([[CP]])
takesConstVoidPointer(cp)
- // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySVF
// CHECK: apply [[TAKES_CONST_VOID_POINTER]]
takesConstRawPointer(cp)
- // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafePointer<Int>, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
// CHECK: apply [[TAKES_CONST_RAW_POINTER]]
takesConstRawPointer(mrp)
- // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s017_convertPointerToB8Argument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer, UnsafeRawPointer>
+ // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF
// CHECK: apply [[TAKES_CONST_RAW_POINTER]]
}
@@ -88,43 +88,42 @@
var ints = [1,2,3]
takesMutablePointer(&ints)
- // CHECK: [[TAKES_MUTABLE_POINTER:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[CONVERT_MUTABLE:%.*]] = function_ref @_T0s37_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 @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_MUTABLE_POINTER]]([[DEPENDENT]])
// CHECK: destroy_value [[OWNER]]
takesConstPointer(ints)
- // CHECK: [[TAKES_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiGF
// CHECK: [[CONVERT_CONST:%.*]] = function_ref @_T0s35_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 @_T018pointer_conversion17takesConstPointerySPySiGF
// CHECK: apply [[TAKES_CONST_POINTER]]([[DEPENDENT]])
// CHECK: destroy_value [[OWNER]]
takesMutableRawPointer(&ints)
- // CHECK: [[TAKES_MUTABLE_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointerySvF :
// CHECK: [[CONVERT_MUTABLE:%.*]] = function_ref @_T0s37_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 @_T018pointer_conversion22takesMutableRawPointerySvF :
// CHECK: apply [[TAKES_MUTABLE_RAW_POINTER]]([[DEPENDENT]])
// CHECK: destroy_value [[OWNER]]
takesConstRawPointer(ints)
- // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySVF :
// CHECK: [[CONVERT_CONST:%.*]] = function_ref @_T0s35_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 @_T018pointer_conversion20takesConstRawPointerySVF :
// CHECK: apply [[TAKES_CONST_RAW_POINTER]]([[DEPENDENT]])
// CHECK: destroy_value [[OWNER]]
takesOptConstPointer(ints, and: sideEffect1())
- // CHECK: [[TAKES_OPT_CONST_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF :
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
// CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
// CHECK: [[CONVERT_CONST:%.*]] = function_ref @_T0s35_convertConstArrayToPointerArgument{{[_0-9a-zA-Z]*}}F
@@ -132,6 +131,7 @@
// 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 @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF :
// CHECK: apply [[TAKES_OPT_CONST_POINTER]]([[OPTPTR]], [[RESULT1]])
// CHECK: destroy_value [[OWNER]]
}
@@ -139,25 +139,24 @@
// CHECK-LABEL: sil hidden @_T018pointer_conversion15stringToPointerySSF
func stringToPointer(_ s: String) {
takesConstVoidPointer(s)
- // CHECK: [[TAKES_CONST_VOID_POINTER:%.*]] = function_ref @_T018pointer_conversion21takesConstVoidPointerySV{{[_0-9a-zA-Z]*}}F
// CHECK: [[CONVERT_STRING:%.*]] = function_ref @_T0s40_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 @_T018pointer_conversion21takesConstVoidPointerySV{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_CONST_VOID_POINTER]]([[DEPENDENT]])
// CHECK: destroy_value [[OWNER]]
takesConstRawPointer(s)
- // CHECK: [[TAKES_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion20takesConstRawPointerySV{{[_0-9a-zA-Z]*}}F
// CHECK: [[CONVERT_STRING:%.*]] = function_ref @_T0s40_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 @_T018pointer_conversion20takesConstRawPointerySV{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_CONST_RAW_POINTER]]([[DEPENDENT]])
// CHECK: destroy_value [[OWNER]]
takesOptConstRawPointer(s, and: sideEffect1())
- // CHECK: [[TAKES_OPT_CONST_RAW_POINTER:%.*]] = function_ref @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF :
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
// CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
// CHECK: [[CONVERT_STRING:%.*]] = function_ref @_T0s40_convertConstStringToUTF8PointerArgument{{[_0-9a-zA-Z]*}}F
@@ -165,6 +164,7 @@
// 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 @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF :
// CHECK: apply [[TAKES_OPT_CONST_RAW_POINTER]]([[OPTPTR]], [[RESULT1]])
// CHECK: destroy_value [[OWNER]]
}
@@ -175,11 +175,11 @@
// CHECK: [[INT:%.*]] = alloc_box ${ var Int }
// CHECK: [[PB:%.*]] = project_box [[INT]]
takesMutablePointer(&int)
- // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
// CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_MUTABLE]]
var logicalInt: Int {
@@ -187,29 +187,29 @@
set { }
}
takesMutablePointer(&logicalInt)
- // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[GETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivg
// CHECK: apply [[GETTER]]
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<Int>>
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_MUTABLE]]
// CHECK: [[SETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivs
// CHECK: apply [[SETTER]]
takesMutableRawPointer(&int)
- // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
// CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_MUTABLE]]
takesMutableRawPointer(&logicalInt)
- // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[GETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivg
// CHECK: apply [[GETTER]]
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutableRawPointer>
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion22takesMutableRawPointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_MUTABLE]]
// CHECK: [[SETTER:%.*]] = function_ref @_T018pointer_conversion14inoutToPointeryyF10logicalIntL_Sivs
// CHECK: apply [[SETTER]]
@@ -227,15 +227,14 @@
// CHECK: [[VAR:%.*]] = alloc_box ${ var C }
// CHECK: [[PB:%.*]] = project_box [[VAR]]
takesPlusOnePointer(&c)
- // CHECK: [[TAKES_PLUS_ONE:%.*]] = function_ref @_T018pointer_conversion19takesPlusOnePointer{{[_0-9a-zA-Z]*}}F
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
// CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITE]]
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<UnsafeMutablePointer<C>>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_PLUS_ONE:%.*]] = function_ref @_T018pointer_conversion19takesPlusOnePointer{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[TAKES_PLUS_ONE]]
takesPlusZeroPointer(&c)
- // CHECK: [[TAKES_PLUS_ZERO:%.*]] = function_ref @_T018pointer_conversion20takesPlusZeroPointerys026AutoreleasingUnsafeMutableF0VyAA1CCGF
// CHECK: [[WRITEBACK:%.*]] = alloc_stack $@sil_unmanaged C
// CHECK: [[OWNED:%.*]] = load_borrow [[PB]]
// CHECK: [[UNOWNED:%.*]] = ref_to_unmanaged [[OWNED]]
@@ -243,6 +242,7 @@
// CHECK: [[POINTER:%.*]] = address_to_pointer [[WRITEBACK]]
// CHECK: [[CONVERT:%.*]] = function_ref @_T0s30_convertInOutToPointerArgument{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[CONVERT]]<AutoreleasingUnsafeMutablePointer<C>>({{%.*}}, [[POINTER]])
+ // CHECK: [[TAKES_PLUS_ZERO:%.*]] = function_ref @_T018pointer_conversion20takesPlusZeroPointerys026AutoreleasingUnsafeMutableF0VyAA1CCGF
// CHECK: apply [[TAKES_PLUS_ZERO]]
// CHECK: [[UNOWNED_OUT:%.*]] = load [trivial] [[WRITEBACK]]
// CHECK: [[OWNED_OUT:%.*]] = unmanaged_to_ref [[UNOWNED_OUT]]
@@ -280,23 +280,23 @@
// CHECK: store {{.*}} to [init] [[ARRAY]]
var array = [Int]()
- // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointerySpySiG_Si3andtF
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
// CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
// CHECK: [[SIDE2:%.*]] = function_ref @_T018pointer_conversion11sideEffect2SiyF
// CHECK: [[RESULT2:%.*]] = apply [[SIDE2]]()
// CHECK: [[ACCESS:%.*]] = begin_access [modify] [unknown] [[ARRAY]] : $*Array<Int>
+ // CHECK: [[TAKES_MUTABLE:%.*]] = function_ref @_T018pointer_conversion19takesMutablePointerySpySiG_Si3andtF
// CHECK: apply [[TAKES_MUTABLE]]({{.*}}, [[RESULT2]])
// CHECK: strong_unpin
// CHECK: end_access [[ACCESS]]
takesMutablePointer(&array[sideEffect1()], and: sideEffect2())
- // CHECK: [[TAKES_CONST:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiG_Si3andtF
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
// CHECK: [[RESULT1:%.*]] = apply [[SIDE1]]()
// CHECK: [[SIDE2:%.*]] = function_ref @_T018pointer_conversion11sideEffect2SiyF
// CHECK: [[RESULT2:%.*]] = apply [[SIDE2]]()
// CHECK: [[ACCESS:%.*]] = begin_access [read] [unknown] [[ARRAY]] : $*Array<Int>
+ // CHECK: [[TAKES_CONST:%.*]] = function_ref @_T018pointer_conversion17takesConstPointerySPySiG_Si3andtF
// CHECK: apply [[TAKES_CONST]]({{.*}}, [[RESULT2]])
// CHECK: end_access [[ACCESS]]
takesConstPointer(&array[sideEffect1()], and: sideEffect2())
@@ -305,7 +305,6 @@
// rdar://problem/31542269
// CHECK-LABEL: sil hidden @_T018pointer_conversion20optArrayToOptPointerySaySiGSg5array_tF
func optArrayToOptPointer(array: [Int]?) {
- // CHECK: [[TAKES:%.*]] = function_ref @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF
// CHECK: [[BORROW:%.*]] = begin_borrow %0
// CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -324,6 +323,7 @@
// 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 @_T018pointer_conversion20takesOptConstPointerySPySiGSg_Si3andtF
// CHECK: apply [[TAKES]]([[OPTDEP]], [[RESULT1]])
// CHECK: destroy_value [[OWNER]]
// CHECK: end_borrow [[BORROW]]
@@ -337,7 +337,6 @@
// CHECK-LABEL: sil hidden @_T018pointer_conversion013optOptArrayTodD7PointerySaySiGSgSg5array_tF
func optOptArrayToOptOptPointer(array: [Int]??) {
- // CHECK: [[TAKES:%.*]] = function_ref @_T018pointer_conversion08takesOptD12ConstPointerySPySiGSgSg_Si3andtF
// CHECK: [[BORROW:%.*]] = begin_borrow %0
// CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -367,6 +366,7 @@
// 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 @_T018pointer_conversion08takesOptD12ConstPointerySPySiGSgSg_Si3andtF
// CHECK: apply [[TAKES]]([[OPTOPTDEP]], [[RESULT1]])
// CHECK: destroy_value [[OWNER]]
// CHECK: end_borrow [[BORROW]]
@@ -384,7 +384,6 @@
// CHECK-LABEL: sil hidden @_T018pointer_conversion21optStringToOptPointerySSSg6string_tF
func optStringToOptPointer(string: String?) {
- // CHECK: [[TAKES:%.*]] = function_ref @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF
// CHECK: [[BORROW:%.*]] = begin_borrow %0
// CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -403,6 +402,7 @@
// 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 @_T018pointer_conversion23takesOptConstRawPointerySVSg_Si3andtF
// CHECK: apply [[TAKES]]([[OPTDEP]], [[RESULT1]])
// CHECK: destroy_value [[OWNER]]
// CHECK: end_borrow [[BORROW]]
@@ -416,7 +416,6 @@
// CHECK-LABEL: sil hidden @_T018pointer_conversion014optOptStringTodD7PointerySSSgSg6string_tF
func optOptStringToOptOptPointer(string: String??) {
- // CHECK: [[TAKES:%.*]] = function_ref @_T018pointer_conversion08takesOptD15ConstRawPointerySVSgSg_Si3andtF
// CHECK: [[BORROW:%.*]] = begin_borrow %0
// CHECK: [[COPY:%.*]] = copy_value [[BORROW]]
// CHECK: [[SIDE1:%.*]] = function_ref @_T018pointer_conversion11sideEffect1SiyF
@@ -447,6 +446,7 @@
// 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 @_T018pointer_conversion08takesOptD15ConstRawPointerySVSgSg_Si3andtF
// CHECK: apply [[TAKES]]([[OPTOPTDEP]], [[RESULT1]])
// CHECK: destroy_value [[OWNER]]
// CHECK: end_borrow [[BORROW]]
diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift
index 35058c5..443245b 100644
--- a/test/SILGen/properties.swift
+++ b/test/SILGen/properties.swift
@@ -123,8 +123,7 @@
// CHECK: [[BORROWED_ARG1:%.*]] = begin_borrow [[ARG1]]
// CHECK: [[ARG1_COPY:%.*]] = copy_value [[BORROWED_ARG1]] : $RefSubclass
// CHECK: [[R_SUP:%[0-9]+]] = upcast [[ARG1_COPY]] : $RefSubclass to $Ref
- // CHECK: [[BORROWED_R_SUP:%.*]] = begin_borrow [[R_SUP]]
- // CHECK: [[FN:%[0-9]+]] = class_method [[BORROWED_R_SUP]] : $Ref, #Ref.y!setter.1 : (Ref) -> (Int) -> (), $@convention(method) (Int, @guaranteed 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]]
// CHECK: end_borrow [[BORROWED_ARG1]] from [[ARG1]]
@@ -160,8 +159,7 @@
return class_rvalue().y
// CHECK: [[FUNC:%[0-9]+]] = function_ref @_T010properties12class_rvalueAA3RefCyF
// CHECK: [[CLASS:%[0-9]+]] = apply [[FUNC]]()
- // CHECK: [[BORROWED_CLASS:%.*]] = begin_borrow [[CLASS]]
- // CHECK: [[FN:%[0-9]+]] = class_method [[BORROWED_CLASS]] : $Ref, #Ref.y!getter.1
+ // CHECK: [[FN:%[0-9]+]] = class_method [[CLASS]] : $Ref, #Ref.y!getter.1
// CHECK: [[RET:%[0-9]+]] = apply [[FN]]([[CLASS]])
// CHECK: return [[RET]]
}
@@ -180,8 +178,8 @@
func logical_struct_set(_ value: inout Val, z: Int) {
// CHECK: bb0([[VAL:%[0-9]+]] : $*Val, [[Z:%[0-9]+]] : $Int):
value.z = z
- // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[VAL]]
+ // CHECK: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
// CHECK: apply [[Z_SET_METHOD]]([[Z]], [[WRITE]])
// CHECK: return
}
@@ -190,9 +188,9 @@
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: [[Z_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
// 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 @_T010properties3ValV1z{{[_0-9a-zA-Z]*}}vs
// CHECK: apply [[Z_SET_METHOD]]([[Z]], [[VAL_1]])
// CHECK: return
}
@@ -221,9 +219,9 @@
// -- 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: [[GET_Z_TUPLE_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV7z_tupleSi_Sitvg
// 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 @_T010properties3ValV7z_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
@@ -268,9 +266,9 @@
// 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: [[Z_GET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV7z_tupleSi_Sitvg
// 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 @_T010properties3ValV7z_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
@@ -371,8 +369,8 @@
// CHECK: [[XADDR:%[0-9]+]] = alloc_box ${ var Int }
// CHECK: [[PB:%.*]] = project_box [[XADDR]]
inout_arg(&x)
- // CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @_T010properties9inout_arg{{[_0-9a-zA-Z]*}}F
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[INOUT_ARG:%[0-9]+]] = function_ref @_T010properties9inout_arg{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[INOUT_ARG]]([[WRITE]])
}
@@ -399,8 +397,8 @@
v[i] = x
// CHECK: [[VADDR:%[0-9]+]] = alloc_box ${ var Val }
// CHECK: [[PB:%.*]] = project_box [[VADDR]]
- // CHECK: [[SUBSCRIPT_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV{{[_0-9a-zA-Z]*}}is
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]]
+ // CHECK: [[SUBSCRIPT_SET_METHOD:%[0-9]+]] = function_ref @_T010properties3ValV{{[_0-9a-zA-Z]*}}is
// CHECK: apply [[SUBSCRIPT_SET_METHOD]]([[X]], [[I]], [[WRITE]])
}
@@ -515,12 +513,11 @@
takeInt(a)
- // CHECK-NEXT: // function_ref properties.takeInt
- // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
// 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 @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: apply [[TAKEINTFN]]([[A]]) : $@convention(thin) (Int) -> ()
takeInt(newA)
@@ -539,12 +536,12 @@
takeInt(a)
- // CHECK-NEXT: // function_ref properties.takeInt(Swift.Int) -> ()
- // CHECK-NEXT: [[TAKEINTFN:%.*]] = function_ref @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
// 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 @_T010properties7takeInt{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: apply [[TAKEINTFN]]([[A]]) : $@convention(thin) (Int) -> ()
a = zero // reassign, but don't infinite loop.
@@ -589,18 +586,18 @@
// 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 @_T010properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vw
- // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
// 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 @_T010properties010DidSetWillC5TestsV1a{{[_0-9a-zA-Z]*}}vW : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
- // CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown] %1
// CHECK-NEXT: apply [[DIDSETFN]]([[OLDVAL]], [[WRITE]]) : $@convention(method) (Int, @inout DidSetWillSetTests) -> ()
// CHECK-LABEL: sil hidden @_T010properties010DidSetWillC5TestsV{{[_0-9a-zA-Z]*}}fC
@@ -734,9 +731,7 @@
// CHECK: [[BASEPTR:%[0-9]+]] = upcast {{.*}} : $rdar16151899Derived to $rdar16151899Base
// CHECK: load{{.*}}Int
// CHECK-NEXT: end_access {{.*}} : $*Int
- // CHECK-NEXT: begin_borrow {{.*}} : $rdar16151899Base
// CHECK-NEXT: [[SETTER:%[0-9]+]] = class_method {{.*}} : $rdar16151899Base, #rdar16151899Base.x!setter.1 : (rdar16151899Base)
- // CHECK-NEXT: end_borrow
// CHECK-NEXT: apply [[SETTER]]({{.*}}, [[BASEPTR]])
}
}
@@ -1191,9 +1186,7 @@
// 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: [[BORROWED_C:%.*]] = begin_borrow [[C]]
-// CHECK-NEXT: [[GETTER:%.*]] = class_method [[BORROWED_C]] : $ReferenceType, #ReferenceType.p!getter.1 : (ReferenceType) -> () -> NonmutatingProtocol, $@convention(method) (@guaranteed ReferenceType) -> @out NonmutatingProtocol
-// CHECK-NEXT: end_borrow
+// 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: destroy_value [[C]] : $ReferenceType
// CHECK-NEXT: [[C_FIELD_PAYLOAD:%.*]] = open_existential_addr immutable_access [[C_FIELD_BOX]] : $*NonmutatingProtocol to $*@opened("{{.*}}") NonmutatingProtocol
diff --git a/test/SILGen/property_abstraction.swift b/test/SILGen/property_abstraction.swift
index 943313e..8fb926d 100644
--- a/test/SILGen/property_abstraction.swift
+++ b/test/SILGen/property_abstraction.swift
@@ -44,7 +44,6 @@
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: store [[ARG_COPY]] to [init] [[XBOX_PB]]
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
-// CHECK: [[INOUTFUNC:%.*]] = function_ref @_T020property_abstraction9inOutFunc{{[_0-9a-zA-Z]*}}F
// 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
@@ -52,6 +51,7 @@
// CHECK: [[REABSTRACT_FN:%.*]] = function_ref @_T0{{.*}}TR :
// CHECK: [[F_SUBST_IN:%.*]] = partial_apply [[REABSTRACT_FN]]([[F_ORIG]])
// CHECK: store [[F_SUBST_IN]] to [init] [[F_SUBST_MAT]]
+// CHECK: [[INOUTFUNC:%.*]] = function_ref @_T020property_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 @_T0{{.*}}TR :
@@ -140,10 +140,10 @@
}
// CHECK: sil hidden @_T020property_abstraction10setBuilder{{[_0-9a-zA-Z]*}}F : $@convention(thin) <F where F : Factory, F.Product == MyClass> (@inout F) -> ()
// CHECK: bb0(%0 : @trivial $*F):
-// CHECK: [[SETTER:%.*]] = witness_method $F, #Factory.builder!setter.1
// CHECK: [[F0:%.*]] = function_ref @_T020property_abstraction10setBuilder{{[_0-9a-zA-Z]*}} : $@convention(thin) () -> @owned MyClass
// CHECK: [[F1:%.*]] = thin_to_thick_function [[F0]]
// CHECK: [[REABSTRACTOR:%.*]] = function_ref @_T0{{.*}}TR :
// CHECK: [[F2:%.*]] = partial_apply [[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/property_behavior_init.swift b/test/SILGen/property_behavior_init.swift
index 39b3d8b..b478742 100644
--- a/test/SILGen/property_behavior_init.swift
+++ b/test/SILGen/property_behavior_init.swift
@@ -47,13 +47,13 @@
// CHECK: apply [[GETTER]]([[SELF]])
_ = self.x
- // CHECK: [[WHACK:%.*]] = function_ref @_T022property_behavior_init5whackyxzlF
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB_BOX]]
// CHECK: [[INOUT:%.*]] = alloc_stack
// CHECK: [[SELF:%.*]] = load [trivial] [[WRITE]]
// CHECK: [[GETTER:%.*]] = function_ref @_T022property_behavior_init3FooV1xSivg
// CHECK: [[VALUE:%.*]] = apply [[GETTER]]([[SELF]])
// CHECK: store [[VALUE]] to [trivial] [[INOUT]]
+ // CHECK: [[WHACK:%.*]] = function_ref @_T022property_behavior_init5whackyxzlF
// CHECK: apply [[WHACK]]<Int>([[INOUT]])
// CHECK: [[VALUE:%.*]] = load [trivial] [[INOUT]]
// CHECK: [[SETTER:%.*]] = function_ref @_T022property_behavior_init3FooV1xSivs
diff --git a/test/SILGen/protocol_class_refinement.swift b/test/SILGen/protocol_class_refinement.swift
index 4de2ca2..f940ec6 100644
--- a/test/SILGen/protocol_class_refinement.swift
+++ b/test/SILGen/protocol_class_refinement.swift
@@ -30,51 +30,51 @@
var x = x
// CHECK: [[XBOX:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : ObjectUID> { var τ_0_0 } <T>
// CHECK: [[PB:%.*]] = project_box [[XBOX]]
- // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
// -- call x.uid()
- // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
// CHECK: [[X:%.*]] = load [copy] [[READ]]
// CHECK: [[X_TMP:%.*]] = alloc_stack
// CHECK: store [[X]] to [init] [[X_TMP]]
+ // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
// CHECK: destroy_value [[X2]]
// -- call set x.clsid
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+ // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
// CHECK: apply [[SET_CLSID]]<T>([[UID]], [[WRITE]])
x.clsid = x.uid()
- // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
// -- call x.uid()
- // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
// CHECK: [[X:%.*]] = load [copy] [[READ]]
// CHECK: [[X_TMP:%.*]] = alloc_stack
// CHECK: store [[X]] to [init] [[X_TMP]]
+ // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
// CHECK: destroy_value [[X2]]
// -- call nextCLSID from protocol ext
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+ // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
// CHECK: apply [[SET_NEXTCLSID]]<T>([[UID]], [[WRITE]])
x.nextCLSID = x.uid()
// -- call x.uid()
// CHECK: [[READ1:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
// CHECK: [[X1:%.*]] = load [copy] [[READ1]]
- // CHECK: [[SET_SECONDNEXT:%.*]] = function_ref @_T025protocol_class_refinement9ObjectUIDPAAE15secondNextCLSIDSivs
// CHECK: [[BORROWED_X1:%.*]] = begin_borrow [[X1]]
- // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
// CHECK: [[X:%.*]] = load [copy] [[READ]]
// CHECK: [[X_TMP:%.*]] = alloc_stack
// CHECK: store [[X]] to [init] [[X_TMP]]
+ // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
// CHECK: destroy_value [[X2]]
// -- call secondNextCLSID from class-constrained protocol ext
+ // CHECK: [[SET_SECONDNEXT:%.*]] = function_ref @_T025protocol_class_refinement9ObjectUIDPAAE15secondNextCLSIDSivs
// CHECK: apply [[SET_SECONDNEXT]]<T>([[UID]], [[BORROWED_X1]])
// CHECK: end_borrow [[BORROWED_X1]] from [[X1]]
// CHECK: destroy_value [[X1]]
@@ -89,33 +89,33 @@
var x = x
// CHECK: [[XBOX:%.*]] = alloc_box $<τ_0_0 where τ_0_0 : Base, τ_0_0 : UID> { var τ_0_0 } <T>
// CHECK: [[PB:%.*]] = project_box [[XBOX]]
- // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
// -- call x.uid()
- // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
// CHECK: [[X:%.*]] = load [copy] [[READ]]
// CHECK: [[X_TMP:%.*]] = alloc_stack
// CHECK: store [[X]] to [init] [[X_TMP]]
+ // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
// CHECK: destroy_value [[X2]]
// -- call set x.clsid
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+ // CHECK: [[SET_CLSID:%.*]] = witness_method $T, #UID.clsid!setter.1
// CHECK: apply [[SET_CLSID]]<T>([[UID]], [[WRITE]])
x.clsid = x.uid()
- // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
// -- call x.uid()
- // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PB]] : $*T
// CHECK: [[X:%.*]] = load [copy] [[READ]]
// CHECK: [[X_TMP:%.*]] = alloc_stack
// CHECK: store [[X]] to [init] [[X_TMP]]
+ // CHECK: [[GET_UID:%.*]] = witness_method $T, #UID.uid!1
// CHECK: [[UID:%.*]] = apply [[GET_UID]]<T>([[X_TMP]])
// CHECK: [[X2:%.*]] = load [take] [[X_TMP]]
// CHECK: destroy_value [[X2]]
// -- call nextCLSID from protocol ext
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*T
+ // CHECK: [[SET_NEXTCLSID:%.*]] = function_ref @_T025protocol_class_refinement3UIDPAAE9nextCLSIDSivs
// CHECK: apply [[SET_NEXTCLSID]]<T>([[UID]], [[WRITE]])
x.nextCLSID = x.uid()
return (x.iid, x.clsid, x.nextCLSID)
diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift
index 76eefa4..aabfc84 100644
--- a/test/SILGen/protocol_extensions.swift
+++ b/test/SILGen/protocol_extensions.swift
@@ -100,10 +100,10 @@
func testD(_ m: MetaHolder, dd: D.Type, d: D) {
// CHECK: [[D2:%[0-9]+]] = alloc_box ${ var D }
// CHECK: [[RESULT:%.*]] = project_box [[D2]]
- // CHECK: [[FN:%[0-9]+]] = function_ref @_T019protocol_extensions2P1PAAE11returnsSelf{{[_0-9a-zA-Z]*}}F
// CHECK: [[BORROWED_D:%.*]] = begin_borrow [[D]]
// CHECK: [[MATERIALIZED_BORROWED_D:%[0-9]+]] = alloc_stack $D
// CHECK: store_borrow [[BORROWED_D]] to [[MATERIALIZED_BORROWED_D]]
+ // CHECK: [[FN:%[0-9]+]] = function_ref @_T019protocol_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]]
// CHECK-NEXT: end_borrow [[BORROWED_D]] from [[D]]
@@ -139,11 +139,11 @@
// CHECK: dealloc_stack
D.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: metatype $@thick D.Type
// CHECK: alloc_stack $Box
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
@@ -174,10 +174,10 @@
// CHECK: dealloc_stack
dd.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
@@ -208,10 +208,10 @@
// CHECK: dealloc_stack
m.d.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
@@ -222,121 +222,121 @@
// CHECK-LABEL: sil hidden @_T019protocol_extensions5testSyAA10MetaHolderV_AA1SVm2sstF
func testS(_ m: MetaHolder, ss: S.Type) {
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
let _ = S.staticReadOnlyProperty
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
S.staticReadWrite1 = 1
// CHECK: alloc_stack $Int
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: dealloc_stack
S.staticReadWrite1 += 1
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
S.staticReadWrite2 = Box(number: 2)
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
S.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
inout_func(&S.staticReadWrite2.number)
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
let _ = ss.staticReadOnlyProperty
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
ss.staticReadWrite1 = 1
// CHECK: alloc_stack $Int
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: dealloc_stack
ss.staticReadWrite1 += 1
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
ss.staticReadWrite2 = Box(number: 2)
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
ss.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
inout_func(&ss.staticReadWrite2.number)
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
let _ = m.s.staticReadOnlyProperty
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
m.s.staticReadWrite1 = 1
// CHECK: alloc_stack $Int
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: dealloc_stack
m.s.staticReadWrite1 += 1
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
m.s.staticReadWrite2 = Box(number: 2)
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
m.s.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick S.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
@@ -347,121 +347,121 @@
// CHECK-LABEL: sil hidden @_T019protocol_extensions5testG{{[_0-9a-zA-Z]*}}F
func testG<T>(_ m: GenericMetaHolder<T>, gg: G<T>.Type) {
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
let _ = G<T>.staticReadOnlyProperty
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
G<T>.staticReadWrite1 = 1
// CHECK: alloc_stack $Int
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: dealloc_stack
G<T>.staticReadWrite1 += 1
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
G<T>.staticReadWrite2 = Box(number: 2)
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
G<T>.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
inout_func(&G<T>.staticReadWrite2.number)
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
let _ = gg.staticReadOnlyProperty
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
gg.staticReadWrite1 = 1
// CHECK: alloc_stack $Int
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: dealloc_stack
gg.staticReadWrite1 += 1
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
gg.staticReadWrite2 = Box(number: 2)
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
gg.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
inout_func(&gg.staticReadWrite2.number)
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE22staticReadOnlyPropertySivgZ
let _ = m.g.staticReadOnlyProperty
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
m.g.staticReadWrite1 = 1
// CHECK: alloc_stack $Int
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite1SivsZ
// CHECK: dealloc_stack
m.g.staticReadWrite1 += 1
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
m.g.staticReadWrite2 = Box(number: 2)
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
m.g.staticReadWrite2.number += 5
- // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: alloc_stack $Box
- // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: metatype $@thick G<T>.Type
+ // CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvgZ
// CHECK: store
+ // CHECK: function_ref @_T019protocol_extensions10inout_funcySizF
// CHECK: load
// CHECK: function_ref @_T019protocol_extensions2P1PAAE16staticReadWrite2AA3BoxVvsZ
// CHECK: dealloc_stack
@@ -698,11 +698,11 @@
// CHECK: [[SELF_BOX:%.*]] = alloc_box
// CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
// CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
- // 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: [[SELF_BOX:%.*]] = alloc_stack $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]]
@@ -720,10 +720,10 @@
// CHECK: [[SELF_BOX:%.*]] = alloc_box
// CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
// CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
- // CHECK: [[DELEGATEE:%.*]] = function_ref @_T019protocol_extensions15InitRequirementPAAExAA1DC1d_tcfC
- // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $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 @_T019protocol_extensions15InitRequirementPAAExAA1DC1d_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]]
@@ -741,11 +741,11 @@
// CHECK: [[SELF_BOX:%.*]] = alloc_box
// CHECK-NEXT: [[UNINIT_SELF:%.*]] = mark_uninitialized [delegatingself] [[SELF_BOX]]
// CHECK-NEXT: [[SELF_BOX_ADDR:%.*]] = project_box [[UNINIT_SELF]]
- // CHECK: [[DELEGATEE:%.*]] = witness_method $Self, #InitRequirement.init!allocator.1
- // CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $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]]
@@ -767,10 +767,10 @@
extension ClassInitRequirement {
// CHECK-LABEL: sil hidden @_T019protocol_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: [[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: [[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]]
@@ -796,11 +796,11 @@
// 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: [[WITNESS:%.*]] = witness_method [volatile] $Self, #ObjCInitRequirement.init!initializer.1.foreign : {{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjCInitRequirement> (OC, OC, @owned τ_0_0) -> @owned τ_0_0
// 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:%.*]] = witness_method [volatile] $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]]
@@ -828,8 +828,7 @@
// 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: [[BORROWED_SELF_ALLOC_C:%.*]] = begin_borrow [[SELF_ALLOC_C]]
- // CHECK: [[OBJC_INIT:%[0-9]+]] = class_method [[BORROWED_SELF_ALLOC_C]] : $ObjCInitClass, #ObjCInitClass.init!initializer.1 : (ObjCInitClass.Type) -> () -> ObjCInitClass, $@convention(method) (@owned ObjCInitClass) -> @owned 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
diff --git a/test/SILGen/protocol_optional.swift b/test/SILGen/protocol_optional.swift
index d711925..54bca84 100644
--- a/test/SILGen/protocol_optional.swift
+++ b/test/SILGen/protocol_optional.swift
@@ -62,9 +62,9 @@
// CHECK: project_box [[OPT_BOX]]
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PT]] : $*T
// CHECK: [[T:%[0-9]+]] = load [copy] [[READ]] : $*T
- // CHECK: [[INTCONV:%[0-9]+]] = function_ref @_T0S2i{{[_0-9a-zA-Z]*}}fC
// CHECK: [[INT64:%[0-9]+]] = metatype $@thin Int.Type
// CHECK: [[FIVELIT:%[0-9]+]] = integer_literal $Builtin.Int2048, 5
+ // CHECK: [[INTCONV:%[0-9]+]] = function_ref @_T0S2i{{[_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
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 62a43d2..17af5ad 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -26,10 +26,10 @@
// 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: end_access [[READ]] : $*SubscriptableGet
// 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]]
@@ -103,8 +103,8 @@
}
// CHECK-LABEL: sil hidden @{{.*}}use_subscript_archetype_lvalue_set
// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
-// CHECK: [[METH:%[0-9]+]] = witness_method $T, #SubscriptableGetSet.subscript!setter.1
// 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]])
@@ -133,6 +133,7 @@
// 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: end_access [[READ]] : $*PropertyWithGetter
// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetter.a!getter.1
// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[COPY]])
@@ -199,8 +200,8 @@
}
// CHECK-LABEL: sil hidden @{{.*}}use_property_archetype_lvalue_set
// CHECK: bb0(%0 : @trivial $*T, %1 : @trivial $Int):
-// CHECK: [[METH:%[0-9]+]] = witness_method $T, #PropertyWithGetterSetter.b!setter.1
// 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]])
//===----------------------------------------------------------------------===//
@@ -212,9 +213,9 @@
// CHECK-LABEL: sil hidden @_T09protocols27use_initializable_archetype{{[_0-9a-zA-Z]*}}F
func use_initializable_archetype<T: Initializable>(_ t: T, i: Int) {
- // 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:%[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
@@ -416,7 +417,6 @@
modify(&x.b)
}
// CHECK-LABEL: sil hidden @_T09protocols14modifyPropertyyxzAA0C16WithGetterSetterRzlF
-// CHECK: [[MODIFY_FN:%.*]] = function_ref @_T09protocols6modifyySizF
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*T
// CHECK: [[WITNESS_FN:%.*]] = witness_method $T, #PropertyWithGetterSetter.b!materializeForSet.1
// CHECK: [[RESULT:%.*]] = apply [[WITNESS_FN]]<T>
@@ -424,6 +424,7 @@
// 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 @_T09protocols6modifyySizF
// 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):
diff --git a/test/SILGen/reabstract-tuple.swift b/test/SILGen/reabstract-tuple.swift
index 8a69014..6a04bc1 100644
--- a/test/SILGen/reabstract-tuple.swift
+++ b/test/SILGen/reabstract-tuple.swift
@@ -12,8 +12,6 @@
// CHECK: sil @_T04main7testBoxyyF : $@convention(thin) () -> () {
// CHECK: bb0:
-// CHECK: // function_ref Box.__allocating_init(_:)
-// CHECK: [[INIT_F:%.*]] = function_ref @_T04main3BoxCACyxGxcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thick Box<τ_0_0>.Type) -> @owned Box<τ_0_0> // user: %26
// CHECK: // function_ref closure #1 in testBox()
// CHECK: [[CLOSURE:%.*]] = function_ref @_T04main7testBoxyyFyycfU_ : $@convention(thin) () -> ()
// CHECK: [[THICK:%.*]] = thin_to_thick_function [[CLOSURE]] : $@convention(thin) () -> () to $@callee_owned () -> ()
@@ -30,6 +28,8 @@
// CHECK: [[TUPLEB_0:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_owned (@in ()) -> @out ()), 0
// CHECK: [[TUPLEB_1:%.*]] = tuple_extract [[BORROWB]] : $(Int, @callee_owned (@in ()) -> @out ()), 1
// CHECK: [[COPYB_1:%.*]] = copy_value [[TUPLEB_1]] : $@callee_owned (@in ()) -> @out ()
+// CHECK: // function_ref Box.__allocating_init(_:)
+// CHECK: [[INIT_F:%.*]] = function_ref @_T04main3BoxCACyxGxcfC : $@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_owned (@in ()) -> @out ()), $(Int, @callee_owned (@in ()) -> @out ())
// CHECK: destroy_value [[TUPLEB]] : $(Int, @callee_owned (@in ()) -> @out ())
diff --git a/test/SILGen/reabstract.swift b/test/SILGen/reabstract.swift
index 45ce946..708cd96 100644
--- a/test/SILGen/reabstract.swift
+++ b/test/SILGen/reabstract.swift
@@ -7,10 +7,9 @@
takeFn(liftOptional)
}
// CHECK: sil hidden @_T010reabstract5test0yyF : $@convention(thin) () -> () {
-// CHECK: [[T0:%.*]] = function_ref @_T010reabstract6takeFn{{[_0-9a-zA-Z]*}}F
// Emit a generalized reference to liftOptional.
// TODO: just emit a globalized thunk
-// CHECK-NEXT: reabstract.liftOptional
+// CHECK: reabstract.liftOptional
// CHECK-NEXT: [[T1:%.*]] = function_ref @_T010reabstract12liftOptional{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: [[T2:%.*]] = thin_to_thick_function [[T1]]
// CHECK-NEXT: [[CVT:%.*]] = convert_function [[T2]]
@@ -18,6 +17,7 @@
// CHECK-NEXT: [[T3:%.*]] = function_ref [[THUNK:@.*]] :
// CHECK-NEXT: [[T4:%.*]] = partial_apply [[T3]]([[CVT]])
// CHECK-NEXT: [[CVT:%.*]] = convert_function [[T4]]
+// CHECK: [[T0:%.*]] = function_ref @_T010reabstract6takeFn{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: apply [[T0]]<Int>([[CVT]])
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return
diff --git a/test/SILGen/reabstract_lvalue.swift b/test/SILGen/reabstract_lvalue.swift
index a785c11..4f8daf5 100644
--- a/test/SILGen/reabstract_lvalue.swift
+++ b/test/SILGen/reabstract_lvalue.swift
@@ -17,13 +17,13 @@
// CHECK: [[ARG:%.*]] = function_ref @_T017reabstract_lvalue9transformSdSiF
// CHECK: [[THICK_ARG:%.*]] = thin_to_thick_function [[ARG]]
// CHECK: store [[THICK_ARG:%.*]] to [init] [[PB]]
- // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[PB]] : $*@callee_owned (Int) -> Double
// CHECK: [[ABSTRACTED_BOX:%.*]] = alloc_stack $@callee_owned (@in Int) -> @out Double
// CHECK: [[THICK_ARG:%.*]] = load [copy] [[WRITE]]
// CHECK: [[THUNK1:%.*]] = function_ref @_T0SiSdIexyd_SiSdIexir_TR
// CHECK: [[ABSTRACTED_ARG:%.*]] = partial_apply [[THUNK1]]([[THICK_ARG]])
// CHECK: store [[ABSTRACTED_ARG]] to [init] [[ABSTRACTED_BOX]]
+ // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_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 @_T0SiSdIexir_SiSdIexyd_TR
@@ -38,10 +38,10 @@
// CHECK-LABEL: sil hidden @_T017reabstract_lvalue0A13MetatypeInOutyyF : $@convention(thin) () -> ()
func reabstractMetatypeInOut() {
var thinMetatype = MyMetatypeIsThin.self
- // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
// CHECK: [[BOX:%.*]] = alloc_stack $@thick MyMetatypeIsThin.Type
// CHECK: [[THICK:%.*]] = metatype $@thick MyMetatypeIsThin.Type
// CHECK: store [[THICK]] to [trivial] [[BOX]]
+ // CHECK: [[FUNC:%.*]] = function_ref @_T017reabstract_lvalue19consumeGenericInOut{{[_0-9a-zA-Z]*}}F
// CHECK: apply [[FUNC]]<MyMetatypeIsThin.Type>([[BOX]])
consumeGenericInOut(&thinMetatype)
}
diff --git a/test/SILGen/rethrows.swift b/test/SILGen/rethrows.swift
index 671d37d..ceddf1b 100644
--- a/test/SILGen/rethrows.swift
+++ b/test/SILGen/rethrows.swift
@@ -8,10 +8,10 @@
func nonthrower() -> Int { return 0 }
// CHECK-LABEL: sil hidden @_T08rethrows5test0yyKF : $@convention(thin) () -> @error Error {
-// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: [[THROWER:%.*]] = function_ref @_T08rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error)
// CHECK: [[T0:%.*]] = thin_to_thick_function [[THROWER]]
// CHECK: [[CVT:%.*]] = convert_function [[T0]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
// CHECK-NEXT: [[T1:%.*]] = tuple ()
@@ -23,10 +23,10 @@
}
// CHECK-LABEL: sil hidden @_T08rethrows5test1yyKF : $@convention(thin) () -> @error Error {
-// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: [[CLOSURE:%.*]] = function_ref @_T08rethrows5test1yyKFSiyKcfU_ : $@convention(thin) () -> (Int, @error Error)
// CHECK: [[CVT:%.*]] = convert_function [[CLOSURE]]
// CHECK: [[T0:%.*]] = thin_to_thick_function [[CVT]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: try_apply [[RETHROWER]]([[T0]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
// CHECK-NEXT: [[T1:%.*]] = tuple ()
@@ -35,10 +35,10 @@
// CHECK-NEXT: throw [[T0]]
// Closure.
// CHECK-LABEL: sil private @_T08rethrows5test1yyKFSiyKcfU_ : $@convention(thin) () -> (Int, @error Error) {
-// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: [[THROWER:%.*]] = function_ref @_T08rethrows7throwerSiyKF : $@convention(thin) () -> (Int, @error Error)
// CHECK: [[T0:%.*]] = thin_to_thick_function [[THROWER]]
// CHECK: [[CVT:%.*]] = convert_function [[T0]]
+// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: try_apply [[RETHROWER]]([[CVT]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
// CHECK-NEXT: return [[T0]]
@@ -49,10 +49,10 @@
}
// CHECK-LABEL: sil hidden @_T08rethrows5test2yyF : $@convention(thin) () -> () {
-// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: [[NONTHROWER:%.*]] = function_ref @_T08rethrows10nonthrowerSiyF : $@convention(thin) () -> Int
// CHECK: [[T0:%.*]] = thin_to_thick_function [[NONTHROWER]]
// CHECK: [[T1:%.*]] = convert_function [[T0]] : $@callee_owned () -> Int to $@noescape @callee_owned () -> (Int, @error Error)
+// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: try_apply [[RETHROWER]]([[T1]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
// CHECK-NEXT: [[T1:%.*]] = tuple ()
@@ -64,11 +64,11 @@
}
// CHECK-LABEL: sil hidden @_T08rethrows5test3yyF : $@convention(thin) () -> () {
-// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: [[CLOSURE:%.*]] = function_ref @_T08rethrows5test3yyFSiycfU_ : $@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_owned () -> Int to $@noescape @callee_owned () -> (Int, @error Error)
+// CHECK: [[RETHROWER:%.*]] = function_ref @_T08rethrows9rethrowerS2iyKcKF : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error)
// CHECK: try_apply [[RETHROWER]]([[T1]]) : $@convention(thin) (@owned @noescape @callee_owned () -> (Int, @error Error)) -> (Int, @error Error), normal [[NORMAL:bb1]], error [[ERROR:bb2]]
// CHECK: [[NORMAL]]([[T0:%.*]] : $Int):
// CHECK-NEXT: [[T1:%.*]] = tuple ()
diff --git a/test/SILGen/scalar_to_tuple_args.swift b/test/SILGen/scalar_to_tuple_args.swift
index 1dbdfd5..14ef601 100644
--- a/test/SILGen/scalar_to_tuple_args.swift
+++ b/test/SILGen/scalar_to_tuple_args.swift
@@ -13,46 +13,45 @@
var x = 0
// CHECK: [[X_ADDR:%.*]] = global_addr @_T020scalar_to_tuple_args1xSivp : $*Int
-// CHECK: [[INOUT_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args17inoutWithDefaultsySiz_Si1ySi1ztF
// 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 @_T020scalar_to_tuple_args17inoutWithDefaultsySiz_Si1ySi1ztF
// CHECK: apply [[INOUT_WITH_DEFAULTS]]([[WRITE]], [[DEFAULT_Y]], [[DEFAULT_Z]])
inoutWithDefaults(&x)
-// CHECK: [[INOUT_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args27inoutWithCallerSideDefaultsySiz_Si1ytF
// 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 @_T020scalar_to_tuple_args27inoutWithCallerSideDefaultsySiz_Si1ytF
// CHECK: apply [[INOUT_WITH_CALLER_DEFAULTS]]([[WRITE]], [[LINE]])
inoutWithCallerSideDefaults(&x)
-// CHECK: [[SCALAR_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A12WithDefaultsySi_Si1ySi1ztF
// 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 @_T020scalar_to_tuple_args0A12WithDefaultsySi_Si1ySi1ztF
// CHECK: apply [[SCALAR_WITH_DEFAULTS]]([[X]], [[DEFAULT_Y]], [[DEFAULT_Z]])
scalarWithDefaults(x)
-// CHECK: [[SCALAR_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A22WithCallerSideDefaultsySi_Si1ytF
// CHECK: [[X:%.*]] = load [trivial] [[X_ADDR]]
// CHECK: [[LINE_VAL:%.*]] = integer_literal
// CHECK: [[LINE:%.*]] = apply {{.*}}([[LINE_VAL]]
+// CHECK: [[SCALAR_WITH_CALLER_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0A22WithCallerSideDefaultsySi_Si1ytF
// CHECK: apply [[SCALAR_WITH_CALLER_DEFAULTS]]([[X]], [[LINE]])
scalarWithCallerSideDefaults(x)
-// CHECK: [[TUPLE_WITH_DEFAULTS:%.*]] = function_ref @_T020scalar_to_tuple_args0C12WithDefaultsySi_Sit1x_Si1ySi1ztF
// 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 @_T020scalar_to_tuple_args0C12WithDefaultsySi_Sit1x_Si1ySi1ztF
// CHECK: apply [[TUPLE_WITH_DEFAULTS]]([[X1]], [[X2]], [[DEFAULT_Y]], [[DEFAULT_Z]])
tupleWithDefaults(x: (x,x))
-// CHECK: [[VARIADIC_FIRST:%.*]] = function_ref @_T020scalar_to_tuple_args13variadicFirstySid_tF
// 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
@@ -64,10 +63,10 @@
// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
// CHECK: [[X:%.*]] = load [trivial] [[READ]]
// CHECK: store [[X]] to [trivial] [[ADDR]]
+// CHECK: [[VARIADIC_FIRST:%.*]] = function_ref @_T020scalar_to_tuple_args13variadicFirstySid_tF
// CHECK: apply [[VARIADIC_FIRST]]([[ARRAY]])
variadicFirst(x)
-// CHECK: [[VARIADIC_SECOND:%.*]] = function_ref @_T020scalar_to_tuple_args14variadicSecondySi_SidtF
// 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
@@ -75,5 +74,6 @@
// CHECK: end_borrow [[BORROWED_ALLOC_ARRAY]] from [[ALLOC_ARRAY]]
// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
// CHECK: [[X:%.*]] = load [trivial] [[READ]]
+// CHECK: [[VARIADIC_SECOND:%.*]] = function_ref @_T020scalar_to_tuple_args14variadicSecondySi_SidtF
// CHECK: apply [[VARIADIC_SECOND]]([[X]], [[ARRAY]])
variadicSecond(x)
diff --git a/test/SILGen/shared.swift b/test/SILGen/shared.swift
index ff2fb2e..6b7a27d 100644
--- a/test/SILGen/shared.swift
+++ b/test/SILGen/shared.swift
@@ -7,9 +7,9 @@
// CHECK-LABEL: sil hidden @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF : $@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: [[OWNED_FUNC:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF
// 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 @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF
// CHECK: {{%.*}} = apply [[OWNED_FUNC]]([[TRIVIAL_VAL]], [[COPY_VALUE_VAL]], [[COPY_REF_VAL]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
// CHECK: } // end sil function '_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF'
return owned_arguments(trivial: trivial, value: value, ref: ref)
@@ -18,9 +18,9 @@
// CHECK-LABEL: sil hidden @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF : $@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: [[SHARED_FUNC:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF
// 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 @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF
// 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
@@ -55,9 +55,9 @@
// CHECK-LABEL: sil private @_T06shared0A17_argument_captureySih7trivial_AA14ValueAggregateVh5valueAA03RefF0Ch3reftFyycfU_ : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
// CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate):
- // CHECK: [[SHARED_CALL:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF : $@convention(thin) (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: [[SHARED_CALL:%[0-9]+]] = function_ref @_T06shared0A10_argumentsySih7trivial_AA14ValueAggregateVh5valueAA03RefE0Ch3reftF : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
// CHECK: {{%.*}} = apply [[SHARED_CALL]]([[TRIVIAL_VAL]], [[BORROW_VALUE_VAL]], [[BORROW_REF_VAL]]) : $@convention(thin) (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
@@ -69,11 +69,11 @@
// CHECK-LABEL: sil private @_T06shared0A17_argument_captureySih7trivial_AA14ValueAggregateVh5valueAA03RefF0Ch3reftFyycfU0_ : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> () {
// CHECK: bb0([[TRIVIAL_VAL:%[0-9]+]] : @trivial $Int, [[VALUE_VAL:%[0-9]+]] : @owned $ValueAggregate, [[REF_VAL:%[0-9]+]] : @owned $RefAggregate):
- // CHECK: [[OWNED_CALL:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
// CHECK: [[BORROW_VALUE_VAL:%[0-9]+]] = begin_borrow [[VALUE_VAL]] : $ValueAggregate
// CHECK: [[COPY_BORROW_VALUE_VAL:%[0-9]+]] = copy_value [[BORROW_VALUE_VAL]] : $ValueAggregate
// CHECK: [[BORROW_REF_VAL:%[0-9]+]] = begin_borrow [[REF_VAL]] : $RefAggregate
// CHECK: [[COPY_BORROW_REF_VAL:%[0-9]+]] = copy_value [[BORROW_REF_VAL]] : $RefAggregate
+ // CHECK: [[OWNED_CALL:%[0-9]+]] = function_ref @_T06shared15owned_argumentsySi7trivial_AA14ValueAggregateV5valueAA03RefF0C3reftF : $@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_borrow [[BORROW_REF_VAL]] from [[REF_VAL]] : $RefAggregate, $RefAggregate
// CHECK: end_borrow [[BORROW_VALUE_VAL]] from [[VALUE_VAL]] : $ValueAggregate, $ValueAggregate
@@ -85,13 +85,13 @@
// CHECK-LABEL: sil hidden @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
func shared_to_owned_conversion(_ f : (__shared Int, __shared ValueAggregate, __shared RefAggregate) -> Void) {
// CHECK: bb0([[UNUSED_FUNC:%[0-9]+]] : @owned $@noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()):
- // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
// CHECK: [[OWNED_THUNK:%[0-9]+]] = function_ref @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcFySi_AdFtcfU_ : $@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_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
// CHECK: [[GUARANTEED_TO_OWNED_THUNK:%[0-9]+]] = function_ref @_T0Si6shared14ValueAggregateVAA03RefC0CIxyxx_SiAcEIxygg_TR : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
// CHECK: [[APPLIED_THUNK:%[0-9]+]] = partial_apply [[GUARANTEED_TO_OWNED_THUNK]]([[THICK_OWNED_THUNK]]) : $@convention(thin) (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate, @owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_THUNK]]
+ // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
// CHECK: {{%.*}} = apply [[RECUR_FN]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
// CHECK: destroy_value [[UNUSED_FUNC]] : $@noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
// CHECK: } // end sil function '_T06shared0A20_to_owned_conversionyySih_AA14ValueAggregateVhAA03RefF0ChtcF'
@@ -111,13 +111,13 @@
// CHECK-LABEL: sil hidden @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
func owned_to_shared_conversion(_ f : (Int, ValueAggregate, RefAggregate) -> Void) {
// CHECK: bb0([[UNUSED_FUNC:%[0-9]+]] : @owned $@noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()):
- // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
// CHECK: [[SHARED_THUNK:%[0-9]+]] = function_ref @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcFySih_ADhAFhtcfU_ : $@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_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()
// CHECK: [[OWNED_TO_GUARANTEED_THUNK:%[0-9]+]] = function_ref @_T0Si6shared14ValueAggregateVAA03RefC0CIxygg_SiAcEIxyxx_TR : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
// CHECK: [[APPLIED_THUNK:%[0-9]+]] = partial_apply [[OWNED_TO_GUARANTEED_THUNK]]([[THICK_SHARED_THUNK]]) : $@convention(thin) (Int, @owned ValueAggregate, @owned RefAggregate, @owned @noescape @callee_owned (Int, @guaranteed ValueAggregate, @guaranteed RefAggregate) -> ()) -> ()
// CHECK: [[CONVERT:%.*]] = convert_function [[APPLIED_THUNK]]
+ // CHECK: [[RECUR_FN:%[0-9]+]] = function_ref @_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
// CHECK: {{%.*}} = apply [[RECUR_FN]]([[CONVERT]]) : $@convention(thin) (@owned @noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()) -> ()
// CHECK: destroy_value [[UNUSED_FUNC]] : $@noescape @callee_owned (Int, @owned ValueAggregate, @owned RefAggregate) -> ()
// CHECK: } // end sil function '_T06shared09owned_to_A11_conversionyySi_AA14ValueAggregateVAA03RefF0CtcF'
diff --git a/test/SILGen/source_location.swift b/test/SILGen/source_location.swift
index 8ea33a9..df1405f 100644
--- a/test/SILGen/source_location.swift
+++ b/test/SILGen/source_location.swift
@@ -4,11 +4,11 @@
#sourceLocation(file: "caller.swift", line: 10000)
_ = printSourceLocation()
-// CHECK: [[PRINT_SOURCE_LOCATION:%.*]] = function_ref @_T015source_location19printSourceLocationySS4file_Si4linetF
// CHECK: [[CALLER_FILE_VAL:%.*]] = string_literal utf16 "caller.swift",
// CHECK: [[CALLER_FILE:%.*]] = apply {{.*}}([[CALLER_FILE_VAL]],
// CHECK: [[CALLER_LINE_VAL:%.*]] = integer_literal $Builtin.Int{{[0-9]+}}, 10000,
// CHECK: [[CALLER_LINE:%.*]] = apply {{.*}}([[CALLER_LINE_VAL]],
+// CHECK: [[PRINT_SOURCE_LOCATION:%.*]] = function_ref @_T015source_location19printSourceLocationySS4file_Si4linetF
// CHECK: apply [[PRINT_SOURCE_LOCATION]]([[CALLER_FILE]], [[CALLER_LINE]])
#sourceLocation(file: "inplace.swift", line: 20000)
diff --git a/test/SILGen/statements.swift b/test/SILGen/statements.swift
index 82f573d..464bec8 100644
--- a/test/SILGen/statements.swift
+++ b/test/SILGen/statements.swift
@@ -164,9 +164,9 @@
// CHECK-LABEL: sil hidden @{{.*}}for_loops2
func for_loops2() {
// rdar://problem/19316670
- // CHECK: [[NEXT:%[0-9]+]] = function_ref @_T0s16IndexingIteratorV4next{{[_0-9a-zA-Z]*}}F
- // CHECK-NEXT: alloc_stack $Optional<MyClass>
+ // CHECK: alloc_stack $Optional<MyClass>
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [unknown]
+ // CHECK: [[NEXT:%[0-9]+]] = function_ref @_T0s16IndexingIteratorV4next{{[_0-9a-zA-Z]*}}F
// CHECK-NEXT: apply [[NEXT]]<[MyClass]>
// CHECK: class_method [[OBJ:%[0-9]+]] : $MyClass, #MyClass.foo!1
let objects = [MyClass(), MyClass() ]
@@ -365,8 +365,8 @@
// CHECK-LABEL: sil hidden @_T010statements7test_doyyF
func test_do() {
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 0
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(0)
// CHECK-NOT: br bb
@@ -376,8 +376,8 @@
let obj = MyClass()
_ = obj
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 1
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(1)
@@ -386,16 +386,16 @@
// CHECK-NOT: br bb
}
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 2
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(2)
}
// CHECK-LABEL: sil hidden @_T010statements15test_do_labeledyyF
func test_do_labeled() {
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 0
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(0)
// CHECK: br bb1
@@ -406,8 +406,8 @@
let obj = MyClass()
_ = obj
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 1
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(1)
@@ -421,8 +421,8 @@
}
// CHECK: bb3:
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 2
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(2)
@@ -436,8 +436,8 @@
}
// CHECK: bb5:
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 3
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(3)
@@ -445,8 +445,8 @@
// CHECK: br bb6
}
- // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: integer_literal $Builtin.Int2048, 4
+ // CHECK: [[BAR:%.*]] = function_ref @_T010statements3barySiF
// CHECK: apply [[BAR]](
bar(4)
}
diff --git a/test/SILGen/struct_resilience.swift b/test/SILGen/struct_resilience.swift
index ce8a8c9..5877d84 100644
--- a/test/SILGen/struct_resilience.swift
+++ b/test/SILGen/struct_resilience.swift
@@ -16,11 +16,11 @@
// CHECK: copy_addr %1 to [initialization] [[OTHER_SIZE_BOX:%[0-9]*]] : $*Size
var s2 = s
-// CHECK: [[SETTER:%.*]] = function_ref @_T016resilient_struct4SizeV1wSivs : $@convention(method) (Int, @inout Size) -> ()
// CHECK: copy_addr %1 to [initialization] [[SIZE_BOX:%.*]] : $*Size
// CHECK: [[GETTER:%.*]] = function_ref @_T016resilient_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 @_T016resilient_struct4SizeV1wSivs : $@convention(method) (Int, @inout Size) -> ()
// CHECK: apply [[SETTER]]([[RESULT]], [[WRITE]])
s2.w = s.w
@@ -39,14 +39,14 @@
// Use materializeForSet for inout access of properties in resilient structs
// from a different resilience domain
-func inoutFunc(_ x: inout Int) {}
+public func inoutFunc(_ x: inout Int) {}
// CHECK-LABEL: sil hidden @_T017struct_resilience18resilientInOutTesty0c1_A04SizeVzF : $@convention(thin) (@inout Size) -> ()
func resilientInOutTest(_ s: inout Size) {
-// CHECK: function_ref @_T017struct_resilience9inoutFuncySizF
// CHECK: function_ref @_T016resilient_struct4SizeV1wSivm
+// CHECK: function_ref @_T017struct_resilience9inoutFuncySizF
inoutFunc(&s.w)
@@ -255,11 +255,26 @@
@_versioned
@_transparent func useVersionedResilientStruct(_ s: VersionedResilientStruct)
-> VersionedResilientStruct {
- // CHECK: function_ref @_T017struct_resilience24VersionedResilientStructVACSi1x_Si1ytcfC
// CHECK: function_ref @_T017struct_resilience24VersionedResilientStructV1ySivg
// CHECK: function_ref @_T017struct_resilience24VersionedResilientStructV1xSivg
+ // CHECK: function_ref @_T017struct_resilience24VersionedResilientStructVACSi1x_Si1ytcfC
return VersionedResilientStruct(x: s.y, y: s.x)
+
+ // CHECK: return
+}
+
+// CHECK-LABEL: sil [serialized] @_T017struct_resilience19inlineableInoutTestyAA6MySizeVzF : $@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 @_T017struct_resilience6MySizeV1wSivm
+ inoutFunc(&s.w)
+
+ // CHECK: return
}
// Initializers for resilient structs
diff --git a/test/SILGen/subclass_existentials.swift b/test/SILGen/subclass_existentials.swift
index f37e55b..b7126bd 100644
--- a/test/SILGen/subclass_existentials.swift
+++ b/test/SILGen/subclass_existentials.swift
@@ -126,8 +126,7 @@
// CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[BORROW]] : $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: [[BORROWED_CLASS_REF:%.*]] = begin_borrow [[CLASS_REF]]
- // CHECK: [[METHOD:%.*]] = class_method [[BORROWED_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: [[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
@@ -138,10 +137,10 @@
// CHECK: [[BORROW:%.*]] = begin_borrow %0 : $Base<Int> & P
// CHECK: [[PAYLOAD:%.*]] = open_existential_ref [[BORROW]] : $Base<Int> & P to $@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: [[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
@@ -152,8 +151,8 @@
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: [[METHOD:%.*]] = function_ref @_T021subclass_existentials4BaseC15classSelfReturnACyxGXDyFZ : $@convention(method) <τ_0_0> (@thick Base<τ_0_0>.Type) -> @owned Base<τ_0_0>
// CHECK: [[METATYPE_REF:%.*]] = upcast [[METATYPE]] : $@thick (@opened("{{.*}}") (Base<Int> & P)).Type to $@thick Base<Int>.Type
+ // CHECK: [[METHOD:%.*]] = function_ref @_T021subclass_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
@@ -161,8 +160,8 @@
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: [[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: [[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
diff --git a/test/SILGen/super_init_refcounting.swift b/test/SILGen/super_init_refcounting.swift
index ab154d6..2809ebf 100644
--- a/test/SILGen/super_init_refcounting.swift
+++ b/test/SILGen/super_init_refcounting.swift
@@ -84,13 +84,13 @@
// CHECK: assign {{.*}} to [[WRITE]] : $*Int
// CHECK: [[SELF_OBJ:%.*]] = load [take] [[PB_SELF_BOX]] : $*Good
// CHECK: [[SUPER_OBJ:%.*]] = upcast [[SELF_OBJ]] : $Good to $Foo
- // CHECK: [[SUPER_INIT:%.*]] = function_ref @_T022super_init_refcounting3FooCACSicfc : $@convention(method) (Int, @owned Foo) -> @owned Foo
// CHECK: [[BORROWED_SUPER:%.*]] = begin_borrow [[SUPER_OBJ]]
// CHECK: [[DOWNCAST_BORROWED_SUPER:%.*]] = unchecked_ref_cast [[BORROWED_SUPER]] : $Foo to $Good
// CHECK: [[X_ADDR:%.*]] = ref_element_addr [[DOWNCAST_BORROWED_SUPER]] : $Good, #Good.x
// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[X_ADDR]] : $*Int
// CHECK: [[X:%.*]] = load [trivial] [[READ]] : $*Int
// CHECK: end_borrow [[BORROWED_SUPER]] from [[SUPER_OBJ]]
+ // CHECK: [[SUPER_INIT:%.*]] = function_ref @_T022super_init_refcounting3FooCACSicfc : $@convention(method) (Int, @owned Foo) -> @owned Foo
// CHECK: apply [[SUPER_INIT]]([[X]], [[SUPER_OBJ]])
override init() {
x = 10
diff --git a/test/SILGen/switch_var.swift b/test/SILGen/switch_var.swift
index 342c633..cff6657 100644
--- a/test/SILGen/switch_var.swift
+++ b/test/SILGen/switch_var.swift
@@ -50,9 +50,9 @@
// CHECK: [[X:%.*]] = project_box [[XADDR]]
// CHECK-NOT: br bb
case var x:
- // CHECK: function_ref @_T010switch_var1aySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1aySi1x_tF
// CHECK: destroy_value [[XADDR]]
// CHECK: br [[CONT:bb[0-9]+]]
a(x: x)
@@ -68,31 +68,31 @@
switch foo() {
// CHECK: [[XADDR:%.*]] = alloc_box ${ var Int }
// CHECK: [[X:%.*]] = project_box [[XADDR]]
- // CHECK: function_ref @_T010switch_var6runcedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var6runcedSbSi1x_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: function_ref @_T010switch_var1aySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1aySi1x_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: function_ref @_T010switch_var6fungedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var6fungedSbSi1x_tF
// CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
case var y where funged(x: y):
// CHECK: [[CASE2]]:
- // CHECK: function_ref @_T010switch_var1bySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1bySi1x_tF
// CHECK: destroy_value [[YADDR]]
// CHECK: br [[CONT]]
b(x: y)
@@ -102,9 +102,9 @@
// CHECK: [[CASE3]]:
// CHECK: [[ZADDR:%.*]] = alloc_box ${ var Int }
// CHECK: [[Z:%.*]] = project_box [[ZADDR]]
- // CHECK: function_ref @_T010switch_var1cySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1cySi1x_tF
// CHECK: destroy_value [[ZADDR]]
// CHECK: br [[CONT]]
c(x: z)
@@ -121,15 +121,15 @@
switch (foo(), bar()) {
// CHECK: [[XADDR:%.*]] = alloc_box ${ var (Int, Int) }
// CHECK: [[X:%.*]] = project_box [[XADDR]]
- // CHECK: function_ref @_T010switch_var6runcedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
// CHECK: tuple_element_addr [[READ]] : {{.*}}, 0
+ // CHECK: function_ref @_T010switch_var6runcedSbSi1x_tF
// CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
case var x where runced(x: x.0):
// CHECK: [[CASE1]]:
- // CHECK: function_ref @_T010switch_var2aaySi_Sit1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var2aaySi_Sit1x_tF
// CHECK: destroy_value [[XADDR]]
// CHECK: br [[CONT:bb[0-9]+]]
aa(x: x)
@@ -141,18 +141,18 @@
// CHECK: [[Y:%.*]] = project_box [[YADDR]]
// CHECK: [[ZADDR:%.*]] = alloc_box ${ var Int }
// CHECK: [[Z:%.*]] = project_box [[ZADDR]]
- // CHECK: function_ref @_T010switch_var6fungedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var6fungedSbSi1x_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: function_ref @_T010switch_var1aySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
// CHECK: load [trivial] [[READ]]
- // CHECK: function_ref @_T010switch_var1bySi1x_tF
+ // CHECK: function_ref @_T010switch_var1aySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1bySi1x_tF
// CHECK: destroy_value [[ZADDR]]
// CHECK: destroy_value [[YADDR]]
// CHECK: br [[CONT]]
@@ -161,15 +161,15 @@
// CHECK: [[NO_CASE2]]:
// CHECK: [[WADDR:%.*]] = alloc_box ${ var (Int, Int) }
// CHECK: [[W:%.*]] = project_box [[WADDR]]
- // CHECK: function_ref @_T010switch_var5ansedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]]
// CHECK: tuple_element_addr [[READ]] : {{.*}}, 0
+ // CHECK: function_ref @_T010switch_var5ansedSbSi1x_tF
// CHECK: cond_br {{%.*}}, [[CASE3:bb[0-9]+]], [[NO_CASE3:bb[0-9]+]]
case var w where ansed(x: w.0):
// CHECK: [[CASE3]]:
- // CHECK: function_ref @_T010switch_var2bbySi_Sit1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var2bbySi_Sit1x_tF
// CHECK: br [[CONT]]
bb(x: w)
// CHECK: [[NO_CASE3]]:
@@ -179,9 +179,9 @@
// CHECK: [[CASE4]]:
// CHECK: [[VADDR:%.*]] = alloc_box ${ var (Int, Int) }
// CHECK: [[V:%.*]] = project_box [[VADDR]]
- // CHECK: function_ref @_T010switch_var2ccySi_Sit1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[V]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var2ccySi_Sit1x_tF
// CHECK: destroy_value [[VADDR]]
// CHECK: br [[CONT]]
cc(x: v)
@@ -214,9 +214,9 @@
// CHECK: [[XADDR:%.*]] = alloc_box ${ var Int }
// CHECK: [[X:%.*]] = project_box [[XADDR]]
// CHECK: store [[PAIR_1]] to [trivial] [[X]]
- // CHECK: function_ref @_T010switch_var6runcedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[X]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var6runcedSbSi1x_tF
// CHECK: cond_br {{%.*}}, [[CASE1:bb[0-9]+]], [[NO_CASE1:bb[0-9]+]]
case (is X, var x) where runced(x: x):
// CHECK: [[CASE1]]:
@@ -245,16 +245,16 @@
// CHECK: [[YADDR:%.*]] = alloc_box ${ var Int }
// CHECK: [[Y:%.*]] = project_box [[YADDR]]
// CHECK: store [[PAIR_1]] to [trivial] [[Y]]
- // CHECK: function_ref @_T010switch_var6fungedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var6fungedSbSi1x_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: function_ref @_T010switch_var1bySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Y]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1bySi1x_tF
// CHECK: destroy_value [[YADDR]]
// CHECK: dealloc_stack [[TMP]]
// CHECK: destroy_addr [[PAIR_0]] : $*P
@@ -273,15 +273,15 @@
// CHECK: [[NEXT]]:
// CHECK: [[ZADDR:%.*]] = alloc_box ${ var (P, Int) }
// CHECK: [[Z:%.*]] = project_box [[ZADDR]]
- // CHECK: function_ref @_T010switch_var5ansedSbSi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
// CHECK: tuple_element_addr [[READ]] : {{.*}}, 1
+ // CHECK: function_ref @_T010switch_var5ansedSbSi1x_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: function_ref @_T010switch_var1cySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[Z]]
// CHECK: tuple_element_addr [[READ]] : {{.*}}, 1
+ // CHECK: function_ref @_T010switch_var1cySi1x_tF
// CHECK: destroy_value [[ZADDR]]
// CHECK-NEXT: dealloc_stack [[PAIR]]
// CHECK: br [[CONT]]
@@ -295,9 +295,9 @@
// CHECK: [[PAIR_0:%.*]] = tuple_element_addr [[PAIR]] : $*(P, Int), 0
// CHECK: [[WADDR:%.*]] = alloc_box ${ var Int }
// CHECK: [[W:%.*]] = project_box [[WADDR]]
- // CHECK: function_ref @_T010switch_var1dySi1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[W]]
// CHECK: load [trivial] [[READ]]
+ // CHECK: function_ref @_T010switch_var1dySi1x_tF
// CHECK: destroy_value [[WADDR]]
// CHECK: destroy_addr [[PAIR_0]] : $*P
// CHECK: dealloc_stack [[PAIR]]
@@ -407,9 +407,9 @@
switch foos() {
case let x where runced():
// CHECK: [[CASE1]]:
- // CHECK: [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
// CHECK: [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
// CHECK: [[VAL_COPY_COPY:%.*]] = copy_value [[BORROWED_VAL_COPY]]
+ // CHECK: [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
// CHECK: apply [[A]]([[VAL_COPY_COPY]])
// CHECK: end_borrow [[BORROWED_VAL_COPY]] from [[VAL_COPY]]
// CHECK: destroy_value [[VAL_COPY]]
@@ -425,9 +425,9 @@
// CHECK: cond_br {{%.*}}, [[CASE2:bb[0-9]+]], [[NO_CASE2:bb[0-9]+]]
case let y where funged():
// CHECK: [[CASE2]]:
- // CHECK: [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
// CHECK: [[BORROWED_VAL_COPY_2:%.*]] = begin_borrow [[VAL_COPY_2]]
// CHECK: [[VAL_COPY_2_COPY:%.*]] = copy_value [[BORROWED_VAL_COPY_2]]
+ // CHECK: [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
// CHECK: apply [[B]]([[VAL_COPY_2_COPY]])
// CHECK: end_borrow [[BORROWED_VAL_COPY_2]] from [[VAL_COPY_2]]
// CHECK: destroy_value [[VAL_COPY_2]]
@@ -486,9 +486,9 @@
// CHECK: cond_br {{.*}}, [[CASE1:bb[0-9]+]], [[NOCASE1:bb[0-9]+]]
case var x where runced():
// CHECK: [[CASE1]]:
- // CHECK: [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
// CHECK: [[READ:%.*]] = begin_access [read] [unknown] [[PBOX]]
// CHECK: [[X:%.*]] = load [copy] [[READ]]
+ // CHECK: [[A:%.*]] = function_ref @_T010switch_var1aySS1x_tF
// CHECK: apply [[A]]([[X]])
// CHECK: destroy_value [[BOX]]
// CHECK: br [[CONT:bb[0-9]+]]
@@ -504,9 +504,9 @@
case let y where funged():
// CHECK: [[CASE2]]:
- // CHECK: [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
// CHECK: [[BORROWED_VAL_COPY:%.*]] = begin_borrow [[VAL_COPY]]
// CHECK: [[VAL_COPY_COPY:%.*]] = copy_value [[BORROWED_VAL_COPY]]
+ // CHECK: [[B:%.*]] = function_ref @_T010switch_var1bySS1x_tF
// CHECK: apply [[B]]([[VAL_COPY_COPY]])
// CHECK: end_borrow [[BORROWED_VAL_COPY]] from [[VAL_COPY]]
// CHECK: destroy_value [[VAL_COPY]]
@@ -721,8 +721,8 @@
// CHECK: [[CASE_BODY]]([[BODY_X:%.*]] : $Int):
// CHECK: store [[BODY_X]] to [trivial] [[BOX_X:%.*]] : $*Int
- // CHECK: [[FUNC_AAA:%.*]] = function_ref @_T010switch_var3aaaySiz1x_tF
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] [[BOX_X]]
+ // CHECK: [[FUNC_AAA:%.*]] = function_ref @_T010switch_var3aaaySiz1x_tF
// CHECK: apply [[FUNC_AAA]]([[WRITE]])
aaa(x: &x)
}
diff --git a/test/SILGen/transparent_attribute.swift b/test/SILGen/transparent_attribute.swift
index 8174a77..f0a72fd 100644
--- a/test/SILGen/transparent_attribute.swift
+++ b/test/SILGen/transparent_attribute.swift
@@ -1,212 +1,14 @@
// RUN: %target-swift-frontend -emit-silgen -emit-verbose-sil -enable-sil-ownership %s | %FileCheck %s
// Test that the attribute gets set on default argument generators.
+
+// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tFfA_ : $@convention(thin) () -> Int {
+
+// CHECK-LABEL: sil hidden [transparent] @_T021transparent_attribute0A23FuncWithDefaultArgumentS2i1x_tF : $@convention(thin) (Int) -> Int {
+
@_transparent func transparentFuncWithDefaultArgument (x: Int = 1) -> Int {
return x
}
func useTransparentFuncWithDefaultArgument() -> Int {
- return transparentFuncWithDefaultArgument();
-
- // CHECK-LABEL: sil hidden @_T021transparent_attribute37useTransparentFuncWithDefaultArgumentSiyF
- // CHECK: apply {{.*}} line:8:44
- // CHECK: apply {{.*}} line:8:10
- // CHECK: return
-
-}
-
-func transparentFuncWithoutDefaultArgument (x: Int = 1) -> Int {
- return x
-}
-func useTransparentFuncWithoutDefaultArgument() -> Int {
- return transparentFuncWithoutDefaultArgument();
-
- // CHECK-LABEL: sil hidden @_T021transparent_attribute40useTransparentFuncWithoutDefaultArgumentSiyF
- // CHECK: apply {{.*}} line:21:47
- // CHECK-NOT: transparent
- // CHECK: apply {{.*}} line:21:10
- // CHECK: return
-
-}
-
-// Make sure the transparent attribute is set on constructors (allocating and initializing).
-struct StructWithTranspConstructor {
- @_transparent init () {}
-}
-func testStructWithTranspConstructor() -> StructWithTranspConstructor {
- return StructWithTranspConstructor()
-
- // transparent_attribute.StructWithTranspConstructor.constructor
- // CHECK-APPLY: sil hidden @_T021transparent_attribute27StructWithTranspConstructorV{{[_0-9a-zA-Z]*}}fC
-
- // testStructWithTranspConstructor
- // CHECK-APPLY: _T21transparent_attribute31testStructWithTranspConstructorFT_VS_27StructWithTranspConstructor
- // CHECK: apply {{.*}} line:36:10
-
-}
-
-struct MySt {}
-var _x = MySt()
-var x1 : MySt {
- @_transparent
- get {
- return _x
- }
- @_transparent
- set {
- _x = newValue
- }
-}
-var x2 : MySt {
- @_transparent
- set(v) {
- _x = v
- }
- @_transparent
- get {
- return _x
- }
-}
-func testProperty(z: MySt) {
- x1 = z
- x2 = z
- var m1 : MySt = x1
- var m2 : MySt = x2
- // CHECK-APPLY: sil hidden @_T021transparent_attribute12testPropertyyAA4MyStV1z_tF
- // CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvs
- // CHECK-NEXT: apply
- // CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvs
- // CHECK-NEXT: apply
- // CHECK: function_ref @_T021transparent_attribute2x1AA4MyStVvg
- // CHECK-NEXT: apply
- // CHECK: function_ref @_T021transparent_attribute2x2AA4MyStVvg
- // CHECK-NEXT: apply
-}
-
-var _tr2 = MySt()
-var _tr3 = MySt()
-struct MyTranspStruct {}
-extension MyTranspStruct {
- @_transparent
- init(input : MySt) {}
- mutating
- func tr1() {}
- var tr2: MySt {
- get {
- return _tr2
- }
- set {
- _tr2 = newValue
- }
- }
-}
-
-extension MyTranspStruct {
- @_transparent
- var tr3: MySt {
- get {
- return _tr3
- }
- set {
- _tr3 = newValue
- }
- }
-}
-
-func testStructExtension() {
- var c : MyTranspStruct = MyTranspStruct(input: _x)
- c.tr1()
- var s : MySt = c.tr2
- var t : MySt = c.tr3
- // CHECK-APPLY: sil hidden @_TF21transparent_attribute13testStructExtensionFT_T_
- // CHECK: [[INIT:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV{{[_0-9a-zA-Z]*}}fC
- // CHECK: apply [[INIT]]
- // CHECK: [[TR1:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr1{{[_0-9a-zA-Z]*}}F
- // CHECK: apply [[TR1]]
- // CHECK: [[TR2:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr2AA0C2StVvg
- // CHECK: apply [[TR2]]
- // CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute14MyTranspStructV3tr3AA0C2StVvg
- // CHECK: apply [[TR3]]
-}
-
-enum MyEnum {
- case onetransp
- case twotransp
-}
-
-extension MyEnum {
- @_transparent
- func tr3() {}
-}
-
-func testEnumExtension() {
- MyEnum.onetransp.tr3()
- // CHECK-APPLY: sil hidden @_T021transparent_attribute17testEnumExtensionyyF
- // CHECK: [[TR3:%[0-9]+]] = function_ref @_T021transparent_attribute6MyEnumO3tr3{{[_0-9a-zA-Z]*}}F
- // CHECK: [[INIT:%[0-9]+]] = enum $MyEnum, #MyEnum.onetransp!enumelt
- // CHECK: apply [[TR3]]([[INIT]])
-}
-
-struct testVarDecl {
- @_transparent var max: Int {
- get {
- return 0xFF
- }
- mutating
- set {
- max = 0xFF
- }
- }
- func testVarDeclFoo () {
- var z: Int = max
- // CHECK-APPLY: sil hidden @_T021transparent_attribute11testVarDeclV0cdE3Foo{{[_0-9a-zA-Z]*}}F
- // CHECK: [[TR4:%[0-9]+]] = function_ref @_T021transparent_attribute11testVarDeclV3maxSivg
- // CHECK: apply [[TR4]]
- }
-}
-
-struct testVarDeclShortenedSyntax {
- @_transparent static var max: Int { return 0xFF };
- func testVarDeclShortenedSyntaxfoo () {
- var z: Int = testVarDeclShortenedSyntax.max
- // CHECK-APPLY: sil hidden @_T021transparent_attribute26testVarDeclShortenedSyntaxV0cdeF9Syntaxfoo{{[_0-9a-zA-Z]*}}F
- // CHECK: [[TR5:%[0-9]+]] = function_ref @_T021transparent_attribute26testVarDeclShortenedSyntaxV3maxSivgZ
- // CHECK: apply [[TR5]]
- }
-};
-
-@_transparent var transparentOnGlobalVar: Int {
- get {
- return 0xFF
- }
-}
-// CHECK: sil hidden [transparent] @_T021transparent_attribute0A11OnGlobalVarSivg
-
-// Local functions in transparent context are fragile.
-@_transparent public func foo() {
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3barL_yyF : $@convention(thin) () -> ()
- func bar() {}
- bar()
-
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyFyycfU_ : $@convention(thin) () -> () {
- let f: () -> () = {}
- f()
-
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF : $@convention(thin) () -> () {
- func zim() {
- // CHECK-LABEL: sil shared [serialized] @_T021transparent_attribute3fooyyF3zimL_yyF4zangL_yyF : $@convention(thin) () -> () {
- func zang() {
- }
- zang()
- }
- zim()
-}
-
-
-// Check that @_versioned entities have public linkage.
-// CHECK-LABEL: sil @_T021transparent_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
-@_versioned func referencedFromTransparent() {}
-
-// CHECK-LABEL: sil [transparent] [serialized] @_T021transparent_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
-@_transparent public func referencesVersionedFunc() -> () -> () {
- return referencedFromTransparent
+ return transparentFuncWithDefaultArgument()
}
diff --git a/test/SILGen/tsan_instrumentation.swift b/test/SILGen/tsan_instrumentation.swift
index 2bf6ec0..070cc9d 100644
--- a/test/SILGen/tsan_instrumentation.swift
+++ b/test/SILGen/tsan_instrumentation.swift
@@ -18,9 +18,9 @@
// CHECK-LABEL: sil hidden @_T020tsan_instrumentation17inoutGlobalStructyyF : $@convention(thin) () -> () {
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @_T020tsan_instrumentation7gStructAA02MyC0Vvp : $*MyStruct
-// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutyAA8MyStructVzF : $@convention(thin) (@inout MyStruct) -> ()
// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]] : $*MyStruct
// CHECK: {{%.*}} = builtin "tsanInoutAccess"([[WRITE]] : $*MyStruct) : $()
+// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutyAA8MyStructVzF : $@convention(thin) (@inout MyStruct) -> ()
// CHECK: {{%.*}} = apply [[TAKES_INOUT_FUNC]]([[WRITE]]) : $@convention(thin) (@inout MyStruct) -> ()
func inoutGlobalStruct() {
takesInout(&gStruct)
@@ -29,11 +29,11 @@
// CHECK-LABEL: sil hidden @_T020tsan_instrumentation31inoutGlobalStructStoredPropertyyyF : $@convention(thin) () -> () {
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @_T020tsan_instrumentation7gStructAA02MyC0Vvp : $*MyStruct
-// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
// CHECK: [[WRITE:%.*]] = begin_access [modify] [dynamic] [[GLOBAL_ADDR]] : $*MyStruct
// CHECK: {{%.*}} = builtin "tsanInoutAccess"([[WRITE]] : $*MyStruct) : $()
// CHECK: [[ELEMENT_ADDR:%.*]] = struct_element_addr [[WRITE]] : $*MyStruct, #MyStruct.storedProperty
// CHECK: {{%.*}} = builtin "tsanInoutAccess"([[ELEMENT_ADDR]] : $*Int) : $()
+// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
// CHECK: {{%.*}} = apply [[TAKES_INOUT_FUNC]]([[ELEMENT_ADDR]]) : $@convention(thin) (@inout Int) -> ()
func inoutGlobalStructStoredProperty() {
// This should generate two TSan inout instrumentations; one for the address
@@ -43,15 +43,14 @@
// CHECK-LABEL: sil hidden @_T020tsan_instrumentation30inoutGlobalClassStoredPropertyyyF : $@convention(thin) () -> () {
// CHECK: [[GLOBAL_ADDR:%.*]] = global_addr @_T020tsan_instrumentation6gClassAA02MyC0Cvp : $*MyClass
-// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
// CHECK: [[READ:%.*]] = begin_access [read] [dynamic] [[GLOBAL_ADDR]] : $*MyClass
// CHECK: [[LOADED_CLASS:%.*]] = load [copy] [[READ]] : $*MyClass
// CHECK: [[VALUE_BUFFER:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK: [[TEMPORARY:%.*]] = alloc_stack $Int
// CHECK: [[BORROWED_CLASS:%.*]] = begin_borrow [[LOADED_CLASS]] : $MyClass
// CHECK: [[TEMPORARY_RAW:%.*]] = address_to_pointer [[TEMPORARY]] : $*Int to $Builtin.RawPointer
-// CHECK: [[MATERIALIZE_FOR_SET:%.*]] = class_method [[BORROWED_CLASS]] : $MyClass, #MyClass.storedProperty!materializeForSet.1 : (MyClass) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?), $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed MyClass) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
// CHECK: {{%.*}} = builtin "tsanInoutAccess"([[VALUE_BUFFER]] : $*Builtin.UnsafeValueBuffer) : $()
+// CHECK: [[MATERIALIZE_FOR_SET:%.*]] = class_method [[BORROWED_CLASS]] : $MyClass, #MyClass.storedProperty!materializeForSet.1 : (MyClass) -> (Builtin.RawPointer, inout Builtin.UnsafeValueBuffer) -> (Builtin.RawPointer, Builtin.RawPointer?), $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed MyClass) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
// CHECK: [[MATERIALIZE_FOR_SET_TUPLE:%.*]] = apply [[MATERIALIZE_FOR_SET]]([[TEMPORARY_RAW]], [[VALUE_BUFFER]], [[BORROWED_CLASS]]) : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed MyClass) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
// CHECK: [[TEMPORARY_BUFFER:%.*]] = tuple_extract [[MATERIALIZE_FOR_SET_TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 0
// CHECK: [[OPTIONAL_CALLBACK:%.*]] = tuple_extract [[MATERIALIZE_FOR_SET_TUPLE]] : $(Builtin.RawPointer, Optional<Builtin.RawPointer>), 1
@@ -59,6 +58,7 @@
// CHECK: [[BUFFER_ADDRESS_DEPENDENCE:%.*]] = mark_dependence [[BUFFER_ADDRESS]] : $*Int on [[LOADED_CLASS]] : $MyClass
// CHECK: end_borrow [[BORROWED_CLASS]] from [[LOADED_CLASS]] : $MyClass, $MyClass
// CHECK: {{%.*}} builtin "tsanInoutAccess"([[BUFFER_ADDRESS_DEPENDENCE]] : $*Int) : $()
+// CHECK: [[TAKES_INOUT_FUNC:%.*]] = function_ref @_T020tsan_instrumentation10takesInoutySizF : $@convention(thin) (@inout Int) -> ()
// CHECK: {{%.*}} apply [[TAKES_INOUT_FUNC]]([[BUFFER_ADDRESS_DEPENDENCE]]) : $@convention(thin) (@inout Int) -> ()
func inoutGlobalClassStoredProperty() {
// This generates two TSan inout instrumentations. One for the value
diff --git a/test/SILGen/tuples.swift b/test/SILGen/tuples.swift
index 3d7d9d3..349690d 100644
--- a/test/SILGen/tuples.swift
+++ b/test/SILGen/tuples.swift
@@ -43,9 +43,9 @@
// 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 @_T06tuples7make_xySi1x_AA1P_p1ytyF
- // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
// 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
@@ -90,9 +90,9 @@
// CHECK-NEXT: // function_ref
// CHECK: [[T0:%.*]] = function_ref @_T06tuples8make_intSiyF
// CHECK-NEXT: [[INT:%.*]] = apply [[T0]]()
+ // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T06tuples6make_pAA1P_pyF
- // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $P
// 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
diff --git a/test/SILGen/unowned.swift b/test/SILGen/unowned.swift
index 6d8b9a8..68a045f 100644
--- a/test/SILGen/unowned.swift
+++ b/test/SILGen/unowned.swift
@@ -122,8 +122,6 @@
// 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: end_borrow [[BORROWED_UNOWNED_ARG]]
-// CHECK-NEXT: [[BORROWED_UNOWNED_ARG:%.*]] = begin_borrow [[UNOWNED_ARG]]
// 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]]
diff --git a/test/SILGen/versioned_attribute.swift b/test/SILGen/versioned_attribute.swift
index 5a01525..b544b48 100644
--- a/test/SILGen/versioned_attribute.swift
+++ b/test/SILGen/versioned_attribute.swift
@@ -1,5 +1,14 @@
// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership -emit-verbose-sil %s | %FileCheck %s
+// Check that @_versioned entities have public linkage.
+// CHECK-LABEL: sil @_T019versioned_attribute25referencedFromTransparentyyF : $@convention(thin) () -> () {
+@_versioned func referencedFromTransparent() {}
+
+// CHECK-LABEL: sil [serialized] @_T019versioned_attribute23referencesVersionedFuncyycyF : $@convention(thin) () -> @owned @callee_owned () -> () {
+@_inlineable public func referencesVersionedFunc() -> () -> () {
+ return referencedFromTransparent
+}
+
@_versioned class Horse {
var mouth: AnyObject?
}
diff --git a/test/SILGen/witnesses_class.swift b/test/SILGen/witnesses_class.swift
index 9c5d97a..c2b2dfc 100644
--- a/test/SILGen/witnesses_class.swift
+++ b/test/SILGen/witnesses_class.swift
@@ -26,10 +26,10 @@
// CHECK-LABEL: sil hidden @_T015witnesses_class3genyxAA7FooableRzlF
// CHECK: bb0([[SELF:%.*]] : @owned $T)
-// CHECK: [[METHOD:%.*]] = witness_method $T
// CHECK-NOT: copy_value [[SELF]]
// CHECK: [[BORROWED_SELF:%.*]] = begin_borrow [[SELF]]
// CHECK-NOT: copy_value [[SELF]]
+// CHECK: [[METHOD:%.*]] = witness_method $T
// CHECK: apply [[METHOD]]<T>([[BORROWED_SELF]])
// CHECK: end_borrow [[BORROWED_SELF]] from [[SELF]]
// CHECK: destroy_value [[SELF]]
diff --git a/test/SILGen/writeback.swift b/test/SILGen/writeback.swift
index 1232bc6..de739d8 100644
--- a/test/SILGen/writeback.swift
+++ b/test/SILGen/writeback.swift
@@ -43,11 +43,11 @@
// Writeback to value type 'self' argument
x.foo()
-// CHECK: [[FOO:%.*]] = function_ref @_T09writeback3FooV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout Foo) -> ()
// CHECK: [[X_TEMP:%.*]] = alloc_stack $Foo
// CHECK: [[GET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvg : $@convention(thin) () -> Foo
// CHECK: [[X:%.*]] = apply [[GET_X]]() : $@convention(thin) () -> Foo
// CHECK: store [[X]] to [trivial] [[X_TEMP]]
+// CHECK: [[FOO:%.*]] = function_ref @_T09writeback3FooV3foo{{[_0-9a-zA-Z]*}}F : $@convention(method) (@inout Foo) -> ()
// CHECK: apply [[FOO]]([[X_TEMP]]) : $@convention(method) (@inout Foo) -> ()
// CHECK: [[X1:%.*]] = load [trivial] [[X_TEMP]] : $*Foo
// CHECK: [[SET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
@@ -56,11 +56,11 @@
// Writeback to inout argument
bar(x: &x)
-// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
// CHECK: [[X_TEMP:%.*]] = alloc_stack $Foo
// CHECK: [[GET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvg : $@convention(thin) () -> Foo
// CHECK: [[X:%.*]] = apply [[GET_X]]() : $@convention(thin) () -> Foo
// CHECK: store [[X]] to [trivial] [[X_TEMP]] : $*Foo
+// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
// CHECK: apply [[BAR]]([[X_TEMP]]) : $@convention(thin) (@inout Foo) -> ()
// CHECK: [[X1:%.*]] = load [trivial] [[X_TEMP]] : $*Foo
// CHECK: [[SET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvs : $@convention(thin) (Foo) -> ()
@@ -81,12 +81,12 @@
// Ensure that subscripts are only evaluated once.
bar(x: &x[zung()])
-// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
// CHECK: [[ZUNG:%.*]] = function_ref @_T09writeback4zungSiyF : $@convention(thin) () -> Int
// CHECK: [[INDEX:%.*]] = apply [[ZUNG]]() : $@convention(thin) () -> Int
// CHECK: [[GET_X:%.*]] = function_ref @_T09writeback1xAA3FooVvg : $@convention(thin) () -> Foo
// CHECK: [[GET_SUBSCRIPT:%.*]] = function_ref @_T09writeback3FooV{{[_0-9a-zA-Z]*}}ig : $@convention(method) (Int, Foo) -> Foo
// CHECK: apply [[GET_SUBSCRIPT]]([[INDEX]], {{%.*}}) : $@convention(method) (Int, Foo) -> Foo
+// CHECK: [[BAR:%.*]] = function_ref @_T09writeback3baryAA3FooVz1x_tF : $@convention(thin) (@inout Foo) -> ()
// CHECK: apply [[BAR]]({{%.*}}) : $@convention(thin) (@inout Foo) -> ()
// CHECK: [[SET_SUBSCRIPT:%.*]] = function_ref @_T09writeback3FooV{{[_0-9a-zA-Z]*}}is : $@convention(method) (Foo, Int, @inout Foo) -> ()
// CHECK: apply [[SET_SUBSCRIPT]]({{%.*}}, [[INDEX]], {{%.*}}) : $@convention(method) (Foo, Int, @inout Foo) -> ()
@@ -105,10 +105,10 @@
func funge(x x: inout Fungible) {}
funge(x: &addressOnly)
-// CHECK: [[FUNGE:%.*]] = function_ref @_T09writeback5fungeyAA8Fungible_pz1x_tF : $@convention(thin) (@inout Fungible) -> ()
// CHECK: [[TEMP:%.*]] = alloc_stack $Fungible
// CHECK: [[GET:%.*]] = function_ref @_T09writeback11addressOnlyAA8Fungible_pvg : $@convention(thin) () -> @out Fungible
// CHECK: apply [[GET]]([[TEMP]]) : $@convention(thin) () -> @out Fungible
+// CHECK: [[FUNGE:%.*]] = function_ref @_T09writeback5fungeyAA8Fungible_pz1x_tF : $@convention(thin) (@inout Fungible) -> ()
// CHECK: apply [[FUNGE]]([[TEMP]]) : $@convention(thin) (@inout Fungible) -> ()
// CHECK: [[SET:%.*]] = function_ref @_T09writeback11addressOnlyAA8Fungible_pvs : $@convention(thin) (@in Fungible) -> ()
// CHECK: apply [[SET]]([[TEMP]]) : $@convention(thin) (@in Fungible) -> ()
@@ -130,8 +130,8 @@
}
// CHECK-LABEL: sil hidden @_T09writeback12test_generic{{[_0-9a-zA-Z]*}}F
-// CHECK: witness_method $Runce.Frob, #Frobable.anse!setter.1
// CHECK: witness_method $Runce, #Runcible.frob!materializeForSet.1
+// CHECK: witness_method $Runce.Frob, #Frobable.anse!setter.1
func test_generic<Runce: Runcible>(runce runce: inout Runce, anse: Runce.Frob.Anse) {
runce.frob.anse = anse
}
diff --git a/test/SILOptimizer/access_enforcement_selection.sil b/test/SILOptimizer/access_enforcement_selection.sil
index dbf440e..ed69a81 100644
--- a/test/SILOptimizer/access_enforcement_selection.sil
+++ b/test/SILOptimizer/access_enforcement_selection.sil
@@ -180,3 +180,39 @@
%closure = partial_apply %f(%var) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
unreachable
}
+
+// Borrowed closure can be statically checked.
+//
+// CHECK-LABEL: sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+// CHECK: begin_access [read] [static]
+// CHECK-LABEL: } // end sil function 'borrowedClosure'
+sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+bb0(%0 : $*Builtin.Int64):
+ %access = begin_access [read] [unknown] %0 : $*Builtin.Int64
+ %val = load [trivial] %access : $*Builtin.Int64
+ end_access %access : $*Builtin.Int64
+ %empty = tuple ()
+ return %empty : $()
+}
+
+// Borrow an escaping closure. The closure body will be dynamically checked.
+sil @borrowClosure : $@convention(thin) () -> () {
+ %box = alloc_box ${ var Builtin.Int64 }, var, name "x"
+ %addr = project_box %box : ${ var Builtin.Int64 }, 0
+ // box escapes.
+ %copy = copy_value %box : ${ var Builtin.Int64 }
+
+ %f = function_ref @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+ %closure = partial_apply %f(%addr) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+
+ // closure is borrowed.
+ %borrow = begin_borrow %closure : $@callee_owned () -> ()
+ %closure_copy = copy_value %borrow : $@callee_owned () -> ()
+ end_borrow %borrow from %closure : $@callee_owned () -> (), $@callee_owned () -> ()
+
+ destroy_value %closure_copy : $@callee_owned () -> ()
+ destroy_value %copy : ${ var Builtin.Int64 }
+ destroy_value %box : ${ var Builtin.Int64 }
+ %empty = tuple ()
+ return %empty : $()
+}
diff --git a/test/SILOptimizer/access_marker_mandatory.swift b/test/SILOptimizer/access_marker_mandatory.swift
index ded9e41..feadd10 100644
--- a/test/SILOptimizer/access_marker_mandatory.swift
+++ b/test/SILOptimizer/access_marker_mandatory.swift
@@ -49,9 +49,9 @@
// CHECK: [[ADDRI:%.*]] = struct_element_addr [[WRITE]] : $*S, #S.i
// CHECK: store %{{.*}} to [[ADDRI]] : $*Int
// CHECK: end_access [[WRITE]]
-// CHECK: [[FTAKE:%.*]] = function_ref @_T023access_marker_mandatory5takeSyAA1SVF : $@convention(thin) (@owned S) -> ()
// CHECK: [[READ:%.*]] = begin_access [read] [static] [[STK]] : $*S
// CHECK: end_access [[READ]]
+// CHECK: [[FTAKE:%.*]] = function_ref @_T023access_marker_mandatory5takeSyAA1SVF : $@convention(thin) (@owned S) -> ()
// CHECK: apply [[FTAKE]](%{{.*}}) : $@convention(thin) (@owned S) -> ()
// CHECK-LABEL: } // end sil function '_T023access_marker_mandatory14modifyAndReadSyyXl1o_tF'
public func modifyAndReadS(o: AnyObject) {
diff --git a/test/SILOptimizer/anyhashable_to_protocol.swift b/test/SILOptimizer/anyhashable_to_protocol.swift
new file mode 100644
index 0000000..e4153f5
--- /dev/null
+++ b/test/SILOptimizer/anyhashable_to_protocol.swift
@@ -0,0 +1,18 @@
+// RUN: %target-swift-frontend -O -emit-sil %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+import Foundation
+
+protocol FooProtocol : class {
+}
+
+class FooProtocolImplementation : NSObject, FooProtocol {
+}
+
+// CHECK-LABEL: sil @{{.*}}testit
+// CHECK: checked_cast_addr_br {{.*}} AnyHashable {{.*}} to FooProtocol
+public func testit(_ x: AnyHashable) -> Bool {
+ return (x as? FooProtocol) != nil
+}
+
diff --git a/test/SILOptimizer/character_literals.swift b/test/SILOptimizer/character_literals.swift
index 3254167..109c99b 100644
--- a/test/SILOptimizer/character_literals.swift
+++ b/test/SILOptimizer/character_literals.swift
@@ -1,9 +1,12 @@
-// RUN: %target-swift-frontend -parse-as-library -O -emit-ir %s | %FileCheck %s
+// RUN: %target-swift-frontend -parse-as-library -O -target-cpu core2 -emit-ir %s | %FileCheck %s
// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib,CPU=x86_64
// This is an end-to-end test to ensure that the optimizer generates
// a simple literal for character literals.
+// Please note: this test targets "core2" to ensure consistent output
+// on all x86 host processors.
+
// CHECK-LABEL: define {{.*}}charArray
// CHECK: store <2 x i64> <i64 97, i64 98>
// CHECK: store <2 x i64> <i64 99, i64 100>
diff --git a/test/SILOptimizer/definite_init_failable_initializers.swift b/test/SILOptimizer/definite_init_failable_initializers.swift
index 46d7a51..1d3cc4b 100644
--- a/test/SILOptimizer/definite_init_failable_initializers.swift
+++ b/test/SILOptimizer/definite_init_failable_initializers.swift
@@ -60,7 +60,7 @@
// CHECK-NEXT: br bb1
// CHECK: bb1:
// CHECK-NEXT: [[X_ADDR:%.*]] = struct_element_addr [[SELF_BOX]]
-// CHECK-NEXT: strong_release [[CANARY]]
+// CHECK-NEXT: destroy_addr [[X_ADDR]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
@@ -86,8 +86,7 @@
// CHECK-NEXT: end_access [[WRITE]] : $*FailableStruct
// CHECK-NEXT: br bb1
// CHECK: bb1:
-// CHECK-NEXT: [[SELF:%.*]] = struct $FailableStruct ([[CANARY1]] : $Canary, [[CANARY2]] : $Canary)
-// CHECK-NEXT: release_value [[SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
@@ -108,7 +107,7 @@
// CHECK-NEXT: end_access [[WRITE]] : $*FailableStruct
// CHECK-NEXT: br bb1
// CHECK: bb1:
-// CHECK-NEXT: release_value [[CANARY]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[SELF_VALUE:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
@@ -127,7 +126,7 @@
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
// CHECK-NEXT: br bb1
// CHECK: bb1:
-// CHECK-NEXT: release_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
@@ -153,7 +152,9 @@
// CHECK: [[SUCC_BB]]:
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT: retain_value [[SELF_VALUE]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableStruct>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableStruct>)
//
@@ -225,9 +226,9 @@
// CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers22FailableAddrOnlyStructV{{[_0-9a-zA-Z]*}}failAfterPartialInitialization{{.*}}tcfC
// CHECK: bb0(%0 : $*Optional<FailableAddrOnlyStruct<T>>, %1 : $@thin FailableAddrOnlyStruct<T>.Type):
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $FailableAddrOnlyStruct<T>
-// CHECK: [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
-// CHECK-NEXT: [[X_BOX:%.*]] = alloc_stack $T
+// CHECK: [[X_BOX:%.*]] = alloc_stack $T
// CHECK-NEXT: [[T_TYPE:%.*]] = metatype $@thick T.Type
+// CHECK: [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
// CHECK-NEXT: apply [[T_INIT_FN]]<T>([[X_BOX]], [[T_TYPE]])
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*FailableAddrOnlyStruct<T>
// CHECK-NEXT: [[X_ADDR:%.*]] = struct_element_addr [[WRITE]]
@@ -251,18 +252,18 @@
// CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers22FailableAddrOnlyStructV{{[_0-9a-zA-Z]*}}failAfterFullInitialization{{.*}}tcfC
// CHECK: bb0(%0 : $*Optional<FailableAddrOnlyStruct<T>>, %1 : $@thin FailableAddrOnlyStruct<T>.Type):
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $FailableAddrOnlyStruct<T>
-// CHECK: [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
-// CHECK-NEXT: [[X_BOX:%.*]] = alloc_stack $T
+// CHECK: [[X_BOX:%.*]] = alloc_stack $T
// CHECK-NEXT: [[T_TYPE:%.*]] = metatype $@thick T.Type
+// CHECK: [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
// CHECK-NEXT: apply [[T_INIT_FN]]<T>([[X_BOX]], [[T_TYPE]])
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*FailableAddrOnlyStruct<T>
// CHECK-NEXT: [[X_ADDR:%.*]] = struct_element_addr [[WRITE]]
// CHECK-NEXT: copy_addr [take] [[X_BOX]] to [initialization] [[X_ADDR]]
// CHECK-NEXT: end_access [[WRITE]] : $*FailableAddrOnlyStruct<T>
// CHECK-NEXT: dealloc_stack [[X_BOX]]
-// CHECK-NEXT: [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
// CHECK-NEXT: [[Y_BOX:%.*]] = alloc_stack $T
// CHECK-NEXT: [[T_TYPE:%.*]] = metatype $@thick T.Type
+// CHECK-NEXT: [[T_INIT_FN:%.*]] = witness_method $T, #Pachyderm.init!allocator.1
// CHECK-NEXT: apply [[T_INIT_FN]]<T>([[Y_BOX]], [[T_TYPE]])
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*FailableAddrOnlyStruct<T>
// CHECK-NEXT: [[Y_ADDR:%.*]] = struct_element_addr [[WRITE]]
@@ -346,6 +347,8 @@
// CHECK: [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACyt6noFail_tcfC
// CHECK-NEXT: [[NEW_SELF:%.*]] = apply [[INIT_FN]](%1)
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -366,6 +369,8 @@
// CHECK-NEXT: try_apply [[INIT_FN]](%1)
// CHECK: bb2([[NEW_SELF:%.*]] : $ThrowStruct):
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb3([[ERROR:%.*]] : $Error):
@@ -383,10 +388,10 @@
// CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers11ThrowStructVACSi29failBeforeOrDuringDelegation2_tKcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin ThrowStruct.Type):
// CHECK: [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct
-// CHECK: [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACSi20failBeforeDelegation_tKcfC
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb1([[RESULT:%.*]] : $Int):
+// CHECK: [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACSi20failBeforeDelegation_tKcfC
// CHECK-NEXT: try_apply [[INIT_FN]]([[RESULT]], %1)
// CHECK: bb2([[NEW_SELF:%.*]] : $ThrowStruct):
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
@@ -410,6 +415,8 @@
// CHECK-NEXT: try_apply [[INIT_FN]](%1)
// CHECK: bb1([[NEW_SELF:%.*]] : $ThrowStruct):
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -428,10 +435,12 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
-// CHECK: release_value [[NEW_SELF]]
+// CHECK: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: throw [[ERROR]]
init(failAfterDelegation: Int) throws {
@@ -454,6 +463,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
@@ -493,6 +504,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
@@ -537,7 +550,9 @@
// CHECK: [[SUCC_BB]]:
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT: retain_value [[SELF_VALUE]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<ThrowStruct>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<ThrowStruct>)
//
@@ -584,13 +599,15 @@
// CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers11ThrowStructVACSi25failDuringSelfReplacement_tKcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin ThrowStruct.Type):
// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct
+// CHECK: [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
// CHECK: [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACyt4fail_tKcfC
-// CHECK-NEXT: [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
// CHECK-NEXT: try_apply [[INIT_FN]]([[SELF_TYPE]])
// CHECK: bb1([[NEW_SELF:%.*]] : $ThrowStruct):
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*ThrowStruct
// CHECK-NEXT: store [[NEW_SELF]] to [[WRITE]]
// CHECK-NEXT: end_access [[WRITE]] : $*ThrowStruct
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -603,8 +620,8 @@
// CHECK-LABEL: sil hidden @_T035definite_init_failable_initializers11ThrowStructVACSi24failAfterSelfReplacement_tKcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin ThrowStruct.Type):
// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $ThrowStruct
+// CHECK: [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
// CHECK: [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers11ThrowStructVACyt6noFail_tcfC
-// CHECK-NEXT: [[SELF_TYPE:%.*]] = metatype $@thin ThrowStruct.Type
// CHECK-NEXT: [[NEW_SELF:%.*]] = apply [[INIT_FN]]([[SELF_TYPE]])
// CHECK-NEXT: [[WRITE:%.*]] = begin_access [modify] [static] [[SELF_BOX]] : $*ThrowStruct
// CHECK-NEXT: store [[NEW_SELF]] to [[WRITE]]
@@ -612,10 +629,12 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: retain_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
-// CHECK-NEXT: release_value [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: throw [[ERROR]]
init(failAfterSelfReplacement: Int) throws {
@@ -782,7 +801,7 @@
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
// CHECK-NEXT: br bb1
// CHECK: bb1:
-// CHECK-NEXT: strong_release [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: [[RESULT:%.*]] = enum $Optional<FailableBaseClass>, #Optional.none!enumelt
// CHECK-NEXT: br bb2
@@ -809,7 +828,9 @@
// CHECK: [[SUCC_BB]]:
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[SELF_VALUE]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableBaseClass>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableBaseClass>)
//
@@ -891,7 +912,9 @@
// CHECK-NEXT: [[BASE_SELF_VALUE:%.*]] = unchecked_enum_data [[SELF_OPTIONAL]]
// CHECK-NEXT: [[SELF_VALUE:%.*]] = unchecked_ref_cast [[BASE_SELF_VALUE]]
// CHECK-NEXT: store [[SELF_VALUE]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[SELF_VALUE]]
// CHECK-NEXT: [[NEW_SELF:%.*]] = enum $Optional<FailableDerivedClass>, #Optional.some!enumelt.1, [[SELF_VALUE]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: br [[EPILOG_BB:bb[0-9]+]]([[NEW_SELF]] : $Optional<FailableDerivedClass>)
//
@@ -952,6 +975,8 @@
// CHECK: bb1([[NEW_SELF:%.*]] : $ThrowBaseClass):
// CHECK-NEXT: [[DERIVED_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]]
// CHECK-NEXT: store [[DERIVED_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -977,6 +1002,8 @@
// CHECK-NEXT: [[NEW_SELF:%.*]] = apply [[INIT_FN]]([[BASE_SELF]])
// CHECK-NEXT: [[DERIVED_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]]
// CHECK-NEXT: store [[DERIVED_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]] : $ThrowDerivedClass
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -1007,6 +1034,8 @@
// CHECK: bb2([[NEW_SELF:%.*]] : $ThrowBaseClass):
// CHECK-NEXT: [[DERIVED_SELF:%.*]] = unchecked_ref_cast [[NEW_SELF]]
// CHECK-NEXT: store [[DERIVED_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]]
@@ -1044,10 +1073,12 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
-// CHECK-NEXT: strong_release [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: throw [[ERROR]]
init(failAfterFullInitialization: Int) throws {
@@ -1073,6 +1104,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]]
@@ -1122,6 +1155,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%1)
// CHECK: bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]]
@@ -1184,6 +1219,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%2)
// CHECK: bb3([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[DERIVED_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[DERIVED_SELF]]
@@ -1239,6 +1276,8 @@
// CHECK: [[INIT_FN:%.*]] = function_ref @_T035definite_init_failable_initializers17ThrowDerivedClassCACyt6noFail_tcfc
// CHECK-NEXT: [[NEW_SELF:%.*]] = apply [[INIT_FN]](%1)
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -1259,6 +1298,8 @@
// CHECK-NEXT: try_apply [[INIT_FN]](%1)
// CHECK: bb1([[NEW_SELF:%.*]] : $ThrowDerivedClass):
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
@@ -1284,6 +1325,8 @@
// CHECK-NEXT: try_apply [[INIT_FN]](%1)
// CHECK: bb2([[NEW_SELF:%.*]] : $ThrowDerivedClass):
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
@@ -1325,6 +1368,8 @@
// CHECK-NEXT: try_apply [[INIT_FN]]([[ARG]], %1)
// CHECK: bb2([[NEW_SELF:%.*]] : $ThrowDerivedClass):
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
@@ -1361,10 +1406,12 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb1([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
// CHECK: bb2([[ERROR:%.*]] : $Error):
-// CHECK-NEXT: strong_release [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: throw [[ERROR]]
convenience init(failAfterDelegation: Int) throws {
@@ -1390,6 +1437,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
@@ -1437,6 +1486,8 @@
// CHECK: [[UNWRAP_FN:%.*]] = function_ref @_T035definite_init_failable_initializers6unwrapS2iKF
// CHECK-NEXT: try_apply [[UNWRAP_FN]](%0)
// CHECK: bb2([[RESULT:%.*]] : $Int):
+// CHECK-NEXT: strong_retain [[NEW_SELF]]
+// CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[BITMAP_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
diff --git a/test/SILOptimizer/definite_init_failable_initializers_objc.swift b/test/SILOptimizer/definite_init_failable_initializers_objc.swift
index a9126d0..9a5810c 100644
--- a/test/SILOptimizer/definite_init_failable_initializers_objc.swift
+++ b/test/SILOptimizer/definite_init_failable_initializers_objc.swift
@@ -50,7 +50,10 @@
// CHECK-NEXT: [[NEW_SUPER_SELF:%.*]] = apply [[SUPER_FN]]([[SUPER]]) : $@convention(objc_method) (@owned FakeNSObject) -> @owned FakeNSObject
// CHECK-NEXT: [[NEW_SELF:%.*]] = unchecked_ref_cast [[NEW_SUPER_SELF]] : $FakeNSObject to $Cat
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]] : $*Cat
+ // TODO: Once we re-enable arbitrary take promotion, this retain and the associated destroy_addr will go away.
+ // CHECK-NEXT: strong_retain [[NEW_SELF]]
// CHECK-NEXT: [[RESULT:%.*]] = enum $Optional<Cat>, #Optional.some!enumelt.1, [[NEW_SELF]] : $Cat
+ // CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]] : $*Cat
// CHECK-NEXT: br bb4([[RESULT]] : $Optional<Cat>)
diff --git a/test/SILOptimizer/definite_init_objc_factory_init.swift b/test/SILOptimizer/definite_init_objc_factory_init.swift
index 3ddeef5..1002361 100644
--- a/test/SILOptimizer/definite_init_objc_factory_init.swift
+++ b/test/SILOptimizer/definite_init_objc_factory_init.swift
@@ -26,8 +26,8 @@
// CHECK: [[SELF_ADDR:%[0-9]+]] = alloc_stack $Hive
// CHECK: store [[OLD_SELF:%[0-9]+]] to [[SELF_ADDR]]
// CHECK: [[META:%[0-9]+]] = value_metatype $@thick Hive.Type, [[OLD_SELF]] : $Hive
- // CHECK: [[FACTORY:%[0-9]+]] = objc_method [[META]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[META]] : $@thick Hive.Type to $@objc_metatype Hive.Type
+ // CHECK: [[FACTORY:%[0-9]+]] = objc_method [[OBJC_META]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!, $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: apply [[FACTORY]]([[QUEEN:%[0-9]+]], [[OBJC_META]]) : $@convention(objc_method) (Optional<Bee>, @objc_metatype Hive.Type) -> @autoreleased Optional<Hive>
// CHECK: store [[NEW_SELF:%[0-9]+]] to [[SELF_ADDR]]
// CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[OLD_SELF]] : $Hive
@@ -58,8 +58,8 @@
convenience init(delegatesToInherited: ()) {
// CHECK: [[UPCAST:%.*]] = upcast %0 : $SubHive to $Hive
// CHECK: [[METATYPE:%.*]] = value_metatype $@thick Hive.Type, [[UPCAST]] : $Hive
- // CHECK: [[METHOD:%.*]] = objc_method [[METATYPE]] : $@thick Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!
// CHECK: [[OBJC:%.*]] = thick_to_objc_metatype [[METATYPE]] : $@thick Hive.Type to $@objc_metatype Hive.Type
+ // CHECK: [[METHOD:%.*]] = objc_method [[OBJC]] : $@objc_metatype Hive.Type, #Hive.init!allocator.1.foreign : (Hive.Type) -> (Bee!) -> Hive!
// CHECK: apply [[METHOD]]({{.*}}, [[OBJC]])
// CHECK: [[METATYPE:%.*]] = value_metatype $@thick SubHive.Type, %0 : $SubHive
diff --git a/test/SILOptimizer/definite_init_protocol_init.swift b/test/SILOptimizer/definite_init_protocol_init.swift
index 79d69fe..ff72ad8 100644
--- a/test/SILOptimizer/definite_init_protocol_init.swift
+++ b/test/SILOptimizer/definite_init_protocol_init.swift
@@ -31,15 +31,18 @@
// CHECK-NEXT: debug_value
// CHECK-NEXT: store [[OLD_SELF]] to [[SELF_BOX]]
// CHECK-NEXT: [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self TrivialClass.Type, %1
+ // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $TrivialClass
// CHECK-NEXT: // function_ref
// CHECK-NEXT: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
- // CHECK-NEXT: [[RESULT:%.*]] = alloc_stack $TrivialClass
// CHECK-NEXT: apply [[FN]]<@dynamic_self TrivialClass>([[RESULT]], %0, [[METATYPE]])
// CHECK-NEXT: [[NEW_SELF:%.*]] = load [[RESULT]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF_BOX]]
// CHECK-NEXT: [[METATYPE:%.*]] = value_metatype $@thick TrivialClass.Type, %1
// CHECK-NEXT: dealloc_partial_ref %1 : $TrivialClass, [[METATYPE]] : $@thick TrivialClass.Type
// CHECK-NEXT: dealloc_stack [[RESULT]]
+ // TODO: Once we restore arbitrary takes, the strong_retain/destroy_addr pair below will go away.
+ // CHECK-NEXT: strong_retain [[NEW_SELF]]
+ // CHECK-NEXT: destroy_addr [[SELF_BOX]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
// CHECK-NEXT: return [[NEW_SELF]]
convenience init(upper: Int) {
@@ -63,9 +66,9 @@
// CHECK-LABEL: sil hidden @_T0023definite_init_protocol_B013TrivialStructVACSi5upper_tcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin TrivialStruct.Type):
// CHECK-NEXT: [[SELF:%.*]] = alloc_stack $TrivialStruct
-// CHECK: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $TrivialStruct
+// CHECK: [[SELF_BOX:%.*]] = alloc_stack $TrivialStruct
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick TrivialStruct.Type
+// CHECK: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
// CHECK-NEXT: apply [[FN]]<TrivialStruct>([[SELF_BOX]], %0, [[METATYPE]])
// CHECK-NEXT: [[NEW_SELF:%.*]] = load [[SELF_BOX]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF]]
@@ -93,9 +96,9 @@
// CHECK-LABEL: sil hidden @_T0023definite_init_protocol_B017AddressOnlyStructVACSi5upper_tcfC
// CHECK: bb0(%0 : $*AddressOnlyStruct, %1 : $Int, %2 : $@thin AddressOnlyStruct.Type):
// CHECK-NEXT: [[SELF:%.*]] = alloc_stack $AddressOnlyStruct
-// CHECK: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $AddressOnlyStruct
+// CHECK: [[SELF_BOX:%.*]] = alloc_stack $AddressOnlyStruct
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick AddressOnlyStruct.Type
+// CHECK: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
// CHECK-NEXT: apply [[FN]]<AddressOnlyStruct>([[SELF_BOX]], %1, [[METATYPE]])
// CHECK-NEXT: copy_addr [take] [[SELF_BOX]] to [initialization] [[SELF]]
// CHECK-NEXT: dealloc_stack [[SELF_BOX]]
@@ -126,9 +129,9 @@
// CHECK-LABEL: sil hidden @_T0023definite_init_protocol_B011TrivialEnumOACSi5upper_tcfC
// CHECK: bb0(%0 : $Int, %1 : $@thin TrivialEnum.Type):
// CHECK-NEXT: [[SELF:%.*]] = alloc_stack $TrivialEnum
-// CHECK: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
-// CHECK-NEXT: [[SELF_BOX:%.*]] = alloc_stack $TrivialEnum
+// CHECK: [[SELF_BOX:%.*]] = alloc_stack $TrivialEnum
// CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thick TrivialEnum.Type
+// CHECK: [[FN:%.*]] = function_ref @_T0023definite_init_protocol_B022TriviallyConstructiblePAAExSi6middle_tcfC
// CHECK-NEXT: apply [[FN]]<TrivialEnum>([[SELF_BOX]], %0, [[METATYPE]])
// CHECK-NEXT: [[NEW_SELF:%.*]] = load [[SELF_BOX]]
// CHECK-NEXT: store [[NEW_SELF]] to [[SELF]]
diff --git a/test/SILOptimizer/devirt_conditional_conformance.swift b/test/SILOptimizer/devirt_conditional_conformance.swift
new file mode 100644
index 0000000..a992775
--- /dev/null
+++ b/test/SILOptimizer/devirt_conditional_conformance.swift
@@ -0,0 +1,56 @@
+// RUN: %target-swift-frontend -O -Xllvm -sil-inline-generics=false -Xllvm -sil-disable-pass=GlobalOpt %s -emit-sil -sil-verify-all | %FileCheck %s
+
+
+public protocol Foo {
+ func foo_method()
+}
+public protocol Bar {
+ func bar_method()
+}
+
+@inline(never)
+func bar_marker() {}
+
+public struct Inner: Bar {
+ public func bar_method() {
+ bar_marker()
+ }
+}
+
+public struct Outer<T> {
+ var x: T
+}
+
+@inline(never)
+func foo_marker() {}
+extension Outer: Foo where T: Bar {
+ public func foo_method() {
+ foo_marker()
+ x.bar_method()
+ }
+}
+
+func callFoo<T: Foo>(_ x: T) {
+ x.foo_method()
+}
+
+func genericLayer<T: Bar>(_ x: T) {
+ callFoo(Outer(x: x))
+}
+
+// See that we devirtualize/inline enough to get down to the @inline(never)
+// function calls.
+
+// CHECK-LABEL: sil @_T030devirt_conditional_conformance12throughLayeryyF : $@convention(thin) () -> ()
+// CHECK: function_ref @_T030devirt_conditional_conformance10foo_markeryyF
+// CHECK: function_ref @_T030devirt_conditional_conformance10bar_markeryyF
+public func throughLayer() {
+ genericLayer(Inner())
+}
+
+// CHECK-LABEL: sil @_T030devirt_conditional_conformance6directyyF : $@convention(thin) () -> ()
+// CHECK: function_ref @_T030devirt_conditional_conformance10foo_markeryyF
+// CHECK: function_ref @_T030devirt_conditional_conformance10bar_markeryyF
+public func direct() {
+ callFoo(Outer(x: Inner()))
+}
diff --git a/test/SILOptimizer/devirt_materializeForSet.swift b/test/SILOptimizer/devirt_materializeForSet.swift
index 1e87bec..de9f12f 100644
--- a/test/SILOptimizer/devirt_materializeForSet.swift
+++ b/test/SILOptimizer/devirt_materializeForSet.swift
@@ -2,12 +2,10 @@
// Check that compiler does not crash on the devirtualization of materializeForSet methods
// and produces a correct code.
+//
+// Note: now we no longer speculatively devirtualize inside thunks, so this test does nothing.
// CHECK-LABEL: sil shared [transparent] [thunk] @_T024devirt_materializeForSet7BaseFooCAA0F0A2aDP3barSSvmTW
-// CHECK: checked_cast_br [exact] %{{.*}} : $BaseFoo to $ChildFoo
-// CHECK: thin_function_to_pointer %{{.*}} : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout ChildFoo, @thick ChildFoo.Type) -> () to $Builtin.RawPointer
-// CHECK: enum $Optional<Builtin.RawPointer>, #Optional.some!enumelt.1, %{{.*}} : $Builtin.RawPointer
-// CHECK: tuple (%{{.*}} : $Builtin.RawPointer, %{{.*}} : $Optional<Builtin.RawPointer>)
public protocol Foo {
var bar: String { get set }
diff --git a/test/SILOptimizer/devirt_static_covariant_return.swift b/test/SILOptimizer/devirt_static_covariant_return.swift
new file mode 100644
index 0000000..fa52598
--- /dev/null
+++ b/test/SILOptimizer/devirt_static_covariant_return.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -O -whole-module-optimization %s -emit-sil -sil-verify-all | %FileCheck %s
+
+// CHECK-NOT: class_method
+
+// Static method returning Self in generic class
+public class Factory<T> {
+ public required init() {}
+
+ @inline(never) class func bar() -> Self {
+ return self.init()
+ }
+
+ @inline(never) class func foo() -> Self {
+ return bar()
+ }
+}
+
+public func foo(m: Factory<Int>.Type) {
+ m.foo()
+}
diff --git a/test/SILOptimizer/generic_inline_self.swift b/test/SILOptimizer/generic_inline_self.swift
index 7351c27..367e809 100644
--- a/test/SILOptimizer/generic_inline_self.swift
+++ b/test/SILOptimizer/generic_inline_self.swift
@@ -27,8 +27,8 @@
// CHECK-LABEL: sil hidden @_T019generic_inline_self1CC18returnsNewInstanceACXDyF : $@convention(method) (@guaranteed C) -> @owned C
// CHECK: bb0(%0 : $C):
+// CHECK: [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self C.Type, %0 : $C
// CHECK: [[FN:%.*]] = function_ref @_T019generic_inline_self12makeInstancexxmAA1CCRbzlF : $@convention(thin) <τ_0_0 where τ_0_0 : C> (@thick τ_0_0.Type) -> @owned τ_0_0
-// CHECK-NEXT: [[METATYPE:%.*]] = value_metatype $@thick @dynamic_self C.Type, %0 : $C
// CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<@dynamic_self C>([[METATYPE]]) : $@convention(thin) <τ_0_0 where τ_0_0 : C> (@thick τ_0_0.Type) -> @owned τ_0_0
// CHECK-NEXT: return [[RESULT]] : $C
func returnsNewInstance() -> Self {
diff --git a/test/SILOptimizer/inline_recursive.swift b/test/SILOptimizer/inline_recursive.swift
index 0440fbf..2f0dfd8 100644
--- a/test/SILOptimizer/inline_recursive.swift
+++ b/test/SILOptimizer/inline_recursive.swift
@@ -9,9 +9,9 @@
// CHECK-LABEL: sil {{.*}}callit
// CHECK: bb0:
-// CHECK: [[REF:%.*]] = function_ref @_T016inline_recursive7recFunc33_38E63D320CFF538A1F98BBC31453B1EBLLs5Int32VAEF
// CHECK: [[INTLIT:%.*]] = integer_literal $Builtin.Int32, 3
// CHECK: [[STRUCT:%.*]] = struct $Int32 ([[INTLIT]] : $Builtin.Int32)
+// CHECK: [[REF:%.*]] = function_ref @_T016inline_recursive7recFunc33_38E63D320CFF538A1F98BBC31453B1EBLLs5Int32VAEF
// CHECK: [[APPLY:%.*]] = apply [[REF]]([[STRUCT]])
// CHECK: return [[APPLY]]
diff --git a/test/SILOptimizer/inline_self.swift b/test/SILOptimizer/inline_self.swift
index 79e657b..ec93abb 100644
--- a/test/SILOptimizer/inline_self.swift
+++ b/test/SILOptimizer/inline_self.swift
@@ -76,9 +76,9 @@
// CHECK: [[F:%[0-9]+]] = function_ref @_T011inline_self1CC7factory{{[_0-9a-zA-Z]*}}FZ : $@convention(method) (Int, @thick C.Type) -> @owned C
// CHECK: apply [[F]](%{{.+}}, %{{.+}}) : $@convention(method) (Int, @thick C.Type) -> @owned C
+// CHECK: [[Z:%.*]] = alloc_ref $Z
// CHECK: function_ref inline_self.Z.capturesSelf() -> Self
// CHECK: [[F:%[0-9]+]] = function_ref @_T011inline_self1ZC12capturesSelfACXDyF : $@convention(method) (@guaranteed Z) -> @owned Z
-// CHECK: [[Z:%.*]] = alloc_ref $Z
// CHECK: apply [[F]]([[Z]]) : $@convention(method) (@guaranteed Z) -> @owned
// CHECK: return
diff --git a/test/SILOptimizer/inliner_coldblocks.sil b/test/SILOptimizer/inliner_coldblocks.sil
index 18ec8a5..58d5c68 100644
--- a/test/SILOptimizer/inliner_coldblocks.sil
+++ b/test/SILOptimizer/inliner_coldblocks.sil
@@ -193,7 +193,7 @@
%c30 = builtin "assert_configuration"() : $Builtin.Int32
%f = function_ref @update_global: $@convention(thin) () -> ()
- // REMARKS_PASSED: inliner_coldblocks.sil:223:3: remark: update_global inlined into regular_large_callee (cost = {{.*}}, benefit = {{.*}})
+ // REMARKS_PASSED: inliner_coldblocks.sil:223:3: remark: "update_global" inlined into "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
// YAML: --- !Passed
// YAML-NEXT: Pass: sil-inliner
// YAML-NEXT: Name: Inlined
@@ -203,13 +203,13 @@
// YAML-NEXT: Column: 3
// YAML-NEXT: Function: regular_large_callee
// YAML-NEXT: Args:
- // YAML-NEXT: - Callee: update_global
+ // YAML-NEXT: - Callee: '"update_global"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 20
// YAML-NEXT: Column: 6
// YAML-NEXT: - String: ' inlined into '
- // YAML-NEXT: - Caller: regular_large_callee
+ // YAML-NEXT: - Caller: '"regular_large_callee"'
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
// YAML-NEXT: Line: 162
@@ -233,17 +233,23 @@
sil @dont_inline_regular_large_callee : $@convention(thin) () -> () {
bb0:
%f = function_ref @regular_large_callee : $@convention(thin) () -> ()
- // REMARKS_MISSED: inliner_coldblocks.sil:252:8: remark: Not profitable to inline (cost = {{.*}}, benefit = {{.*}})
+ // REMARKS_MISSED: inliner_coldblocks.sil:258:8: remark: Not profitable to inline function "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
// YAML: --- !Missed
// YAML-NEXT: Pass: sil-inliner
// YAML-NEXT: Name: NoInlinedCost
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
- // YAML-NEXT: Line: 252
+ // YAML-NEXT: Line: 258
// YAML-NEXT: Column: 8
// YAML-NEXT: Function: dont_inline_regular_large_callee
// YAML-NEXT: Args:
- // YAML-NEXT: - String: 'Not profitable to inline (cost = '
+ // YAML-NEXT: - String: 'Not profitable to inline function '
+ // YAML-NEXT: - Callee: '"regular_large_callee"'
+ // YAML-NEXT: DebugLoc:
+ // YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
+ // YAML-NEXT: Line: 162
+ // YAML-NEXT: Column: 6
+ // YAML-NEXT: - String: ' (cost = '
// YAML-NEXT: - Cost: '{{.*}}'
// YAML-NEXT: - String: ', benefit = '
// YAML-NEXT: - Benefit: '{{.*}}'
diff --git a/test/SILOptimizer/linker.swift b/test/SILOptimizer/linker.swift
index 7959a07..8a17b90 100644
--- a/test/SILOptimizer/linker.swift
+++ b/test/SILOptimizer/linker.swift
@@ -13,9 +13,9 @@
// CHECK: sil @unknown
+// CHECK: sil @_T0s1AVABycfC
+
// CHECK: sil [noinline] @_T0s12doSomething3yxlF
// CHECK-NOT: return
-// CHECK: sil @_T0s1AVABycfC
-
callDoSomething3()
diff --git a/test/SILOptimizer/mandatory_nil_comparison_inlining.swift b/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
index 425d4a6..8a4665b 100644
--- a/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
+++ b/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
@@ -1,5 +1,6 @@
// RUN: %target-swift-frontend -enable-sil-ownership -sil-verify-all -primary-file %s -module-name=test -emit-sil -o - -verify | %FileCheck %s
+struct X { }
// CHECK-LABEL: sil {{.*}} @{{.*}}generic_func
// CHECK: switch_enum_addr
@@ -11,28 +12,28 @@
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_rhs_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_rhs_nil(x: [Int]?) -> Bool {
+func array_func_rhs_nil(x: [X]?) -> Bool {
return x == nil
}
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_lhs_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_lhs_nil(x: [Int]?) -> Bool {
+func array_func_lhs_nil(x: [X]?) -> Bool {
return nil == x
}
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_rhs_non_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_rhs_non_nil(x: [Int]?) -> Bool {
+func array_func_rhs_non_nil(x: [X]?) -> Bool {
return x != nil
}
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_lhs_non_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_lhs_non_nil(x: [Int]?) -> Bool {
+func array_func_lhs_non_nil(x: [X]?) -> Bool {
return nil != x
}
diff --git a/test/SILOptimizer/opt_mode.swift b/test/SILOptimizer/opt_mode.swift
new file mode 100644
index 0000000..d2257d7
--- /dev/null
+++ b/test/SILOptimizer/opt_mode.swift
@@ -0,0 +1,51 @@
+// RUN: %target-swift-frontend -primary-file %s -O -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend -primary-file %s -Osize -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend -primary-file %s -O -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
+// RUN: %target-swift-frontend -primary-file %s -Osize -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
+// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
+
+class A {
+ func foo(_ x: Int) -> Int { return x }
+}
+
+class B : A {
+ override func foo(_ x: Int) -> Int { return x + 1 }
+}
+
+
+func donothing(_ x: Int) -> Int { return x }
+
+// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
+// CHECK: checked_cast_br
+// CHECK: checked_cast_br
+// CHECK: }
+// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
+@_optimize(speed)
+func test_ospeed(_ a: A) -> Int {
+ return donothing(a.foo(27))
+}
+
+// CHECK-LABEL: sil {{.*}} [Osize] @{{.*}}test_osize
+// CHECK: [[M:%[0-9]+]] = class_method
+// CHECK: [[A:%[0-9]+]] = apply [[M]]
+// CHECK: return [[A]]
+// CHECK-IR: define hidden {{.*}}test_osize{{.*}} [[SIZE_ATTR:#[0-9]+]]
+@_optimize(size)
+func test_osize(_ a: A) -> Int {
+ return donothing(a.foo(27))
+}
+
+// CHECK-LABEL: sil {{.*}} [Onone] @{{.*}}test_onone
+// CHECK: [[M:%[0-9]+]] = class_method
+// CHECK: [[A:%[0-9]+]] = apply [[M]]
+// CHECK: [[A2:%[0-9]+]] = apply
+// CHECK: return [[A2]]
+// CHECK-IR: define hidden {{.*}}test_onone{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
+@_optimize(none)
+func test_onone(_ a: A) -> Int {
+ return donothing(a.foo(27))
+}
+
+
+// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "
+// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize "
diff --git a/test/SILOptimizer/partial_specialization_debug.sil b/test/SILOptimizer/partial_specialization_debug.sil
new file mode 100644
index 0000000..2fd5eb4
--- /dev/null
+++ b/test/SILOptimizer/partial_specialization_debug.sil
@@ -0,0 +1,66 @@
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -generic-specializer -sil-partial-specialization=0 -sil-partial-specialization-with-generic-substitutions -debug-only=generic-specializer %s -o /dev/null 2>&1 | %FileCheck %s
+
+// REQUIRES: asserts
+
+// Test the debug messages from Generic Specialization. It's based on
+// partial_specialization.sil.
+
+// CHECK: *** ApplyInst in function simple_generic_caller1:
+// CHECK: Partial specialization is not supported.{{$}}
+
+sil_stage canonical
+
+import Builtin
+import Swift
+import SwiftShims
+
+@_silgen_name("use")
+public func use<T>(_ t: T)
+
+@inline(never) public func simple_generic_callee<U, V>(_ u: U, _ v: V)
+
+public func simple_generic_caller1<U>(_ u: U)
+
+// use
+sil @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+
+// simple_generic_callee<A, B>(_:_:)
+sil [noinline] @simple_generic_callee : $@convention(thin) <U, V> (@in U, @in V) -> () {
+bb0(%0 : $*U, %1 : $*V):
+ // function_ref use
+ %4 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ %5 = alloc_stack $U
+ copy_addr %0 to [initialization] %5 : $*U
+ %7 = apply %4<U>(%5) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ dealloc_stack %5 : $*U
+ // function_ref use
+ %9 = function_ref @use : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ %10 = alloc_stack $V
+ copy_addr %1 to [initialization] %10 : $*V
+ %12 = apply %9<V>(%10) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
+ dealloc_stack %10 : $*V
+ destroy_addr %1 : $*V
+ destroy_addr %0 : $*U
+ %16 = tuple ()
+ return %16 : $()
+} // end sil function 'simple_generic_callee'
+
+// simple_generic_caller1<A>(_:)
+sil @simple_generic_caller1 : $@convention(thin) <U> (@in U) -> () {
+bb0(%0 : $*U):
+ // function_ref simple_generic_callee<A, B>(_:_:)
+ %2 = function_ref @simple_generic_callee : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> ()
+ %3 = alloc_stack $U
+ copy_addr %0 to [initialization] %3 : $*U
+ %5 = integer_literal $Builtin.Int32, 1
+ %6 = struct $Int32 (%5 : $Builtin.Int32)
+ %7 = alloc_stack $Int32
+ store %6 to %7 : $*Int32
+ %9 = apply %2<U, Int32>(%3, %7) : $@convention(thin) <τ_0_0, τ_0_1> (@in τ_0_0, @in τ_0_1) -> ()
+ dealloc_stack %7 : $*Int32
+ dealloc_stack %3 : $*U
+ destroy_addr %0 : $*U
+ %13 = tuple ()
+ return %13 : $()
+} // end sil function 'simple_generic_caller1'
+
diff --git a/test/SILOptimizer/pointer_conversion.swift b/test/SILOptimizer/pointer_conversion.swift
index c408fb4..4c3eaae 100644
--- a/test/SILOptimizer/pointer_conversion.swift
+++ b/test/SILOptimizer/pointer_conversion.swift
@@ -22,10 +22,10 @@
public func testArray() {
let array: [Int] = get()
takesConstRawPointer(array)
- // CHECK: [[FN:%.+]] = function_ref @takesConstRawPointer
// CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
// CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeRawPointer (
// CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]] : $Optional<AnyObject>
+ // CHECK: [[FN:%.+]] = function_ref @takesConstRawPointer
// CHECK-NEXT: apply [[FN]]([[DEP_POINTER]])
// CHECK-NOT: release
// CHECK-NOT: {{^bb[0-9]+:}}
@@ -38,11 +38,11 @@
public func testArrayToOptional() {
let array: [Int] = get()
takesOptConstRawPointer(array)
- // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
// CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
// CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeRawPointer (
// CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeRawPointer on [[OWNER]] : $Optional<AnyObject>
// CHECK-NEXT: [[OPT_POINTER:%.+]] = enum $Optional<UnsafeRawPointer>, #Optional.some!enumelt.1, [[DEP_POINTER]]
+ // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
// CHECK-NEXT: apply [[FN]]([[OPT_POINTER]])
// CHECK-NOT: release
// CHECK-NOT: {{^bb[0-9]+:}}
@@ -55,10 +55,10 @@
public func testMutableArray() {
var array: [Int] = get()
takesMutableRawPointer(&array)
- // CHECK: [[FN:%.+]] = function_ref @takesMutableRawPointer
// CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
// CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeMutableRawPointer (
// CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeMutableRawPointer on [[OWNER]] : $Optional<AnyObject>
+ // CHECK: [[FN:%.+]] = function_ref @takesMutableRawPointer
// CHECK-NEXT: apply [[FN]]([[DEP_POINTER]])
// CHECK-NOT: release
// CHECK-NOT: {{^bb[0-9]+:}}
@@ -72,11 +72,11 @@
public func testMutableArrayToOptional() {
var array: [Int] = get()
takesOptMutableRawPointer(&array)
- // CHECK: [[FN:%.+]] = function_ref @takesOptMutableRawPointer
// CHECK: [[OWNER:%.+]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1,
// CHECK-NEXT: [[POINTER:%.+]] = struct $UnsafeMutableRawPointer (
// CHECK-NEXT: [[DEP_POINTER:%.+]] = mark_dependence [[POINTER]] : $UnsafeMutableRawPointer on [[OWNER]] : $Optional<AnyObject>
// CHECK-NEXT: [[OPT_POINTER:%.+]] = enum $Optional<UnsafeMutableRawPointer>, #Optional.some!enumelt.1, [[DEP_POINTER]]
+ // CHECK: [[FN:%.+]] = function_ref @takesOptMutableRawPointer
// CHECK-NEXT: apply [[FN]]([[OPT_POINTER]])
// CHECK-NOT: release
// CHECK-NOT: {{^bb[0-9]+:}}
@@ -98,8 +98,8 @@
// CHECK: [[CALL_BRANCH]]([[OPT_POINTER:%.+]] : $Optional<UnsafeRawPointer>, [[OWNER:%.+]] : $Optional<AnyObject>):
// CHECK-NOT: release
- // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
// CHECK-NEXT: [[DEP_OPT_POINTER:%.+]] = mark_dependence [[OPT_POINTER]] : $Optional<UnsafeRawPointer> on [[OWNER]] : $Optional<AnyObject>
+ // CHECK: [[FN:%.+]] = function_ref @takesOptConstRawPointer
// CHECK-NEXT: apply [[FN]]([[DEP_OPT_POINTER]])
// CHECK-NOT: release
// CHECK-NOT: {{^bb[0-9]+:}}
diff --git a/test/SILOptimizer/predictable_memopt.sil b/test/SILOptimizer/predictable_memopt.sil
index 4e2ccdf..75ffb68 100644
--- a/test/SILOptimizer/predictable_memopt.sil
+++ b/test/SILOptimizer/predictable_memopt.sil
@@ -5,8 +5,10 @@
// CHECK-LABEL: sil @simple_reg_promotion
+// CHECK: bb0(%0 : $Int):
+// CHECK-NEXT: return %0 : $Int
sil @simple_reg_promotion : $@convention(thin) (Int) -> Int {
-bb0(%0 : $Int): // CHECK: bb0(%0 : $Int):
+bb0(%0 : $Int):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
store %0 to %1a : $*Int
@@ -18,41 +20,32 @@
strong_release %3 : $<τ_0_0> { var τ_0_0 } <Int>
strong_release %1 : $<τ_0_0> { var τ_0_0 } <Int>
return %6 : $Int
-
- // CHECK-NEXT: return %0 : $Int
}
-
+// Verify that promotion has promoted the tuple load away, and we know that
+// %0 is being returned through scalar instructions in SSA form.
+//
// CHECK-LABEL: sil @tuple_reg_promotion
+// CHECK: bb0(%0 : $Int):
+// CHECK-NEXT: [[TUPLE:%[0-9]+]] = tuple ({{.*}} : $Int, {{.*}} : $Int)
+// CHECK-NEXT: [[TUPLE_ELT:%[0-9]+]] = tuple_extract [[TUPLE]] : $(Int, Int), 0
+// CHECK-NEXT: return [[TUPLE_ELT]] : $Int
sil @tuple_reg_promotion : $@convention(thin) (Int) -> Int {
-bb0(%0 : $Int): // CHECK: bb0(%0 : $Int):
+bb0(%0 : $Int):
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <(Int, Int)>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <(Int, Int)>, 0
-
%a = tuple_element_addr %1a : $*(Int, Int), 0
%b = tuple_element_addr %1a : $*(Int, Int), 1
store %0 to %a : $*Int
store %0 to %b : $*Int
-
%c = load %1a : $*(Int, Int)
%d = tuple_extract %c : $(Int, Int), 0
-
strong_release %1 : $<τ_0_0> { var τ_0_0 } <(Int, Int)>
-
return %d : $Int
-
- // Verify that promotion has promoted the tuple load away, and we know that
- // %0 is being returned through scalar instructions in SSA form.
- // CHECK-NEXT: [[TUPLE:%[0-9]+]] = tuple ({{.*}} : $Int, {{.*}} : $Int)
- // CHECK-NEXT: [[TUPLE_ELT:%[0-9]+]] = tuple_extract [[TUPLE]] : $(Int, Int), 0
-
- // CHECK-NEXT: return [[TUPLE_ELT]] : $Int
}
-
sil @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
-
-
+sil @takes_NativeObject_inout : $@convention(thin) (@inout Builtin.NativeObject) -> ()
// Verify that load promotion works properly with inout arguments.
//
@@ -61,26 +54,32 @@
// takes_Int_inout(&a)
// return (t, a)
//}
-// CHECK-LABEL: sil @used_by_inout
+//
+// CHECK-LABEL: sil @used_by_inout : $@convention(thin) (Int) -> (Int, Int) {
+// CHECK: bb0([[ARG:%.*]] : $Int):
sil @used_by_inout : $@convention(thin) (Int) -> (Int, Int) {
bb0(%0 : $Int):
// This alloc_stack can't be removed since it is used by an inout call.
- // CHECK: %1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ // CHECK: [[BOX:%.*]] = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
+ // CHECK: [[PB_BOX:%.*]] = project_box [[BOX]]
%1 = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
%1a = project_box %1 : $<τ_0_0> { var τ_0_0 } <Int>, 0
store %0 to %1a : $*Int
// This load should be eliminated.
+ // CHECK-NOT: load
+ // CHECK: [[FUNC:%.*]] = function_ref @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
+ // CHECK: apply [[FUNC]]([[PB_BOX]])
%3 = load %1a : $*Int
%5 = function_ref @takes_Int_inout : $@convention(thin) (@inout Int) -> ()
%6 = apply %5(%1a) : $@convention(thin) (@inout Int) -> ()
// This load is needed in case the callee modifies the allocation.
- // CHECK: [[RES:%[0-9]+]] = load
+ // CHECK: [[RES:%[0-9]+]] = load [[PB_BOX]]
%7 = load %1a : $*Int
// This should use the incoming argument to the function.
- // CHECK: tuple ({{.*}} : $Int, {{.*}} : $Int)
+ // CHECK: tuple ([[ARG]] : $Int, [[RES]] : $Int)
%8 = tuple (%3 : $Int, %7 : $Int)
strong_release %1 : $<τ_0_0> { var τ_0_0 } <Int>
return %8 : $(Int, Int)
@@ -148,13 +147,75 @@
struct ContainsNativeObject {
- var x : Int
- var y : Builtin.NativeObject
+ var x : Builtin.NativeObject
+ var y : Int32
+ var z : Builtin.NativeObject
+}
+
+// CHECK-LABEL: sil @multiple_level_extract_1 : $@convention(thin) (@owned ContainsNativeObject) -> Builtin.Int32 {
+// CHECK: bb0([[ARG:%.*]] : $ContainsNativeObject):
+// CHECK: [[FIELD1:%.*]] = struct_extract [[ARG]] : $ContainsNativeObject, #ContainsNativeObject.y
+// CHECK: [[FIELD2:%.*]] = struct_extract [[FIELD1]] : $Int32, #Int32._value
+// CHECK: release_value [[ARG]]
+// CHECK: return [[FIELD2]]
+// CHECK: } // end sil function 'multiple_level_extract_1'
+sil @multiple_level_extract_1 : $@convention(thin) (@owned ContainsNativeObject) -> Builtin.Int32 {
+bb0(%0 : $ContainsNativeObject):
+ %1 = alloc_stack $ContainsNativeObject
+ store %0 to %1 : $*ContainsNativeObject
+
+ %2 = struct_element_addr %1 : $*ContainsNativeObject, #ContainsNativeObject.y
+ %3 = struct_element_addr %2 : $*Int32, #Int32._value
+ %4 = load %3 : $*Builtin.Int32
+
+ destroy_addr %1 : $*ContainsNativeObject
+ dealloc_stack %1 : $*ContainsNativeObject
+ return %4 : $Builtin.Int32
+}
+
+struct ComplexStruct {
+ var f1 : Builtin.NativeObject
+ var f2 : ContainsNativeObject
+ var f3 : Builtin.Int32
+}
+
+// CHECK-LABEL: sil @multiple_level_extract_2 : $@convention(thin) (@owned ComplexStruct) -> (@owned Builtin.NativeObject, @owned Builtin.NativeObject, Builtin.Int32) {
+// CHECK: bb0([[ARG:%.*]] : $ComplexStruct):
+// CHECK: [[f1:%.*]] = struct_extract [[ARG]] : $ComplexStruct, #ComplexStruct.f3
+// CHECK: [[f2:%.*]] = struct_extract [[ARG]] : $ComplexStruct, #ComplexStruct.f2
+// CHECK: [[f2_x:%.*]] = struct_extract [[f2]] : $ContainsNativeObject, #ContainsNativeObject.x
+// CHECK: [[f3:%.*]] = struct_extract [[ARG]] : $ComplexStruct, #ComplexStruct.f1
+// CHECK-NEXT: strong_retain [[f3]]
+// CHECK-NEXT: strong_retain [[f2_x]]
+// CHECK-NEXT: release_value [[ARG]]
+// CHECK: [[RESULT:%.*]] = tuple ([[f3]] : $Builtin.NativeObject, [[f2_x]] : $Builtin.NativeObject, [[f1]] : $Builtin.Int32)
+// CHECK: return [[RESULT]]
+// CHECK: } // end sil function 'multiple_level_extract_2'
+sil @multiple_level_extract_2 : $@convention(thin) (@owned ComplexStruct) -> (@owned Builtin.NativeObject, @owned Builtin.NativeObject, Builtin.Int32) {
+bb0(%0 : $ComplexStruct):
+ %1 = alloc_stack $ComplexStruct
+ store %0 to %1 : $*ComplexStruct
+
+ %2 = struct_element_addr %1 : $*ComplexStruct, #ComplexStruct.f1
+ %3 = struct_element_addr %1 : $*ComplexStruct, #ComplexStruct.f2
+ %4 = struct_element_addr %3 : $*ContainsNativeObject, #ContainsNativeObject.x
+ %5 = struct_element_addr %1 : $*ComplexStruct, #ComplexStruct.f3
+
+ %6 = load %2 : $*Builtin.NativeObject
+ strong_retain %6 : $Builtin.NativeObject
+ %7 = load %4 : $*Builtin.NativeObject
+ strong_retain %7 : $Builtin.NativeObject
+ %8 = load %5 : $*Builtin.Int32
+
+ destroy_addr %1 : $*ComplexStruct
+ dealloc_stack %1 : $*ComplexStruct
+
+ %9 = tuple(%6 : $Builtin.NativeObject, %7 : $Builtin.NativeObject, %8 : $Builtin.Int32)
+ return %9 : $(Builtin.NativeObject, Builtin.NativeObject, Builtin.Int32)
}
var int_global : Int
-
// CHECK-LABEL: sil @promote_alloc_stack
sil @promote_alloc_stack : $@convention(thin) (Int32) -> Builtin.Int32 {
bb0(%0 : $Int32):
@@ -296,8 +357,8 @@
}
-// CHECK-LABEL: sil @destroy_addr
-sil @destroy_addr : $@convention(method) (@owned SomeClass) -> @owned SomeClass {
+// CHECK-LABEL: sil @destroy_addr_test
+sil @destroy_addr_test : $@convention(method) (@owned SomeClass) -> @owned SomeClass {
bb0(%0 : $SomeClass):
%1 = alloc_stack $SomeClass
%2 = tuple ()
@@ -416,3 +477,364 @@
return %r : $Bool
}
+///////////////////
+// Diamond Tests //
+///////////////////
+
+struct NativeObjectPair {
+ var f1: Builtin.NativeObject
+ var f2: Builtin.NativeObject
+}
+
+// These tests ensure that we insert all gep operations, before the stores and
+// any new load operations at the location where the old load was. It also
+// ensures that we are able to handle values that are provided with multilple
+// available values from different stores. Today the tests use the exact same
+// value since pred mem opts is so conservative (it will not support having
+// different available values from different blocks due to the predicate it uses
+// while merging).
+
+// We should just remove the stores here.
+// CHECK-LABEL: sil @diamond_test_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK-NOT: alloc_stack
+// CHECK-NOT: store
+// CHECK-NOT: load
+// CHECK: } // end sil function 'diamond_test_1'
+sil @diamond_test_1 : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = alloc_stack $Builtin.NativeObject
+ cond_br undef, bb1, bb2
+
+bb1:
+ store %0 to %1 : $*Builtin.NativeObject
+ br bb3
+
+bb2:
+ store %0 to %1 : $*Builtin.NativeObject
+ br bb3
+
+bb3:
+ %2 = load %1 : $*Builtin.NativeObject
+ strong_retain %2 : $Builtin.NativeObject
+ strong_release %2 : $Builtin.NativeObject
+ dealloc_stack %1 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+}
+
+// This test makes sure that we insert the tuple_extracts that we need before
+// the store in bb0, not at the load block.
+// CHECK-LABEL: sil @diamond_test_2 : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject {
+// CHECK: bb0([[ARG:%.*]] : $NativeObjectPair):
+// CHECK: [[LHS1:%.*]] = struct_extract [[ARG]] : $NativeObjectPair, #NativeObjectPair.f1
+// CHECK: [[LHS2:%.*]] = struct_extract [[ARG]] : $NativeObjectPair, #NativeObjectPair.f1
+// CHECK: cond_br undef, bb1, bb2
+//
+// CHECK: bb1:
+// CHECK: strong_retain [[LHS2]]
+// CHECK: br bb3([[LHS2]] :
+//
+// CHECK: bb2:
+// CHECK: strong_retain [[LHS1]] : $Builtin.NativeObject
+// CHECK: br bb3([[LHS1]] :
+//
+// CHECK: bb3([[PHI:%.*]] :
+// CHECK: release_value [[ARG]]
+// CHECK: return [[PHI]]
+// CHECK: } // end sil function 'diamond_test_2'
+sil @diamond_test_2 : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject {
+bb0(%0 : $NativeObjectPair):
+ %1 = alloc_stack $NativeObjectPair
+ store %0 to %1 : $*NativeObjectPair
+ cond_br undef, bb1, bb2
+
+bb1:
+ %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.f1
+ %3 = load %2 : $*Builtin.NativeObject
+ strong_retain %3 : $Builtin.NativeObject
+ br bb3(%3 : $Builtin.NativeObject)
+
+bb2:
+ %4 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.f1
+ %5 = load %4 : $*Builtin.NativeObject
+ strong_retain %5 : $Builtin.NativeObject
+ br bb3(%5 : $Builtin.NativeObject)
+
+bb3(%6 : $Builtin.NativeObject):
+ destroy_addr %1 : $*NativeObjectPair
+ dealloc_stack %1 : $*NativeObjectPair
+ return %6 : $Builtin.NativeObject
+}
+
+// We should be able to promote all memory operations here.
+//
+// CHECK-LABEL: sil @diamond_test_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
+// CHECK-NOT: alloc_stack
+// CHECK-NOT: load
+// CHECK-NOT: store
+// CHECK: } // end sil function 'diamond_test_3'
+sil @diamond_test_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
+bb0(%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject):
+ %2 = alloc_stack $NativeObjectPair
+ %3 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f1
+ %4 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f2
+ store %0 to %3 : $*Builtin.NativeObject
+ store %1 to %4 : $*Builtin.NativeObject
+ cond_br undef, bb1, bb2
+
+bb1:
+ %tup_addr_1 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f1
+ %tup_val_1 = load %tup_addr_1 : $*Builtin.NativeObject
+ strong_retain %tup_val_1 : $Builtin.NativeObject
+ br bb3(%tup_val_1 : $Builtin.NativeObject)
+
+bb2:
+ %tup_addr_2 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.f1
+ %tup_val_2 = load %tup_addr_2 : $*Builtin.NativeObject
+ strong_retain %tup_val_2 : $Builtin.NativeObject
+ br bb3(%tup_val_2 : $Builtin.NativeObject)
+
+bb3(%result : $Builtin.NativeObject):
+ destroy_addr %2 : $*NativeObjectPair
+ dealloc_stack %2 : $*NativeObjectPair
+ return %result : $Builtin.NativeObject
+}
+
+struct NativeObjectTriple {
+ var f1: Builtin.NativeObject
+ var f2: NativeObjectPair
+}
+
+// Make sure we insert the struct_extracts in bb1, bb2.
+//
+// CHECK-LABEL: sil @diamond_test_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair) -> @owned Builtin.NativeObject {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $NativeObjectPair):
+// CHECK: cond_br undef, bb1, bb2
+//
+// CHECK: bb1:
+// CHECK-NEXT: [[PAIR_LHS:%.*]] = struct_extract [[ARG1]]
+// CHECK-NEXT: br bb3([[PAIR_LHS]] :
+//
+// CHECK: bb2:
+// CHECK-NEXT: [[PAIR_LHS:%.*]] = struct_extract [[ARG1]]
+// CHECK-NEXT: br bb3([[PAIR_LHS]] :
+//
+// CHECK: bb3([[PHI:%.*]] : $Builtin.NativeObject):
+// CHECK-NOT: struct_extract
+// CHECK: strong_retain [[PHI]]
+// CHECK-NOT: struct_extract
+// CHECK: [[REFORMED:%.*]] = struct $NativeObjectTriple ([[ARG0]] : {{.*}}, [[ARG1]] : {{.*}})
+// CHECK-NOT: struct_extract
+// CHECK: release_value [[REFORMED]]
+// CHECK-NOT: struct_extract
+// CHECK: return [[PHI]]
+// CHECK: } // end sil function 'diamond_test_4'
+sil @diamond_test_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair) -> @owned Builtin.NativeObject {
+bb0(%0 : $Builtin.NativeObject, %1 : $NativeObjectPair):
+ %2 = alloc_stack $NativeObjectTriple
+ cond_br undef, bb1, bb2
+
+bb1:
+ %3 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+ %4 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ store %0 to %3 : $*Builtin.NativeObject
+ store %1 to %4 : $*NativeObjectPair
+ br bb3
+
+bb2:
+ %5 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+ %6 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ store %0 to %5 : $*Builtin.NativeObject
+ store %1 to %6 : $*NativeObjectPair
+ br bb3
+
+bb3:
+ %11 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ %12 = struct_element_addr %11 : $*NativeObjectPair, #NativeObjectPair.f1
+ %13 = load %12 : $*Builtin.NativeObject
+ strong_retain %13 : $Builtin.NativeObject
+ destroy_addr %2 : $*NativeObjectTriple
+ dealloc_stack %2 : $*NativeObjectTriple
+ return %13 : $Builtin.NativeObject
+}
+
+// Make sure that we do the right thing if our definite init value is partially
+// overridden along one path
+//
+// CHECK-LABEL: sil @diamond_test_5 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $NativeObjectPair, [[ARG2:%.*]] : $Builtin.NativeObject):
+// CHECK: [[BOX:%.*]] = alloc_stack $NativeObjectTriple
+// CHECK: br bb1
+//
+// CHECK: bb1:
+// CHECK: [[TRIPLE_LHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f1
+// CHECK: [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK: store [[ARG0]] to [[TRIPLE_LHS]]
+// CHECK: [[TRIPLE_RHS_RHS_VAL:%.*]] = struct_extract [[ARG1]] : $NativeObjectPair, #NativeObjectPair.f2
+// CHECK: store [[ARG1]] to [[TRIPLE_RHS]]
+// CHECK: cond_br undef, bb2, bb3
+//
+// CHECK: bb2:
+// CHECK: [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]]
+// CHECK: store [[ARG2]] to [[TRIPLE_RHS_LHS]]
+// CHECK: br bb4
+//
+// CHECK: bb3:
+// CHECK: br bb4
+//
+// CHECK: bb4:
+// CHECK: [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]] : $*NativeObjectPair, #NativeObjectPair.f1
+// CHECK: [[TRIPLE_RHS_LHS_VAL:%.*]] = load [[TRIPLE_RHS_LHS]] : $*Builtin.NativeObject
+// CHECK: [[STRUCT:%.*]] = struct $NativeObjectPair ([[TRIPLE_RHS_LHS_VAL]] : {{.*}}, [[TRIPLE_RHS_RHS_VAL]] : {{.*}})
+// CHECK: retain_value [[STRUCT]]
+// CHECK: destroy_addr [[BOX]]
+// CHECK: return [[STRUCT]]
+// CHECK: } // end sil function 'diamond_test_5'
+sil @diamond_test_5 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+bb0(%0 : $Builtin.NativeObject, %1 : $NativeObjectPair, %arg2 : $Builtin.NativeObject):
+ %2 = alloc_stack $NativeObjectTriple
+ br bb1
+
+bb1:
+ %5 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+ %6 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ store %0 to %5 : $*Builtin.NativeObject
+ store %1 to %6 : $*NativeObjectPair
+ cond_br undef, bb2, bb3
+
+bb2:
+ %11 = struct_element_addr %6 : $*NativeObjectPair, #NativeObjectPair.f1
+ store %arg2 to %11 : $*Builtin.NativeObject
+ br bb4
+
+bb3:
+ br bb4
+
+bb4:
+ %13 = load %6 : $*NativeObjectPair
+ retain_value %13 : $NativeObjectPair
+ destroy_addr %2 : $*NativeObjectTriple
+ dealloc_stack %2 : $*NativeObjectTriple
+ return %13 : $NativeObjectPair
+}
+
+// CHECK-LABEL: sil @diamond_test_6 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+// CHECK: bb0([[ARG0:%.*]] : $Builtin.NativeObject, [[ARG1:%.*]] : $NativeObjectPair, [[ARG2:%.*]] : $Builtin.NativeObject):
+// CHECK: [[BOX:%.*]] = alloc_stack $NativeObjectTriple
+// CHECK: cond_br undef, bb1, bb2
+//
+// CHECK: bb1:
+// CHECK: [[TRIPLE_LHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f1
+// CHECK: [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK: store [[ARG0]] to [[TRIPLE_LHS]]
+// CHECK: [[TRIPLE_RHS_RHS_VAL:%.*]] = struct_extract [[ARG1]] : $NativeObjectPair, #NativeObjectPair.f2
+// CHECK: store [[ARG1]] to [[TRIPLE_RHS]]
+// CHECK: cond_br undef, bb3([[TRIPLE_RHS_RHS_VAL]] : {{.*}}), bb4([[TRIPLE_RHS_RHS_VAL]] : {{.*}})
+//
+// CHECK: bb2:
+// CHECK: [[TRIPLE_LHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f1
+// CHECK: [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK: store [[ARG0]] to [[TRIPLE_LHS]]
+// CHECK: [[TRIPLE_RHS_RHS_VAL:%.*]] = struct_extract [[ARG1]] : $NativeObjectPair, #NativeObjectPair.f2
+// CHECK: store [[ARG1]] to [[TRIPLE_RHS]]
+// CHECK: cond_br undef, bb3([[TRIPLE_RHS_RHS_VAL]] : {{.*}}), bb4([[TRIPLE_RHS_RHS_VAL]] : {{.*}})
+//
+// CHECK: bb3([[PHI1:%.*]] : $Builtin.NativeObject):
+// CHECK: [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK: [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]]
+// CHECK: store [[ARG2]] to [[TRIPLE_RHS_LHS]]
+// CHECK: br bb5([[PHI1:%.*]] : $Builtin.NativeObject)
+//
+// CHECK: bb4([[PHI:%.*]] : $Builtin.NativeObject):
+// CHECK: br bb5([[PHI]] : {{.*}})
+//
+// CHECK: bb5([[PHI:%.*]] : $Builtin.NativeObject
+// CHECK: [[TRIPLE_RHS:%.*]] = struct_element_addr [[BOX]] : $*NativeObjectTriple, #NativeObjectTriple.f2
+// CHECK: [[TRIPLE_RHS_LHS:%.*]] = struct_element_addr [[TRIPLE_RHS]] : $*NativeObjectPair, #NativeObjectPair.f1
+// CHECK: [[TRIPLE_RHS_LHS_VAL:%.*]] = load [[TRIPLE_RHS_LHS]] : $*Builtin.NativeObject
+// CHECK: [[STRUCT:%.*]] = struct $NativeObjectPair ([[TRIPLE_RHS_LHS_VAL]] : {{.*}}, [[PHI]] : {{.*}})
+// CHECK: retain_value [[STRUCT]]
+// CHECK: destroy_addr [[BOX]]
+// CHECK: return [[STRUCT]]
+// CHECK: } // end sil function 'diamond_test_6'
+sil @diamond_test_6 : $@convention(thin) (@owned Builtin.NativeObject, @owned NativeObjectPair, @owned Builtin.NativeObject) -> @owned NativeObjectPair {
+bb0(%0 : $Builtin.NativeObject, %1 : $NativeObjectPair, %arg2 : $Builtin.NativeObject):
+ %2 = alloc_stack $NativeObjectTriple
+ cond_br undef, bb1, bb2
+
+bb1:
+ %5 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+ %6 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ store %0 to %5 : $*Builtin.NativeObject
+ store %1 to %6 : $*NativeObjectPair
+ cond_br undef, bb3, bb4
+
+bb2:
+ %7 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f1
+ %8 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ store %0 to %7 : $*Builtin.NativeObject
+ store %1 to %8 : $*NativeObjectPair
+ cond_br undef, bb3, bb4
+
+bb3:
+ %11 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ %12 = struct_element_addr %11 : $*NativeObjectPair, #NativeObjectPair.f1
+ store %arg2 to %12 : $*Builtin.NativeObject
+ br bb5
+
+bb4:
+ br bb5
+
+bb5:
+ %13 = struct_element_addr %2 : $*NativeObjectTriple, #NativeObjectTriple.f2
+ %14 = load %13 : $*NativeObjectPair
+ retain_value %14 : $NativeObjectPair
+ destroy_addr %2 : $*NativeObjectTriple
+ dealloc_stack %2 : $*NativeObjectTriple
+ return %14 : $NativeObjectPair
+}
+
+///////////////////////
+// Unreachable Tests //
+///////////////////////
+
+// Make sure that we can handle a dead allocation with a destroy_addr in an
+// unreachable block.
+//
+// TODO: We can support this with trivial changes to canPromoteDestroyAddr. We
+// just need to distinguish a promotion failure around lack of availability vs
+// promotion failure for other reasons.
+//
+//
+// CHECK-LABEL: sil @dead_allocation_with_unreachable_destroy_addr : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+// CHECK: bb0([[ARG:%.*]] : $Builtin.NativeObject):
+// CHECK-NEXT: alloc_stack
+// CHECK-NEXT: store
+// CHECK-NEXT: br bb1
+//
+// CHECK: bb1:
+// CHECK-NEXT: destroy_addr
+// CHECK-NEXT: dealloc_stack
+// CHECK-NEXT: tuple
+// CHECK-NEXT: return
+//
+// CHECK: bb2:
+// CHECK-NEXT: destroy_addr
+// CHECK-NEXT: unreachable
+// CHECK: } // end sil function 'dead_allocation_with_unreachable_destroy_addr'
+sil @dead_allocation_with_unreachable_destroy_addr : $@convention(thin) (@owned Builtin.NativeObject) -> () {
+bb0(%0 : $Builtin.NativeObject):
+ %1 = alloc_stack $Builtin.NativeObject
+ store %0 to %1 : $*Builtin.NativeObject
+ br bb1
+
+bb1:
+ destroy_addr %1 : $*Builtin.NativeObject
+ dealloc_stack %1 : $*Builtin.NativeObject
+ %9999 = tuple()
+ return %9999 : $()
+
+bb2:
+ destroy_addr %1 : $*Builtin.NativeObject
+ unreachable
+}
\ No newline at end of file
diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index cc08acb..9751347 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -463,3 +463,59 @@
apply %closure() : $@callee_guaranteed () -> ()
return %closure : $@callee_guaranteed () -> ()
}
+
+sil @guaranteed_closure_throws : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @error Error
+
+// CHECK: sil @test_guaranteed_closure_try_apply
+// CHECK: bb0(%0 : $C, %1 : $Builtin.Int32):
+// CHECK: strong_retain %0 : $C
+// CHECK: [[FUN:%.*]] = function_ref @guaranteed_closure_throws
+// CHECK: [[CL:%.*]] = partial_apply [callee_guaranteed] [[FUN]](%1)
+// CHECK: try_apply [[FUN]](%0, %1)
+// CHECK: bb1({{.*}}):
+// CHECK-NOT: strong_release
+// CHECK: br bb3
+// CHECK: bb2({{.*}}):
+// CHECK-NOT: strong_release
+// CHECK: br bb3
+// CHECK: bb3:
+// CHECK: return [[CL]]
+
+sil @test_guaranteed_closure_try_apply : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @owned @callee_guaranteed (@guaranteed C) -> @error Error {
+bb0(%0: $C, %1: $Builtin.Int32):
+ strong_retain %0 : $C
+ %closure_fun = function_ref @guaranteed_closure_throws : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @error Error
+ %closure = partial_apply [callee_guaranteed] %closure_fun(%1) : $@convention(thin) (@guaranteed C, Builtin.Int32) -> @error Error
+ try_apply %closure(%0) : $@callee_guaranteed (@guaranteed C) -> @error Error, normal bb7, error bb11
+
+bb7(%callret : $()):
+ br bb99
+
+bb11(%128 : $Error):
+ br bb99
+
+bb99:
+ return %closure : $@callee_guaranteed (@guaranteed C) -> @error Error
+}
+
+// Make sure convert_function -> apply does the right thing with metatypes
+class Base {}
+class Derived {}
+
+sil @takesMetatype : $@convention(thin) (@thick Base.Type) -> ()
+
+// CHECK-LABEL: sil @passesMetatype
+// CHECK: [[METATYPE:%.*]] = metatype $@thick Derived.Type
+// CHECK: [[FN:%.*]] = function_ref @takesMetatype
+// CHECK: [[CONVERTED:%.*]] = unchecked_trivial_bit_cast [[METATYPE]] : $@thick Derived.Type to $@thick Base.Type
+// CHECK: [[RESULT:%.*]] = apply [[FN]]([[CONVERTED]])
+
+sil @passesMetatype : $@convention(thin) () -> () {
+bb0:
+ %metatype = metatype $@thick Derived.Type
+ %fn = function_ref @takesMetatype : $@convention(thin) (@thick Base.Type) -> ()
+ %converted = convert_function %fn : $@convention(thin) (@thick Base.Type) -> () to $@convention(thin) (@thick Derived.Type) -> ()
+ %result = apply %converted(%metatype) : $@convention(thin) (@thick Derived.Type) -> ()
+ %return = tuple ()
+ return %return : $()
+}
diff --git a/test/Sema/accessibility.swift b/test/Sema/accessibility.swift
index 36864f6..65a49c2 100644
--- a/test/Sema/accessibility.swift
+++ b/test/Sema/accessibility.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -swift-version 5
public protocol PublicProto {
func publicReq()
@@ -426,6 +426,25 @@
class DefaultSubclassInternal : InternalClass {}
class DefaultSubclassPrivate : PrivateClass {} // expected-error {{class must be declared private or fileprivate because its superclass is private}}
+public class PublicGenericClass<T> {}
+// expected-note@+2 * {{type declared here}}
+// expected-note@+1 * {{superclass is declared here}}
+internal class InternalGenericClass<T> {}
+// expected-note@+1 * {{type declared here}}
+private class PrivateGenericClass<T> {}
+
+open class OpenConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-error {{class cannot be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<Int>' of open class must be open}}
+public class PublicConcreteSubclassPublic : PublicGenericClass<Int> {}
+public class PublicConcreteSubclassInternal : InternalGenericClass<Int> {} // expected-error {{class cannot be declared public because its superclass is internal}}
+public class PublicConcreteSubclassPrivate : PrivateGenericClass<Int> {} // expected-error {{class cannot be declared public because its superclass is private}}
+public class PublicConcreteSubclassPublicPrivateArg : PublicGenericClass<PrivateStruct> {} // expected-error {{class cannot be declared public because its superclass is private}}
+
+open class OpenGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-error {{class cannot be declared open because its superclass is internal}} expected-error {{superclass 'InternalGenericClass<T>' of open class must be open}}
+public class PublicGenericSubclassPublic<T> : PublicGenericClass<T> {}
+public class PublicGenericSubclassInternal<T> : InternalGenericClass<T> {} // expected-error {{class cannot be declared public because its superclass is internal}}
+public class PublicGenericSubclassPrivate<T> : PrivateGenericClass<T> {} // expected-error {{class cannot be declared public because its superclass is private}}
+
+
public enum PublicEnumPrivate {
case A(PrivateStruct) // expected-error {{enum case in a public enum uses a private type}}
@@ -647,3 +666,24 @@
fileprivate typealias Assoc = Int // expected-error {{type alias 'Assoc' must be as accessible as its enclosing type because it matches a requirement in protocol 'AssocTypeProto'}} {{5-16=internal}}
}
}
+
+internal typealias InternalComposition = PublicClass & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalComposition : InternalComposition { // expected-error {{class cannot be declared public because its superclass is internal}}
+ public func publicReq() {}
+}
+
+internal typealias InternalGenericComposition<T> = PublicGenericClass<T> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalGenericComposition : InternalGenericComposition<Int> { // expected-error {{class cannot be declared public because its superclass is internal}}
+ public func publicReq() {}
+}
+
+internal typealias InternalConcreteGenericComposition = PublicGenericClass<Int> & PublicProto // expected-note {{declared here}}
+public class DerivedFromInternalConcreteGenericComposition : InternalConcreteGenericComposition { // expected-error {{class cannot be declared public because its superclass is internal}}
+ public func publicReq() {}
+}
+
+public typealias BadPublicComposition1 = InternalClass & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition2 = PublicClass & InternalProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition3<T> = InternalGenericClass<T> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition4 = InternalGenericClass<Int> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
+public typealias BadPublicComposition5 = PublicGenericClass<InternalStruct> & PublicProto // expected-error {{type alias cannot be declared public because its underlying type uses an internal type}}
diff --git a/test/Sema/diag_erroneous_iuo.swift b/test/Sema/diag_erroneous_iuo.swift
index 2e51057..d938be6 100644
--- a/test/Sema/diag_erroneous_iuo.swift
+++ b/test/Sema/diag_erroneous_iuo.swift
@@ -81,6 +81,8 @@
var x: V
var y: W
+ var fn1: (Int!) -> Int // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ var fn2: (Int) -> Int! // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
subscript (
index: ImplicitlyUnwrappedOptional<Int> // expected-error {{the spelling 'ImplicitlyUnwrappedOptional' is unsupported; use '!' after the type name}}{{12-40=}}{{43-43=!}}{{43-44=}}
@@ -138,18 +140,53 @@
func vararg(_ first: Int, more: Int!...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
}
+func varargIdentifier(_ first: Int, more: ImplicitlyUnwrappedOptional<Int>...) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+}
+
func iuoInTuple() -> (Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return 1
}
-func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+func iuoInTupleIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return 1
}
+func iuoInTuple2() -> (Float, Int!) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return (1.0, 1)
+}
+
+func iuoInTuple2Identifier() -> (Float, ImplicitlyUnwrappedOptional<Int>) { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return (1.0, 1)
+}
+
func takesFunc(_ fn: (Int!) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return fn(0)
}
+func takesFuncIdentifier(_ fn: (ImplicitlyUnwrappedOptional<Int>) -> Int) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
+func takesFunc2(_ fn: (Int) -> Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
+func takesFunc2Identifier(_ fn: (Int) -> ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return fn(0)
+}
+
func returnsFunc() -> (Int!) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
return { $0 }
}
+
+func returnsFuncIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
+
+func returnsFunc2() -> (Int) -> Int! { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
+
+func returnsFunc2Identifier() -> (Int) -> ImplicitlyUnwrappedOptional<Int> { // expected-error {{implicitly unwrapped optionals are only allowed at top level and as function results}}
+ return { $0 }
+}
diff --git a/test/Sema/enum_equatable_hashable.swift b/test/Sema/enum_equatable_hashable.swift
index b5c334d..a915449 100644
--- a/test/Sema/enum_equatable_hashable.swift
+++ b/test/Sema/enum_equatable_hashable.swift
@@ -226,6 +226,18 @@
case end(Int)
}
+// Check the use of conditional conformances.
+enum ArrayOfEquatables : Equatable {
+case only([Int])
+}
+
+struct NotEquatable { }
+
+// FIXME: rdar://problem/35518088 this should fail.
+enum ArrayOfNotEquatables : Equatable {
+case only([NotEquatable])
+}
+
// FIXME: Remove -verify-ignore-unknown.
// <unknown>:0: error: unexpected error produced: invalid redeclaration of 'hashValue'
// <unknown>:0: error: unexpected note produced: candidate has non-matching type '(Foo, Foo) -> Bool'
diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift
index 138f9a9..9793e58 100644
--- a/test/Sema/enum_raw_representable.swift
+++ b/test/Sema/enum_raw_representable.swift
@@ -78,8 +78,6 @@
let a: Int = E.a // expected-error {{cannot convert value of type 'Outer.E' to specified type 'Int'}}
enum E : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
- // expected-error@-1 {{'Outer.E' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
- // expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
case a
}
}
@@ -146,3 +144,10 @@
let _ = choice == "bar"
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{11-11=}} {{17-17=.rawValue}}
}
+
+
+struct NotEquatable { }
+
+enum ArrayOfNewEquatable : Array<NotEquatable> { }
+// expected-error@-1{{raw type 'Array<NotEquatable>' is not expressible by any literal}}
+// expected-error@-2{{'ArrayOfNewEquatable' declares raw type 'Array<NotEquatable>', but does not conform to RawRepresentable and conformance could not be synthesized}}
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 3e8cbdd..60104ea 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -920,6 +920,27 @@
return %2 : $()
}
+// CHECK-LABEL: [Onone] @test_onone : $@convention(thin) () -> ()
+sil [serialized] [Onone] @test_onone : $@convention(thin) () -> () {
+bb0:
+ %2 = tuple ()
+ return %2 : $()
+}
+
+// CHECK-LABEL: [Ospeed] @test_ospeed : $@convention(thin) () -> ()
+sil [serialized] [Ospeed] @test_ospeed : $@convention(thin) () -> () {
+bb0:
+ %2 = tuple ()
+ return %2 : $()
+}
+
+// CHECK-LABEL: [Osize] @test_osize : $@convention(thin) () -> ()
+sil [serialized] [Osize] @test_osize : $@convention(thin) () -> () {
+bb0:
+ %2 = tuple ()
+ return %2 : $()
+}
+
sil [serialized] @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> @callee_owned () -> @callee_owned () -> Int
sil [serialized] @takes_int64_float32 : $@convention(thin) (Int, Float32) -> ()
@@ -1420,6 +1441,9 @@
%130 = function_ref @noinline_callee : $@convention(thin) () -> Int
%132 = function_ref @always_inline_callee : $@convention(thin) () -> Int
%131 = function_ref @test_semantics : $@convention(thin) () -> ()
+ %136 = function_ref @test_onone : $@convention(thin) () -> ()
+ %137 = function_ref @test_ospeed : $@convention(thin) () -> ()
+ %138 = function_ref @test_osize : $@convention(thin) () -> ()
%111 = function_ref @test_partial_apply : $@convention(thin) Float32 -> @callee_owned Int -> ()
%113 = function_ref @test_dynamic_lookup_br : $@convention(thin) (AnyObject) -> ()
%115 = function_ref @test_mark_fn_escape : $@convention(thin) () -> ()
diff --git a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
index 7bf9c7a..6eaf68c 100644
--- a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
+++ b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
@@ -115,3 +115,22 @@
//- (nonnull instancetype)initWithValue:(long)value;
#endif
@end
+
+
+#if !BAD
+struct BoxedInt {
+ int value;
+};
+#endif
+
+@interface MethodWithDisappearingType : Object
+#if !BAD
+- (struct BoxedInt)boxItUp;
+#endif
+@end
+
+@interface InitializerWithDisappearingType : Object
+#if !BAD
+- (nonnull instancetype)initWithBoxedInt:(struct BoxedInt)box;
+#endif
+@end
diff --git a/test/Serialization/Recovery/overrides.swift b/test/Serialization/Recovery/overrides.swift
index c0b7b25..486f6c0 100644
--- a/test/Serialization/Recovery/overrides.swift
+++ b/test/Serialization/Recovery/overrides.swift
@@ -311,4 +311,33 @@
// CHECK-RECOVERY-NEXT: /* placeholder for init(value:) */
// CHECK-RECOVERY-NEXT: {{^}$}}
+public class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+ public override func boxItUp() -> BoxedInt { fatalError() }
+}
+
+// CHECK-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-NEXT: override func boxItUp() -> BoxedInt
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
+public class E2_InitializerStub : InitializerWithDisappearingType {
+ public init(unrelatedValue: Int) { fatalError() }
+}
+
+// CHECK-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-NEXT: init(unrelatedValue: Int)
+// CHECK-NEXT: init(boxedInt box: BoxedInt)
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init(unrelatedValue: Int)
+// CHECK-RECOVERY-NEXT: /* placeholder for init(boxedInt:) */
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
#endif // TEST
diff --git a/test/Serialization/function.swift b/test/Serialization/function.swift
index 5b3b69a..9a12e9a 100644
--- a/test/Serialization/function.swift
+++ b/test/Serialization/function.swift
@@ -35,18 +35,18 @@
// SIL: {{%.+}} = apply [[USE_NESTED]]({{%.+}}, {{%.+}}, {{%.+}}) : $@convention(thin) (Int, Int, Int) -> ()
useNested((raw, raw2), n: raw3)
-// SIL: [[VARIADIC:%.+]] = function_ref @_T08def_func8variadicySd1x_SidtF : $@convention(thin) (Double, @owned Array<Int>) -> ()
// SIL: [[VA_SIZE:%.+]] = integer_literal $Builtin.Word, 2
// SIL: {{%.+}} = apply {{%.*}}<Int>([[VA_SIZE]])
+// SIL: [[VARIADIC:%.+]] = function_ref @_T08def_func8variadicySd1x_SidtF : $@convention(thin) (Double, @owned Array<Int>) -> ()
// SIL: {{%.+}} = apply [[VARIADIC]]({{%.+}}, {{%.+}}) : $@convention(thin) (Double, @owned Array<Int>) -> ()
variadic(x: 2.5, 4, 5)
// SIL: [[VARIADIC:%.+]] = function_ref @_T08def_func9variadic2ySid_Sd1xtF : $@convention(thin) (@owned Array<Int>, Double) -> ()
variadic2(1, 2, 3, x: 5.0)
-// SIL: [[SLICE:%.+]] = function_ref @_T08def_func5sliceySaySiG1x_tF : $@convention(thin) (@owned Array<Int>) -> ()
// SIL: [[SLICE_SIZE:%.+]] = integer_literal $Builtin.Word, 3
// SIL: {{%.+}} = apply {{%.*}}<Int>([[SLICE_SIZE]])
+// SIL: [[SLICE:%.+]] = function_ref @_T08def_func5sliceySaySiG1x_tF : $@convention(thin) (@owned Array<Int>) -> ()
// SIL: {{%.+}} = apply [[SLICE]]({{%.+}}) : $@convention(thin) (@owned Array<Int>) -> ()
slice(x: [2, 4, 5])
diff --git a/test/Serialization/inherited-initializer.swift b/test/Serialization/inherited-initializer.swift
index 7042b69..b2936f3 100644
--- a/test/Serialization/inherited-initializer.swift
+++ b/test/Serialization/inherited-initializer.swift
@@ -8,15 +8,15 @@
// CHECK-LABEL: sil hidden @_T04main10testSimpleyyF
func testSimple() {
- // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
// CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase0C0CACSicfcfA_
// CHECK: [[ARG:%.+]] = apply [[DEFAULT]]()
+ // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
// CHECK: apply [[INIT]]([[ARG]], {{%.+}})
_ = InheritsInit()
- // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
// CHECK: [[VALUE:%.+]] = integer_literal $Builtin.Int2048, 5
// CHECK: [[ARG:%.+]] = apply {{%.+}}([[VALUE]], {{%.+}}) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
+ // CHECK: [[INIT:%.+]] = function_ref @_T04main12InheritsInitCACSicfC
// CHECK: apply [[INIT]]([[ARG]], {{%.+}})
_ = InheritsInit(5)
} // CHECK: end sil function '_T04main10testSimpleyyF'
@@ -31,24 +31,24 @@
// CHECK-LABEL: sil hidden @_T04main11testGenericyyF
func testGeneric() {
- // CHECK: [[INIT:%.+]] = function_ref @_T04main10GenericSubCACyxGxcfC
// CHECK: [[TYPE:%.+]] = metatype $@thick GenericSub<Reinitializable<Int8>>.Type
// CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase07GenericC0CACyxGxcfcfA_
// CHECK: apply [[DEFAULT]]<Reinitializable<Int8>>({{%.+}})
+ // CHECK: [[INIT:%.+]] = function_ref @_T04main10GenericSubCACyxGxcfC
// CHECK: apply [[INIT]]<Reinitializable<Int8>>({{%.+}}, [[TYPE]])
_ = GenericSub<Reinitializable<Int8>>.init() // works around SR-3806
- // CHECK: [[INIT:%.+]] = function_ref @_T04main18ModifiedGenericSubCACyxGAA15ReinitializableVyxGcfC
// CHECK: [[TYPE:%.+]] = metatype $@thick ModifiedGenericSub<Int16>.Type
// CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase07GenericC0CACyxGxcfcfA_
// CHECK: apply [[DEFAULT]]<Reinitializable<Int16>>({{%.+}})
+ // CHECK: [[INIT:%.+]] = function_ref @_T04main18ModifiedGenericSubCACyxGAA15ReinitializableVyxGcfC
// CHECK: apply [[INIT]]<Int16>({{%.+}}, [[TYPE]])
_ = ModifiedGenericSub<Int16>()
- // CHECK: [[INIT:%.+]] = function_ref @_T04main13NonGenericSubCAcA15ReinitializableVySiGcfC
// CHECK: [[TYPE:%.+]] = metatype $@thick NonGenericSub.Type
// CHECK: [[DEFAULT:%.+]] = function_ref @_T024InheritedInitializerBase07GenericC0CACyxGxcfcfA_
// CHECK: apply [[DEFAULT]]<Reinitializable<Int>>({{%.+}})
+ // CHECK: [[INIT:%.+]] = function_ref @_T04main13NonGenericSubCAcA15ReinitializableVySiGcfC
// CHECK: apply [[INIT]]({{%.+}}, [[TYPE]])
_ = NonGenericSub()
} // CHECK: end sil function '_T04main11testGenericyyF'
diff --git a/test/Serialization/objc.swift b/test/Serialization/objc.swift
index 92684b1..85e07af 100644
--- a/test/Serialization/objc.swift
+++ b/test/Serialization/objc.swift
@@ -18,7 +18,7 @@
// SIL: = objc_method %{{.+}} : $ObjCClass, #ObjCClass.implicitlyObjC!1.foreign
obj.implicitlyObjC()
- // SIL: = objc_method %{{.+}} : $@thick ObjCClass.Type, #ObjCClass.classMethod!1.foreign
+ // SIL: = objc_method %{{.+}} : $@objc_metatype ObjCClass.Type, #ObjCClass.classMethod!1.foreign
ObjCClass.classMethod()
}
diff --git a/test/Serialization/serialize_attr.swift b/test/Serialization/serialize_attr.swift
index a062448..0fc5004 100644
--- a/test/Serialization/serialize_attr.swift
+++ b/test/Serialization/serialize_attr.swift
@@ -13,6 +13,27 @@
@_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
// -----------------------------------------------------------------------------
diff --git a/test/SourceKit/Indexing/index_swift_lib.swift b/test/SourceKit/Indexing/index_swift_lib.swift
deleted file mode 100644
index 16f52a2..0000000
--- a/test/SourceKit/Indexing/index_swift_lib.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-// REQUIRES: FIXME
-
-// RUN: %sourcekitd-test -req=index %swiftlib_dir/macosx/x86_64/Swift.swiftmodule -- %mcp_opt > %t.txt
-// RUN: %FileCheck %s -input-file %t.txt
-
-// CHECK: key.name: "Dictionary",
-// CHECK-NEXT: key.usr: "s:Vs10Dictionary",
-
-// RUN: %FileCheck %s -input-file %t.txt -check-prefix=CHECK-INTERNAL
-// RUN: %sourcekitd-test -req=index %swiftlib_dir/macosx/x86_64/Foundation.swiftmodule -- %clang-importer-sdk %mcp_opt > %t.foundation.txt
-// RUN: %FileCheck %s -input-file %t.foundation.txt -check-prefix=CHECK-FOUNDATION
-
-// CHECK-INTERNAL-NOT: key.name: "_bridgeToObjectiveCUnconditional",
-
-// CHECK-FOUNDATION-NOT: _convertStringToNSString
diff --git a/test/SourceKit/Misc/ignore_bridging_pch.swift b/test/SourceKit/Misc/ignore_bridging_pch.swift
deleted file mode 100644
index b2c9812..0000000
--- a/test/SourceKit/Misc/ignore_bridging_pch.swift
+++ /dev/null
@@ -1,7 +0,0 @@
-// RUN: %sourcekitd-test -req=complete -pos=5:3 %s -- -enable-bridging-pch %s | %FileCheck %s
-// RUN: %sourcekitd-test -req=complete -pos=5:3 %s -- -disable-bridging-pch %s | %FileCheck %s
-
-var s = 10
-s.
-
-// CHECK: littleEndian
diff --git a/test/SourceKit/Misc/ignored-flags.swift b/test/SourceKit/Misc/ignored-flags.swift
new file mode 100644
index 0000000..9e7b437
--- /dev/null
+++ b/test/SourceKit/Misc/ignored-flags.swift
@@ -0,0 +1,11 @@
+var s = 10
+s.
+
+// CHECK: littleEndian
+
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -j4 %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -c %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -v %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -embed-bitcode %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -enable-bridging-pch %s | %FileCheck %s
+// RUN: %sourcekitd-test -req=complete -pos=2:3 %s -- -disable-bridging-pch %s | %FileCheck %s
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index 6c36768..3eb5364 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -1,19 +1,43 @@
-<UnknownDecl>// RUN: %swift-syntax-test -input-source-filename %s -parse-gen > %t
+// RUN: %swift-syntax-test -input-source-filename %s -parse-gen > %t
// RUN: diff -u %s %t
// RUN: %swift-syntax-test -input-source-filename %s -parse-gen -print-node-kind > %t.withkinds
// RUN: diff -u %S/Outputs/round_trip_parse_gen.swift.withkinds %t.withkinds
-class C {<UnknownDecl>
- func bar(_ a: Int) <CodeBlock>{}</CodeBlock></UnknownDecl><UnknownDecl>
- func bar1(_ a: Float) -> Float <CodeBlock>{ <UnknownStmt>return <UnknownExpr><FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr></UnknownExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
- func foo() <CodeBlock>{<UnknownDecl>
- var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr></UnknownDecl><UnknownDecl>
- var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr></UnknownDecl><UnknownExpr>
- bar(<IntegerLiteralExpr>1</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar(<IntegerLiteralExpr>+10</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar(<IntegerLiteralExpr>-10</IntegerLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar1(<FloatLiteralExpr>-1.1</FloatLiteralExpr>)</UnknownExpr><UnknownExpr>
- bar1(<FloatLiteralExpr>1.1</FloatLiteralExpr>)</UnknownExpr><UnknownDecl>
- var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr></UnknownDecl>
- }</CodeBlock></UnknownDecl>
-}</UnknownDecl>
+class C {
+ func bar(_ a: Int) <CodeBlock>{}</CodeBlock>
+ func bar1(_ a: Float) -> Float <CodeBlock>{ return <FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr>}</CodeBlock>
+ func bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+ func bar3(a: Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+ func bar4(_ a: Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+ func foo() <CodeBlock>{
+ var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr>
+ var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr><IdentifierExpr>
+ bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)
+ var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr><IdentifierExpr>
+ foo</IdentifierExpr>()
+ }</CodeBlock>
+
+ func foo1() <CodeBlock>{<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>), </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><IntegerLiteralExpr>1</IntegerLiteralExpr>:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>2</IntegerLiteralExpr>:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>3</IntegerLiteralExpr>:<IntegerLiteralExpr>3</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>4</IntegerLiteralExpr>:<IntegerLiteralExpr>4</IntegerLiteralExpr></DictionaryElement>]</DictionaryExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</DictionaryElement>]</DictionaryExpr><IdentifierExpr>
+ foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)
+ }</CodeBlock>
+ func boolAnd() -> Bool <CodeBlock>{ return <BooleanLiteralExpr>true </BooleanLiteralExpr>&& <BooleanLiteralExpr>false </BooleanLiteralExpr>}</CodeBlock>
+ func boolOr() -> Bool <CodeBlock>{ return <BooleanLiteralExpr>true </BooleanLiteralExpr>|| <BooleanLiteralExpr>false </BooleanLiteralExpr>}</CodeBlock>
+
+ func foo2() <CodeBlock>{<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <TernaryExpr>(<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) ? (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) : (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>)</TernaryExpr>
+ }</CodeBlock>
+}
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 839126a..a9d72bb 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -6,6 +6,9 @@
class C {
func bar(_ a: Int) {}
func bar1(_ a: Float) -> Float { return -0.6 + 0.1 - 0.3 }
+ func bar2(a: Int, b: Int, c:Int) -> Int { return 1 }
+ func bar3(a: Int) -> Int { return 1 }
+ func bar4(_ a: Int) -> Int { return 1 }
func foo() {
var a = /*comment*/"abc"/*comment*/
var b = /*comment*/+2/*comment*/
@@ -15,5 +18,26 @@
bar1(-1.1)
bar1(1.1)
var f = /*comments*/+0.1/*comments*/
+ foo()
+ }
+
+ func foo1() {
+ _ = bar2(a:1, b:2, c:2)
+ _ = bar2(a:1 + 1, b:2 * 2 + 2, c:2 + 2)
+ _ = bar2(a : bar2(a: 1, b: 2, c: 3), b: 2, c: 3)
+ _ = bar3(a : bar3(a: bar3(a: 1)))
+ _ = bar4(bar4(bar4(1)))
+ _ = [1, 2, 3, 4]
+ _ = [1:1, 2:2, 3:3, 4:4]
+ _ = [bar3(a:1), bar3(a:1), bar3(a:1), bar3(a:1)]
+ _ = ["a": bar3(a:1), "b": bar3(a:1), "c": bar3(a:1), "d": bar3(a:1)]
+ foo(nil, nil, nil)
+ }
+ func boolAnd() -> Bool { return true && false }
+ func boolOr() -> Bool { return true || false }
+
+ func foo2() {
+ _ = true ? 1 : 0
+ _ = (true ? 1 : 0) ? (true ? 1 : 0) : (true ? 1 : 0)
}
}
diff --git a/test/attr/attr_availability_transitive_ios.swift b/test/attr/attr_availability_transitive_ios.swift
new file mode 100644
index 0000000..8ed79a0
--- /dev/null
+++ b/test/attr/attr_availability_transitive_ios.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=ios
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(iOS, unavailable)
+func ios() {} // expected-note 2{{'ios()' has been explicitly marked unavailable here}}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension() {}
+
+func call_ios_extension() {
+ ios_extension() // OK; ios_extension is only unavailable if -application-extension is passed.
+}
+func call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios_extension() {
+ ios_extension() // OK; ios_extension is only unavailable if -application-extension is passed.
+}
+
+@available(iOS, unavailable)
+func ios_call_ios() {
+ ios() // OK; same
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios_extension() {
+ ios_extension()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_ios_extension.swift b/test/attr/attr_availability_transitive_ios_extension.swift
new file mode 100644
index 0000000..6f73286
--- /dev/null
+++ b/test/attr/attr_availability_transitive_ios_extension.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift -application-extension
+// REQUIRES: OS=ios
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(iOS, unavailable)
+func ios() {} // expected-note 2{{'ios()' has been explicitly marked unavailable here}}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension() {} // expected-note 2{{'ios_extension()' has been explicitly marked unavailable here}}
+
+func call_ios_extension() {
+ ios_extension() // expected-error {{'ios_extension()' is unavailable}}
+}
+func call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios_extension() {
+ ios_extension() // expected-error {{'ios_extension()' is unavailable}}
+}
+
+@available(iOS, unavailable)
+func ios_call_ios() {
+ ios()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios_extension() {
+ ios_extension()
+}
+
+@available(iOSApplicationExtension, unavailable)
+func ios_extension_call_ios() {
+ ios() // expected-error {{'ios()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_multiple.swift b/test/attr/attr_availability_transitive_multiple.swift
new file mode 100644
index 0000000..8ef579d
--- /dev/null
+++ b/test/attr/attr_availability_transitive_multiple.swift
@@ -0,0 +1,18 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Check that only the platform we are compiling for is considered when allowing access to unavailable declarations.
+
+@available(iOS, unavailable)
+@available(OSX, unavailable)
+func unavailable() {} // expected-note {{'unavailable()' has been explicitly marked unavailable here}}
+
+@available(iOS, unavailable)
+func call_with_ios_unavailable() {
+ unavailable() // expected-error {{'unavailable()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func call_with_osx_unavailable() {
+ unavailable() // OK: same
+}
diff --git a/test/attr/attr_availability_transitive_nested.swift b/test/attr/attr_availability_transitive_nested.swift
new file mode 100644
index 0000000..7d8b474
--- /dev/null
+++ b/test/attr/attr_availability_transitive_nested.swift
@@ -0,0 +1,25 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Make sure that a compatible unavailable wrapping doesn't allow referencing declarations that are completely unavailable.
+
+@available(iOS, unavailable)
+class Outer {
+ @available(*, unavailable)
+ func completelyBadMethod() {} // expected-note {{'completelyBadMethod()' has been explicitly marked unavailable here}}
+}
+
+@available(iOS, unavailable)
+func test(outer: Outer) {
+ outer.completelyBadMethod() // expected-error {{'completelyBadMethod()' is unavailable}}
+}
+
+@available(*, unavailable)
+class Outer2 { // expected-note {{'Outer2' has been explicitly marked unavailable here}}
+ @available(iOS, unavailable)
+ func innerUnavailable() {}
+}
+@available(iOS, unavailable)
+func test2(outer: Outer2) { // expected-error {{'Outer2' is unavailable}}
+ outer.innerUnavailable()
+}
diff --git a/test/attr/attr_availability_transitive_osx.swift b/test/attr/attr_availability_transitive_osx.swift
new file mode 100644
index 0000000..eadaf60
--- /dev/null
+++ b/test/attr/attr_availability_transitive_osx.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift
+// REQUIRES: OS=macosx
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(OSX, unavailable)
+func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension() {}
+
+func call_osx_extension() {
+ osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
+}
+func call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx_extension() {
+ osx_extension() // OK; osx_extension is only unavailable if -application-extension is passed.
+}
+
+@available(OSX, unavailable)
+func osx_call_osx() {
+ osx() // OK; same
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx_extension() {
+ osx_extension()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
diff --git a/test/attr/attr_availability_transitive_osx_extension.swift b/test/attr/attr_availability_transitive_osx_extension.swift
new file mode 100644
index 0000000..949ef68
--- /dev/null
+++ b/test/attr/attr_availability_transitive_osx_extension.swift
@@ -0,0 +1,37 @@
+// RUN: %target-typecheck-verify-swift -application-extension
+// REQUIRES: OS=macosx
+
+// Allow referencing unavailable API in situations where the caller is marked unavailable in the same circumstances.
+
+@available(OSX, unavailable)
+func osx() {} // expected-note 2{{'osx()' has been explicitly marked unavailable here}}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension() {} // expected-note 2{{'osx_extension()' has been explicitly marked unavailable here}}
+
+func call_osx_extension() {
+ osx_extension() // expected-error {{'osx_extension()' is unavailable}}
+}
+func call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx_extension() {
+ osx_extension() // expected-error {{'osx_extension()' is unavailable}}
+}
+
+@available(OSX, unavailable)
+func osx_call_osx() {
+ osx()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx_extension() {
+ osx_extension()
+}
+
+@available(OSXApplicationExtension, unavailable)
+func osx_extension_call_osx() {
+ osx() // expected-error {{'osx()' is unavailable}}
+}
diff --git a/test/attr/attr_inlineable.swift b/test/attr/attr_inlineable.swift
index d675917..4dc3a491 100644
--- a/test/attr/attr_inlineable.swift
+++ b/test/attr/attr_inlineable.swift
@@ -24,10 +24,10 @@
public init() {}
@_inlineable public var storedProperty: Int
- // expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
+ // expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
@_inlineable public lazy var lazyProperty: Int = 0
- // expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
+ // expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
}
public struct Struct {
diff --git a/test/attr/attributes.swift b/test/attr/attributes.swift
index 966ae39..993b5fe 100644
--- a/test/attr/attributes.swift
+++ b/test/attr/attributes.swift
@@ -215,6 +215,11 @@
@inline(__always) class FooClass2 { // expected-error {{@inline(__always) cannot be applied to this declaration}} {{1-19=}}
}
+@_optimize(speed) func OspeedFunc() {}
+@_optimize(speed) var OpeedVar : Int // expected-error {{@_optimize(speed) cannot be applied to stored properties}} {{1-19=}}
+@_optimize(speed) class OspeedClass { // expected-error {{@_optimize(speed) cannot be applied to this declaration}} {{1-19=}}
+}
+
class A {
@inline(never) init(a : Int) {}
var b : Int {
@@ -237,6 +242,18 @@
}
}
+class C {
+ @_optimize(speed) init(a : Int) {}
+ var b : Int {
+ @_optimize(none) get {
+ return 42
+ }
+ @_optimize(size) set {
+ }
+ }
+ @_optimize(size) var c : Int // expected-error {{@_optimize(size) cannot be applied to stored properties}}
+}
+
class SILStored {
@sil_stored var x : Int = 42 // expected-error {{'sil_stored' only allowed in SIL modules}}
}
diff --git a/test/decl/ext/protocol.swift b/test/decl/ext/protocol.swift
index 117a0b5..36af2df 100644
--- a/test/decl/ext/protocol.swift
+++ b/test/decl/ext/protocol.swift
@@ -959,3 +959,43 @@
extension A & B { // okay
}
+
+// Suppress near-miss warning for unlabeled initializers.
+protocol P9 {
+ init(_: Int)
+ init(_: Double)
+}
+
+extension P9 {
+ init(_ i: Int) {
+ self.init(Double(i))
+ }
+}
+
+struct X9 : P9 {
+ init(_: Float) { }
+}
+
+extension X9 {
+ init(_: Double) { }
+}
+
+// Suppress near-miss warning for unlabeled subscripts.
+protocol P10 {
+ subscript (_: Int) -> Int { get }
+ subscript (_: Double) -> Double { get }
+}
+
+extension P10 {
+ subscript(i: Int) -> Int {
+ return Int(self[Double(i)])
+ }
+}
+
+struct X10 : P10 {
+ subscript(f: Float) -> Float { return f }
+}
+
+extension X10 {
+ subscript(d: Double) -> Double { return d }
+}
diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift
index 066556c..2498292 100644
--- a/test/expr/unary/keypath/keypath.swift
+++ b/test/expr/unary/keypath/keypath.swift
@@ -269,7 +269,10 @@
subscript(keyPath kp: PartialKeyPath<ZwithSubscript>) -> Any { return 0 }
}
+struct NotZ {}
+
func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscript,
+ wrongType: inout NotZ,
kp: KeyPath<ZwithSubscript, Int>,
wkp: WritableKeyPath<ZwithSubscript, Int>,
rkp: ReferenceWritableKeyPath<ZwithSubscript, Int>) {
@@ -312,6 +315,12 @@
readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign to immutable}}
// FIXME: silently falls back to keypath application, which seems inconsistent
writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}}
+
+ _ = wrongType[keyPath: kp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: wkp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: rkp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: pkp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: akp]
}
func testKeyPathSubscriptMetatype(readonly: Z.Type, writable: inout Z.Type,
@@ -358,10 +367,33 @@
_ = base[keyPath: kp]
}
-func testKeyPathSubscriptExistentialBase(base: B, kp: KeyPath<P, String>) {
- _ = base[keyPath: kp]
-}
+func testKeyPathSubscriptExistentialBase(concreteBase: inout B,
+ existentialBase: inout P,
+ kp: KeyPath<P, String>,
+ wkp: WritableKeyPath<P, String>,
+ rkp: ReferenceWritableKeyPath<P, String>,
+ pkp: PartialKeyPath<P>,
+ s: String) {
+ _ = concreteBase[keyPath: kp]
+ _ = concreteBase[keyPath: wkp]
+ _ = concreteBase[keyPath: rkp]
+ _ = concreteBase[keyPath: pkp]
+ concreteBase[keyPath: kp] = s // expected-error{{}}
+ concreteBase[keyPath: wkp] = s // expected-error{{}}
+ concreteBase[keyPath: rkp] = s
+ concreteBase[keyPath: pkp] = s // expected-error{{}}
+
+ _ = existentialBase[keyPath: kp]
+ _ = existentialBase[keyPath: wkp]
+ _ = existentialBase[keyPath: rkp]
+ _ = existentialBase[keyPath: pkp]
+
+ existentialBase[keyPath: kp] = s // expected-error{{}}
+ existentialBase[keyPath: wkp] = s
+ existentialBase[keyPath: rkp] = s
+ existentialBase[keyPath: pkp] = s // expected-error{{}}
+}
struct AA {
subscript(x: Int) -> Int { return x }
diff --git a/test/expr/unary/keypath/salvage-with-other-type-errors.swift b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
index e035613..7a6af78 100644
--- a/test/expr/unary/keypath/salvage-with-other-type-errors.swift
+++ b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
@@ -52,6 +52,7 @@
extension Bindable {
func test<Value>(to targetKeyPath: ReferenceWritableKeyPath<Self, Value>, change: Value?) {
if self[keyPath:targetKeyPath] != change { // expected-error{{}}
+ // expected-note@-1{{overloads for '!=' exist with these partially matching parameter lists: (Self, Self), (_OptionalNilComparisonType, Wrapped?)}}
self[keyPath: targetKeyPath] = change!
}
}
diff --git a/test/expr/unary/selector/selector.swift b/test/expr/unary/selector/selector.swift
index 127d1cf..7b7a468 100644
--- a/test/expr/unary/selector/selector.swift
+++ b/test/expr/unary/selector/selector.swift
@@ -134,7 +134,7 @@
}
switch optionalSel {
-case #selector(SR1827.bar): // expected-error{{expression pattern of type 'Selector' cannot match values of type 'Selector?'}} {{27-27=?}}
+case #selector(SR1827.bar):
break
case #selector(SR1827.bar)!: // expected-error{{cannot force unwrap value of non-optional type 'Selector'}}
break
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L2-5.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L2-5.swift.expected
new file mode 100644
index 0000000..4f6768a
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L2-5.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+
+
+ func methodWithParameters(param1: Foo, param2: Foo) {
+ }
+
+ @discardableResult
+ private func privateMethodWithAnnotation() -> Foo? {
+ return nil
+ }
+
+ var anInstanceVariable: String?
+
+ func justAnotherMethod() {
+ }
+}
+
+extension Foo {
+/// This is just some documentation
+ func methodWithoutParameters() {
+ }
+}
+
+class OtherClass {
+ func foo() {
+ }
+
+ var computedVariable: Int {
+ return 0
+ }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L24-27.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L24-27.swift.expected
new file mode 100644
index 0000000..b28cecb
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L24-27.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+ /// This is just some documentation
+ func methodWithoutParameters() {
+ }
+
+ func methodWithParameters(param1: Foo, param2: Foo) {
+ }
+
+ @discardableResult
+ private func privateMethodWithAnnotation() -> Foo? {
+ return nil
+ }
+
+ var anInstanceVariable: String?
+
+ func justAnotherMethod() {
+ }
+}
+
+class OtherClass {
+ func foo() {
+ }
+
+
+}
+
+extension OtherClass {
+var computedVariable: Int {
+ return 0
+ }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L3-13.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L3-13.swift.expected
new file mode 100644
index 0000000..6606d15
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L3-13.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+
+
+ var anInstanceVariable: String?
+
+ func justAnotherMethod() {
+ }
+}
+
+extension Foo {
+/// This is just some documentation
+ func methodWithoutParameters() {
+ }
+
+ func methodWithParameters(param1: Foo, param2: Foo) {
+ }
+
+ @discardableResult
+ private func privateMethodWithAnnotation() -> Foo? {
+ return nil
+ }
+}
+
+class OtherClass {
+ func foo() {
+ }
+
+ var computedVariable: Int {
+ return 0
+ }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L3-5.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L3-5.swift.expected
new file mode 100644
index 0000000..4f6768a
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L3-5.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+
+
+ func methodWithParameters(param1: Foo, param2: Foo) {
+ }
+
+ @discardableResult
+ private func privateMethodWithAnnotation() -> Foo? {
+ return nil
+ }
+
+ var anInstanceVariable: String?
+
+ func justAnotherMethod() {
+ }
+}
+
+extension Foo {
+/// This is just some documentation
+ func methodWithoutParameters() {
+ }
+}
+
+class OtherClass {
+ func foo() {
+ }
+
+ var computedVariable: Int {
+ return 0
+ }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/Outputs/L6-8.swift.expected b/test/refactoring/MoveMembersToExtension/Outputs/L6-8.swift.expected
new file mode 100644
index 0000000..5d2b19a
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/Outputs/L6-8.swift.expected
@@ -0,0 +1,32 @@
+class Foo {
+ /// This is just some documentation
+ func methodWithoutParameters() {
+ }
+
+
+
+ @discardableResult
+ private func privateMethodWithAnnotation() -> Foo? {
+ return nil
+ }
+
+ var anInstanceVariable: String?
+
+ func justAnotherMethod() {
+ }
+}
+
+extension Foo {
+func methodWithParameters(param1: Foo, param2: Foo) {
+ }
+}
+
+class OtherClass {
+ func foo() {
+ }
+
+ var computedVariable: Int {
+ return 0
+ }
+}
+
diff --git a/test/refactoring/MoveMembersToExtension/basic.swift b/test/refactoring/MoveMembersToExtension/basic.swift
new file mode 100644
index 0000000..a485a9b
--- /dev/null
+++ b/test/refactoring/MoveMembersToExtension/basic.swift
@@ -0,0 +1,48 @@
+class Foo {
+ /// This is just some documentation
+ func methodWithoutParameters() {
+ }
+
+ func methodWithParameters(param1: Foo, param2: Foo) {
+ }
+
+ @discardableResult
+ private func privateMethodWithAnnotation() -> Foo? {
+ return nil
+ }
+
+ var anInstanceVariable: String?
+
+ func justAnotherMethod() {
+ }
+}
+
+class OtherClass {
+ func foo() {
+ }
+
+ var computedVariable: Int {
+ return 0
+ }
+}
+
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=2:1 -end-pos=5:1 > %t.result/L2-5.swift
+// RUN: diff -u %S/Outputs/L2-5.swift.expected %t.result/L2-5.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=3:1 -end-pos=5:1 > %t.result/L3-5.swift
+// RUN: diff -u %S/Outputs/L3-5.swift.expected %t.result/L3-5.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=6:1 -end-pos=8:1 > %t.result/L6-8.swift
+// RUN: diff -u %S/Outputs/L6-8.swift.expected %t.result/L6-8.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=3:1 -end-pos=13:1 > %t.result/L3-13.swift
+// RUN: diff -u %S/Outputs/L3-13.swift.expected %t.result/L3-13.swift
+// RUN: rm -rf %t.result && mkdir -p %t.result
+// RUN: %refactor -move-to-extension -source-filename %s -pos=24:1 -end-pos=27:1 > %t.result/L24-27.swift
+// RUN: diff -u %S/Outputs/L24-27.swift.expected %t.result/L24-27.swift
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=3:1 -end-pos=4:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=4:1 -end-pos=8:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=1:1 -end-pos=14:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=14:1 -end-pos=15:1
+// RUN: not %refactor -move-to-extension -source-filename %s -pos=15:1 -end-pos=23:1
diff --git a/test/stdlib/AppKit_Swift3.swift b/test/stdlib/AppKit_Swift3.swift
index 30432c2..07dbebc 100644
--- a/test/stdlib/AppKit_Swift3.swift
+++ b/test/stdlib/AppKit_Swift3.swift
@@ -17,4 +17,36 @@
expectEqual(eventMask, .keyDown)
}
+AppKitTests.test("NSLayoutPriority") {
+ let highPriority: NSLayoutPriority = NSLayoutPriorityDefaultHigh
+
+ let adjustedPriority1 = highPriority + 1
+ let adjustedPriority1RawValue: Float = NSLayoutPriorityDefaultHigh + 1
+ expectEqual(adjustedPriority1, adjustedPriority1RawValue)
+
+ let adjustedPriority2 = highPriority - 5.0
+ let adjustedPriority2RawValue: Float = NSLayoutPriorityDefaultHigh - 5.0
+ expectEqual(adjustedPriority2, adjustedPriority2RawValue)
+
+ let adjustedPriority3 = 5.0 + highPriority
+ let adjustedPriority3RawValue: Float = 5.0 + NSLayoutPriorityDefaultHigh
+ expectEqual(adjustedPriority3, adjustedPriority3RawValue)
+
+ // Inferred typing from result type
+ let adjustedPriority4: NSLayoutPriority = NSLayoutPriorityDefaultHigh + 2.0
+ let adjustedPriority4RawValue: Float = NSLayoutPriorityDefaultHigh + 2.0
+ expectEqual(adjustedPriority4, adjustedPriority4RawValue)
+
+ // Comparable
+ expectTrue(adjustedPriority1 > adjustedPriority2)
+ expectTrue(adjustedPriority2 < adjustedPriority1)
+
+ // Compound assignment
+ var variablePriority: NSLayoutPriority = NSLayoutPriorityDefaultHigh
+ variablePriority += 1
+ variablePriority -= 5.0
+ let variablePriorityRawValue: Float = NSLayoutPriorityDefaultHigh + 1 - 5.0
+ expectEqual(variablePriority, variablePriorityRawValue)
+}
+
runAllTests()
diff --git a/test/stdlib/AppKit_Swift4.swift b/test/stdlib/AppKit_Swift4.swift
index 78406fd..843396e 100644
--- a/test/stdlib/AppKit_Swift4.swift
+++ b/test/stdlib/AppKit_Swift4.swift
@@ -105,4 +105,36 @@
}
}
+AppKitTests.test("NSLayoutPriority") {
+ let highPriority: NSLayoutConstraint.Priority = .defaultHigh
+
+ let adjustedPriority1 = highPriority + 1
+ let adjustedPriority1RawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue + 1
+ expectEqual(adjustedPriority1.rawValue, adjustedPriority1RawValue)
+
+ let adjustedPriority2 = highPriority - 5.0
+ let adjustedPriority2RawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue - 5.0
+ expectEqual(adjustedPriority2.rawValue, adjustedPriority2RawValue)
+
+ let adjustedPriority3 = 5.0 + highPriority
+ let adjustedPriority3RawValue: Float = 5.0 + NSLayoutConstraint.Priority.defaultHigh.rawValue
+ expectEqual(adjustedPriority3.rawValue, adjustedPriority3RawValue)
+
+ // Inferred typing from result type
+ let adjustedPriority4: NSLayoutConstraint.Priority = .defaultHigh + 2.0
+ let adjustedPriority4RawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue + 2.0
+ expectEqual(adjustedPriority4.rawValue, adjustedPriority4RawValue)
+
+ // Comparable
+ expectTrue(adjustedPriority1 > adjustedPriority2)
+ expectTrue(adjustedPriority2 < adjustedPriority1)
+
+ // Compound assignment
+ var variablePriority: NSLayoutConstraint.Priority = .defaultHigh
+ variablePriority += 1
+ variablePriority -= 5.0
+ let variablePriorityRawValue: Float = NSLayoutConstraint.Priority.defaultHigh.rawValue + 1 - 5.0
+ expectEqual(variablePriority.rawValue, variablePriorityRawValue)
+}
+
runAllTests()
diff --git a/test/stdlib/ArrayDiagnostics.swift b/test/stdlib/ArrayDiagnostics.swift
index d1f6f6b..144a107 100644
--- a/test/stdlib/ArrayDiagnostics.swift
+++ b/test/stdlib/ArrayDiagnostics.swift
@@ -5,7 +5,8 @@
func test_ArrayOfNotEquatableIsNotEquatable() {
var a = [ NotEquatable(), NotEquatable() ]
// FIXME: This is an awful error.
- if a == a {} // expected-error {{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+ if a == a {} // expected-error {{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+ // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+ // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
}
diff --git a/test/stdlib/Intents.swift b/test/stdlib/Intents.swift
index de7a3fd..d0b19bf 100644
--- a/test/stdlib/Intents.swift
+++ b/test/stdlib/Intents.swift
@@ -75,4 +75,32 @@
}
#endif
+#if os(iOS)
+if #available(iOS 11.0, *) {
+ IntentsTestSuite.test("INSetProfileInCarIntent Initializers/\(swiftVersion)") {
+#if swift(>=4)
+ _ = INSetProfileInCarIntent()
+ _ = INSetProfileInCarIntent(isDefaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileName: nil)
+ _ = INSetProfileInCarIntent(profileName: nil, isDefaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, isDefaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, profileName: nil)
+ _ = INSetProfileInCarIntent(
+ profileNumber: nil, profileName: nil, isDefaultProfile: nil)
+#else
+ _ = INSetProfileInCarIntent()
+ _ = INSetProfileInCarIntent(defaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileName: nil)
+ _ = INSetProfileInCarIntent(profileName: nil, defaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, defaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, profileName: nil)
+ _ = INSetProfileInCarIntent(
+ profileNumber: nil, profileName: nil, defaultProfile: nil)
+#endif
+ }
+}
+#endif
+
runAllTests()
diff --git a/test/stdlib/KeyPathImplementation.swift b/test/stdlib/KeyPathImplementation.swift
index 8ccde01..8151dc1 100644
--- a/test/stdlib/KeyPathImplementation.swift
+++ b/test/stdlib/KeyPathImplementation.swift
@@ -12,8 +12,7 @@
return (offset + alignMask) & ~alignMask
}
-// FIXME: Object header size will eventually be MemoryLayout<Int>.size * 2
-let classHeaderSize = MemoryLayout<Int>.size + 8
+let classHeaderSize = MemoryLayout<Int>.size * 2
class C<T> {
var x: Int
diff --git a/test/stdlib/StringDiagnostics.swift b/test/stdlib/StringDiagnostics.swift
index 2712ee3..1d36b11 100644
--- a/test/stdlib/StringDiagnostics.swift
+++ b/test/stdlib/StringDiagnostics.swift
@@ -53,6 +53,9 @@
let a10 = nsString <= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
let a11 = nsString >= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
let a12 = nsString > s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
+
+ // Shouldn't suggest 'as' in a pattern-matching context, as opposed to all these other situations
+ if case nsString = "" {} // expected-error{{expression pattern of type 'NSString' cannot match values of type 'String'}}
}
func testStringDeprecation(hello: String) {
diff --git a/test/stdlib/TestData.swift b/test/stdlib/TestData.swift
index 70792c1..6910166 100644
--- a/test/stdlib/TestData.swift
+++ b/test/stdlib/TestData.swift
@@ -3677,6 +3677,50 @@
let h3 = d3.hashValue
expectEqual(h1, h3)
}
+
+ func test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+ var data = Data(bytes: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])[4..<6]
+ data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+ ptr.advanced(by: 1).pointee = 0xFF
+ }
+ expectEqual(data, Data(bytes: [4, 0xFF]))
+ }
+
+ func test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+ var data = Data(referencing: NSData(bytes: "hello world", length: 11))[4..<6]
+ data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+ ptr.advanced(by: 1).pointee = 0xFF
+ }
+ expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+ }
+
+ func test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+ var base = Data(referencing: NSData(bytes: "hello world", length: 11))
+ base.append(contentsOf: [1, 2, 3, 4, 5, 6])
+ var data = base[4..<6]
+ data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+ ptr.advanced(by: 1).pointee = 0xFF
+ }
+ expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+ }
+
+ func test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+ var data = Data(referencing: AllOnesImmutableData(length: 10))[4..<6]
+ data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+ ptr.advanced(by: 1).pointee = 0xFF
+ }
+ expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+ }
+
+ func test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() {
+ var base = Data(referencing: AllOnesData(length: 1))
+ base.count = 10
+ var data = base[4..<6]
+ data.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) in
+ ptr.advanced(by: 1).pointee = 0xFF
+ }
+ expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
+ }
}
#if !FOUNDATION_XCTEST
@@ -3988,6 +4032,11 @@
DataTests.test("test_slice_resize_growth") { TestData().test_slice_resize_growth() }
DataTests.test("test_sliceEnumeration") { TestData().test_sliceEnumeration() }
DataTests.test("test_hashEmptyData") { TestData().test_hashEmptyData() }
+DataTests.test("test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_immutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
// XCTest does not have a crash detection, whereas lit does
DataTests.test("bounding failure subdata") {
diff --git a/test/stdlib/TestJSONEncoder.swift b/test/stdlib/TestJSONEncoder.swift
index 5ed50b8..b0bf177 100644
--- a/test/stdlib/TestJSONEncoder.swift
+++ b/test/stdlib/TestJSONEncoder.swift
@@ -478,6 +478,22 @@
_testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self)
}
+ func testDecodingConcreteTypeParameter() {
+ let encoder = JSONEncoder()
+ guard let json = try? encoder.encode(Employee.testValue) else {
+ expectUnreachable("Unable to encode Employee.")
+ return
+ }
+
+ let decoder = JSONDecoder()
+ guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: json) else {
+ expectUnreachable("Failed to decode Employee as Person from JSON.")
+ return
+ }
+
+ expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.")
+ }
+
// MARK: - Helper Functions
private var _jsonEmptyDictionary: Data {
return "{}".data(using: .utf8)!
@@ -1104,5 +1120,6 @@
JSONEncoderTests.test("testInterceptDecimal") { TestJSONEncoder().testInterceptDecimal() }
JSONEncoderTests.test("testInterceptURL") { TestJSONEncoder().testInterceptURL() }
JSONEncoderTests.test("testTypeCoercion") { TestJSONEncoder().testTypeCoercion() }
+JSONEncoderTests.test("testDecodingConcreteTypeParameter") { TestJSONEncoder().testDecodingConcreteTypeParameter() }
runAllTests()
#endif
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index f5c4685..489261a 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -522,7 +522,7 @@
let float = (number!) as? Float
let expectedFloat = Float(uint32!)
// these are disabled because of https://bugs.swift.org/browse/SR-4634
- if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+ if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
testFloat(expectedFloat, float)
}
@@ -658,16 +658,16 @@
let uint = (number!) as? UInt
expectEqual(UInt(exactly: interestingValue), uint)
- // these are disabled because of https://bugs.swift.org/browse/SR-4634
- if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
- let float = (number!) as? Float
- let expectedFloat = Float(uint!)
- testFloat(expectedFloat, float)
+ let float = (number!) as? Float
+ let expectedFloat = Float(exactly: uint!)
+ if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+ expectNil(expectedFloat)
+ } else {
+ testFloat(expectedFloat, float)
}
-
-
+
let double = (number!) as? Double
- let expectedDouble = Double(uint!)
+ let expectedDouble = Double(exactly: uint!)
testDouble(expectedDouble, double)
}
let bridged = interestingValue as NSNumber
diff --git a/test/stdlib/TestPlistEncoder.swift b/test/stdlib/TestPlistEncoder.swift
index d7b037b..d38ef76 100644
--- a/test/stdlib/TestPlistEncoder.swift
+++ b/test/stdlib/TestPlistEncoder.swift
@@ -198,6 +198,22 @@
_testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self)
}
+ func testDecodingConcreteTypeParameter() {
+ let encoder = PropertyListEncoder()
+ guard let plist = try? encoder.encode(Employee.testValue) else {
+ expectUnreachable("Unable to encode Employee.")
+ return
+ }
+
+ let decoder = PropertyListDecoder()
+ guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: plist) else {
+ expectUnreachable("Failed to decode Employee as Person from plist.")
+ return
+ }
+
+ expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.")
+ }
+
// MARK: - Helper Functions
private var _plistEmptyDictionaryBinary: Data {
return Data(base64Encoded: "YnBsaXN0MDDQCAAAAAAAAAEBAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJ")!
@@ -731,5 +747,6 @@
PropertyListEncoderTests.test("testInterceptData") { TestPropertyListEncoder().testInterceptData() }
PropertyListEncoderTests.test("testInterceptDate") { TestPropertyListEncoder().testInterceptDate() }
PropertyListEncoderTests.test("testTypeCoercion") { TestPropertyListEncoder().testTypeCoercion() }
+PropertyListEncoderTests.test("testDecodingConcreteTypeParameter") { TestPropertyListEncoder().testDecodingConcreteTypeParameter() }
runAllTests()
#endif
diff --git a/test/stdlib/UIKit.swift b/test/stdlib/UIKit.swift
index 800668d..a5703ff 100644
--- a/test/stdlib/UIKit.swift
+++ b/test/stdlib/UIKit.swift
@@ -1,13 +1,21 @@
-// RUN: %target-run-simple-swift
+// RUN: rm -rf %t && mkdir -p %t
+// RUN: %target-build-swift -swift-version 3 %s -o %t/a.out3 && %target-run %t/a.out3
+// RUN: %target-build-swift -swift-version 4 %s -o %t/a.out4 && %target-run %t/a.out4
// REQUIRES: executable_test
-// REQUIRES: OS=ios
+// UNSUPPORTED: OS=macosx
+// REQUIRES: objc_interop
import UIKit
import StdlibUnittest
import StdlibUnittestFoundationExtras
-let UIKitTests = TestSuite("UIKit")
+#if swift(>=4)
+ let UIKitTests = TestSuite("UIKit_Swift4")
+#else
+ let UIKitTests = TestSuite("UIKit_Swift3")
+#endif
+#if !os(watchOS) && !os(tvOS)
private func printDevice(_ o: UIDeviceOrientation) -> String {
var s = "\(o.isPortrait) \(UIDeviceOrientationIsPortrait(o)), "
s += "\(o.isLandscape) \(UIDeviceOrientationIsLandscape(o)), "
@@ -60,6 +68,7 @@
expectEqual("false false, true true",
printInterface(.landscapeRight))
}
+#endif
UIKitTests.test("UIEdgeInsets") {
let insets = [
@@ -79,6 +88,66 @@
checkEquatable(offsets, oracle: { $0 == $1 })
}
+UIKitTests.test("UIFont.Weight") {
+ guard #available(iOS 8.2, *) else { return }
+ #if swift(>=4) // Swift 4
+ let regularFontWeight: UIFont.Weight = .regular
+
+ expectTrue(regularFontWeight == .regular)
+ expectTrue(regularFontWeight > .light)
+ expectTrue(regularFontWeight < .heavy)
+ expectTrue(regularFontWeight + 0.1 == 0.1 + regularFontWeight)
+ #else // Swift 3
+ let regularFontWeight: UIFontWeight = UIFontWeightRegular
+
+ expectTrue(regularFontWeight == UIFontWeightRegular)
+ expectTrue(regularFontWeight > UIFontWeightLight)
+ expectTrue(regularFontWeight < UIFontWeightHeavy)
+ expectTrue(regularFontWeight + 0.1 == 0.1 + UIFontWeightRegular)
+ #endif
+}
+
+#if !os(watchOS)
+UIKitTests.test("UILayoutPriority") {
+ #if swift(>=4) // Swift 4
+ let lowLayoutPriority: UILayoutPriority = .defaultLow
+ let highLayoutPriority: UILayoutPriority = .defaultHigh
+
+ expectTrue(lowLayoutPriority < highLayoutPriority)
+
+ expectTrue(lowLayoutPriority + 2.0 == UILayoutPriority(lowLayoutPriority.rawValue + 2.0))
+ expectTrue(2.0 + lowLayoutPriority == UILayoutPriority(lowLayoutPriority.rawValue + 2.0))
+ expectTrue(lowLayoutPriority - 2.0 == UILayoutPriority(lowLayoutPriority.rawValue - 2.0))
+ expectTrue(highLayoutPriority - lowLayoutPriority == highLayoutPriority.rawValue - lowLayoutPriority.rawValue)
+
+ expectTrue(lowLayoutPriority + (highLayoutPriority - lowLayoutPriority) == highLayoutPriority)
+
+ var mutablePriority = lowLayoutPriority
+ mutablePriority -= 1.0
+ mutablePriority += 2.0
+ expectTrue(mutablePriority == lowLayoutPriority + 1.0)
+
+ let priorotyRange = lowLayoutPriority...highLayoutPriority
+ expectTrue(priorotyRange.contains(.defaultLow))
+ expectFalse(priorotyRange.contains(.required))
+ #else // Swift 3
+ let lowLayoutPriority: UILayoutPriority = UILayoutPriorityDefaultLow
+ let highLayoutPriority: UILayoutPriority = UILayoutPriorityDefaultHigh
+
+ expectTrue(lowLayoutPriority < highLayoutPriority)
+
+ expectTrue(2.0 + lowLayoutPriority == lowLayoutPriority + 2.0)
+ expectTrue(lowLayoutPriority + (highLayoutPriority - lowLayoutPriority) == highLayoutPriority)
+
+ var mutablePriority = lowLayoutPriority
+ mutablePriority -= 1.0
+ mutablePriority += 2.0
+ expectTrue(mutablePriority == lowLayoutPriority + 1.0)
+ #endif
+}
+#endif
+
+#if !os(watchOS)
class TestChildView : UIView, CustomPlaygroundQuickLookable {
convenience init() {
self.init(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
@@ -95,6 +164,7 @@
"TestChildView custom quicklookable should have been invoked")
}
}
+#endif
UIKitTests.test("NSValue bridging") {
expectBridgeToNSValue(UIEdgeInsets(top: 17, left: 38, bottom: 6, right: 79),
diff --git a/test/stdlib/UnsafeRawBufferPointer.swift b/test/stdlib/UnsafeRawBufferPointer.swift
index a5f5897..442f6fc 100644
--- a/test/stdlib/UnsafeRawBufferPointer.swift
+++ b/test/stdlib/UnsafeRawBufferPointer.swift
@@ -100,7 +100,10 @@
let buffer = UnsafeMutableRawBufferPointer.allocate(count: 30)
defer { buffer.deallocate() }
let source = stride(from: 5 as Int64, to: 0, by: -1)
- var (it,bound) = buffer.initializeMemory(as: Int64.self, from: source)
+ if _isDebugAssertConfiguration() {
+ expectCrashLater()
+ }
+ var (it, bound) = buffer.initializeMemory(as: Int64.self, from: source)
let idx = bound.endIndex * MemoryLayout<Int64>.stride
expectEqual(it.next()!, 2)
expectEqual(idx, 24)
diff --git a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
index 2efa730..7b487bc 100644
--- a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
+++ b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
@@ -283,6 +283,8 @@
KIND(RangeSingleExpression, "source.lang.swift.range.singleexpression")
KIND(RangeSingleDeclaration, "source.lang.swift.range.singledeclaration")
KIND(RangeMultiStatement, "source.lang.swift.range.multistatement")
+KIND(RangeMultiTypeMemberDeclaration,
+ "source.lang.swift.range.multitypememberdeclaration")
KIND(RangeInvalid, "source.lang.swift.range.invalid")
KIND(NameObjc, "source.lang.name.kind.objc")
KIND(NameSwift, "source.lang.name.kind.swift")
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 22f3457..7848c72 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -377,6 +377,8 @@
continue;
if (Arg == "-c")
continue;
+ if (Arg == "-v")
+ continue;
if (Arg == "-Xfrontend")
continue;
if (Arg == "-embed-bitcode")
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 4ffea4c..9be32b6 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -21,11 +21,11 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/GenericSignature.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/IDE/Refactoring.h"
// This is included only for createLazyResolver(). Move to different header ?
@@ -346,7 +346,7 @@
if (DefaultImplementationOf) {
llvm::raw_svector_ostream OS(Info.ProvideImplementationOfUSR);
- SwiftLangSupport::printUSR((ValueDecl*)DefaultImplementationOf, OS);
+ SwiftLangSupport::printUSR((const ValueDecl*)DefaultImplementationOf, OS);
}
Info.IsUnavailable = AvailableAttr::isUnavailable(D);
@@ -369,13 +369,13 @@
assert(DocRef.find(Open) != StringRef::npos);
auto FirstPart = DocRef.substr(0, DocRef.find(Open) + (Open).size());
auto SecondPart = DocRef.substr(FirstPart.size());
- auto ExtendedName = ((ExtensionDecl*)D)->getExtendedType()->
+ auto ExtendedName = ((const ExtensionDecl*)D)->getExtendedType()->
getAnyNominal()->getName().str();
assert(SecondPart.startswith(ExtendedName));
SecondPart = SecondPart.substr(ExtendedName.size());
llvm::SmallString<128> UpdatedDocBuffer;
UpdatedDocBuffer.append(FirstPart);
- UpdatedDocBuffer.append(((NominalTypeDecl*)SynthesizedTarget)->getName().
+ UpdatedDocBuffer.append(((const NominalTypeDecl*)SynthesizedTarget)->getName().
str());
UpdatedDocBuffer.append(SecondPart);
OS << UpdatedDocBuffer;
@@ -522,7 +522,7 @@
return;
if (const auto *ED = dyn_cast<ExtensionDecl>(D)) {
if (SynthesizedTarget) {
- passExtends((ValueDecl*)SynthesizedTarget, Consumer);
+ passExtends((const ValueDecl*)SynthesizedTarget, Consumer);
} else if (Type T = ED->getExtendedType()) {
if (auto TD = getTypeDeclFromType(T))
passExtends(TD, Consumer);
@@ -1041,10 +1041,11 @@
}
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override {
// Treat both open and close brackets equally
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
bool isLocal(Decl *D) const {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 397f25b..4471725 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -23,7 +23,6 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/Basic/SourceManager.h"
@@ -33,6 +32,7 @@
#include "swift/IDE/CodeCompletion.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/Formatting.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/Subsystems.h"
@@ -876,10 +876,11 @@
}
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override {
// We should treat both open and close brackets equally
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
void annotate(const Decl *D, bool IsRef, CharSourceRange Range) {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 8c4a44a..563177b 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -451,6 +451,8 @@
case swift::ide::RangeKind::SingleStatement: return KindRangeSingleStatement;
case swift::ide::RangeKind::SingleDecl: return KindRangeSingleDeclaration;
case swift::ide::RangeKind::MultiStatement: return KindRangeMultiStatement;
+ case swift::ide::RangeKind::MultiTypeMemberDecl:
+ return KindRangeMultiTypeMemberDeclaration;
case swift::ide::RangeKind::PartOfExpression: return KindRangeInvalid;
case swift::ide::RangeKind::Invalid: return KindRangeInvalid;
}
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 7993900..a96492b 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -19,13 +19,13 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/SwiftNameTranslation.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/Utils.h"
#include "swift/IDE/Refactoring.h"
#include "swift/Markup/XMLUtils.h"
@@ -1515,6 +1515,7 @@
return;
}
case RangeKind::SingleDecl:
+ case RangeKind::MultiTypeMemberDecl:
case RangeKind::MultiStatement:
case RangeKind::SingleStatement: {
Receiver(Result);
diff --git a/tools/SwiftSyntax/SwiftSyntax.swift b/tools/SwiftSyntax/SwiftSyntax.swift
index 343f705..c3a3244 100644
--- a/tools/SwiftSyntax/SwiftSyntax.swift
+++ b/tools/SwiftSyntax/SwiftSyntax.swift
@@ -37,12 +37,10 @@
throw ParserError.swiftcFailed(result.exitCode, result.stderr)
}
let decoder = JSONDecoder()
- let raw = try decoder.decode([RawSyntax].self, from: result.stdoutData)
- let topLevelNodes = raw.map { Syntax.fromRaw($0) }
- let eof = topLevelNodes.last! as! TokenSyntax
- let decls = Array(topLevelNodes.dropLast()) as! [DeclSyntax]
- let declList = SyntaxFactory.makeDeclList(decls)
- return SyntaxFactory.makeSourceFile(topLevelDecls: declList,
- eofToken: eof)
+ let raw = try decoder.decode(RawSyntax.self, from: result.stdoutData)
+ guard let file = Syntax.fromRaw(raw) as? SourceFileSyntax else {
+ throw ParserError.invalidFile
+ }
+ return file
}
}
diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp
index 701113a..0a812af 100644
--- a/tools/sil-func-extractor/SILFunctionExtractor.cpp
+++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp
@@ -254,34 +254,15 @@
Invocation.getLangOptions().EnableAccessControl = false;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size()
- ? StringRef(ModuleName)
- : llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- Invocation.setModuleName("main");
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
SILOptions &SILOpts = Invocation.getSILOptions();
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
@@ -300,7 +281,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(
diff --git a/tools/sil-llvm-gen/SILLLVMGen.cpp b/tools/sil-llvm-gen/SILLLVMGen.cpp
index c04f619..5498216 100644
--- a/tools/sil-llvm-gen/SILLLVMGen.cpp
+++ b/tools/sil-llvm-gen/SILLLVMGen.cpp
@@ -167,35 +167,15 @@
Opts.OutputFilenames.push_back(OutputFilename);
Opts.OutputKind = OutputKind;
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size()
- ? StringRef(ModuleName)
- : llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
- Invocation.setModuleName(Name);
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
CompilerInstance CI;
PrintingDiagnosticConsumer PrintDiags;
CI.addDiagnosticConsumer(&PrintDiags);
@@ -216,7 +196,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(SILModule::createEmptyModule(
diff --git a/tools/sil-nm/SILNM.cpp b/tools/sil-nm/SILNM.cpp
index ec5df3c..b3eddc9 100644
--- a/tools/sil-nm/SILNM.cpp
+++ b/tools/sil-nm/SILNM.cpp
@@ -168,34 +168,15 @@
Invocation.getLangOptions().EnableAccessControl = false;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size()
- ? StringRef(ModuleName)
- : llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- Invocation.setModuleName("main");
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
SILOptions &SILOpts = Invocation.getSILOptions();
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
@@ -214,7 +195,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index d7d5e66..b222dcd 100644
--- a/tools/sil-opt/SILOpt.cpp
+++ b/tools/sil-opt/SILOpt.cpp
@@ -311,7 +311,7 @@
SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts;
SILOpts.AssertConfig = AssertConfId;
if (OptimizationGroup != OptGroup::Diagnostics)
- SILOpts.Optimization = SILOptions::SILOptMode::Optimize;
+ SILOpts.OptMode = OptimizationMode::ForSpeed;
SILOpts.EnableSILOwnership = EnableSILOwnershipOpt;
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
@@ -342,35 +342,15 @@
}
}
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size() ?
- StringRef(ModuleName) :
- llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
- Invocation.setModuleName(Name);
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
CompilerInstance CI;
PrintingDiagnosticConsumer PrintDiags;
CI.addDiagnosticConsumer(&PrintDiags);
@@ -391,7 +371,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(SILModule::createEmptyModule(
diff --git a/tools/swift-api-digester/swift-api-digester.cpp b/tools/swift-api-digester/swift-api-digester.cpp
index 5cf9e47..943ae43 100644
--- a/tools/swift-api-digester/swift-api-digester.cpp
+++ b/tools/swift-api-digester/swift-api-digester.cpp
@@ -1282,6 +1282,9 @@
return true;
if (VD->getBaseName().empty())
return true;
+ // This shouldn't happen, being forgiving here.
+ if (!VD->hasAccess())
+ return true;
switch (VD->getFormalAccess()) {
case AccessLevel::Internal:
case AccessLevel::Private:
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index abb6af8..2b18f5c 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -22,7 +22,6 @@
#include "swift/AST/ASTMangler.h"
#include "swift/AST/PrintOptions.h"
#include "swift/AST/RawComment.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Basic/LangOptions.h"
@@ -35,6 +34,7 @@
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
#include "swift/IDE/REPLCodeCompletion.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/IDE/Utils.h"
#include "swift/Index/Index.h"
@@ -1264,9 +1264,10 @@
}
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override {
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
bool visitCallArgName(Identifier Name, CharSourceRange Range,
diff --git a/tools/swift-llvm-opt/LLVMOpt.cpp b/tools/swift-llvm-opt/LLVMOpt.cpp
index d3d9f05..cba627f 100644
--- a/tools/swift-llvm-opt/LLVMOpt.cpp
+++ b/tools/swift-llvm-opt/LLVMOpt.cpp
@@ -302,7 +302,7 @@
if (Optimized) {
IRGenOptions Opts;
- Opts.Optimize = true;
+ Opts.OptMode = OptimizationMode::ForSpeed;
// Then perform the optimizations.
performLLVMOptimizations(Opts, M.get(), TM.get());
diff --git a/tools/swift-refactor/swift-refactor.cpp b/tools/swift-refactor/swift-refactor.cpp
index 10613bb..fc048f6 100644
--- a/tools/swift-refactor/swift-refactor.cpp
+++ b/tools/swift-refactor/swift-refactor.cpp
@@ -50,6 +50,8 @@
"strings-concatenation-to-interpolation", "Perform strings concatenation to interpolation refactoring"),
clEnumValN(RefactoringKind::ExtractFunction,
"extract-function", "Perform extract function refactoring"),
+ clEnumValN(RefactoringKind::MoveMembersToExtension,
+ "move-to-extension", "Move selected members to an extension"),
clEnumValN(RefactoringKind::GlobalRename,
"syntactic-rename", "Perform syntactic rename"),
clEnumValN(RefactoringKind::FindGlobalRenameRanges,
diff --git a/unittests/Reflection/TypeRef.cpp b/unittests/Reflection/TypeRef.cpp
index 29d943f..c736ce5 100644
--- a/unittests/Reflection/TypeRef.cpp
+++ b/unittests/Reflection/TypeRef.cpp
@@ -147,7 +147,7 @@
EXPECT_NE(F4, F1);
// Test parameter with and without inout/shared/variadic and/or label.
- ParameterTypeFlags paramFlags;
+ ParameterFlags paramFlags;
auto inoutFlags = paramFlags.withInOut(true);
auto variadicFlags = paramFlags.withVariadic(true);
auto sharedFlags = paramFlags.withShared(true);
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index 32c4c20..f9b897e 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -938,17 +938,27 @@
// Tests for resilient witness table instantiation, with runtime-provided
// default requirements
+struct WitnessTableSlice {
+ WitnessTable **tables;
+ size_t count;
+};
+
static void witnessTableInstantiator(WitnessTable *instantiatedTable,
const Metadata *type,
void * const *instantiationArgs) {
EXPECT_EQ(type, nullptr);
- EXPECT_EQ(instantiationArgs, nullptr);
EXPECT_EQ(((void **) instantiatedTable)[0], (void*) 123);
EXPECT_EQ(((void **) instantiatedTable)[1], (void*) 234);
// The last witness is computed dynamically at instantiation time.
((void **) instantiatedTable)[2] = (void *) 345;
+
+ auto conditionalTables = (WitnessTableSlice *)instantiationArgs;
+
+ EXPECT_EQ(conditionalTables->count, 1UL);
+ EXPECT_EQ(conditionalTables->tables[0], (void *)678);
+ ((void **)instantiatedTable)[-1] = conditionalTables->tables[0];
}
static void fakeDefaultWitness1() {}
@@ -1013,6 +1023,9 @@
(void *) 567
};
+WitnessTable *conditionalTablesBuffer[] = {(WitnessTable *)678};
+WitnessTableSlice conditionalTablesSlice = {conditionalTablesBuffer, 1};
+
TEST(WitnessTableTest, getGenericWitnessTable) {
EXPECT_EQ(sizeof(GenericWitnessTableStorage), sizeof(GenericWitnessTable));
@@ -1048,7 +1061,7 @@
// and an initializer, so we must instantiate.
{
tableStorage2.WitnessTableSizeInWords = 5;
- tableStorage2.WitnessTablePrivateSizeInWords = 1;
+ tableStorage2.WitnessTablePrivateSizeInWords = 1 + 1;
initializeRelativePointer(&tableStorage2.Protocol, &testProtocol.descriptor);
initializeRelativePointer(&tableStorage2.Pattern, witnesses);
initializeRelativePointer(&tableStorage2.Instantiator,
@@ -1060,12 +1073,13 @@
RaceTest_ExpectEqual<const WitnessTable *>(
[&]() -> const WitnessTable * {
- const WitnessTable *instantiatedTable =
- swift_getGenericWitnessTable(table, nullptr, nullptr);
+ const WitnessTable *instantiatedTable = swift_getGenericWitnessTable(
+ table, nullptr, (void**)&conditionalTablesSlice);
EXPECT_NE(instantiatedTable, table->Pattern.get());
- EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 0);
+ EXPECT_EQ(((void **) instantiatedTable)[-2], (void *) 0);
+ EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 678);
EXPECT_EQ(((void **) instantiatedTable)[0], (void *) 123);
EXPECT_EQ(((void **) instantiatedTable)[1], (void *) 234);
@@ -1080,7 +1094,7 @@
// Conformance needs one default requirement to be filled in
{
tableStorage3.WitnessTableSizeInWords = 4;
- tableStorage3.WitnessTablePrivateSizeInWords = 1;
+ tableStorage3.WitnessTablePrivateSizeInWords = 1 + 1;
initializeRelativePointer(&tableStorage3.Protocol, &testProtocol.descriptor);
initializeRelativePointer(&tableStorage3.Pattern, witnesses);
initializeRelativePointer(&tableStorage3.Instantiator, witnessTableInstantiator);
@@ -1091,12 +1105,13 @@
RaceTest_ExpectEqual<const WitnessTable *>(
[&]() -> const WitnessTable * {
- const WitnessTable *instantiatedTable =
- swift_getGenericWitnessTable(table, nullptr, nullptr);
+ const WitnessTable *instantiatedTable = swift_getGenericWitnessTable(
+ table, nullptr, (void**)&conditionalTablesSlice);
EXPECT_NE(instantiatedTable, table->Pattern.get());
- EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 0);
+ EXPECT_EQ(((void **) instantiatedTable)[-2], (void *) 0);
+ EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 678);
EXPECT_EQ(((void **) instantiatedTable)[0], (void *) 123);
EXPECT_EQ(((void **) instantiatedTable)[1], (void *) 234);
@@ -1112,7 +1127,7 @@
// to be filled in
{
tableStorage4.WitnessTableSizeInWords = 3;
- tableStorage4.WitnessTablePrivateSizeInWords = 1;
+ tableStorage4.WitnessTablePrivateSizeInWords = 1 + 1;
initializeRelativePointer(&tableStorage4.Protocol, &testProtocol.descriptor);
initializeRelativePointer(&tableStorage4.Pattern, witnesses);
initializeRelativePointer(&tableStorage4.Instantiator, witnessTableInstantiator);
@@ -1123,12 +1138,13 @@
RaceTest_ExpectEqual<const WitnessTable *>(
[&]() -> const WitnessTable * {
- const WitnessTable *instantiatedTable =
- swift_getGenericWitnessTable(table, nullptr, nullptr);
+ const WitnessTable *instantiatedTable = swift_getGenericWitnessTable(
+ table, nullptr, (void**)&conditionalTablesSlice);
EXPECT_NE(instantiatedTable, table->Pattern.get());
- EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 0);
+ EXPECT_EQ(((void **) instantiatedTable)[-2], (void *) 0);
+ EXPECT_EQ(((void **) instantiatedTable)[-1], (void *) 678);
EXPECT_EQ(((void **) instantiatedTable)[0], (void *) 123);
EXPECT_EQ(((void **) instantiatedTable)[1], (void *) 234);
diff --git a/utils/build-script-impl b/utils/build-script-impl
index ff0bbb2..1bfbcc5 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -2481,6 +2481,11 @@
continue
fi
+ # FIXME: Always re-build foundation on non-darwin platforms.
+ # Remove this when products build in the CMake system.
+ echo "Cleaning the Foundation build directory"
+ call rm -rf "${build_dir}"
+
with_pushd "${FOUNDATION_SOURCE_DIR}" \
call env SWIFTC="${SWIFTC_BIN}" CLANG="${LLVM_BIN}"/clang SWIFT="${SWIFT_BIN}" \
SDKROOT="${SWIFT_BUILD_PATH}" BUILD_DIR="${build_dir}" DSTROOT="$(get_host_install_destdir ${host})" PREFIX="$(get_host_install_prefix ${host})" ./configure "${FOUNDATION_BUILD_TYPE}" ${FOUNDATION_BUILD_ARGS[@]} -DXCTEST_BUILD_DIR=${XCTEST_BUILD_DIR} $LIBDISPATCH_BUILD_ARGS
@@ -2526,6 +2531,7 @@
else
echo "Skipping reconfiguration of libdispatch"
fi
+
with_pushd "${LIBDISPATCH_BUILD_DIR}" \
call make
with_pushd "${LIBDISPATCH_BUILD_DIR}/tests" \
@@ -2535,6 +2541,11 @@
continue
;;
*)
+ # FIXME: Always re-build libdispatch on non-darwin platforms.
+ # Remove this when products build in the CMake system.
+ echo "Cleaning the libdispatch build directory"
+ call rm -rf "${LIBDISPATCH_BUILD_DIR}"
+
cmake_options=(
${cmake_options[@]}
-DCMAKE_BUILD_TYPE:STRING="${LIBDISPATCH_BUILD_TYPE}"
diff --git a/utils/cmpcodesize/cmpcodesize/main.py b/utils/cmpcodesize/cmpcodesize/main.py
index 3f02353..224e556 100644
--- a/utils/cmpcodesize/cmpcodesize/main.py
+++ b/utils/cmpcodesize/cmpcodesize/main.py
@@ -24,7 +24,7 @@
SHORTCUTS = {
"O": "bin/Benchmark_O",
- "Ounchecked": "bin/Benchmark_Ounchecked",
+ "Osize": "bin/Benchmark_Osize",
"Onone": "bin/Benchmark_Onone",
"dylib": "lib/swift/macosx/x86_64/libswiftCore.dylib",
}
@@ -53,7 +53,7 @@
Compares the files in the new and old build-dirs.
Aliases:
O => bin/Benchmark_O
- Ounchecked => bin/Benchmark_Ounchecked
+ Osize => bin/Benchmark_Osize
Onone => bin/Benchmark_Onone
dylib => lib/swift/macosx/x86_64/libswiftCore.dylib
Examples:
diff --git a/utils/dev-scripts/split-cmdline b/utils/dev-scripts/split-cmdline
index 364009e..736b1a2 100755
--- a/utils/dev-scripts/split-cmdline
+++ b/utils/dev-scripts/split-cmdline
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# splitcmdline - Split swift compiler command lines -------------*- python -*-
+# split-cmdline - Split swift compiler command lines ------------*- python -*-
#
# This source file is part of the Swift.org open source project
#
@@ -14,7 +14,19 @@
# Split swift compiler command lines into multiple lines.
#
# Reads the command line from stdin an outputs the split line to stdout.
+# Example:
#
+# $ swiftc -c hello.swift -### | split-cmdline
+# /path-to-swift/bin/swift \
+# -frontend \
+# -c \
+# -primary-file hello.swift \
+# -target x86_64-apple-macosx10.9 \
+# -enable-objc-interop \
+# -color-diagnostics \
+# -module-name hello \
+# -o hello.o
+#
# Example usage in vim:
# *) make sure that split-cmdline is in the $PATH
# *) copy-paste the swift command line the text buffer
@@ -29,16 +41,15 @@
import re
import sys
import os
-
+import shlex
def main():
for line in sys.stdin:
first = True
is_arg_param = False
# Handle escaped spaces
- args = re.sub('\\\\ ', '@#space#@', line).split()
+ args = shlex.split(line)
for arg in args:
- arg = re.sub('@#space#@', '\\ ', arg)
if arg == '':
continue
if not first:
@@ -59,7 +70,10 @@
first = True
continue
- print(arg, end='')
+ if ' ' in arg:
+ print('"' + arg + '"', end='')
+ else:
+ print(arg, end='')
# A hard-coded list of options which expect a parameter
is_arg_param = (arg in [
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index 07a9d5a..d6c57e1 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -19,6 +19,12 @@
Node('FunctionCallArgumentList', kind='SyntaxCollection',
element='FunctionCallArgument'),
+ Node('ArrayElementList', kind='SyntaxCollection',
+ element='ArrayElement'),
+
+ Node('DictionaryElementList', kind='SyntaxCollection',
+ element='DictionaryElement'),
+
# The try operator.
# try foo()
# try? foo()
@@ -34,6 +40,24 @@
]),
]),
+ # An identifier expression.
+ Node('IdentifierExpr', kind='Expr',
+ children=[
+ Child('Identifier', kind='IdentifierToken'),
+ ]),
+
+ # A nil expression.
+ Node('NilLiteralExpr', kind='Expr',
+ children=[
+ Child('NilKeyword', kind='NilToken'),
+ ]),
+
+ # A _ expression.
+ Node('DiscardAssignmentExpr', kind='Expr',
+ children=[
+ Child('Wildcard', kind='WildcardToken'),
+ ]),
+
# A #line expression.
Node('PoundLineExpr', kind='Expr',
children=[
@@ -89,6 +113,22 @@
Child('RightParen', kind='RightParenToken'),
]),
+ # Array literal, e.g. [1, 2, 3]
+ Node('ArrayExpr', kind='Expr',
+ children=[
+ Child('LeftSquare', kind='LeftSquareToken'),
+ Child('Elements', kind='ArrayElementList'),
+ Child('RightSquare', kind='RightSquareToken'),
+ ]),
+
+ # Dictionary literal, e.g. [1:1, 2:2, 3:3]
+ Node('DictionaryExpr', kind='Expr',
+ children=[
+ Child('LeftSquare', kind='LeftSquareToken'),
+ Child('Elements', kind='DictionaryElementList'),
+ Child('RightSquare', kind='RightSquareToken'),
+ ]),
+
# function-call-argument -> label? ':'? expression ','?
Node('FunctionCallArgument', kind='Syntax',
children=[
@@ -101,6 +141,22 @@
is_optional=True),
]),
+ # element inside an array expression: expression ','?
+ Node('ArrayElement', kind='Syntax',
+ children=[
+ Child('Expression', kind='Expr'),
+ Child('TrailingComma', kind='CommaToken', is_optional=True),
+ ]),
+
+ # element inside an array expression: expression ','?
+ Node('DictionaryElement', kind='Syntax',
+ children=[
+ Child('KeyExpression', kind='Expr'),
+ Child('Colon', kind='ColonToken'),
+ Child('ValueExpression', kind='Expr'),
+ Child('TrailingComma', kind='CommaToken', is_optional=True),
+ ]),
+
# An integer literal.
# 3
# +3_400
@@ -115,5 +171,25 @@
Node('StringLiteralExpr', kind='Expr',
children=[
Child("StringLiteral", kind='StringLiteralToken')
- ])
+ ]),
+
+ # true or false
+ Node('BooleanLiteralExpr', kind='Expr',
+ children=[
+ Child("BooleanLiteral", kind='Token',
+ token_choices=[
+ 'TrueToken',
+ 'FalseToken',
+ ])
+ ]),
+
+ # a ? 1 : 0
+ Node('TernaryExpr', kind='Expr',
+ children=[
+ Child("ConditionExpression", kind='Expr'),
+ Child("QuestionMark", kind='InfixQuestionMarkToken'),
+ Child("FirstChoice", kind='Expr'),
+ Child("ColonMark", kind='ColonToken'),
+ Child("SecondChoice", kind='Expr')
+ ]),
]
diff --git a/utils/update_checkout.py b/utils/update_checkout.py
index df10b57..8221365 100755
--- a/utils/update_checkout.py
+++ b/utils/update_checkout.py
@@ -479,6 +479,14 @@
skip_history,
skip_repo_list)
+ # Quick check whether somebody is calling update in an empty directory
+ directory_contents = os.listdir(SWIFT_SOURCE_ROOT)
+ if not ('cmark' in directory_contents or
+ 'llvm' in directory_contents or
+ 'clang' in directory_contents):
+ print("You don't have all swift sources. "
+ "Call this script with --clone to get them.")
+
update_results = update_all_repositories(args, config, scheme,
cross_repos_pr)
fail_count = 0
diff --git a/validation-test/Evolution/Inputs/class_add_virtual_method.swift b/validation-test/Evolution/Inputs/class_add_virtual_method.swift
new file mode 100644
index 0000000..28df044
--- /dev/null
+++ b/validation-test/Evolution/Inputs/class_add_virtual_method.swift
@@ -0,0 +1,43 @@
+
+public func getVersion() -> Int {
+#if BEFORE
+ return 0
+#else
+ return 1
+#endif
+}
+
+#if BEFORE
+
+public class AddVirtualMethod {
+ public init() {}
+
+ public func firstMethod() -> Int {
+ return 1
+ }
+
+ public func secondMethod() -> Int {
+ return 2
+ }
+}
+
+#else
+
+public class AddVirtualMethod {
+ // Note: methods were re-ordered, new method added in the middle
+ public func secondMethod() -> Int {
+ return 2
+ }
+
+ public func thirdMethod() -> Int {
+ return 3
+ }
+
+ public func firstMethod() -> Int {
+ return 1
+ }
+
+ public init() {}
+}
+
+#endif
diff --git a/validation-test/Evolution/test_class_add_virtual_method.swift b/validation-test/Evolution/test_class_add_virtual_method.swift
new file mode 100644
index 0000000..dfa4084
--- /dev/null
+++ b/validation-test/Evolution/test_class_add_virtual_method.swift
@@ -0,0 +1,19 @@
+// RUN: %target-resilience-test
+// REQUIRES: executable_test
+
+import StdlibUnittest
+import class_add_virtual_method
+
+
+var ClassAddVirtualMethodTest = TestSuite("ClassAddVirtualMethod")
+
+ClassAddVirtualMethodTest.test("ClassAddVirtualMethod") {
+ let c = AddVirtualMethod()
+
+ do {
+ expectEqual(1, c.firstMethod())
+ expectEqual(2, c.secondMethod())
+ }
+}
+
+runAllTests()
diff --git a/validation-test/Reflection/functions.swift b/validation-test/Reflection/functions.swift
index 3b4e0b2..8786247 100644
--- a/validation-test/Reflection/functions.swift
+++ b/validation-test/Reflection/functions.swift
@@ -26,8 +26,8 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
@@ -45,8 +45,8 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=28 alignment=4 stride=28
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=24 alignment=4 stride=24
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=metadata offset=12
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096)))))
@@ -85,8 +85,8 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
@@ -103,12 +103,12 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=40 alignment=4 stride=40
+// CHECK-32-NEXT: (closure_context size=36 alignment=4 stride=36
+// CHECK-32-NEXT: (field offset=24
+// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=28
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=32
-// CHECK-32-NEXT: (reference kind=strong refcounting=native))
-// CHECK-32-NEXT: (field offset=36
// CHECK-32-NEXT: (reference kind=strong refcounting=native)))
// CHECK-64: Type info:
@@ -132,14 +132,14 @@
// CHECK-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=28 alignment=4 stride=28
+// CHECK-32-NEXT: (closure_context size=24 alignment=4 stride=24
+// CHECK-32-NEXT: (field offset=8
+// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=12
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=20
-// CHECK-32-NEXT: (reference kind=strong refcounting=native))
-// CHECK-32-NEXT: (field offset=24
// CHECK-32-NEXT: (reference kind=strong refcounting=native)))
// CHECK-64: Type info:
@@ -171,7 +171,7 @@
// CHECK-32: (class functions.CapturingClass)
// CHECK-32: Type info:
- // CHECK-32: (class_instance size=12 alignment=1 stride=12
+ // CHECK-32: (class_instance size=8 alignment=1 stride=8
@_semantics("optimize.sil.never")
func arity0Capture1() -> () -> () {
let closure = {
@@ -204,8 +204,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32-NEXT: (field offset=16
+ // CHECK-32: (closure_context size=24 alignment=8 stride=24
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
@@ -245,8 +245,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=20 alignment=4 stride=20
- // CHECK-32-NEXT: (field offset=12
+ // CHECK-32: (closure_context size=16 alignment=4 stride=16
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (tuple size=8 alignment=4 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
@@ -283,8 +283,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=16 alignment=4 stride=16
- // CHECK-32-NEXT: (field offset=12
+ // CHECK-32: (closure_context size=12 alignment=4 stride=12
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (single_payload_enum size=4 alignment=4 stride=4 num_extra_inhabitants=4095
// CHECK-32-NEXT: (field name=some offset=0
// CHECK-32-NEXT: (class_existential size=4 alignment=4 stride=4 num_extra_inhabitants=4096
@@ -326,7 +326,7 @@
// CHECK-32: Type info:
// CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32-NEXT: (field offset=12
+ // CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (reference kind=strong refcounting=native))
// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -367,10 +367,10 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
- // CHECK-32: (closure_context size=20 alignment=4 stride=20
- // CHECK-32: (field offset=12
+ // CHECK-32: (closure_context size=16 alignment=4 stride=16
+ // CHECK-32: (field offset=8
// CHECK-32: (reference kind=strong refcounting=native))
- // CHECK-32: (field offset=16
+ // CHECK-32: (field offset=12
// CHECK-32: (reference kind=strong refcounting=native)))
@_semantics("optimize.sil.never")
func arity1Capture2() -> (Int) -> () {
@@ -408,7 +408,7 @@
// CHECK-32: Type info:
// CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32: (field offset=12
+ // CHECK-32: (field offset=8
// CHECK-32: (reference kind=strong refcounting=native))
// CHECK-32: (field offset=16
// CHECK-32: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -457,7 +457,7 @@
// CHECK-32: Type info:
// CHECK-32: (closure_context size=32 alignment=8 stride=32
- // CHECK-32: (field offset=12
+ // CHECK-32: (field offset=8
// CHECK-32: (reference kind=strong refcounting=native))
// CHECK-32: (field offset=16
// CHECK-32: (tuple size=16 alignment=8 stride=16 num_extra_inhabitants=0
@@ -510,8 +510,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (reference kind=weak refcounting=native)))
reflect(function: C().captureUnownedSelf())
@@ -531,8 +531,8 @@
// CHECK-32: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32: (closure_context size=16 alignment=4 stride=16
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32: (closure_context size=12 alignment=4 stride=12
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (reference kind=unowned refcounting=native)))
doneReflecting()
diff --git a/validation-test/Reflection/functions_objc.swift b/validation-test/Reflection/functions_objc.swift
index dd56664..8e05508 100644
--- a/validation-test/Reflection/functions_objc.swift
+++ b/validation-test/Reflection/functions_objc.swift
@@ -15,16 +15,16 @@
// CHECK-32-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (closure_context size=40 alignment=4 stride=40 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field offset=12
+// CHECK-32-NEXT: (closure_context size=36 alignment=4 stride=36 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field offset=16
+// CHECK-32-NEXT: (field offset=12
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field offset=20
+// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (builtin size=16 alignment=4 stride=16 num_extra_inhabitants=0))
-// CHECK-32-NEXT: (field offset=36
+// CHECK-32-NEXT: (field offset=32
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown)))
// CHECK-64: Type reference:
diff --git a/validation-test/Reflection/inherits_Swift.swift b/validation-test/Reflection/inherits_Swift.swift
index 67a1c50..7b0aa77 100644
--- a/validation-test/Reflection/inherits_Swift.swift
+++ b/validation-test/Reflection/inherits_Swift.swift
@@ -37,12 +37,12 @@
// CHECK-32: (class inherits_Swift.BaseClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=17 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=w offset=12
+// CHECK-32-NEXT: (class_instance size=13 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=w offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=x offset=16
+// CHECK-32-NEXT: (field name=x offset=12
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254)))))
@@ -73,12 +73,12 @@
// CHECK-32: (class inherits_Swift.DerivedClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=4 stride=24 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=y offset=17
+// CHECK-32-NEXT: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=y offset=13
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254))))
-// CHECK-32-NEXT: (field name=z offset=20
+// CHECK-32-NEXT: (field name=z offset=16
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Array.swift b/validation-test/Reflection/reflect_Array.swift
index c8b84e7..01996e3 100644
--- a/validation-test/Reflection/reflect_Array.swift
+++ b/validation-test/Reflection/reflect_Array.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_Array.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=1
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_Bool.swift b/validation-test/Reflection/reflect_Bool.swift
index 9cabb01..7f0fe57 100644
--- a/validation-test/Reflection/reflect_Bool.swift
+++ b/validation-test/Reflection/reflect_Bool.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Bool.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254)))))
diff --git a/validation-test/Reflection/reflect_Character.swift b/validation-test/Reflection/reflect_Character.swift
index d6911ed..cb05d37 100644
--- a/validation-test/Reflection/reflect_Character.swift
+++ b/validation-test/Reflection/reflect_Character.swift
@@ -42,8 +42,8 @@
// CHECK-32: (class reflect_Character.TestClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=t offset=16
+// CHECK-32-NEXT: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=t offset=8
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_representation offset=0
// CHECK-32-NEXT: (multi_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=0
diff --git a/validation-test/Reflection/reflect_Dictionary.swift b/validation-test/Reflection/reflect_Dictionary.swift
index 2eecc2d..5a33cdf 100644
--- a/validation-test/Reflection/reflect_Dictionary.swift
+++ b/validation-test/Reflection/reflect_Dictionary.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_Dictionary.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_Double.swift b/validation-test/Reflection/reflect_Double.swift
index 80904ed..f95deee 100644
--- a/validation-test/Reflection/reflect_Double.swift
+++ b/validation-test/Reflection/reflect_Double.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Double.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Float.swift b/validation-test/Reflection/reflect_Float.swift
index d59b985..fec3513 100644
--- a/validation-test/Reflection/reflect_Float.swift
+++ b/validation-test/Reflection/reflect_Float.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Float.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int.swift b/validation-test/Reflection/reflect_Int.swift
index a8b8488..056943b 100644
--- a/validation-test/Reflection/reflect_Int.swift
+++ b/validation-test/Reflection/reflect_Int.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int16.swift b/validation-test/Reflection/reflect_Int16.swift
index d51a0e1..3818d73 100644
--- a/validation-test/Reflection/reflect_Int16.swift
+++ b/validation-test/Reflection/reflect_Int16.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int16.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=14 alignment=2 stride=14 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=10 alignment=2 stride=10 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int32.swift b/validation-test/Reflection/reflect_Int32.swift
index a2d642e..26da3ae 100644
--- a/validation-test/Reflection/reflect_Int32.swift
+++ b/validation-test/Reflection/reflect_Int32.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int32.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int64.swift b/validation-test/Reflection/reflect_Int64.swift
index d1a1c1b..9ef651c 100644
--- a/validation-test/Reflection/reflect_Int64.swift
+++ b/validation-test/Reflection/reflect_Int64.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int64.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_Int8.swift b/validation-test/Reflection/reflect_Int8.swift
index b79ff1f..fd8db13 100644
--- a/validation-test/Reflection/reflect_Int8.swift
+++ b/validation-test/Reflection/reflect_Int8.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_Int8.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_NSArray.swift b/validation-test/Reflection/reflect_NSArray.swift
index 7abeb2c..f0d735a 100644
--- a/validation-test/Reflection/reflect_NSArray.swift
+++ b/validation-test/Reflection/reflect_NSArray.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSArray.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSNumber.swift b/validation-test/Reflection/reflect_NSNumber.swift
index 4f8c3f8..e80fd09 100644
--- a/validation-test/Reflection/reflect_NSNumber.swift
+++ b/validation-test/Reflection/reflect_NSNumber.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSNumber.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSSet.swift b/validation-test/Reflection/reflect_NSSet.swift
index f0c1f5c..5704edb 100644
--- a/validation-test/Reflection/reflect_NSSet.swift
+++ b/validation-test/Reflection/reflect_NSSet.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSSet.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_NSString.swift b/validation-test/Reflection/reflect_NSString.swift
index ee02334..ab8fa0c 100644
--- a/validation-test/Reflection/reflect_NSString.swift
+++ b/validation-test/Reflection/reflect_NSString.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_NSString.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (reference kind=strong refcounting=unknown)))
doneReflecting()
diff --git a/validation-test/Reflection/reflect_Set.swift b/validation-test/Reflection/reflect_Set.swift
index dcfb477..267bd21 100644
--- a/validation-test/Reflection/reflect_Set.swift
+++ b/validation-test/Reflection/reflect_Set.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_Set.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_String.swift b/validation-test/Reflection/reflect_String.swift
index 2e8dde6..2941249 100644
--- a/validation-test/Reflection/reflect_String.swift
+++ b/validation-test/Reflection/reflect_String.swift
@@ -34,8 +34,8 @@
// CHECK-32: (class reflect_String.TestClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=24 alignment=4 stride=24
-// CHECK-32-NEXT: (field name=t offset=12
+// CHECK-32-NEXT: (class_instance size=20 alignment=4 stride=20
+// CHECK-32-NEXT: (field name=t offset=8
// CHECK-32-NEXT: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0
// (unstable implementation details omitted)
diff --git a/validation-test/Reflection/reflect_UInt.swift b/validation-test/Reflection/reflect_UInt.swift
index 3f951d3..94309fb 100644
--- a/validation-test/Reflection/reflect_UInt.swift
+++ b/validation-test/Reflection/reflect_UInt.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt16.swift b/validation-test/Reflection/reflect_UInt16.swift
index 8d9ee6b..d7ec13b 100644
--- a/validation-test/Reflection/reflect_UInt16.swift
+++ b/validation-test/Reflection/reflect_UInt16.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt16.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=14 alignment=2 stride=14 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=10 alignment=2 stride=10 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt32.swift b/validation-test/Reflection/reflect_UInt32.swift
index 4fd5dcd..5123abd 100644
--- a/validation-test/Reflection/reflect_UInt32.swift
+++ b/validation-test/Reflection/reflect_UInt32.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt32.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=12 alignment=4 stride=12 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt64.swift b/validation-test/Reflection/reflect_UInt64.swift
index 2c8248a..6e672df 100644
--- a/validation-test/Reflection/reflect_UInt64.swift
+++ b/validation-test/Reflection/reflect_UInt64.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt64.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=24 alignment=8 stride=24 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=16
+// CHECK-32: (class_instance size=16 alignment=8 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_UInt8.swift b/validation-test/Reflection/reflect_UInt8.swift
index e02710a..4f94618 100644
--- a/validation-test/Reflection/reflect_UInt8.swift
+++ b/validation-test/Reflection/reflect_UInt8.swift
@@ -35,8 +35,8 @@
// CHECK-32: (class reflect_UInt8.TestClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=13 alignment=1 stride=13 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=9 alignment=1 stride=9 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/Reflection/reflect_empty_class.swift b/validation-test/Reflection/reflect_empty_class.swift
index 1f337fe..6c54d94 100644
--- a/validation-test/Reflection/reflect_empty_class.swift
+++ b/validation-test/Reflection/reflect_empty_class.swift
@@ -26,7 +26,7 @@
// CHECK-32: (class reflect_empty_class.EmptyClass)
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=12 alignment=1 stride=12 num_extra_inhabitants=0)
+// CHECK-32: (class_instance size=8 alignment=1 stride=8 num_extra_inhabitants=0)
doneReflecting()
diff --git a/validation-test/Reflection/reflect_existential.swift b/validation-test/Reflection/reflect_existential.swift
index 1247dc6..a871580 100644
--- a/validation-test/Reflection/reflect_existential.swift
+++ b/validation-test/Reflection/reflect_existential.swift
@@ -37,8 +37,8 @@
// CHECK-32: (protocol_composition))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=28 alignment=4 stride=28 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=24 alignment=4 stride=24 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=0
// CHECK-32: (field name=metadata offset=12
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096)))))
@@ -65,8 +65,8 @@
// CHECK-32: (protocol reflect_existential.P)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=32 alignment=4 stride=32 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=28 alignment=4 stride=28 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (opaque_existential size=20 alignment=4 stride=20 num_extra_inhabitants=0
// CHECK-32: (field name=metadata offset=12
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096))
@@ -95,8 +95,8 @@
// CHECK-32: (protocol reflect_existential.P)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
// CHECK-32: (field name=object offset=0
// CHECK-32: (reference kind=strong refcounting=unknown))
@@ -125,8 +125,8 @@
// CHECK-32: (protocol reflect_existential.CP)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
// CHECK-32: (field name=object offset=0
// CHECK-32: (reference kind=strong refcounting=unknown))
@@ -157,8 +157,8 @@
// CHECK-32: (protocol reflect_existential.P)))
// CHECK-32: Type info:
-// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0
-// CHECK-32: (field name=t offset=12
+// CHECK-32: (class_instance size=16 alignment=4 stride=16 num_extra_inhabitants=0
+// CHECK-32: (field name=t offset=8
// CHECK-32: (class_existential size=8 alignment=4 stride=8 num_extra_inhabitants=4096
// CHECK-32: (field name=object offset=0
// CHECK-32: (reference kind=strong refcounting=native))
diff --git a/validation-test/Reflection/reflect_multiple_types.swift b/validation-test/Reflection/reflect_multiple_types.swift
index bdcfba9..c477b22 100644
--- a/validation-test/Reflection/reflect_multiple_types.swift
+++ b/validation-test/Reflection/reflect_multiple_types.swift
@@ -205,15 +205,15 @@
// CHECK-32: (class reflect_multiple_types.TestClass)
// CHECK-32: Type info:
-// CHECK-32-NEXT: (class_instance size=129 alignment=8 stride=136 num_extra_inhabitants=0
-// CHECK-32-NEXT: (field name=t00 offset=12
+// CHECK-32-NEXT: (class_instance size=121 alignment=8 stride=128 num_extra_inhabitants=0
+// CHECK-32-NEXT: (field name=t00 offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=1
// (unstable implementation details omitted)
-// CHECK-32: (field name=t01 offset=16
+// CHECK-32: (field name=t01 offset=12
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=254
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=254))))
-// CHECK-32-NEXT: (field name=t02 offset=24
+// CHECK-32-NEXT: (field name=t02 offset=16
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_representation offset=0
// CHECK-32-NEXT: (multi_payload_enum size=8 alignment=8 stride=8 num_extra_inhabitants=0
@@ -223,68 +223,68 @@
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=4096
// CHECK-32-NEXT: (field name=_nativeBuffer offset=0
// CHECK-32-NEXT: (reference kind=strong refcounting=native))))))
-// CHECK-32-NEXT: (field name=t03 offset=32
+// CHECK-32-NEXT: (field name=t03 offset=24
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
-// CHECK-32: (field name=t04 offset=40
+// CHECK-32: (field name=t04 offset=32
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t05 offset=48
+// CHECK-32-NEXT: (field name=t05 offset=40
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t06 offset=52
+// CHECK-32-NEXT: (field name=t06 offset=44
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t07 offset=56
+// CHECK-32-NEXT: (field name=t07 offset=48
// CHECK-32-NEXT: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t08 offset=60
+// CHECK-32-NEXT: (field name=t08 offset=52
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t09 offset=64
+// CHECK-32-NEXT: (field name=t09 offset=56
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t10 offset=72
+// CHECK-32-NEXT: (field name=t10 offset=64
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t11 offset=76
+// CHECK-32-NEXT: (field name=t11 offset=68
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t12 offset=80
+// CHECK-32-NEXT: (field name=t12 offset=72
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t13 offset=84
+// CHECK-32-NEXT: (field name=t13 offset=76
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t14 offset=88
+// CHECK-32-NEXT: (field name=t14 offset=80
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
-// CHECK-32-NEXT: (field name=t15 offset=92
+// CHECK-32-NEXT: (field name=t15 offset=84
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// (unstable implementation details omitted)
-// CHECK-32: (field name=t16 offset=96
+// CHECK-32: (field name=t16 offset=88
// CHECK-32-NEXT: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0
// (unstable implementation details omitted)
-// CHECK-32: (field name=t17 offset=108
+// CHECK-32: (field name=t17 offset=100
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t18 offset=112
+// CHECK-32-NEXT: (field name=t18 offset=104
// CHECK-32-NEXT: (struct size=2 alignment=2 stride=2 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=2 alignment=2 stride=2 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t19 offset=116
+// CHECK-32-NEXT: (field name=t19 offset=108
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t20 offset=120
+// CHECK-32-NEXT: (field name=t20 offset=112
// CHECK-32-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0))))
-// CHECK-32-NEXT: (field name=t21 offset=128
+// CHECK-32-NEXT: (field name=t21 offset=120
// CHECK-32-NEXT: (struct size=1 alignment=1 stride=1 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=1 alignment=1 stride=1 num_extra_inhabitants=0)))))
diff --git a/validation-test/compiler_crashers/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
deleted file mode 100644
index 30eb21f..0000000
--- a/validation-test/compiler_crashers/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-// This source file is part of the Swift.org open source project
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
-[(Int
-(Int
-&_
diff --git a/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift b/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
index ec99b6a..b4378e9 100644
--- a/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
+++ b/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
class a<T where g:d{class A{class A<T>:A{init(){T{
diff --git a/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift b/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
index e48931e..359453f 100644
--- a/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
+++ b/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
struct c{class A:A{}var f=A.s
diff --git a/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift b/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
index 63fe9ac..dcbf097 100644
--- a/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
+++ b/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
struct B{let d=A.b}class A:A{let a=V
diff --git a/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift b/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
index 00f45d8..f65282f 100644
--- a/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
+++ b/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
{guard let{protocol A{extension{let d}}}let f=d
diff --git a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift b/validation-test/compiler_crashers_fixed/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
similarity index 86%
rename from validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
rename to validation-test/compiler_crashers_fixed/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
index 97abd53..4b95974 100644
--- a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
+++ b/validation-test/compiler_crashers_fixed/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
@@ -5,5 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
[.h=_
diff --git a/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift b/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
index e546946..73f5994 100644
--- a/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
+++ b/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
&[_=(&_
diff --git a/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift b/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
index 8be1db1..5d42a2b 100644
--- a/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
+++ b/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{let c{}typealias e:RangeReplaceableCollection}extension P{typealias e:a
diff --git a/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift b/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
index 8f0ba7d..ee5d02c 100644
--- a/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
+++ b/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
typealias e:a
struct A:a{}typealias a=A
diff --git a/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift b/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
index 9b66b76..9e30b6b 100644
--- a/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
+++ b/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{class a:Self.a
diff --git a/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift b/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
index f54117f..297f82b 100644
--- a/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
+++ b/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P}extension P{{}typealias a:P}extension P.a{protocol P
diff --git a/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift b/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
index f9d112f..d9dc8bd 100644
--- a/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
+++ b/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
&{LazyFilterIndex{
diff --git a/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift b/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
index 8d68e87..fea557c 100644
--- a/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
+++ b/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:a{{}typealias e:a}{}class a:A{typealias e:b
diff --git a/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift b/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
index d8cfda1..0c7cab3 100644
--- a/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
+++ b/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{struct A}class a:P{class a:A
diff --git a/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift b/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
index da91b69..87061d5 100644
--- a/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
+++ b/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
{class a:P{{}typealias a:Self.a}protocol P{typealias a
diff --git a/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift b/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
index 675bf9e..4ee8994 100644
--- a/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
+++ b/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
@objc protocol P{typealias e:P{}var a}{}extension P{typealias e:P
diff --git a/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift b/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
index f14b655..6827b5d 100644
--- a/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
+++ b/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:A{{}class a{let ca{a{
diff --git a/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift b/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
index 06b5bb10..b1db627 100644
--- a/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
+++ b/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:RangeReplaceableCollection
typealias e:a._=A.init(
diff --git a/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift b/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
index 24269e6..3edd0b70 100644
--- a/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
+++ b/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
guard#keyPath($
diff --git a/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift b/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
index 441f3f5..0a37d63 100644
--- a/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
+++ b/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension in($A
diff --git a/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift b/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
index 80bca15..db1c2fe 100644
--- a/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
+++ b/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias e:P{}class a{{}func a:Self.a.e
diff --git a/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift b/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
index eb3ce30..07b3cad 100644
--- a/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
+++ b/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
&_ is Character
diff --git a/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift b/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
index 963d2de..2549064 100644
--- a/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
+++ b/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
guard let f==A:UnfoldSequence
diff --git a/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift b/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
index a50bb7f..5c7f0d2 100644
--- a/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
+++ b/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{{}class a:A{}protocol A:P.a{typealias a{}func a:a
diff --git a/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift b/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
index 5eba003..e22a1c3 100644
--- a/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
+++ b/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
@objc protocol P{struct B{var f=_=a{}}class a{}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift b/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
index 5b4f0e4..1686b88 100644
--- a/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
+++ b/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
Indexable
& ManagedBuffer
diff --git a/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift b/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
index 8c2d8ea..1404712 100644
--- a/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
+++ b/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{protocol b:P{{}typealias e:a.a}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift b/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
index 615f29c..769a13a 100644
--- a/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
+++ b/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a{@objc@dynamic
let d
diff --git a/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 33a3375..36a9536 100644
--- a/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{{}protocol A{typealias e{}}typealias a=A}extension P.a{protocol P
diff --git a/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift b/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
index 26b3ac3..9421946 100644
--- a/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
+++ b/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias a{}class a
{}typealias a{}class a
diff --git a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 1900ef7..57f8aaf 100644
--- a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a:A
protocol A:a{
diff --git a/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift b/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
index af99a3f..34901f3 100644
--- a/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
+++ b/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension P{{}}protocol P{protocol P{protocol A{{}typealias a{}}typealias e:A.a}typealias e:P
diff --git a/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift b/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
index f0e4bf6..08c38fe 100644
--- a/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
+++ b/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{
typealias e:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift b/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
index 7fd018a..aa5c573 100644
--- a/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
+++ b/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:A{struct B{{}var a{class a{class ss:a
diff --git a/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index efc3af8..0374eed 100644
--- a/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:RangeReplaceableCollection
protocol P{
diff --git a/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift b/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
index 1714776..54eafc3 100644
--- a/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
+++ b/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:A.b{func 丏
protocol b:Collection
diff --git a/validation-test/compiler_crashers_fixed/28796-result-second.swift b/validation-test/compiler_crashers_fixed/28796-result-second.swift
index 316ac8c..41a241c 100644
--- a/validation-test/compiler_crashers_fixed/28796-result-second.swift
+++ b/validation-test/compiler_crashers_fixed/28796-result-second.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{{{}}func b{extension{class a<a{{}class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift b/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
index df54499..76fd112b 100644
--- a/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
+++ b/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{protocol A{protocol A{}typealias e where f:A
diff --git a/validation-test/compiler_crashers_fixed/28804-second.swift b/validation-test/compiler_crashers_fixed/28804-second.swift
index edcddea..d2d91d8 100644
--- a/validation-test/compiler_crashers_fixed/28804-second.swift
+++ b/validation-test/compiler_crashers_fixed/28804-second.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{
protocol A{{}typealias e where f=A
diff --git a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
index 3902655..84fc444 100644
--- a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
+++ b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a:RangeReplaceableCollection}protocol P{{}typealias e:a{{}}typealias e:Collection
diff --git a/validation-test/compiler_crashers_fixed/28808-hasval.swift b/validation-test/compiler_crashers_fixed/28808-hasval.swift
index af52480..d930ac5 100644
--- a/validation-test/compiler_crashers_fixed/28808-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28808-hasval.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias a
protocol A:P{
diff --git a/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 70a1cc5..d951e40 100644
--- a/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
{<a.h=a
class a<H
diff --git a/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift b/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
index cebc195..28c2d36 100644
--- a/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
+++ b/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
.a.i(t:&_
diff --git a/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift b/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
index ac9a4e6..5320203 100644
--- a/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
+++ b/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A{{}protocol A{func a:Self.a}typealias e:A.a
diff --git a/validation-test/compiler_crashers_fixed/28824-hasval.swift b/validation-test/compiler_crashers_fixed/28824-hasval.swift
index 59b31af..a920a03 100644
--- a/validation-test/compiler_crashers_fixed/28824-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28824-hasval.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension CountableRange{protocol b{typealias a:RangeReplaceableCollection
protocol P{}
diff --git a/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift b/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
index 1aa2114..71601aa 100644
--- a/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
+++ b/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol b:a{init(t:a}class a{class a
diff --git a/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index cd7ff73..cd937d6 100644
--- a/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ b/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
[(Int
(t:&_
diff --git a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
similarity index 84%
copy from validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
copy to validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index 97abd53..768a520 100644
--- a/validation-test/compiler_crashers/28618-unreachable-executed-at-swift-include-swift-ast-exprnodes-def-78.swift
+++ b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
@@ -5,5 +5,7 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// RUN: not --crash %target-swift-frontend %s -emit-ir
-[.h=_
+// RUN: not %target-swift-frontend %s -emit-ir
+[(Int
+(Int
+&_
diff --git a/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift b/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
index 73776c4..522b887 100644
--- a/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
+++ b/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension CountableRange{{}class a:a&a.a{func a
diff --git a/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
index f0dbe14..c20b4e1 100644
--- a/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
+++ b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{
class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 392b757..b7b0294 100644
--- a/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias e:A
protocol A:P{}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28842-hasval.swift b/validation-test/compiler_crashers_fixed/28842-hasval.swift
index 0a745b8..12fd071 100644
--- a/validation-test/compiler_crashers_fixed/28842-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28842-hasval.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{{}typealias a:A{}class a
protocol a protocol A:P{typealias a
diff --git a/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift b/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
index 504f8d5..2acdaaa 100644
--- a/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
+++ b/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias a{}func a:a.a{}class a{{}protocol 0
diff --git a/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 350c824..3b62d6e 100644
--- a/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:a{{}typealias a=a{}func a{}typealias a}class a:A{func a
diff --git a/validation-test/compiler_crashers_fixed/28853-result-second.swift b/validation-test/compiler_crashers_fixed/28853-result-second.swift
index 122c6ef..d2c10e9 100644
--- a/validation-test/compiler_crashers_fixed/28853-result-second.swift
+++ b/validation-test/compiler_crashers_fixed/28853-result-second.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
func a<a{
extension{{}
diff --git a/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index 14d2e3d..fcf87c7 100644
--- a/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:RangeReplaceableCollection&a:class a:A
diff --git a/validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift b/validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
similarity index 83%
rename from validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift
rename to validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
index 026a0b1..f05671c 100644
--- a/validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift
+++ b/validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
@@ -5,8 +5,7 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
func a
class a<b}let d=a?as?CVarArg
& a
diff --git a/validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift b/validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
similarity index 84%
rename from validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
rename to validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
index 0442f6c..ca51a8b 100644
--- a/validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
+++ b/validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
@@ -5,8 +5,7 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
class a
class a<a{{}class a<a{var f=a
& ManagedBuffer
diff --git a/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift b/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
index 40f673d..f78be0e 100644
--- a/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
+++ b/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{class a}protocol A:P
extension P.a:A
diff --git a/validation-test/stdlib/FloatingPointConversion.swift.gyb b/validation-test/stdlib/FloatingPointConversion.swift.gyb
index 9882102..3a96da7 100644
--- a/validation-test/stdlib/FloatingPointConversion.swift.gyb
+++ b/validation-test/stdlib/FloatingPointConversion.swift.gyb
@@ -115,75 +115,59 @@
% end # for in all_floating_point_types (Other)
-%{
-
-float_to_int_conversion_template = gyb.parse_template("float_to_int_conversion",
-"""
-% for int_ty in all_integer_types(word_bits):
-% OtherInt = int_ty.stdlib_name
-% OtherMin = int_ty.min
-% OtherMax = int_ty.max
-% (FloatMin, FloatMax) = getFtoIBounds(self_type.bits, int_ty.bits, int_ty.is_signed)
-
-% for testValue in [0, FloatMin, FloatMax, FloatMin - 1, FloatMax + 1, OtherMin, OtherMax]:
-
-% if testValue < OtherMin or testValue > OtherMax:
-% # Can't construct `other` value, do nothing and continue.
-
-% elif testValue >= FloatMin and testValue <= FloatMax:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Conversion/${testValue}") {
- expectEqual(${Self}(${testValue} as ${OtherInt}), ${testValue})
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}FailableConversion/${testValue}") {
- expectEqual(${Self}(exactly: ${testValue} as ${OtherInt}), ${testValue})
-}
-
-% else:
-
-FixedPointConversionTruncations.test("${OtherInt}to${Self}Truncation/${testValue}") {
- let value: ${OtherInt} = ${testValue}
- let result = ${Self}(value)
- expectNotEqual(${OtherInt}(result), value)
-}
-
-FixedPointConversionFailures.test("${OtherInt}to${Self}Failure/${testValue}") {
- let value: ${OtherInt} = ${testValue}
- let result = ${Self}(exactly: value)
- expectEqual(result, ${OtherMin} as ${Self})
- expectEqual(${OtherInt}(result!), value)
-}
-
-% end
-
-% end # testValue in testValues
-% end # for in all_integer_types (Other)
-""")
-}%
-
#if arch(i386) || arch(arm)
-
- ${gyb.execute_template(
- float_to_int_conversion_template,
- word_bits=32,
- **locals()
- )}
-
+% int_types = all_integer_types(32)
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x)
-
- ${gyb.execute_template(
- float_to_int_conversion_template,
- word_bits=64,
- **locals()
- )}
-
+% int_types = all_integer_types(64)
#else
-
_UnimplementedError()
-
#endif
+% for int_ty in int_types:
+% OtherInt = int_ty.stdlib_name
+
+extension ${OtherInt} {
+ static var _test${Self}Conversion: [(${OtherInt}, ${OtherInt}, ${OtherInt}?)] {
+ if bitWidth > ${Self}.significandBitCount + 1 {
+ let bitOffset = ${Self}.significandBitCount + 1
+ let limit: ${OtherInt} = ~(~0 << bitOffset)
+ let over: ${OtherInt} = 1 + limit << 1
+ return [
+ (0, 0, 0),
+ (limit, limit, limit),
+ (over, over + 1, nil),
+% if int_ty.is_signed:
+ (-limit, -limit, -limit),
+ (-over, -(over + 1), nil),
+% end
+ ]
+ } else {
+ return [
+ (0, 0, 0),
+ (.min, .min, .min),
+ (.max, .max, .max),
+ ]
+ }
+ }
+}
+
+FixedPointConversionTruncations.test("${OtherInt}to${Self}")
+ .forEach(in: ${OtherInt}._test${Self}Conversion) {
+ value, roundedExpectation, exactExpectation in
+
+ let roundedResult = ${Self}(value)
+ expectEqual(roundedResult, ${Self}(roundedExpectation))
+
+ let exactResult = ${Self}(exactly: value)
+ if let expectation = exactExpectation {
+ expectEqual(exactResult!, ${Self}(expectation))
+ } else {
+ expectNil(exactResult)
+ }
+}
+
+% end # for in int_types
+
% if Self == 'Float80':
#endif
% end
diff --git a/validation-test/stdlib/ModelIO.swift b/validation-test/stdlib/ModelIO.swift
index 6272a35..9ffeb4a 100644
--- a/validation-test/stdlib/ModelIO.swift
+++ b/validation-test/stdlib/ModelIO.swift
@@ -3,6 +3,11 @@
// UNSUPPORTED: OS=watchos
// REQUIRES: objc_interop
+// Currently crashes on iphonesimulator.
+// rdar://35490456
+// UNSUPPORTED: OS=ios
+// UNSUPPORTED: OS=tvos
+
import StdlibUnittest
import Foundation
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 3e99a47..29eae21 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -516,7 +516,7 @@
let float = (number!) as? Float
let expectedFloat = Float(uint32!)
// these are disabled because of https://bugs.swift.org/browse/SR-4634
- if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+ if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
testFloat(expectedFloat, float)
}
@@ -652,16 +652,16 @@
let uint = (number!) as? UInt
expectEqual(UInt(exactly: interestingValue), uint)
- // these are disabled because of https://bugs.swift.org/browse/SR-4634
- if uint! != UInt(UInt32.max) && uint! != UInt(UInt32.max - 1) {
- let float = (number!) as? Float
- let expectedFloat = Float(uint!)
- testFloat(expectedFloat, float)
+ let float = (number!) as? Float
+ let expectedFloat = Float(exactly: uint!)
+ if UInt.bitWidth == 32 && uint! >= UInt.max - 1 {
+ expectNil(expectedFloat)
+ } else {
+ testFloat(expectedFloat, float)
}
-
-
+
let double = (number!) as? Double
- let expectedDouble = Double(uint!)
+ let expectedDouble = Double(exactly: uint!)
testDouble(expectedDouble, double)
}
let bridged = interestingValue as NSNumber