diff --git a/CHANGELOG.md b/CHANGELOG.md
index efb42a832ab..43bb3501a0a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,27 +4,27 @@ CHANGELOG
Note: This is in reverse chronological order, so newer entries are added to the top.
-| Contents |
-| :--------------------- |
-| [Swift Next](#swift-next) |
-| [Swift 5.1](#swift-51) |
-| [Swift 5.0](#swift-50) |
-| [Swift 4.2](#swift-42) |
-| [Swift 4.1](#swift-41) |
-| [Swift 4.0](#swift-40) |
-| [Swift 3.1](#swift-31) |
-| [Swift 3.0](#swift-30) |
-| [Swift 2.2](#swift-22) |
-| [Swift 2.1](#swift-21) |
-| [Swift 2.0](#swift-20) |
-| [Swift 1.2](#swift-12) |
-| [Swift 1.1](#swift-11) |
-| [Swift 1.0](#swift-10) |
+| Version | Released | Toolchain |
+| :--------------------- | :--------- | :---------- |
+| [Swift 5.2](#swift-52) | | |
+| [Swift 5.1](#swift-51) | 2019-09-20 | Xcode 11.0 |
+| [Swift 5.0](#swift-50) | 2019-03-25 | Xcode 10.2 |
+| [Swift 4.2](#swift-42) | 2018-09-17 | Xcode 10.0 |
+| [Swift 4.1](#swift-41) | 2018-03-29 | Xcode 9.3 |
+| [Swift 4.0](#swift-40) | 2017-09-19 | Xcode 9.0 |
+| [Swift 3.1](#swift-31) | 2017-03-27 | Xcode 8.3 |
+| [Swift 3.0](#swift-30) | 2016-09-13 | Xcode 8.0 |
+| [Swift 2.2](#swift-22) | 2016-03-21 | Xcode 7.3 |
+| [Swift 2.1](#swift-21) | 2015-10-21 | Xcode 7.1 |
+| [Swift 2.0](#swift-20) | 2015-09-17 | Xcode 7.0 |
+| [Swift 1.2](#swift-12) | 2015-04-08 | Xcode 6.3 |
+| [Swift 1.1](#swift-11) | 2014-12-02 | Xcode 6.1.1 |
+| [Swift 1.0](#swift-10) | 2014-09-15 | Xcode 6.0 |
-Swift Next
-----------
+Swift 5.2
+---------
* [SR-11429][]:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 95999d4aecc..bad49ba082b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -125,7 +125,7 @@ set(SWIFT_ANALYZE_CODE_COVERAGE FALSE CACHE STRING
# SWIFT_VERSION is deliberately /not/ cached so that an existing build directory
# can be reused when a new version of Swift comes out (assuming the user hasn't
# manually set it as part of their own CMake configuration).
-set(SWIFT_VERSION "5.1")
+set(SWIFT_VERSION "5.1.1")
set(SWIFT_VENDOR "" CACHE STRING
"The vendor name of the Swift compiler")
diff --git a/README.md b/README.md
index dd00bfd1f34..f1cfae1a83d 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,6 @@
| | **Architecture** | **Master** | **Package** |
|---|:---:|:---:|:---:|
| **macOS** | x86_64 |[](https://ci.swift.org/job/oss-swift-incremental-RA-osx)|[](https://ci.swift.org/job/oss-swift-package-osx)|
-| **Ubuntu 14.04** | x86_64 | [](https://ci.swift.org/job/oss-swift-incremental-RA-linux-ubuntu-14_04)|[](https://ci.swift.org/job/oss-swift-package-linux-ubuntu-14_04)|
| **Ubuntu 16.04** | x86_64 | [](https://ci.swift.org/job/oss-swift-incremental-RA-linux-ubuntu-16_04)|[](https://ci.swift.org/job/oss-swift-package-linux-ubuntu-16_04)|
| **Ubuntu 18.04** | x86_64 | [](https://ci.swift.org/job/oss-swift-incremental-RA-linux-ubuntu-18_04)|[](https://ci.swift.org/job/oss-swift-package-linux-ubuntu-18_04)|
diff --git a/docs/CToSwiftNameTranslation.md b/docs/CToSwiftNameTranslation.md
index d9a3778f663..5dcb5f83226 100644
--- a/docs/CToSwiftNameTranslation.md
+++ b/docs/CToSwiftNameTranslation.md
@@ -212,6 +212,29 @@ Additionally, typedefs for `void *` or `const void *` that are themselves annota
If a typedef's underlying type is itself a "CF pointer" typedef, the "alias" typedef will be imported as a regular typealias, with the suffix "Ref" still dropped from its name (if present) unless doing so would conflict with another declaration in the same module as the typedef.
+## Objective-C Properties
+
+By default, most property names are not transformed at all. However, if the getter of a property overrides a superclass or adopted protocol method that is also a property accessor, the Swift name of the overridden accessor's property will be used for consistency. If there's more than one such name, one is chosen arbitrarily.
+
+Properties with the type `BOOL` or `Boolean` use the name of the getter as the name of the Swift property by default, rather than the name of the property in Objective-C. This accounts for a difference in Swift and Objective-C naming conventions for boolean properties that use "is".
+
+```objc
+@property(getter=isContrivedExample) BOOL contrivedExample;
+@property BOOL hasAnotherForm;
+```
+
+```swift
+var isContrivedExample: Bool { get set }
+var hasAnotherForm: Bool { get set }
+```
+
+_This rule should probably have applied to C's native `bool` as well._
+
+A property declaration with the `SwiftImportPropertyAsAccessors` API note will not be imported at all, and its accessors will be imported as methods. Additionally, properties whose names start with "accessibility" in the NSAccessibility protocol are always imported as methods, as are properties whose names start with "accessibility" in an `@interface` declaration (class or category) that provides the adoption of NSAccessibility.
+
+_Objective-C code has historically not been consistent about whether the NSAccessibility declarations should be considered properties and therefore the Swift compiler chooses to import them as methods, as a sort of lowest common denominator._
+
+
## `swift_private`
The `swift_private` Clang attribute prepends `__` onto the base name of any declaration being imported except initializers. For initializers with no arguments, a dummy `Void` argument with the name `__` is inserted; otherwise, the label for the first argument has `__` prepended. This transformation takes place after any other name manipulation, unless the declaration has a custom name. It will not occur if the declaration is an override; in that case the name needs to match the overridden declaration.
@@ -252,6 +275,8 @@ __attribute__((swift_name("SpacecraftCoordinates")))
struct SPKSpacecraftCoordinates {
double x, y, z, t; // space and time, of course
};
+
+// Usually seen as NS_SWIFT_NAME.
```
```swift
@@ -287,12 +312,10 @@ The `swift_name` attribute can be used to give a C function a custom name. The v
```objc
__attribute__((swift_name("doSomething(to:bar:)")))
void doSomethingToFoo(Foo *foo, int bar);
-
-// Usually seen as NS_SWIFT_NAME.
```
```swift
-func doSomething(foo: UnsafeMutablePointer, bar: Int32)
+func doSomething(to foo: UnsafeMutablePointer, bar: Int32)
```
An underscore can be used in place of an empty parameter label, as in Swift.
@@ -430,4 +453,86 @@ Although enumerators always have global scope in C, they are often imported as m
_Currently, `swift_name` does not even allow importing an enum case as a member of the enum type itself, even if the enum is not recognized as an `@objc` enum, error code enum, or option set (i.e. the situation where a case is imported as a global constant)._
+
+### Fields of structs and unions; Objective-C properties
+
+The `swift_name` attribute can be applied to rename a struct or union field or an Objective-C property (whether on a class or a protocol). The value of the attribute must be a valid Swift identifier.
+
+```objc
+struct SPKSpaceflightBooking {
+ const SPKLocation * _Nullable destination;
+ bool roundTrip __attribute__((swift_name("isRoundTrip")));
+};
+```
+
+```swift
+struct SPKSpaceflightBooking {
+ var destination: UnsafePointer?
+ var isRoundTrip: Bool
+}
+```
+
+
+### Objective-C methods
+
+The `swift_name` attribute can be used to give an Objective-C method a custom name. The value of the attribute must be a full Swift function name, including parameter labels.
+
+```objc
+- (void)doSomethingToFoo:(Foo *)foo bar:(int)bar
+ __attribute__((swift_name("doSomethingImportant(to:bar:)")));
+```
+
+```swift
+func doSomethingImportant(to foo: UnsafeMutablePointer, bar: Int32)
+```
+
+As with functions, an underscore can be used to represent an empty parameter label.
+
+Methods that follow the NSError out-parameter convention may provide one fewer parameter label than the number of parameters in the original method to indicate that a parameter should be dropped, but they do not have to. The `swift_error` attribute is still respected even when using a custom name for purposes of transforming an NSError out-parameter and the method return type.
+
+```objc
+- (BOOL)doSomethingRiskyAndReturnError:(NSError **)error
+ __attribute__((swift_name("doSomethingRisky()")));
+- (BOOL)doSomethingContrived:(NSString *)action error:(NSError **)outError
+ __attribute__((swift_name("doSomethingContrived(_:error:)")));
+```
+
+```swift
+func doSomethingRisky() throws
+func doSomethingContrived(_ action: String, error: ()) throws
+```
+
+A base name of "init" can be used on a *class* method that returns `instancetype` or the containing static type in order to import that method as an initializer. Any other custom name *prevents* a class method from being imported as an initializer even if it would normally be inferred as one.
+
+```objc
++ (Action *)makeActionWithHandler:(void(^)(void))handler
+ __attribute__((swift_name("init(handler:)")));
++ (instancetype)makeActionWithName:(NSString *)name
+ __attribute__((swift_name("init(name:)")));
+```
+
+```swift
+/* non-inherited */ init(handler: () -> Void)
+init(name: String)
+```
+
+A no-argument method imported as an initializer can be given a dummy argument label to disambiguate it from the no-argument `init()`, whether the method is an init-family instance method or a factory class method in Objective-C.
+
+```objc
+- (instancetype)initSafely
+ __attribute__((swift_name("init(safe:)")));
++ (instancetype)makeDefaultAction
+ __attribute__((swift_name("init(default:)")));
+```
+
+```swift
+init(safe: ())
+init(default: ())
+```
+
+A custom name on an instance method with one of Objective-C's subscript selectors (`objectAtIndexedSubscript:`, `objectForKeyedSubscript:`, `setObject:atIndexedSubscript:`, or `setObject:forKeyedSubscript:`) prevents that method from being imported as a subscript or used as the accessor for another subscript.
+
+_Currently, this only works if *both* methods in a read/write subscript are given custom names; if just one is, a read/write subscript will still be formed. A read-only subscript only has one method to rename._
+
+
## More to come...
diff --git a/docs/Diagnostics.md b/docs/Diagnostics.md
index 08010b83570..827d2a2e49c 100644
--- a/docs/Diagnostics.md
+++ b/docs/Diagnostics.md
@@ -104,3 +104,19 @@ Most diagnostics have no reason to change behavior under editor mode. An example
- `%error` - Represents a branch in a `%select` that should never be taken. In debug builds of the compiler this produces an assertion failure.
- `%%` - Emits a literal percent sign.
+
+### Diagnostic Verifier ###
+
+(This section is specific to the Swift compiler's diagnostic engine.)
+
+If the `-verify` frontend flag is used, the Swift compiler will check emitted diagnostics against specially formatted comments in the source. This feature is used extensively throughout the test suite to ensure diagnostics are emitted with the correct message and source location.
+
+An expected diagnostic is denoted by a comment which begins with `expected-error`, `expected-warning`, `expected-note`, or `expected-remark`. It is followed by:
+
+- (Optional) Location information. By default, the comment will match any diagnostic emitted on the same line. However, it's possible to override this behavior and/or specify column information as well. `// expected-error@-1 ...` looks for an error on the previous line, `// expected-warning@+1:3 ...` looks for a warning on the next line at the third column, and `// expected-note@:7 ...` looks for a note on the same line at the seventh column.
+
+- (Optional) A match count which specifies how many times the diagnostic is expected to appear. This may be a positive integer or `*`, which allows for zero or more matches. The match count must be surrounded by whitespace if present. For example, `// expected-error 2 ...` looks for two matching errors, and `// expected-warning * ...` looks for any number of matching warnings.
+
+- (Required) The expected error message. The message should be enclosed in double curly braces and should not include the `error:`/`warning:`/`note:`/`remark:` prefix. For example, `// expected-error {{invalid redeclaration of 'y'}}` would match an error with that message on the same line. The expected message does not need to match the emitted message verbatim. As long as the expected message is a substring of the original message, they will match.
+
+- (Optional) Expected fix-its. These are each enclosed in double curly braces and appear after the expected message. An expected fix-it consists of a column range followed by the text it's expected to be replaced with. For example, `let r : Int i = j // expected-error{{consecutive statements}} {{12-12=;}}` will match a fix-it attached to the consecutive statements error which inserts a semicolon at column 12, just after the 't' in 'Int'. The special {{none}} specifier is also supported, which will cause the diagnostic match to fail if unexpected fix-its are produced.
diff --git a/docs/Testing.md b/docs/Testing.md
index c2a7fead5a9..8098f8f2095 100644
--- a/docs/Testing.md
+++ b/docs/Testing.md
@@ -232,7 +232,7 @@ code for the target that is not the build machine:
* ``%target-typecheck-verify-swift``: parse and type check the current Swift file
for the target platform and verify diagnostics, like ``swift -frontend -typecheck -verify
- %s``.
+ %s``. For further explanation of `-verify` mode, see [Diagnostics.md](Diagnostics.md).
Use this substitution for testing semantic analysis in the compiler.
diff --git a/docs/WindowsBuild.md b/docs/WindowsBuild.md
index 01a43744394..74571357f1a 100644
--- a/docs/WindowsBuild.md
+++ b/docs/WindowsBuild.md
@@ -186,13 +186,11 @@ cmake -G "Visual Studio 2017" -A x64 -T "host=x64"^ ...
md "S:\b\lldb"
cd "S:\b\lldb"
cmake -G Ninja^
+ -DLLVM_DIR="S:/b/llvm/lib/cmake/llvm"^
+ -DClang_DIR="S:/b/llvm/lib/cmake/clang"^
+ -DSwift_DIR="S:/b/swift/lib/cmake/swift"^
-DCMAKE_BUILD_TYPE=RelWithDebInfo^
-DLLDB_ALLOW_STATIC_BINDINGS=YES^
- -DLLDB_PATH_TO_CLANG_SOURCE="S:\clang"^
- -DLLDB_PATH_TO_SWIFT_SOURCE="S:\swift"^
- -DLLDB_PATH_TO_CLANG_BUILD="S:\b\llvm"^
- -DLLDB_PATH_TO_LLVM_BUILD="S:\b\llvm"^
- -DLLDB_PATH_TO_SWIFT_BUILD="S:\b\swift"^
-DLLVM_ENABLE_ASSERTIONS=ON^
-DPYTHON_HOME="%ProgramFiles(x86)%\Microsoft Visual Studio\Shared\Python37_64"^
S:\lldb
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index 13766055ad2..2c2c7a65a0a 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -998,8 +998,6 @@ struct TargetClassMetadata : public TargetAnyClassMetadata {
using StoredPointer = typename Runtime::StoredPointer;
using StoredSize = typename Runtime::StoredSize;
- friend class ReflectionContext;
-
TargetClassMetadata() = default;
constexpr TargetClassMetadata(const TargetAnyClassMetadata &base,
ClassFlags flags,
diff --git a/include/swift/AST/ASTNode.h b/include/swift/AST/ASTNode.h
index a549ce939b2..db6884b8472 100644
--- a/include/swift/AST/ASTNode.h
+++ b/include/swift/AST/ASTNode.h
@@ -36,10 +36,10 @@ namespace swift {
enum class DeclKind : uint8_t;
enum class StmtKind;
- struct ASTNode : public llvm::PointerUnion3 {
+ struct ASTNode : public llvm::PointerUnion {
// Inherit the constructors from PointerUnion.
- using PointerUnion3::PointerUnion3;
-
+ using PointerUnion::PointerUnion;
+
SourceRange getSourceRange() const;
/// Return the location of the start of the statement.
diff --git a/include/swift/AST/ASTTypeIDZone.def b/include/swift/AST/ASTTypeIDZone.def
index 124c990c357..2ca97768b86 100644
--- a/include/swift/AST/ASTTypeIDZone.def
+++ b/include/swift/AST/ASTTypeIDZone.def
@@ -26,6 +26,7 @@ SWIFT_TYPEID(Type)
SWIFT_TYPEID(TypePair)
SWIFT_TYPEID_NAMED(CustomAttr *, CustomAttr)
SWIFT_TYPEID_NAMED(Decl *, Decl)
+SWIFT_TYPEID_NAMED(EnumDecl *, EnumDecl)
SWIFT_TYPEID_NAMED(GenericParamList *, GenericParamList)
SWIFT_TYPEID_NAMED(GenericTypeParamType *, GenericTypeParamType)
SWIFT_TYPEID_NAMED(InfixOperatorDecl *, InfixOperatorDecl)
diff --git a/include/swift/AST/ASTTypeIDs.h b/include/swift/AST/ASTTypeIDs.h
index c64b1290d3d..c05fde9e2d9 100644
--- a/include/swift/AST/ASTTypeIDs.h
+++ b/include/swift/AST/ASTTypeIDs.h
@@ -25,6 +25,7 @@ class AbstractFunctionDecl;
class BraceStmt;
class CustomAttr;
class Decl;
+class EnumDecl;
class GenericParamList;
class GenericSignature;
class GenericTypeParamType;
diff --git a/include/swift/AST/AnyRequest.h b/include/swift/AST/AnyRequest.h
index 623fa81d1c8..0b6b9b5f4cf 100644
--- a/include/swift/AST/AnyRequest.h
+++ b/include/swift/AST/AnyRequest.h
@@ -54,7 +54,7 @@ class AnyRequest {
friend llvm::DenseMapInfo;
static hash_code hashForHolder(uint64_t typeID, hash_code requestHash) {
- return hash_combine(hash_value(typeID), requestHash);
+ return hash_combine(typeID, requestHash);
}
/// Abstract base class used to hold the specific request kind.
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 10aca42d60c..571dffe1cc6 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -340,12 +340,7 @@ protected:
IsUserAccessible : 1
);
- SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1+1+1,
- /// Whether a keypath component can directly reference this storage,
- /// or if it must use the overridden declaration instead.
- HasComputedValidKeyPathComponent : 1,
- ValidKeyPathComponent : 1,
-
+ SWIFT_INLINE_BITFIELD(AbstractStorageDecl, ValueDecl, 1,
/// Whether this property is a type property (currently unfortunately
/// called 'static').
IsStatic : 1
@@ -3519,12 +3514,37 @@ public:
class EnumDecl final : public NominalTypeDecl {
SourceLoc EnumLoc;
+ enum SemanticInfoFlags : uint8_t {
+ // Is the raw type valid?
+ HasComputedRawType = 1 << 0,
+ // Is the complete set of (auto-incremented) raw values available?
+ HasFixedRawValues = 1 << 1,
+ // Is the complete set of raw values type checked?
+ HasFixedRawValuesAndTypes = 1 << 2,
+ };
+
struct {
/// The raw type and a bit to indicate whether the
/// raw was computed yet or not.
- llvm::PointerIntPair RawType;
+ llvm::PointerIntPair> RawTypeAndFlags;
+
+ bool hasRawType() const {
+ return RawTypeAndFlags.getInt().contains(HasComputedRawType);
+ }
+ void cacheRawType(Type ty) {
+ auto flags = RawTypeAndFlags.getInt() | HasComputedRawType;
+ RawTypeAndFlags.setPointerAndInt(ty, flags);
+ }
+
+ bool hasFixedRawValues() const {
+ return RawTypeAndFlags.getInt().contains(HasFixedRawValues);
+ }
+ bool hasCheckedRawValues() const {
+ return RawTypeAndFlags.getInt().contains(HasFixedRawValuesAndTypes);
+ }
} LazySemanticInfo;
+ friend class EnumRawValuesRequest;
friend class EnumRawTypeRequest;
friend class TypeChecker;
@@ -3583,6 +3603,9 @@ public:
Bits.EnumDecl.Circularity = static_cast(circularity);
}
+ /// Record that this enum has had all of its raw values computed.
+ void setHasFixedRawValues();
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::Enum;
@@ -3612,9 +3635,11 @@ public:
/// Set the raw type of the enum from its inheritance clause.
void setRawType(Type rawType) {
- LazySemanticInfo.RawType.setPointerAndInt(rawType, true);
+ auto flags = LazySemanticInfo.RawTypeAndFlags.getInt();
+ LazySemanticInfo.RawTypeAndFlags.setPointerAndInt(
+ rawType, flags | HasComputedRawType);
}
-
+
/// True if none of the enum cases have associated values.
///
/// Note that this is true for enums with absolutely no cases.
@@ -4505,8 +4530,6 @@ protected:
Bits.AbstractStorageDecl.IsStatic = IsStatic;
}
- void computeIsValidKeyPathComponent();
-
OpaqueTypeDecl *OpaqueReturn = nullptr;
public:
@@ -4749,18 +4772,9 @@ public:
/// property from the given module?
bool isResilient(ModuleDecl *M, ResilienceExpansion expansion) const;
- void setIsValidKeyPathComponent(bool value) {
- Bits.AbstractStorageDecl.HasComputedValidKeyPathComponent = true;
- Bits.AbstractStorageDecl.ValidKeyPathComponent = value;
- }
-
/// True if the storage can be referenced by a keypath directly.
/// Otherwise, its override must be referenced.
- bool isValidKeyPathComponent() const {
- if (!Bits.AbstractStorageDecl.HasComputedValidKeyPathComponent)
- const_cast(this)->computeIsValidKeyPathComponent();
- return Bits.AbstractStorageDecl.ValidKeyPathComponent;
- }
+ bool isValidKeyPathComponent() const;
/// True if the storage exports a property descriptor for key paths in
/// other modules.
@@ -4810,7 +4824,7 @@ public:
};
protected:
- PointerUnion3 Parent;
+ PointerUnion Parent;
VarDecl(DeclKind kind, bool isStatic, Introducer introducer,
bool issCaptureList, SourceLoc nameLoc, Identifier name,
@@ -6354,6 +6368,8 @@ public:
/// parent EnumDecl, although syntactically they are subordinate to the
/// EnumCaseDecl.
class EnumElementDecl : public DeclContext, public ValueDecl {
+ friend class EnumRawValuesRequest;
+
/// This is the type specified with the enum element, for
/// example 'Int' in 'case Y(Int)'. This is null if there is no type
/// associated with this element, as in 'case Z' or in all elements of enum
@@ -6394,9 +6410,20 @@ public:
ParameterList *getParameterList() const { return Params; }
- bool hasRawValueExpr() const { return RawValueExpr; }
- LiteralExpr *getRawValueExpr() const { return RawValueExpr; }
- void setRawValueExpr(LiteralExpr *e) { RawValueExpr = e; }
+ /// Retrieves a fully typechecked raw value expression associated
+ /// with this enum element, if it exists.
+ LiteralExpr *getRawValueExpr() const;
+
+ /// Retrieves a "structurally" checked raw value expression associated
+ /// with this enum element, if it exists.
+ ///
+ /// The structural raw value may or may not have a type set, but it is
+ /// guaranteed to be suitable for retrieving any non-semantic information
+ /// like digit text for an integral raw value or user text for a string raw value.
+ LiteralExpr *getStructuralRawValueExpr() const;
+
+ /// Reset the raw value expression.
+ void setRawValueExpr(LiteralExpr *e);
/// Return the containing EnumDecl.
EnumDecl *getParentEnum() const {
@@ -6419,6 +6446,10 @@ public:
bool isIndirect() const {
return getAttrs().hasAttribute();
}
+
+ /// Do not call this!
+ /// It exists to let the AST walkers get the raw value without forcing a request.
+ LiteralExpr *getRawValueUnchecked() const { return RawValueExpr; }
static bool classof(const Decl *D) {
return D->getKind() == DeclKind::EnumElement;
diff --git a/include/swift/AST/DiagnosticConsumer.h b/include/swift/AST/DiagnosticConsumer.h
index ee137ee7d04..809463a898b 100644
--- a/include/swift/AST/DiagnosticConsumer.h
+++ b/include/swift/AST/DiagnosticConsumer.h
@@ -38,10 +38,17 @@ enum class DiagnosticKind : uint8_t {
Note
};
-/// Extra information carried along with a diagnostic, which may or
-/// may not be of interest to a given diagnostic consumer.
+/// Information about a diagnostic passed to DiagnosticConsumers.
struct DiagnosticInfo {
DiagID ID = DiagID(0);
+ SourceLoc Loc;
+ DiagnosticKind Kind;
+ StringRef FormatString;
+ ArrayRef FormatArgs;
+ SourceLoc BufferIndirectlyCausingDiagnostic;
+
+ /// DiagnosticInfo of notes which are children of this diagnostic, if any
+ ArrayRef ChildDiagnosticInfo;
/// Represents a fix-it, a replacement of one range of text with another.
class FixIt {
@@ -60,6 +67,24 @@ struct DiagnosticInfo {
/// Extra source ranges that are attached to the diagnostic.
ArrayRef FixIts;
+
+ /// This is a note which has a parent error or warning
+ bool IsChildNote = false;
+
+ DiagnosticInfo() {}
+
+ DiagnosticInfo(DiagID ID, SourceLoc Loc, DiagnosticKind Kind,
+ StringRef FormatString,
+ ArrayRef FormatArgs,
+ SourceLoc BufferIndirectlyCausingDiagnostic,
+ ArrayRef ChildDiagnosticInfo,
+ ArrayRef Ranges, ArrayRef FixIts,
+ bool IsChildNote)
+ : ID(ID), Loc(Loc), Kind(Kind), FormatString(FormatString),
+ FormatArgs(FormatArgs),
+ BufferIndirectlyCausingDiagnostic(BufferIndirectlyCausingDiagnostic),
+ ChildDiagnosticInfo(ChildDiagnosticInfo), Ranges(Ranges),
+ FixIts(FixIts), IsChildNote(IsChildNote) {}
};
/// Abstract interface for classes that present diagnostics to the user.
diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h
index a4ec15134e7..c632d7f251f 100644
--- a/include/swift/AST/DiagnosticEngine.h
+++ b/include/swift/AST/DiagnosticEngine.h
@@ -337,7 +337,9 @@ namespace swift {
SmallVector Args;
SmallVector Ranges;
SmallVector FixIts;
+ std::vector ChildNotes;
SourceLoc Loc;
+ bool IsChildNote = false;
const Decl *Decl = nullptr;
friend DiagnosticEngine;
@@ -362,10 +364,13 @@ namespace swift {
ArrayRef getArgs() const { return Args; }
ArrayRef getRanges() const { return Ranges; }
ArrayRef getFixIts() const { return FixIts; }
+ ArrayRef getChildNotes() const { return ChildNotes; }
+ bool isChildNote() const { return IsChildNote; }
SourceLoc getLoc() const { return Loc; }
const class Decl *getDecl() const { return Decl; }
void setLoc(SourceLoc loc) { Loc = loc; }
+ void setIsChildNote(bool isChildNote) { IsChildNote = isChildNote; }
void setDecl(const class Decl *decl) { Decl = decl; }
/// Returns true if this object represents a particular diagnostic.
@@ -386,6 +391,8 @@ namespace swift {
void addFixIt(FixIt &&F) {
FixIts.push_back(std::move(F));
}
+
+ void addChildNote(Diagnostic &&D);
};
/// Describes an in-flight diagnostic, which is currently active
@@ -665,7 +672,8 @@ namespace swift {
friend class InFlightDiagnostic;
friend class DiagnosticTransaction;
-
+ friend class CompoundDiagnosticTransaction;
+
public:
explicit DiagnosticEngine(SourceManager &SourceMgr)
: SourceMgr(SourceMgr), ActiveDiagnostic(),
@@ -878,6 +886,15 @@ namespace swift {
return diagnose(decl, Diagnostic(id, std::move(args)...));
}
+ /// Emit a parent diagnostic and attached notes.
+ ///
+ /// \param parentDiag An InFlightDiagnostic representing the parent diag.
+ ///
+ /// \param builder A closure which builds and emits notes to be attached to
+ /// the parent diag.
+ void diagnoseWithNotes(InFlightDiagnostic parentDiag,
+ llvm::function_ref builder);
+
/// \returns true if diagnostic is marked with PointsToFirstBadToken
/// option.
bool isDiagnosticPointsToFirstBadToken(DiagID id) const;
@@ -905,6 +922,10 @@ namespace swift {
/// Retrieve the active diagnostic.
Diagnostic &getActiveDiagnostic() { return *ActiveDiagnostic; }
+ /// Generate DiagnosticInfo for a Diagnostic to be passed to consumers.
+ Optional
+ diagnosticInfoForDiagnostic(const Diagnostic &diagnostic);
+
/// Send \c diag to all diagnostic consumers.
void emitDiagnostic(const Diagnostic &diag);
@@ -945,6 +966,7 @@ namespace swift {
/// in LIFO order. An open transaction is implicitly committed upon
/// destruction.
class DiagnosticTransaction {
+ protected:
DiagnosticEngine &Engine;
/// How many tentative diagnostics there were when the transaction
@@ -968,7 +990,6 @@ namespace swift {
Depth(Engine.TransactionCount),
IsOpen(true)
{
- assert(!Engine.ActiveDiagnostic);
Engine.TransactionCount++;
}
@@ -1011,6 +1032,61 @@ namespace swift {
"transactions must be closed LIFO");
}
};
+
+ /// Represents a diagnostic transaction which constructs a compound diagnostic
+ /// from any diagnostics emitted inside. A compound diagnostic consists of a
+ /// parent error, warning, or remark followed by a variable number of child
+ /// notes. The semantics are otherwise the same as a regular
+ /// DiagnosticTransaction.
+ class CompoundDiagnosticTransaction : public DiagnosticTransaction {
+ public:
+ explicit CompoundDiagnosticTransaction(DiagnosticEngine &engine)
+ : DiagnosticTransaction(engine) {}
+
+ ~CompoundDiagnosticTransaction() {
+ if (IsOpen) {
+ commit();
+ }
+
+ if (Depth == 0) {
+ Engine.TransactionStrings.clear();
+ Engine.TransactionAllocator.Reset();
+ }
+ }
+
+ void commit() {
+ assert(PrevDiagnostics < Engine.TentativeDiagnostics.size() &&
+ "CompoundDiagnosticTransaction must contain at least one diag");
+
+ // The first diagnostic is assumed to be the parent. If this is not an
+ // error or warning, we'll assert later when trying to add children.
+ Diagnostic &parent = Engine.TentativeDiagnostics[PrevDiagnostics];
+
+ // Associate the children with the parent.
+ for (auto diag =
+ Engine.TentativeDiagnostics.begin() + PrevDiagnostics + 1;
+ diag != Engine.TentativeDiagnostics.end(); ++diag) {
+ diag->setIsChildNote(true);
+ parent.addChildNote(std::move(*diag));
+ }
+
+ // Erase the children, they'll be emitted alongside their parent.
+ Engine.TentativeDiagnostics.erase(Engine.TentativeDiagnostics.begin() +
+ PrevDiagnostics + 1,
+ Engine.TentativeDiagnostics.end());
+
+ DiagnosticTransaction::commit();
+ }
+ };
+
+ inline void
+ DiagnosticEngine::diagnoseWithNotes(InFlightDiagnostic parentDiag,
+ llvm::function_ref builder) {
+ CompoundDiagnosticTransaction transaction(*this);
+ parentDiag.flush();
+ builder();
+ }
+
} // end namespace swift
#endif
diff --git a/include/swift/AST/DiagnosticsClangImporter.def b/include/swift/AST/DiagnosticsClangImporter.def
index bad492d8f0a..285694e764b 100644
--- a/include/swift/AST/DiagnosticsClangImporter.def
+++ b/include/swift/AST/DiagnosticsClangImporter.def
@@ -91,10 +91,6 @@ WARNING(implicit_bridging_header_imported_from_module,none,
"is deprecated and will be removed in a later version of Swift",
(StringRef, Identifier))
-WARNING(clang_vfs_overlay_is_ignored,none,
- "ignoring '-ivfsoverlay' options provided to '-Xcc' in favor of "
- "'-vfsoverlay'", ())
-
#ifndef DIAG_NO_UNDEF
# if defined(DIAG)
# undef DIAG
diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h
index 4bc41f1e37f..ba6a43eeb3b 100644
--- a/include/swift/AST/GenericSignatureBuilder.h
+++ b/include/swift/AST/GenericSignatureBuilder.h
@@ -92,10 +92,10 @@ public:
class ResolvedType;
using UnresolvedRequirementRHS =
- llvm::PointerUnion3;
+ llvm::PointerUnion;
using RequirementRHS =
- llvm::PointerUnion3;
+ llvm::PointerUnion;
/// The location of a requirement as written somewhere in the source.
typedef llvm::PointerUnion
@@ -1373,8 +1373,8 @@ class GenericSignatureBuilder::FloatingRequirementSource {
} kind;
using Storage =
- llvm::PointerUnion3;
+ llvm::PointerUnion;
Storage storage;
diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h
index 4517315cf46..035fc07c424 100644
--- a/include/swift/AST/Identifier.h
+++ b/include/swift/AST/Identifier.h
@@ -56,8 +56,26 @@ class Identifier {
const char *Pointer;
+public:
+ enum : size_t {
+ NumLowBitsAvailable = 2,
+ RequiredAlignment = 1 << NumLowBitsAvailable,
+ SpareBitMask = ((intptr_t)1 << NumLowBitsAvailable) - 1
+ };
+
+private:
/// Constructor, only accessible by ASTContext, which handles the uniquing.
- explicit Identifier(const char *Ptr) : Pointer(Ptr) {}
+ explicit Identifier(const char *Ptr) : Pointer(Ptr) {
+ assert(((uintptr_t)Ptr & SpareBitMask) == 0
+ && "Identifier pointer does not use any spare bits");
+ }
+
+ /// A type with the alignment expected of a valid \c Identifier::Pointer .
+ struct alignas(uint32_t) Aligner {};
+
+ static_assert(alignof(Aligner) >= RequiredAlignment,
+ "Identifier table will provide enough spare bits");
+
public:
explicit Identifier() : Pointer(nullptr) {}
@@ -153,12 +171,15 @@ public:
bool operator<(Identifier RHS) const { return Pointer < RHS.Pointer; }
static Identifier getEmptyKey() {
- return Identifier((const char*)
- llvm::DenseMapInfo::getEmptyKey());
+ uintptr_t Val = static_cast(-1);
+ Val <<= NumLowBitsAvailable;
+ return Identifier((const char*)Val);
}
+
static Identifier getTombstoneKey() {
- return Identifier((const char*)
- llvm::DenseMapInfo::getTombstoneKey());
+ uintptr_t Val = static_cast(-2);
+ Val <<= NumLowBitsAvailable;
+ return Identifier((const char*)Val);
}
private:
@@ -202,7 +223,7 @@ namespace llvm {
static inline swift::Identifier getFromVoidPointer(void *P) {
return swift::Identifier::getFromOpaquePointer(P);
}
- enum { NumLowBitsAvailable = 2 };
+ enum { NumLowBitsAvailable = swift::Identifier::NumLowBitsAvailable };
};
} // end namespace llvm
@@ -221,15 +242,15 @@ public:
};
private:
- /// In a special DeclName represenenting a subscript, this opaque pointer
+ /// In a special DeclName representing a subscript, this opaque pointer
/// is used as the data of the base name identifier.
/// This is an implementation detail that should never leak outside of
/// DeclName.
- static void *SubscriptIdentifierData;
+ static const Identifier::Aligner SubscriptIdentifierData;
/// As above, for special constructor DeclNames.
- static void *ConstructorIdentifierData;
+ static const Identifier::Aligner ConstructorIdentifierData;
/// As above, for special destructor DeclNames.
- static void *DestructorIdentifierData;
+ static const Identifier::Aligner DestructorIdentifierData;
Identifier Ident;
@@ -239,23 +260,23 @@ public:
DeclBaseName(Identifier I) : Ident(I) {}
static DeclBaseName createSubscript() {
- return DeclBaseName(Identifier((const char *)SubscriptIdentifierData));
+ return DeclBaseName(Identifier((const char *)&SubscriptIdentifierData));
}
static DeclBaseName createConstructor() {
- return DeclBaseName(Identifier((const char *)ConstructorIdentifierData));
+ return DeclBaseName(Identifier((const char *)&ConstructorIdentifierData));
}
static DeclBaseName createDestructor() {
- return DeclBaseName(Identifier((const char *)DestructorIdentifierData));
+ return DeclBaseName(Identifier((const char *)&DestructorIdentifierData));
}
Kind getKind() const {
- if (Ident.get() == SubscriptIdentifierData) {
+ if (Ident.get() == (const char *)&SubscriptIdentifierData) {
return Kind::Subscript;
- } else if (Ident.get() == ConstructorIdentifierData) {
+ } else if (Ident.get() == (const char *)&ConstructorIdentifierData) {
return Kind::Constructor;
- } else if (Ident.get() == DestructorIdentifierData) {
+ } else if (Ident.get() == (const char *)&DestructorIdentifierData) {
return Kind::Destructor;
} else {
return Kind::Normal;
@@ -720,7 +741,7 @@ namespace llvm {
static inline swift::DeclName getFromVoidPointer(void *ptr) {
return swift::DeclName::getFromOpaqueValue(ptr);
}
- enum { NumLowBitsAvailable = 0 };
+ enum { NumLowBitsAvailable = PointerLikeTypeTraits::NumLowBitsAvailable - 2 };
};
// DeclNames hash just like pointers.
diff --git a/include/swift/AST/ModuleLoader.h b/include/swift/AST/ModuleLoader.h
index 8aca44f43b3..af1d372659b 100644
--- a/include/swift/AST/ModuleLoader.h
+++ b/include/swift/AST/ModuleLoader.h
@@ -24,6 +24,10 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/TinyPtrVector.h"
+namespace llvm {
+class FileCollector;
+}
+
namespace clang {
class DependencyCollector;
}
@@ -54,8 +58,9 @@ enum class Bridgeability : unsigned {
class DependencyTracker {
std::shared_ptr clangCollector;
public:
-
- explicit DependencyTracker(bool TrackSystemDeps);
+ explicit DependencyTracker(
+ bool TrackSystemDeps,
+ std::shared_ptr FileCollector = {});
/// Adds a file as a dependency.
///
diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h
index c6eddea58bc..86d95675531 100644
--- a/include/swift/AST/SearchPathOptions.h
+++ b/include/swift/AST/SearchPathOptions.h
@@ -13,6 +13,7 @@
#ifndef SWIFT_AST_SEARCHPATHOPTIONS_H
#define SWIFT_AST_SEARCHPATHOPTIONS_H
+#include "swift/Basic/ArrayRefView.h"
#include "llvm/ADT/Hashing.h"
#include
@@ -81,30 +82,38 @@ public:
/// would for a non-system header.
bool DisableModulesValidateSystemDependencies = false;
+private:
+ static StringRef
+ pathStringFromFrameworkSearchPath(const FrameworkSearchPath &next) {
+ return next.Path;
+ };
+
+public:
/// Return a hash code of any components from these options that should
/// contribute to a Swift Bridging PCH hash.
llvm::hash_code getPCHHashComponents() const {
- using llvm::hash_value;
using llvm::hash_combine;
- auto Code = hash_value(SDKPath);
- for (auto Import : ImportSearchPaths) {
- Code = hash_combine(Code, Import);
- }
- for (auto VFSFile : VFSOverlayFiles) {
- Code = hash_combine(Code, VFSFile);
- }
- for (const auto &FrameworkPath : FrameworkSearchPaths) {
- Code = hash_combine(Code, FrameworkPath.Path);
- }
- for (auto LibraryPath : LibrarySearchPaths) {
- Code = hash_combine(Code, LibraryPath);
- }
- Code = hash_combine(Code, RuntimeResourcePath);
- for (auto RuntimeLibraryImportPath : RuntimeLibraryImportPaths) {
- Code = hash_combine(Code, RuntimeLibraryImportPath);
- }
- Code = hash_combine(Code, DisableModulesValidateSystemDependencies);
- return Code;
+ using llvm::hash_combine_range;
+
+ using FrameworkPathView = ArrayRefView;
+ FrameworkPathView frameworkPathsOnly{FrameworkSearchPaths};
+
+ return hash_combine(SDKPath,
+ hash_combine_range(ImportSearchPaths.begin(),
+ ImportSearchPaths.end()),
+ hash_combine_range(VFSOverlayFiles.begin(),
+ VFSOverlayFiles.end()),
+ // FIXME: Should we include the system-ness of framework
+ // search paths too?
+ hash_combine_range(frameworkPathsOnly.begin(),
+ frameworkPathsOnly.end()),
+ hash_combine_range(LibrarySearchPaths.begin(),
+ LibrarySearchPaths.end()),
+ RuntimeResourcePath,
+ hash_combine_range(RuntimeLibraryImportPaths.begin(),
+ RuntimeLibraryImportPaths.end()),
+ DisableModulesValidateSystemDependencies);
}
};
diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h
index 2df81da4998..510a7c21032 100644
--- a/include/swift/AST/TypeCheckRequests.h
+++ b/include/swift/AST/TypeCheckRequests.h
@@ -367,7 +367,7 @@ struct WhereClauseOwner {
/// The source of the where clause, which can be a generic parameter list
/// or a declaration that can have a where clause.
- llvm::PointerUnion3 source;
+ llvm::PointerUnion source;
WhereClauseOwner(Decl *decl);
@@ -380,8 +380,7 @@ struct WhereClauseOwner {
SourceLoc getLoc() const;
friend hash_code hash_value(const WhereClauseOwner &owner) {
- return hash_combine(hash_value(owner.dc),
- hash_value(owner.source.getOpaqueValue()));
+ return llvm::hash_combine(owner.dc, owner.source.getOpaqueValue());
}
friend bool operator==(const WhereClauseOwner &lhs,
@@ -1209,6 +1208,7 @@ public:
bool isCached() const { return true; }
Optional getCachedResult() const;
void cacheResult(Type value) const;
+ void diagnoseCycle(DiagnosticEngine &diags) const;
};
class OperatorPrecedenceGroupRequest
@@ -1230,6 +1230,48 @@ public:
bool isCached() const { return true; }
};
+class EnumRawValuesRequest :
+ public SimpleRequest {
+public:
+ using SimpleRequest::SimpleRequest;
+
+private:
+ friend SimpleRequest;
+
+ // Evaluation.
+ llvm::Expected
+ evaluate(Evaluator &evaluator, EnumDecl *ED, TypeResolutionStage stage) const;
+
+public:
+ // Cycle handling.
+ void diagnoseCycle(DiagnosticEngine &diags) const;
+ void noteCycleStep(DiagnosticEngine &diags) const;
+
+ // Separate caching.
+ bool isCached() const;
+ Optional getCachedResult() const;
+ void cacheResult(bool value) const;
+};
+
+class IsABICompatibleOverrideRequest
+ : public SimpleRequest {
+public:
+ using SimpleRequest::SimpleRequest;
+
+private:
+ friend SimpleRequest;
+
+ // Evaluation.
+ llvm::Expected evaluate(Evaluator &evaluator, ValueDecl *decl) const;
+
+public:
+ // Caching.
+ bool isCached() const { return true; }
+};
+
// Allow AnyValue to compare two Type values, even though Type doesn't
// support ==.
template<>
diff --git a/include/swift/AST/TypeCheckerTypeIDZone.def b/include/swift/AST/TypeCheckerTypeIDZone.def
index 3dceae84ada..c5e56a34a6a 100644
--- a/include/swift/AST/TypeCheckerTypeIDZone.def
+++ b/include/swift/AST/TypeCheckerTypeIDZone.def
@@ -36,6 +36,9 @@ SWIFT_REQUEST(TypeChecker, DefaultTypeRequest,
NoLocationInfo)
SWIFT_REQUEST(TypeChecker, EmittedMembersRequest, DeclRange(ClassDecl *),
SeparatelyCached, NoLocationInfo)
+SWIFT_REQUEST(TypeChecker, EnumRawValuesRequest,
+ bool (EnumDecl *, TypeResolutionStage), SeparatelyCached,
+ NoLocationInfo)
SWIFT_REQUEST(TypeChecker, EnumRawTypeRequest,
Type(EnumDecl *, TypeResolutionStage), SeparatelyCached,
NoLocationInfo)
@@ -139,3 +142,5 @@ SWIFT_REQUEST(TypeChecker, UnderlyingTypeRequest, Type(TypeAliasDecl *),
SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, USRGenerationRequest, std::string(const ValueDecl *),
Cached, NoLocationInfo)
+SWIFT_REQUEST(TypeChecker, IsABICompatibleOverrideRequest,
+ bool(ValueDecl *), Cached, NoLocationInfo)
diff --git a/include/swift/AST/TypeLoc.h b/include/swift/AST/TypeLoc.h
index 51356fa7d2f..bf4904514a7 100644
--- a/include/swift/AST/TypeLoc.h
+++ b/include/swift/AST/TypeLoc.h
@@ -68,8 +68,7 @@ public:
TypeLoc clone(ASTContext &ctx) const;
friend llvm::hash_code hash_value(const TypeLoc &owner) {
- return hash_combine(llvm::hash_value(owner.Ty.getPointer()),
- llvm::hash_value(owner.TyR));
+ return llvm::hash_combine(owner.Ty.getPointer(), owner.TyR);
}
friend bool operator==(const TypeLoc &lhs,
diff --git a/include/swift/Basic/LLVM.h b/include/swift/Basic/LLVM.h
index ad6327b7432..3ce78f9e583 100644
--- a/include/swift/Basic/LLVM.h
+++ b/include/swift/Basic/LLVM.h
@@ -42,8 +42,7 @@ namespace llvm {
template class MutableArrayRef;
template class TinyPtrVector;
template class Optional;
- template class PointerUnion;
- template class PointerUnion3;
+ template class PointerUnion;
class SmallBitVector;
// Other common classes.
@@ -68,7 +67,6 @@ namespace swift {
using llvm::None;
using llvm::Optional;
using llvm::PointerUnion;
- using llvm::PointerUnion3;
using llvm::SmallBitVector;
using llvm::SmallPtrSet;
using llvm::SmallPtrSetImpl;
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 74e80db3f05..96e35f5dff9 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -441,12 +441,10 @@ namespace swift {
/// Return a hash code of any components from these options that should
/// contribute to a Swift Bridging PCH hash.
llvm::hash_code getPCHHashComponents() const {
- auto code = llvm::hash_value(Target.str());
SmallString<16> Scratch;
llvm::raw_svector_ostream OS(Scratch);
OS << EffectiveLanguageVersion;
- code = llvm::hash_combine(code, OS.str());
- return code;
+ return llvm::hash_combine(Target.str(), OS.str());
}
private:
diff --git a/include/swift/Basic/STLExtras.h b/include/swift/Basic/STLExtras.h
index 1fad1fa1696..231737fecaf 100644
--- a/include/swift/Basic/STLExtras.h
+++ b/include/swift/Basic/STLExtras.h
@@ -253,7 +253,7 @@ inline Iterator prev_or_begin(Iterator it, Iterator begin) {
/// A range of iterators.
/// TODO: Add `llvm::iterator_range::empty()`, then remove this helper, along
-/// with the superfluous FilterIterator and TransformIterator.
+/// with the superfluous TransformIterator.
template
class IteratorRange {
Iterator First, Last;
@@ -279,136 +279,6 @@ makeIteratorRange(Iterator first, Iterator last) {
return IteratorRange(first, last);
}
-/// An iterator that filters the results of an underlying forward
-/// iterator, only passing through those values that satisfy a predicate.
-///
-/// \tparam Iterator the underlying iterator.
-///
-/// \tparam Predicate A predicate that determines whether a value of the
-/// underlying iterator is available in the resulting sequence.
-template
-class FilterIterator {
- Iterator Current, End;
-
- /// FIXME: Could optimize away this storage with EBCO tricks.
- Predicate Pred;
-
- /// Skip any non-matching elements.
- void skipNonMatching() {
- while (Current != End && !Pred(*Current))
- ++Current;
- }
-
-public:
- /// Used to indicate when the current iterator has already been
- /// "primed", meaning that it's at the end or points to a value that
- /// satisfies the predicate.
- enum PrimedT { Primed };
-
- using iterator_category = std::forward_iterator_tag;
- using value_type = typename std::iterator_traits::value_type;
- using reference = typename std::iterator_traits::reference;
- using pointer = typename std::iterator_traits::pointer;
- using difference_type =
- typename std::iterator_traits::difference_type;
-
- /// Construct a new filtering iterator for the given iterator range
- /// and predicate.
- FilterIterator(Iterator current, Iterator end, Predicate pred)
- : Current(current), End(end), Pred(pred)
- {
- // Prime the iterator.
- skipNonMatching();
- }
-
- /// Construct a new filtering iterator for the given iterator range
- /// and predicate, where the iterator range has already been
- /// "primed" by ensuring that it is empty or the current iterator
- /// points to something that matches the predicate.
- FilterIterator(Iterator current, Iterator end, Predicate pred, PrimedT)
- : Current(current), End(end), Pred(pred)
- {
- // Assert that the iterators have already been primed.
- assert(Current == End || Pred(*Current) && "Not primed!");
- }
-
- reference operator*() const {
- return *Current;
- }
-
- pointer operator->() const {
- return Current.operator->();
- }
-
- FilterIterator &operator++() {
- ++Current;
- skipNonMatching();
- return *this;
- }
-
- FilterIterator operator++(int) {
- FilterIterator old = *this;
- ++*this;
- return old;
- }
-
- friend bool operator==(FilterIterator lhs, FilterIterator rhs) {
- return lhs.Current == rhs.Current;
- }
- friend bool operator!=(FilterIterator lhs, FilterIterator rhs) {
- return !(lhs == rhs);
- }
-};
-
-/// Create a new filter iterator.
-template
-inline FilterIterator
-makeFilterIterator(Iterator current, Iterator end, Predicate pred) {
- return FilterIterator(current, end, pred);
-}
-
-/// A range filtered by a specific predicate.
-template
-class FilterRange {
- using Iterator = typename Range::iterator;
-
- Iterator First, Last;
- Predicate Pred;
-
-public:
- using iterator = FilterIterator;
-
- FilterRange(Range range, Predicate pred)
- : First(range.begin()), Last(range.end()), Pred(pred)
- {
- // Prime the sequence.
- while (First != Last && !Pred(*First))
- ++First;
- }
-
- iterator begin() const {
- return iterator(First, Last, Pred, iterator::Primed);
- }
-
- iterator end() const {
- return iterator(Last, Last, Pred, iterator::Primed);
- }
-
- bool empty() const { return First == Last; }
-
- typename std::iterator_traits::value_type front() const {
- assert(!empty() && "Front of empty range");
- return *begin();
- }
-};
-
-/// Create a new filter range.
-template
-inline FilterRange
-makeFilterRange(Range range, Predicate pred) {
- return FilterRange(range, pred);
-}
-
/// An iterator that transforms the result of an underlying bidirectional
/// iterator with a given operation.
///
@@ -488,7 +358,7 @@ class TransformRange {
Operation Op;
public:
- using iterator = TransformIterator;
+ using iterator = TransformIterator;
TransformRange(Range range, Operation op)
: Rng(range), Op(op) { }
@@ -497,6 +367,20 @@ public:
iterator end() const { return iterator(Rng.end(), Op); }
bool empty() const { return begin() == end(); }
+ // The dummy template parameter keeps 'size()' from being eagerly
+ // instantiated.
+ template
+ typename function_traits::result_type
+ size() const {
+ return Rng.size();
+ }
+
+ template
+ typename function_traits::result_type
+ operator[](Index index) const {
+ return Op(Rng[index]);
+ }
+
typename std::iterator_traits::value_type front() const {
assert(!empty() && "Front of empty range");
return *begin();
diff --git a/include/swift/Basic/SourceLoc.h b/include/swift/Basic/SourceLoc.h
index 594dadae7ec..7d351d675a6 100644
--- a/include/swift/Basic/SourceLoc.h
+++ b/include/swift/Basic/SourceLoc.h
@@ -265,10 +265,8 @@ template <> struct DenseMapInfo {
}
static unsigned getHashValue(const swift::SourceRange &Val) {
- return hash_combine(DenseMapInfo::getHashValue(
- Val.Start.getOpaquePointerValue()),
- DenseMapInfo::getHashValue(
- Val.End.getOpaquePointerValue()));
+ return hash_combine(Val.Start.getOpaquePointerValue(),
+ Val.End.getOpaquePointerValue());
}
static bool isEqual(const swift::SourceRange &LHS,
diff --git a/include/swift/Basic/TransformArrayRef.h b/include/swift/Basic/TransformArrayRef.h
deleted file mode 100644
index ce43292f494..00000000000
--- a/include/swift/Basic/TransformArrayRef.h
+++ /dev/null
@@ -1,136 +0,0 @@
-//===--- TransformArrayRef.h ------------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// This file defines TransformArrayRef, a template class that provides a
-/// transformed view of an ArrayRef. The difference from ArrayRefView is that
-/// ArrayRefView takes its transform as a template argument, while
-/// TransformArrayRef only takes a type as its template argument. This means it
-/// can be used to define types used with forward declaration pointers without
-/// needing to define the relevant function in headers.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef SWIFT_BASIC_TRANSFORMARRAYREF_H
-#define SWIFT_BASIC_TRANSFORMARRAYREF_H
-
-#include "swift/Basic/STLExtras.h"
-#include "llvm/ADT/ArrayRef.h"
-
-namespace swift {
-
-/// A transformation of an ArrayRef using a function of type FuncTy. This is
-/// different than ArrayRefView since the underlying function is stored instead
-/// of used as a template parameter. This allows it to be used in declarations
-/// where the underlying function is not known. This is useful when defining the
-/// underlying function would require forward declarations to need to be
-/// defined.
-template
-class TransformArrayRef {
-public:
- using FunctionTraits = function_traits;
- using Orig =
- typename std::tuple_element<0, typename FunctionTraits::argument_types>::type;
- using Projected = typename FunctionTraits::result_type;
-
-private:
- llvm::ArrayRef Array;
- FuncTy Func;
-
-public:
- TransformArrayRef(llvm::ArrayRef array, FuncTy func) : Array(array), Func(func) {}
-
- class iterator {
- friend class TransformArrayRef;
- const Orig *Ptr;
- FuncTy Func;
- iterator(const Orig *ptr, FuncTy func) : Ptr(ptr), Func(func) {}
- public:
- using value_type = Projected;
- using reference = Projected;
- using pointer = void;
- using difference_type = ptrdiff_t;
- using iterator_category = std::random_access_iterator_tag;
-
- Projected operator*() const { return Func(*Ptr); }
- iterator &operator++() { Ptr++; return *this; }
- iterator operator++(int) { return iterator(Ptr++, Func); }
- iterator &operator--() { --Ptr; return *this; }
- iterator operator--(int) { return iterator(Ptr--, Func); }
-
- bool operator==(iterator rhs) const { return Ptr == rhs.Ptr; }
- bool operator!=(iterator rhs) const { return Ptr != rhs.Ptr; }
-
- iterator &operator+=(difference_type i) {
- Ptr += i;
- return *this;
- }
- iterator operator+(difference_type i) const {
- return iterator(Ptr + i, Func);
- }
- friend iterator operator+(difference_type i, iterator base) {
- return iterator(base.Ptr + i, base.Func);
- }
- iterator &operator-=(difference_type i) {
- Ptr -= i;
- return *this;
- }
- iterator operator-(difference_type i) const {
- return iterator(Ptr - i, Func);
- }
- difference_type operator-(iterator rhs) const {
- return Ptr - rhs.Ptr;
- }
- Projected operator[](difference_type i) const {
- return Func(Ptr[i]);
- }
- bool operator<(iterator rhs) const {
- return Ptr < rhs.Ptr;
- }
- bool operator<=(iterator rhs) const {
- return Ptr <= rhs.Ptr;
- }
- bool operator>(iterator rhs) const {
- return Ptr > rhs.Ptr;
- }
- bool operator>=(iterator rhs) const {
- return Ptr >= rhs.Ptr;
- }
- };
- iterator begin() const { return iterator(Array.begin(), Func); }
- iterator end() const { return iterator(Array.end(), Func); }
-
- bool empty() const { return Array.empty(); }
- size_t size() const { return Array.size(); }
- Projected operator[](unsigned i) const { return Func(Array[i]); }
- Projected front() const { return Func(Array.front()); }
- Projected back() const { return Func(Array.back()); }
-
- TransformArrayRef slice(unsigned start) const {
- return TransformArrayRef(Array.slice(start), Func);
- }
- TransformArrayRef slice(unsigned start, unsigned length) const {
- return TransformArrayRef(Array.slice(start, length), Func);
- }
-};
-
-template
-TransformArrayRef>
-makeTransformArrayRef(llvm::ArrayRef Array,
- std::function Func) {
- return TransformArrayRef(Array, Func);
-}
-
-} // namespace swift
-
-#endif
diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h
index bd4a68d73d9..eaa9ecd7a29 100644
--- a/include/swift/ClangImporter/ClangImporter.h
+++ b/include/swift/ClangImporter/ClangImporter.h
@@ -23,6 +23,7 @@
namespace llvm {
class Triple;
+ class FileCollector;
template class function_ref;
}
@@ -149,7 +150,8 @@ public:
/// Create a new clang::DependencyCollector customized to
/// ClangImporter's specific uses.
static std::shared_ptr
- createDependencyCollector(bool TrackSystemDeps);
+ createDependencyCollector(bool TrackSystemDeps,
+ std::shared_ptr FileCollector);
/// Append visible module names to \p names. Note that names are possibly
/// duplicated, and not guaranteed to be ordered in any way.
diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h
index 5e3f0afda83..3cfa1ba678c 100644
--- a/include/swift/ClangImporter/ClangImporterOptions.h
+++ b/include/swift/ClangImporter/ClangImporterOptions.h
@@ -96,29 +96,24 @@ public:
/// When set, don't enforce warnings with -Werror.
bool DebuggerSupport = false;
- /// When set, clobber the Clang instance's virtual file system with the Swift
- /// virtual file system.
- bool ForceUseSwiftVirtualFileSystem = false;
-
/// Return a hash code of any components from these options that should
/// contribute to a Swift Bridging PCH hash.
llvm::hash_code getPCHHashComponents() const {
- using llvm::hash_value;
using llvm::hash_combine;
+ using llvm::hash_combine_range;
- auto Code = hash_value(ModuleCachePath);
- // ExtraArgs ignored - already considered in Clang's module hashing.
- Code = hash_combine(Code, OverrideResourceDir);
- Code = hash_combine(Code, TargetCPU);
- Code = hash_combine(Code, BridgingHeader);
- Code = hash_combine(Code, PrecompiledHeaderOutputDir);
- Code = hash_combine(Code, static_cast(Mode));
- Code = hash_combine(Code, DetailedPreprocessingRecord);
- Code = hash_combine(Code, ImportForwardDeclarations);
- Code = hash_combine(Code, InferImportAsMember);
- Code = hash_combine(Code, DisableSwiftBridgeAttr);
- Code = hash_combine(Code, DisableOverlayModules);
- return Code;
+ return hash_combine(ModuleCachePath,
+ hash_combine_range(ExtraArgs.begin(), ExtraArgs.end()),
+ OverrideResourceDir,
+ TargetCPU,
+ BridgingHeader,
+ PrecompiledHeaderOutputDir,
+ static_cast(Mode),
+ DetailedPreprocessingRecord,
+ ImportForwardDeclarations,
+ InferImportAsMember,
+ DisableSwiftBridgeAttr,
+ DisableOverlayModules);
}
};
diff --git a/include/swift/Frontend/PrintingDiagnosticConsumer.h b/include/swift/Frontend/PrintingDiagnosticConsumer.h
index 22a7696c2ac..b6768f1591f 100644
--- a/include/swift/Frontend/PrintingDiagnosticConsumer.h
+++ b/include/swift/Frontend/PrintingDiagnosticConsumer.h
@@ -50,6 +50,13 @@ public:
bool didErrorOccur() {
return DidErrorOccur;
}
+
+private:
+ void printDiagnostic(SourceManager &SM, SourceLoc Loc, DiagnosticKind Kind,
+ StringRef FormatString,
+ ArrayRef FormatArgs,
+ const DiagnosticInfo &Info,
+ SourceLoc bufferIndirectlyCausingDiagnostic);
};
}
diff --git a/include/swift/IDE/IDERequests.h b/include/swift/IDE/IDERequests.h
index 2247fe65afa..11351e59c85 100644
--- a/include/swift/IDE/IDERequests.h
+++ b/include/swift/IDE/IDERequests.h
@@ -38,8 +38,7 @@ struct CursorInfoOwner {
CursorInfoOwner(SourceFile *File, SourceLoc Loc): File(File), Loc(Loc) { }
friend llvm::hash_code hash_value(const CursorInfoOwner &CI) {
- return hash_combine(hash_value(CI.File),
- hash_value(CI.Loc.getOpaquePointerValue()));
+ return llvm::hash_combine(CI.File, CI.Loc.getOpaquePointerValue());
}
friend bool operator==(const CursorInfoOwner &lhs, const CursorInfoOwner &rhs) {
@@ -97,9 +96,9 @@ struct RangeInfoOwner {
RangeInfoOwner(SourceFile *File, unsigned Offset, unsigned Length);
friend llvm::hash_code hash_value(const RangeInfoOwner &CI) {
- return hash_combine(hash_value(CI.File),
- hash_value(CI.StartLoc.getOpaquePointerValue()),
- hash_value(CI.EndLoc.getOpaquePointerValue()));
+ return llvm::hash_combine(CI.File,
+ CI.StartLoc.getOpaquePointerValue(),
+ CI.EndLoc.getOpaquePointerValue());
}
friend bool operator==(const RangeInfoOwner &lhs, const RangeInfoOwner &rhs) {
@@ -183,9 +182,9 @@ struct OverridenDeclsOwner {
Transitive(Transitive) {}
friend llvm::hash_code hash_value(const OverridenDeclsOwner &CI) {
- return hash_combine(hash_value(CI.VD),
- hash_value(CI.IncludeProtocolRequirements),
- hash_value(CI.Transitive));
+ return llvm::hash_combine(CI.VD,
+ CI.IncludeProtocolRequirements,
+ CI.Transitive);
}
friend bool operator==(const OverridenDeclsOwner &lhs,
diff --git a/include/swift/LLVMPasses/Passes.h b/include/swift/LLVMPasses/Passes.h
index 6a17d7ce46f..4594d11fec6 100644
--- a/include/swift/LLVMPasses/Passes.h
+++ b/include/swift/LLVMPasses/Passes.h
@@ -30,8 +30,14 @@ namespace swift {
const llvm::PreservedAnalyses &) { return false; }
using AAResultBase::getModRefInfo;
- llvm::ModRefInfo getModRefInfo(llvm::ImmutableCallSite CS,
- const llvm::MemoryLocation &Loc);
+ llvm::ModRefInfo getModRefInfo(const llvm::CallBase *Call,
+ const llvm::MemoryLocation &Loc) {
+ llvm::AAQueryInfo AAQI;
+ return getModRefInfo(Call, Loc, AAQI);
+ }
+ llvm::ModRefInfo getModRefInfo(const llvm::CallBase *Call,
+ const llvm::MemoryLocation &Loc,
+ llvm::AAQueryInfo &AAQI);
};
class SwiftAAWrapperPass : public llvm::ImmutablePass {
diff --git a/include/swift/Parse/ASTGen.h b/include/swift/Parse/ASTGen.h
index fe555157065..bfb1270075c 100644
--- a/include/swift/Parse/ASTGen.h
+++ b/include/swift/Parse/ASTGen.h
@@ -16,6 +16,7 @@
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
+#include "swift/AST/TypeRepr.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Syntax/SyntaxNodes.h"
#include "llvm/ADT/DenseMap.h"
@@ -36,9 +37,8 @@ class ASTGen {
// FIXME: remove when Syntax can represent all types and ASTGen can handle
// them
- /// Types that cannot be represented by Syntax or generated by ASTGen.
- llvm::DenseMap Types;
-
+ /// Decl attributes that cannot be represented by Syntax or generated by
+ /// ASTGen.
llvm::DenseMap ParsedDeclAttrs;
public:
@@ -46,6 +46,35 @@ public:
SourceLoc generate(const syntax::TokenSyntax &Tok, const SourceLoc Loc);
+ SourceLoc generateIdentifierDeclName(const syntax::TokenSyntax &Tok,
+ const SourceLoc, Identifier &Identifier);
+
+public:
+ //===--------------------------------------------------------------------===//
+ // Decls.
+
+ Decl *generate(const syntax::DeclSyntax &Decl, const SourceLoc Loc);
+ TypeDecl *generate(const syntax::AssociatedtypeDeclSyntax &Decl,
+ const SourceLoc Loc);
+ TypeDecl *generate(const syntax::TypealiasDeclSyntax &Decl,
+ const SourceLoc Loc);
+
+ TrailingWhereClause *generate(const syntax::GenericWhereClauseSyntax &syntax,
+ const SourceLoc Loc);
+ MutableArrayRef
+ generate(const syntax::TypeInheritanceClauseSyntax &syntax,
+ const SourceLoc Loc, bool allowClassRequirement);
+
+private:
+ DeclAttributes
+ generateDeclAttributes(const syntax::Syntax &D, SourceLoc Loc,
+ bool includeComments);
+
+ void generateFreeStandingGenericWhereClause(
+ const syntax::GenericWhereClauseSyntax &syntax,
+ const SourceLoc Loc,
+ GenericParamList *genericParams);
+
public:
//===--------------------------------------------------------------------===//
// Expressions.
@@ -78,7 +107,8 @@ public:
//===--------------------------------------------------------------------===//
// Types.
- TypeRepr *generate(const syntax::TypeSyntax &Type, const SourceLoc Loc);
+ TypeRepr *generate(const syntax::TypeSyntax &Type, const SourceLoc Loc,
+ bool IsSILFuncDecl = false);
TypeRepr *generate(const syntax::SomeTypeSyntax &Type, const SourceLoc Loc);
TypeRepr *generate(const syntax::CompositionTypeSyntax &Type,
const SourceLoc Loc);
@@ -100,11 +130,21 @@ public:
const SourceLoc Loc);
TypeRepr *generate(const syntax::ImplicitlyUnwrappedOptionalTypeSyntax &Type,
const SourceLoc Loc);
+ TypeRepr *generate(const syntax::ClassRestrictionTypeSyntax &Type,
+ const SourceLoc Loc);
+ TypeRepr *generate(const syntax::SILBoxTypeSyntax &Type, const SourceLoc Loc,
+ bool IsSILFuncDecl);
+ TypeRepr *generate(const syntax::SILFunctionTypeSyntax &Type,
+ const SourceLoc Loc, bool IsSILFuncDecl);
TypeRepr *generate(const syntax::CodeCompletionTypeSyntax &Type,
const SourceLoc Loc);
TypeRepr *generate(const syntax::UnknownTypeSyntax &Type,
const SourceLoc Loc);
+ TypeAttributes
+ generateTypeAttributes(const syntax::AttributeListSyntax &syntax,
+ const SourceLoc Loc);
+
private:
TupleTypeRepr *
generateTuple(const syntax::TokenSyntax &LParen,
@@ -169,10 +209,6 @@ private:
TypeRepr *lookupType(syntax::TypeSyntax Type);
public:
- void addType(TypeRepr *Type, const SourceLoc Loc);
- bool hasType(const SourceLoc Loc) const;
- TypeRepr *getType(const SourceLoc Loc) const;
-
void addDeclAttributes(DeclAttributes attrs, const SourceLoc Loc);
bool hasDeclAttributes(SourceLoc Loc) const;
DeclAttributes getDeclAttributes(const SourceLoc Loc) const;
diff --git a/include/swift/Parse/LibSyntaxGenerator.h b/include/swift/Parse/LibSyntaxGenerator.h
index 1333ed74af2..1e8dc2b74b6 100644
--- a/include/swift/Parse/LibSyntaxGenerator.h
+++ b/include/swift/Parse/LibSyntaxGenerator.h
@@ -38,13 +38,14 @@ public:
assert(Node.isDeferredToken());
auto Kind = Node.getTokenKind();
- auto Range = Node.getDeferredTokenRangeWithTrivia();
+ auto Range = Node.getDeferredTokenRange();
auto LeadingTriviaPieces = Node.getDeferredLeadingTriviaPieces();
auto TrailingTriviaPieces = Node.getDeferredTrailingTriviaPieces();
auto Recorded = Recorder.recordToken(Kind, Range, LeadingTriviaPieces,
TrailingTriviaPieces);
- auto Raw = static_cast(Recorded.takeOpaqueNode());
+ RC Raw{static_cast(Recorded.takeOpaqueNode())};
+ Raw->Release(); // -1 since it's transfer of ownership.
return make(Raw);
}
@@ -55,7 +56,7 @@ public:
auto Children = Node.getDeferredChildren();
auto Recorded = Recorder.recordRawSyntax(Kind, Children);
- RC Raw {static_cast(Recorded.takeOpaqueNode()) };
+ RC Raw{static_cast(Recorded.takeOpaqueNode())};
Raw->Release(); // -1 since it's transfer of ownership.
return make(Raw);
}
diff --git a/include/swift/Parse/ParsedRawSyntaxNode.h b/include/swift/Parse/ParsedRawSyntaxNode.h
index eb55cff04b2..4cbd13f6dfb 100644
--- a/include/swift/Parse/ParsedRawSyntaxNode.h
+++ b/include/swift/Parse/ParsedRawSyntaxNode.h
@@ -119,8 +119,20 @@ public:
assert(getTokenKind() == tokKind && "Token kind with too large value!");
}
+#ifndef NDEBUG
+ bool ensureDataIsNotRecorded() {
+ if (DK != DataKind::Recorded)
+ return true;
+ llvm::dbgs() << "Leaking node: ";
+ dump(llvm::dbgs());
+ llvm::dbgs() << "\n";
+ return false;
+ }
+#endif
+
ParsedRawSyntaxNode &operator=(ParsedRawSyntaxNode &&other) {
- assert(DK != DataKind::Recorded);
+ assert(ensureDataIsNotRecorded() &&
+ "recorded data is being destroyed by assignment");
switch (other.DK) {
case DataKind::Null:
break;
@@ -145,7 +157,7 @@ public:
*this = std::move(other);
}
~ParsedRawSyntaxNode() {
- assert(DK != DataKind::Recorded);
+ assert(ensureDataIsNotRecorded() && "recorded data is being destructed");
}
syntax::SyntaxKind getKind() const { return syntax::SyntaxKind(SynKind); }
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index 840b0dac37e..8ddfcae2ffc 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -40,7 +40,7 @@
#include "llvm/ADT/SetVector.h"
namespace llvm {
- template class PointerUnion3;
+ template class PointerUnion;
}
namespace swift {
@@ -1004,12 +1004,28 @@ public:
bool delayParsingDeclList(SourceLoc LBLoc, SourceLoc &RBLoc,
IterableDeclContext *IDC);
+ ParsedSyntaxResult
+ parseTypeInheritanceClauseSyntax(bool allowClassRequirement,
+ bool allowAnyObject);
+
+ ParsedSyntaxResult
+ parseDeclAssociatedTypeSyntax(ParseDeclOptions flags,
+ Optional attrs,
+ Optional modifiers);
+
+ ParsedSyntaxResult
+ parseDeclTypeAliasSyntax(ParseDeclOptions flags,
+ Optional attrs,
+ Optional modifiers);
+
ParserResult parseDeclTypeAlias(ParseDeclOptions Flags,
- DeclAttributes &Attributes);
+ DeclAttributes &Attributes,
+ SourceLoc leadingLoc);
ParserResult parseDeclAssociatedType(ParseDeclOptions Flags,
- DeclAttributes &Attributes);
-
+ DeclAttributes &Attributes,
+ SourceLoc leadingLoc);
+
/// Parse a #if ... #endif directive.
/// Delegate callback function to parse elements in the blocks.
ParserResult parseIfConfig(
@@ -1071,27 +1087,16 @@ public:
/// an error parsing.
bool parseVersionTuple(llvm::VersionTuple &Version, SourceRange &Range,
const Diagnostic &D);
-
bool parseTypeAttributeList(ParamDecl::Specifier &Specifier,
SourceLoc &SpecifierLoc,
- TypeAttributes &Attributes) {
- if (Tok.isAny(tok::at_sign, tok::kw_inout) ||
- (Tok.is(tok::identifier) &&
- (Tok.getRawText().equals("__shared") ||
- Tok.getRawText().equals("__owned"))))
- return parseTypeAttributeListPresent(Specifier, SpecifierLoc, Attributes);
- return false;
- }
- bool parseTypeAttributeListPresent(ParamDecl::Specifier &Specifier,
- SourceLoc &SpecifierLoc,
- TypeAttributes &Attributes);
- bool parseTypeAttribute(TypeAttributes &Attributes, SourceLoc AtLoc,
- bool justChecking = false);
-
-
+ TypeAttributes &Attributes);
+ ParserStatus parseTypeAttributeListSyntax(Optional &specifier,
+ Optional &attrs);
+ ParsedSyntaxResult parseTypeAttributeSyntax();
+
ParserResult parseDeclImport(ParseDeclOptions Flags,
DeclAttributes &Attributes);
- ParserStatus parseInheritance(SmallVectorImpl &Inherited,
+ ParserStatus parseInheritance(MutableArrayRef &Inherited,
bool allowClassRequirement,
bool allowAnyObject);
ParserStatus parseDeclItem(bool &PreviousHadSemi,
@@ -1179,44 +1184,47 @@ public:
//===--------------------------------------------------------------------===//
// Type Parsing
- using TypeASTResult = ParserResult;
- using TypeResult = ParsedSyntaxResult;
+ ParserResult parseType();
+ ParserResult parseType(Diag<> MessageID,
+ bool HandleCodeCompletion = true,
+ bool IsSILFuncDecl = false);
+ ParserStatus parseGenericArguments(llvm::SmallVectorImpl &ArgsAST,
+ SourceLoc &LAngleLoc,
+ SourceLoc &RAngleLoc);
+ TypeRepr *applyAttributeToType(TypeRepr *Ty, const TypeAttributes &Attr,
+ ParamDecl::Specifier Specifier,
+ SourceLoc SpecifierLoc);
+ ParserResult parseAnyTypeAST();
ParsedSyntaxResult
parseLayoutConstraintSyntax();
- TypeResult parseTypeSyntax();
- TypeResult parseTypeSyntax(Diag<> MessageID, bool HandleCodeCompletion = true,
- bool IsSILFuncDecl = false);
-
- TypeASTResult parseType();
- TypeASTResult parseType(Diag<> MessageID, bool HandleCodeCompletion = true,
- bool IsSILFuncDecl = false);
- ParserStatus
- parseGenericArgumentsAST(llvm::SmallVectorImpl &ArgsAST,
- SourceLoc &LAngleLoc, SourceLoc &RAngleLoc);
- TypeASTResult parseSILBoxType(GenericParamList *generics,
- const TypeAttributes &attrs,
- Optional &GenericsScope);
- TypeASTResult parseTypeSimpleOrCompositionAST(Diag<> MessageID,
- bool HandleCodeCompletion);
- TypeASTResult parseAnyTypeAST();
+ ParsedSyntaxResult parseTypeSyntax();
+ ParsedSyntaxResult
+ parseTypeSyntax(Diag<> MessageID, bool HandleCodeCompletion = true,
+ bool IsSILFuncDecl = false);
ParsedSyntaxResult
parseGenericArgumentClauseSyntax();
- TypeResult parseTypeSimple(Diag<> MessageID, bool HandleCodeCompletion);
- TypeResult parseTypeSimpleOrComposition(Diag<> MessageID, bool HandleCodeCompletion);
- TypeResult parseTypeIdentifier();
- TypeResult parseAnyType();
- TypeResult parseTypeTupleBody();
- TypeResult parseTypeCollection();
- TypeResult parseMetatypeType(ParsedTypeSyntax Base);
- TypeResult parseOptionalType(ParsedTypeSyntax Base);
- TypeResult parseImplicitlyUnwrappedOptionalType(ParsedTypeSyntax Base);
+ ParsedSyntaxResult
+ parseTypeSimple(Diag<> MessageID, bool HandleCodeCompletion);
+ ParsedSyntaxResult
+ parseTypeSimpleOrComposition(Diag<> MessageID, bool HandleCodeCompletion);
+ ParsedSyntaxResult parseTypeIdentifier();
+ ParsedSyntaxResult parseAnyType();
+ ParsedSyntaxResult parseTypeTupleBody();
+ ParsedSyntaxResult parseTypeCollection();
+ ParsedSyntaxResult parseMetatypeType(ParsedTypeSyntax Base);
+ ParsedSyntaxResult parseOptionalType(ParsedTypeSyntax Base);
+ ParsedSyntaxResult
+ parseImplicitlyUnwrappedOptionalType(ParsedTypeSyntax Base);
+ ParsedSyntaxResult parseSILBoxTypeSyntax(
+ Optional genericParams);
- TypeResult parseTypeArray(ParsedTypeSyntax Base, SourceLoc BaseLoc);
- TypeResult parseOldStyleProtocolComposition();
+ ParsedSyntaxResult parseTypeArray(ParsedTypeSyntax Base,
+ SourceLoc BaseLoc);
+ ParsedSyntaxResult parseOldStyleProtocolComposition();
bool isOptionalToken(const Token &T) const;
ParsedTokenSyntax consumeOptionalTokenSyntax();
@@ -1226,9 +1234,10 @@ public:
ParsedTokenSyntax consumeImplicitlyUnwrappedOptionalTokenSyntax();
SourceLoc consumeImplicitlyUnwrappedOptionalToken();
- TypeRepr *applyAttributeToType(TypeRepr *Ty, const TypeAttributes &Attr,
- ParamDecl::Specifier Specifier,
- SourceLoc SpecifierLoc);
+ ParsedSyntaxResult
+ applyAttributeToTypeSyntax(ParsedSyntaxResult &&ty,
+ Optional specifier,
+ Optional attrs);
//===--------------------------------------------------------------------===//
// Pattern Parsing
@@ -1624,6 +1633,9 @@ public:
SmallVectorImpl &GenericParams);
ParserResult maybeParseGenericParams();
void
+ diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams,
+ SourceLoc whereLoc);
+ void
diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams);
enum class WhereClauseKind : unsigned {
diff --git a/include/swift/Parse/SyntaxParsingContext.h b/include/swift/Parse/SyntaxParsingContext.h
index 6df76bebca0..96d4d579244 100644
--- a/include/swift/Parse/SyntaxParsingContext.h
+++ b/include/swift/Parse/SyntaxParsingContext.h
@@ -279,17 +279,9 @@ public:
}
/// Returns the topmost Syntax node.
- template SyntaxNode topNode() {
- ParsedRawSyntaxNode &TopNode = getStorage().back();
- if (TopNode.isRecorded()) {
- OpaqueSyntaxNode OpaqueNode = TopNode.getOpaqueNode();
- return getSyntaxCreator().getLibSyntaxNodeFor(OpaqueNode);
- }
- return getSyntaxCreator().createNode(TopNode.copyDeferred());
- }
+ template SyntaxNode topNode();
- template
- llvm::Optional popIf() {
+ template llvm::Optional popIf() {
auto &Storage = getStorage();
if (Storage.size() <= Offset)
return llvm::None;
@@ -376,5 +368,24 @@ public:
"Only meant for use in the debugger");
};
+template
+inline SyntaxNode SyntaxParsingContext::topNode() {
+ ParsedRawSyntaxNode &TopNode = getStorage().back();
+ if (TopNode.isRecorded()) {
+ OpaqueSyntaxNode OpaqueNode = TopNode.getOpaqueNode();
+ return getSyntaxCreator().getLibSyntaxNodeFor(OpaqueNode);
+ }
+ return getSyntaxCreator().createNode(TopNode.copyDeferred());
+}
+
+template <> inline TokenSyntax SyntaxParsingContext::topNode() {
+ ParsedRawSyntaxNode &TopNode = getStorage().back();
+ if (TopNode.isRecorded()) {
+ OpaqueSyntaxNode OpaqueNode = TopNode.getOpaqueNode();
+ return getSyntaxCreator().getLibSyntaxNodeFor(OpaqueNode);
+ }
+ return getSyntaxCreator().createToken(TopNode.copyDeferred());
+}
+
} // namespace swift
#endif // SWIFT_SYNTAX_PARSING_CONTEXT_H
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index 171f2df7b6d..d534379cf54 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -393,6 +393,8 @@ public:
auto SecBuf = this->getReader().readBytes(
RemoteAddress(SectionHdrAddress + (I * SectionEntrySize)),
SectionEntrySize);
+ if (!SecBuf)
+ return false;
auto SecHdr =
reinterpret_cast(SecBuf.get());
SecHdrVec.push_back(SecHdr);
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index 4c88a7b7ad0..abf7d17cd68 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -376,11 +376,8 @@ public:
// Try to resolve to the underlying type, if we can.
if (opaqueDescriptor->getKind() ==
Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
- if (!OpaqueUnderlyingTypeReader)
- return nullptr;
-
auto underlyingTy = OpaqueUnderlyingTypeReader(
- (const void *)opaqueDescriptor->getIndex(), ordinal);
+ opaqueDescriptor->getIndex(), ordinal);
if (!underlyingTy)
return nullptr;
@@ -598,7 +595,7 @@ private:
unsigned PointerSize;
std::function)>
TypeRefDemangler;
- std::function
+ std::function
OpaqueUnderlyingTypeReader;
public:
@@ -613,9 +610,8 @@ public:
Dem, /*useOpaqueTypeSymbolicReferences*/ true);
}),
OpaqueUnderlyingTypeReader(
- [&reader](const void *descriptor, unsigned ordinal) -> const TypeRef* {
- auto context = (typename Runtime::StoredPointer)descriptor;
- return reader.readUnderlyingTypeForOpaqueTypeDescriptor(context,
+ [&reader](uint64_t descriptorAddr, unsigned ordinal) -> const TypeRef* {
+ return reader.readUnderlyingTypeForOpaqueTypeDescriptor(descriptorAddr,
ordinal);
})
{}
diff --git a/include/swift/Remote/CMemoryReader.h b/include/swift/Remote/CMemoryReader.h
index f7575fa6f9c..989f6bf87c6 100644
--- a/include/swift/Remote/CMemoryReader.h
+++ b/include/swift/Remote/CMemoryReader.h
@@ -66,8 +66,13 @@ public:
bool readString(RemoteAddress address, std::string &dest) override {
auto length = getStringLength(address);
- if (!length)
- return false;
+ if (length == 0) {
+ // A length of zero unfortunately might mean either that there's a zero
+ // length string at the location we're trying to read, or that reading
+ // failed. We can do a one-byte read to tell them apart.
+ auto buf = readBytes(address, 1);
+ return buf && ((const char*)buf.get())[0] == 0;
+ }
auto Buf = readBytes(address, length);
if (!Buf)
diff --git a/include/swift/SIL/OptimizationRemark.h b/include/swift/SIL/OptimizationRemark.h
index f5c74888dcc..5accdbc2e76 100644
--- a/include/swift/SIL/OptimizationRemark.h
+++ b/include/swift/SIL/OptimizationRemark.h
@@ -157,9 +157,9 @@ public:
using RemarkT = decltype(RemarkBuilder());
// Avoid building the remark unless remarks are enabled.
if (isEnabled() || Module.getOptRecordStream()) {
- auto R = RemarkBuilder();
- R.setPassName(PassName);
- emit(R);
+ auto rb = RemarkBuilder();
+ rb.setPassName(PassName);
+ emit(rb);
}
}
diff --git a/include/swift/SIL/SILArgumentArrayRef.h b/include/swift/SIL/SILArgumentArrayRef.h
index ce5c1d8ec60..c01a656efd2 100644
--- a/include/swift/SIL/SILArgumentArrayRef.h
+++ b/include/swift/SIL/SILArgumentArrayRef.h
@@ -22,7 +22,6 @@
#include "swift/Basic/LLVM.h"
#include "swift/Basic/STLExtras.h"
-#include "swift/Basic/TransformArrayRef.h"
namespace swift {
@@ -31,10 +30,11 @@ class SILPhiArgument;
class SILFunctionArgument;
using PhiArgumentArrayRef =
- TransformArrayRef>;
+ TransformRange, SILPhiArgument *(*)(SILArgument *)>;
using FunctionArgumentArrayRef =
- TransformArrayRef>;
+ TransformRange,
+ SILFunctionArgument *(*)(SILArgument *)>;
} // namespace swift
diff --git a/include/swift/SIL/SILBasicBlock.h b/include/swift/SIL/SILBasicBlock.h
index 3536aed2f57..db7f53cd6a5 100644
--- a/include/swift/SIL/SILBasicBlock.h
+++ b/include/swift/SIL/SILBasicBlock.h
@@ -19,7 +19,6 @@
#include "swift/Basic/Compiler.h"
#include "swift/Basic/Range.h"
-#include "swift/Basic/TransformArrayRef.h"
#include "swift/SIL/SILArgumentArrayRef.h"
#include "swift/SIL/SILInstruction.h"
diff --git a/include/swift/SIL/SILGlobalVariable.h b/include/swift/SIL/SILGlobalVariable.h
index 0684c4832f2..eedc850458e 100644
--- a/include/swift/SIL/SILGlobalVariable.h
+++ b/include/swift/SIL/SILGlobalVariable.h
@@ -17,7 +17,6 @@
#ifndef SWIFT_SIL_SILGLOBALVARIABLE_H
#define SWIFT_SIL_SILGLOBALVARIABLE_H
-#include
#include "swift/SIL/SILLinkage.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/SILBasicBlock.h"
diff --git a/include/swift/SIL/SILInstructionWorklist.h b/include/swift/SIL/SILInstructionWorklist.h
index af43d47bf4a..36af8225211 100644
--- a/include/swift/SIL/SILInstructionWorklist.h
+++ b/include/swift/SIL/SILInstructionWorklist.h
@@ -33,7 +33,7 @@
#include "swift/Basic/BlotSetVector.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILValue.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/include/swift/SIL/SILValue.h b/include/swift/SIL/SILValue.h
index 46b3eeb573d..03be26fabe5 100644
--- a/include/swift/SIL/SILValue.h
+++ b/include/swift/SIL/SILValue.h
@@ -387,6 +387,18 @@ public:
NumLowBitsAvailable
};
+ /// If this SILValue is a result of an instruction, return its
+ /// defining instruction. Returns nullptr otherwise.
+ SILInstruction *getDefiningInstruction() {
+ return Value->getDefiningInstruction();
+ }
+
+ /// If this SILValue is a result of an instruction, return its
+ /// defining instruction. Returns nullptr otherwise.
+ const SILInstruction *getDefiningInstruction() const {
+ return Value->getDefiningInstruction();
+ }
+
/// Returns the ValueOwnershipKind that describes this SILValue's ownership
/// semantics if the SILValue has ownership semantics. Returns is a value
/// without any Ownership Semantics.
diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h
index 5bca456a3f4..3bbb363945a 100644
--- a/include/swift/SIL/TypeSubstCloner.h
+++ b/include/swift/SIL/TypeSubstCloner.h
@@ -21,10 +21,10 @@
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/Type.h"
-#include "swift/SIL/SILCloner.h"
#include "swift/SIL/DynamicCasts.h"
+#include "swift/SIL/SILCloner.h"
#include "swift/SIL/SILFunctionBuilder.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "llvm/Support/Debug.h"
diff --git a/include/swift/SILOptimizer/Analysis/CFG.h b/include/swift/SILOptimizer/Analysis/CFG.h
deleted file mode 100644
index 2f8b195b1e0..00000000000
--- a/include/swift/SILOptimizer/Analysis/CFG.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===--- CFG.h - Routines which analyze the CFG of a function ---*- 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_SILOPTIMIZER_ANALYSIS_CFG_H
-#define SWIFT_SILOPTIMIZER_ANALYSIS_CFG_H
-
-namespace llvm {
-
-template class TinyPtrVector;
-
-} // end namespace llvm
-
-namespace swift {
-
-class SILFunction;
-class SILBasicBlock;
-
-/// Return true if we conservatively find all BB's that are non-failure exit
-/// basic blocks and place them in \p BBs. If we find something we don't
-/// understand, bail.
-///
-/// A non-failure exit BB is defined as a BB that:
-///
-/// 1. Has a return terminator.
-/// 2. unreachable + noreturn terminator sequence.
-/// 3. has a throw terminator.
-///
-/// If we just have an unreachable without a noreturn call before it, we must
-/// have a failure BB.
-///
-/// We use a TinyPtrVector since in most cases this will only return one
-/// SILBasicBlock since non-failure noreturn functions should not occur often
-/// implying in most cases this will be one element.
-///
-/// TODO:
-bool findAllNonFailureExitBBs(SILFunction *F,
- llvm::TinyPtrVector &BBs);
-
-} // end namespace swift
-
-#endif
diff --git a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h
index b23570c2e49..b2a722f3ed6 100644
--- a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h
@@ -17,7 +17,7 @@
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SILOptimizer/Analysis/Analysis.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
diff --git a/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h b/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h
index ffce0af3c36..c3682a33f01 100644
--- a/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h
+++ b/include/swift/SILOptimizer/Analysis/LoopRegionAnalysis.h
@@ -384,7 +384,7 @@ public:
private:
/// A pointer to one of a Loop, Basic Block, or Function represented by this
/// region.
- llvm::PointerUnion3 Ptr;
+ llvm::PointerUnion Ptr;
/// The ID of this region.
unsigned ID;
diff --git a/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h
new file mode 100644
index 00000000000..2d0bb0e4578
--- /dev/null
+++ b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h
@@ -0,0 +1,260 @@
+//===--- BasicBlockOptUtils.h - SIL basic block utilities -------*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2019 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// Utilities used by the SILOptimizer for analyzing and operating on whole
+/// basic blocks, including as removal, cloning, and SSA update.
+///
+/// CFGOptUtils.h provides lower-level CFG branch and edge utilities.
+///
+/// SIL/BasicBlockUtils.h provides essential SILBasicBlock utilities.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H
+#define SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H
+
+#include "swift/SIL/SILInstruction.h"
+#include "swift/SIL/SILBasicBlock.h"
+#include "swift/SIL/SILCloner.h"
+
+namespace swift {
+
+class BasicBlockCloner;
+class SILLoop;
+class SILLoopInfo;
+
+/// Remove all instructions in the body of \p bb in safe manner by using
+/// undef.
+void clearBlockBody(SILBasicBlock *bb);
+
+/// Handle the mechanical aspects of removing an unreachable block.
+void removeDeadBlock(SILBasicBlock *bb);
+
+/// Remove all unreachable blocks in a function.
+bool removeUnreachableBlocks(SILFunction &f);
+
+/// Return true if there are any users of v outside the specified block.
+inline bool isUsedOutsideOfBlock(SILValue v) {
+ auto *bb = v->getParentBlock();
+ for (auto *use : v->getUses())
+ if (use->getUser()->getParent() != bb)
+ return true;
+ return false;
+}
+
+/// Rotate a loop's header as long as it is exiting and not equal to the
+/// passed basic block.
+/// If \p RotateSingleBlockLoops is true a single basic block loop will be
+/// rotated once. ShouldVerify specifies whether to perform verification after
+/// the transformation.
+/// Returns true if the loop could be rotated.
+bool rotateLoop(SILLoop *loop, DominanceInfo *domInfo, SILLoopInfo *loopInfo,
+ bool rotateSingleBlockLoops, SILBasicBlock *upToBB,
+ bool shouldVerify);
+
+/// Helper function to perform SSA updates in case of jump threading.
+void updateSSAAfterCloning(BasicBlockCloner &cloner, SILBasicBlock *srcBB,
+ SILBasicBlock *destBB);
+
+/// Clone a single basic block and any required successor edges within the same
+/// function.
+class BasicBlockCloner : public SILCloner {
+ using SuperTy = SILCloner;
+ friend class SILCloner;
+
+protected:
+ /// The original block to be cloned.
+ SILBasicBlock *origBB;
+
+public:
+ /// An ordered list of old to new available value pairs.
+ ///
+ /// updateSSAAfterCloning() expects this public field to hold values that may
+ /// be remapped in the cloned block and live out.
+ SmallVector, 16> AvailVals;
+
+ // Clone blocks starting at `origBB`, within the same function.
+ BasicBlockCloner(SILBasicBlock *origBB)
+ : SILCloner(*origBB->getParent()), origBB(origBB) {}
+
+ void cloneBlock(SILBasicBlock *insertAfterBB = nullptr) {
+ SmallVector successorBBs;
+ successorBBs.reserve(origBB->getSuccessors().size());
+ llvm::copy(origBB->getSuccessors(), std::back_inserter(successorBBs));
+ cloneReachableBlocks(origBB, successorBBs, insertAfterBB);
+ }
+
+ /// Clone the given branch instruction's destination block, splitting
+ /// its successors, and rewrite the branch instruction.
+ void cloneBranchTarget(BranchInst *bi) {
+ assert(origBB == bi->getDestBB());
+
+ cloneBlock(/*insertAfter*/ bi->getParent());
+
+ SILBuilderWithScope(bi).createBranch(bi->getLoc(), getNewBB(),
+ bi->getArgs());
+ bi->eraseFromParent();
+ }
+
+ /// Get the newly cloned block corresponding to `origBB`.
+ SILBasicBlock *getNewBB() {
+ return remapBasicBlock(origBB);
+ }
+
+ /// Call this after processing all instructions to fix the control flow
+ /// graph. The branch cloner may have left critical edges.
+ bool splitCriticalEdges(DominanceInfo *domInfo, SILLoopInfo *loopInfo);
+
+protected:
+ // MARK: CRTP overrides.
+
+ /// Override getMappedValue to allow values defined outside the block to be
+ /// cloned to be reused in the newly cloned block.
+ SILValue getMappedValue(SILValue value) {
+ if (auto si = value->getDefiningInstruction()) {
+ if (!isBlockCloned(si->getParent()))
+ return value;
+ } else if (auto bbArg = dyn_cast(value)) {
+ if (!isBlockCloned(bbArg->getParent()))
+ return value;
+ } else {
+ assert(isa(value) && "Unexpected Value kind");
+ return value;
+ }
+ // `value` is not defined outside the cloned block, so consult the cloner's
+ // map of cloned values.
+ return SuperTy::getMappedValue(value);
+ }
+
+ void mapValue(SILValue origValue, SILValue mappedValue) {
+ SuperTy::mapValue(origValue, mappedValue);
+ AvailVals.emplace_back(origValue, mappedValue);
+ }
+};
+
+// Helper class that provides a callback that can be used in
+// inliners/cloners for collecting new call sites.
+class CloneCollector {
+public:
+ typedef std::pair value_type;
+ typedef std::function CallbackType;
+ typedef std::function FilterType;
+
+private:
+ FilterType filter;
+
+ // Pairs of collected instructions; (new, old)
+ llvm::SmallVector instructionpairs;
+
+ void collect(SILInstruction *oldI, SILInstruction *newI) {
+ if (filter(newI))
+ instructionpairs.push_back(std::make_pair(newI, oldI));
+ }
+
+public:
+ CloneCollector(FilterType filter) : filter(filter) {}
+
+ CallbackType getCallback() {
+ return std::bind(&CloneCollector::collect, this, std::placeholders::_1,
+ std::placeholders::_2);
+ }
+
+ llvm::SmallVectorImpl &getInstructionPairs() {
+ return instructionpairs;
+ }
+};
+
+/// Sink address projections to their out-of-block uses. This is
+/// required after cloning a block and before calling
+/// updateSSAAfterCloning to avoid address-type phis.
+///
+/// This clones address projections at their use points, but does not
+/// mutate the block containing the projections.
+class SinkAddressProjections {
+ // Projections ordered from last to first in the chain.
+ SmallVector projections;
+ SmallSetVector inBlockDefs;
+
+public:
+ /// Check for an address projection chain ending at \p inst. Return true if
+ /// the given instruction is successfully analyzed.
+ ///
+ /// If \p inst does not produce an address, then return
+ /// true. getInBlockDefs() will contain \p inst if any of its
+ /// (non-address) values are used outside its block.
+ ///
+ /// If \p inst does produce an address, return true only of the
+ /// chain of address projections within this block is clonable at
+ /// their use sites. getInBlockDefs will return all non-address
+ /// operands in the chain that are also defined in this block. These
+ /// may require phis after cloning the projections.
+ bool analyzeAddressProjections(SILInstruction *inst);
+
+ /// After analyzing projections, returns the list of (non-address) values
+ /// defined in the same block as the projections which will have uses outside
+ /// the block after cloning.
+ ArrayRef getInBlockDefs() const {
+ return inBlockDefs.getArrayRef();
+ }
+ /// Clone the chain of projections at their use sites.
+ ///
+ /// Return true if anything was done.
+ ///
+ /// getInBlockProjectionOperandValues() can be called before or after cloning.
+ bool cloneProjections();
+};
+
+/// Utility class for cloning init values into the static initializer of a
+/// SILGlobalVariable.
+class StaticInitCloner : public SILCloner {
+ friend class SILInstructionVisitor;
+ friend class SILCloner;
+
+ /// The number of not yet cloned operands for each instruction.
+ llvm::DenseMap numOpsToClone;
+
+ /// List of instructions for which all operands are already cloned (or which
+ /// don't have any operands).
+ llvm::SmallVector readyToClone;
+
+public:
+ StaticInitCloner(SILGlobalVariable *gVar)
+ : SILCloner(gVar) {}
+
+ /// Add \p InitVal and all its operands (transitively) for cloning.
+ ///
+ /// Note: all init values must are added, before calling clone().
+ void add(SILInstruction *initVal);
+
+ /// Clone \p InitVal and all its operands into the initializer of the
+ /// SILGlobalVariable.
+ ///
+ /// \return Returns the cloned instruction in the SILGlobalVariable.
+ SingleValueInstruction *clone(SingleValueInstruction *initVal);
+
+ /// Convenience function to clone a single \p InitVal.
+ static void appendToInitializer(SILGlobalVariable *gVar,
+ SingleValueInstruction *initVal) {
+ StaticInitCloner cloner(gVar);
+ cloner.add(initVal);
+ cloner.clone(initVal);
+ }
+
+protected:
+ SILLocation remapLocation(SILLocation loc) {
+ return ArtificialUnreachableLocation();
+ }
+};
+
+} // namespace swift
+
+#endif
diff --git a/include/swift/SILOptimizer/Utils/CFG.h b/include/swift/SILOptimizer/Utils/CFGOptUtils.h
similarity index 56%
rename from include/swift/SILOptimizer/Utils/CFG.h
rename to include/swift/SILOptimizer/Utils/CFGOptUtils.h
index ceaea27b91f..9c3f8189ff7 100644
--- a/include/swift/SILOptimizer/Utils/CFG.h
+++ b/include/swift/SILOptimizer/Utils/CFGOptUtils.h
@@ -1,20 +1,34 @@
-//===--- CFG.h - Utilities for SIL CFG transformations ----------*- C++ -*-===//
+//===--- CFGOptUtils.h - SIL CFG edge utilities -----------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
-// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Copyright (c) 2014 - 2019 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
//
//===----------------------------------------------------------------------===//
+///
+/// APIs used by the SILOptimizer for low-level branch and CFG edge analysis
+/// and operations. These may merge blocks, split blocks, or create empty
+/// blocks, but don't duplicate whole blocks.
+///
+/// Essential CFG utilities are in SIL/CFG.h.
+///
+/// Whole block-level transformations are in BasicBlockOptUtils.h.
+///
+//===----------------------------------------------------------------------===//
-#ifndef SWIFT_SILOPTIMIZER_UTILS_CFG_H
-#define SWIFT_SILOPTIMIZER_UTILS_CFG_H
+#ifndef SWIFT_SILOPTIMIZER_UTILS_CFGOPTUTILS_H
+#define SWIFT_SILOPTIMIZER_UTILS_CFGOPTUTILS_H
-#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILBuilder.h"
+#include "swift/SIL/SILInstruction.h"
+
+namespace llvm {
+template class TinyPtrVector;
+}
namespace swift {
@@ -25,25 +39,25 @@ class SILLoopInfo;
/// Adds a new argument to an edge between a branch and a destination
/// block.
///
-/// \param Branch The terminator to add the argument to.
-/// \param Dest The destination block of the edge.
-/// \param Val The value to the arguments of the branch.
+/// \param branch The terminator to add the argument to.
+/// \param dest The destination block of the edge.
+/// \param val The value to the arguments of the branch.
/// \return The created branch. The old branch is deleted.
/// The argument is appended at the end of the argument tuple.
-TermInst *addNewEdgeValueToBranch(TermInst *Branch, SILBasicBlock *Dest,
- SILValue Val);
+TermInst *addNewEdgeValueToBranch(TermInst *branch, SILBasicBlock *dest,
+ SILValue val);
/// Changes the edge value between a branch and destination basic block
/// at the specified index. Changes all edges from \p Branch to \p Dest to carry
/// the value.
///
-/// \param Branch The branch to modify.
-/// \param Dest The destination of the edge.
-/// \param Idx The index of the argument to modify.
-/// \param Val The new value to use.
+/// \param branch The branch to modify.
+/// \param dest The destination of the edge.
+/// \param idx The index of the argument to modify.
+/// \param val The new value to use.
/// \return The new branch. Deletes the old one.
-TermInst *changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, size_t Idx,
- SILValue Val);
+TermInst *changeEdgeValue(TermInst *branch, SILBasicBlock *dest, size_t idx,
+ SILValue val);
/// Deletes the edge value between a branch and a destination basic block at the
/// specified index. Asserts internally that the argument along the edge does
@@ -59,24 +73,24 @@ void erasePhiArgument(SILBasicBlock *block, unsigned argIndex);
/// Replace a branch target.
///
-/// \param T The terminating instruction to modify.
-/// \param OldDest The successor block that will be replaced.
-/// \param NewDest The new target block.
-/// \param PreserveArgs If set, preserve arguments on the replaced edge.
-void replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest,
- SILBasicBlock *NewDest, bool PreserveArgs);
+/// \param t The terminating instruction to modify.
+/// \param oldDest The successor block that will be replaced.
+/// \param newDest The new target block.
+/// \param preserveArgs If set, preserve arguments on the replaced edge.
+void replaceBranchTarget(TermInst *t, SILBasicBlock *oldDest,
+ SILBasicBlock *newDest, bool preserveArgs);
/// Check if the edge from the terminator is critical.
-bool isCriticalEdge(TermInst *T, unsigned EdgeIdx);
+bool isCriticalEdge(TermInst *t, unsigned edgeIdx);
/// Splits the edge from terminator if it is critical.
///
/// Updates dominance information and loop information if not null.
/// Returns the newly created basic block on success or nullptr otherwise (if
/// the edge was not critical).
-SILBasicBlock *splitCriticalEdge(TermInst *T, unsigned EdgeIdx,
- DominanceInfo *DT = nullptr,
- SILLoopInfo *LI = nullptr);
+SILBasicBlock *splitCriticalEdge(TermInst *, unsigned edgeIdx,
+ DominanceInfo *domInfo = nullptr,
+ SILLoopInfo *loopInfo = nullptr);
/// Splits the critical edges between from and to. This code assumes there is
/// exactly one edge between the two basic blocks. It will return the wrong
@@ -84,45 +98,39 @@ SILBasicBlock *splitCriticalEdge(TermInst *T, unsigned EdgeIdx,
/// between the two blocks.
///
/// Updates dominance information and loop information if not null.
-SILBasicBlock *splitIfCriticalEdge(SILBasicBlock *From, SILBasicBlock *To,
- DominanceInfo *DT = nullptr,
- SILLoopInfo *LI = nullptr);
+SILBasicBlock *splitIfCriticalEdge(SILBasicBlock *from, SILBasicBlock *to,
+ DominanceInfo *domInfo = nullptr,
+ SILLoopInfo *loopInfo = nullptr);
/// Splits all critical edges originating from `fromBB`.
-bool splitCriticalEdgesFrom(SILBasicBlock *fromBB, DominanceInfo *DT = nullptr,
- SILLoopInfo *LI = nullptr);
+bool splitCriticalEdgesFrom(SILBasicBlock *fromBB,
+ DominanceInfo *domInfo = nullptr,
+ SILLoopInfo *loopInfo = nullptr);
/// Splits the edges between two basic blocks.
///
/// Updates dominance information and loop information if not null.
-void splitEdgesFromTo(SILBasicBlock *From, SILBasicBlock *To,
- DominanceInfo *DT = nullptr, SILLoopInfo *LI = nullptr);
-
-/// Rotate a loop's header as long as it is exiting and not equal to the
-/// passed basic block.
-/// If \p RotateSingleBlockLoops is true a single basic block loop will be
-/// rotated once. ShouldVerify specifies whether to perform verification after
-/// the transformation.
-/// Returns true if the loop could be rotated.
-bool rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI,
- bool RotateSingleBlockLoops, SILBasicBlock *UpTo,
- bool ShouldVerify);
+void splitEdgesFromTo(SILBasicBlock *from, SILBasicBlock *to,
+ DominanceInfo *domInfo = nullptr,
+ SILLoopInfo *loopInfo = nullptr);
/// Splits the basic block before the instruction with an unconditional branch
/// and updates the dominator tree and loop info. Returns the new, branched to
/// block that contains the end of \p SplitBeforeInst's block.
-SILBasicBlock *splitBasicBlockAndBranch(SILBuilder &B,
- SILInstruction *SplitBeforeInst,
- DominanceInfo *DT, SILLoopInfo *LI);
+SILBasicBlock *splitBasicBlockAndBranch(SILBuilder &builder,
+ SILInstruction *splitBeforeInst,
+ DominanceInfo *domInfo,
+ SILLoopInfo *loopInfo);
/// Return true if the function has a critical edge, false otherwise.
-bool hasCriticalEdges(SILFunction &F, bool OnlyNonCondBr);
+bool hasCriticalEdges(SILFunction &f, bool onlyNonCondBr);
/// Split all critical edges in the given function, updating the
/// dominator tree and loop information if they are provided.
///
/// FIXME: This should never be called! Fix passes that create critical edges.
-bool splitAllCriticalEdges(SILFunction &F, DominanceInfo *DT, SILLoopInfo *LI);
+bool splitAllCriticalEdges(SILFunction &F, DominanceInfo *domInfo,
+ SILLoopInfo *loopInfo);
/// Split all cond_br critical edges with non-trivial arguments in the
/// function updating the dominator tree and loop information (if they are not
@@ -130,15 +138,15 @@ bool splitAllCriticalEdges(SILFunction &F, DominanceInfo *DT, SILLoopInfo *LI);
///
/// 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 &Fn,
- DominanceInfo *DT,
- SILLoopInfo *LI);
+bool splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &fn,
+ DominanceInfo *domInfo,
+ SILLoopInfo *loopInfo);
/// 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);
+bool mergeBasicBlockWithSuccessor(SILBasicBlock *bb, DominanceInfo *domInfo,
+ SILLoopInfo *loopInfo);
/// Merge basic blocks in the given function by eliminating all unconditional
/// branches to single-predecessor branch targets.
@@ -148,7 +156,7 @@ bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT,
/// is not done on-the-fly after splitting blocks because merging is linear in
/// the number of instructions, so interleaved merging and splitting is
/// quadratic.
-bool mergeBasicBlocks(SILFunction *F);
+bool mergeBasicBlocks(SILFunction *f);
/// 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
@@ -177,11 +185,29 @@ bool mergeBasicBlocks(SILFunction *F);
///
/// *NOTE* This completion may not be unique.
void completeJointPostDominanceSet(
- ArrayRef UserBlocks, ArrayRef DefBlocks,
- llvm::SmallVectorImpl &Completion);
+ ArrayRef userBlocks, ArrayRef defBlocks,
+ llvm::SmallVectorImpl &completion);
-/// Remove all unreachable blocks in a function.
-bool removeUnreachableBlocks(SILFunction &Fn);
+/// Return true if we conservatively find all bb's that are non-failure exit
+/// basic blocks and place them in \p bbs. If we find something we don't
+/// understand, bail.
+///
+/// A non-failure exit BB is defined as a BB that:
+///
+/// 1. Has a return terminator.
+/// 2. unreachable + noreturn terminator sequence.
+/// 3. has a throw terminator.
+///
+/// If we just have an unreachable without a noreturn call before it, we must
+/// have a failure BB.
+///
+/// We use a TinyPtrVector since in most cases this will only return one
+/// SILBasicBlock since non-failure noreturn functions should not occur often
+/// implying in most cases this will be one element.
+///
+/// TODO:
+bool findAllNonFailureExitBBs(SILFunction *f,
+ llvm::TinyPtrVector &bbs);
} // end namespace swift
diff --git a/include/swift/SILOptimizer/Utils/Devirtualize.h b/include/swift/SILOptimizer/Utils/Devirtualize.h
index d99810f951c..6301c64725e 100644
--- a/include/swift/SILOptimizer/Utils/Devirtualize.h
+++ b/include/swift/SILOptimizer/Utils/Devirtualize.h
@@ -27,7 +27,7 @@
#include "swift/SIL/SILType.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/ArrayRef.h"
namespace swift {
diff --git a/include/swift/SILOptimizer/Utils/GenericCloner.h b/include/swift/SILOptimizer/Utils/GenericCloner.h
index 1c54bdecf16..ea0d3aa617d 100644
--- a/include/swift/SILOptimizer/Utils/GenericCloner.h
+++ b/include/swift/SILOptimizer/Utils/GenericCloner.h
@@ -22,7 +22,7 @@
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/TypeSubstCloner.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h"
#include "swift/SILOptimizer/Utils/Generics.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
diff --git a/include/swift/SILOptimizer/Utils/Generics.h b/include/swift/SILOptimizer/Utils/Generics.h
index 3c78e3c6a1a..50c80b51578 100644
--- a/include/swift/SILOptimizer/Utils/Generics.h
+++ b/include/swift/SILOptimizer/Utils/Generics.h
@@ -20,7 +20,7 @@
#include "swift/AST/SubstitutionMap.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
diff --git a/include/swift/SILOptimizer/Utils/InstOptUtils.h b/include/swift/SILOptimizer/Utils/InstOptUtils.h
new file mode 100644
index 00000000000..15c5f82089d
--- /dev/null
+++ b/include/swift/SILOptimizer/Utils/InstOptUtils.h
@@ -0,0 +1,390 @@
+//===--- InstOptUtils.h - SILOptimizer instruction utilities ----*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2019 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// Utilities used by the SILOptimizer for analyzing and transforming
+/// SILInstructions.
+///
+/// SIL/InstUtils.h provides essential SILInstruction utilities.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H
+#define SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H
+
+#include "swift/SIL/SILBuilder.h"
+#include "swift/SIL/SILInstruction.h"
+#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
+#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
+#include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h"
+#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include
+#include
+
+namespace swift {
+
+class DominanceInfo;
+template class NullablePtr;
+
+/// Transform a Use Range (Operand*) into a User Range (SILInstruction*)
+using UserTransform = std::function;
+using ValueBaseUserRange =
+ TransformRange, UserTransform>;
+
+inline ValueBaseUserRange
+makeUserRange(iterator_range range) {
+ auto toUser = [](Operand *operand) { return operand->getUser(); };
+ return makeTransformRange(makeIteratorRange(range.begin(), range.end()),
+ UserTransform(toUser));
+}
+
+using DeadInstructionSet = llvm::SmallSetVector;
+
+/// Create a retain of \p Ptr before the \p InsertPt.
+NullablePtr createIncrementBefore(SILValue ptr,
+ SILInstruction *insertpt);
+
+/// Create a release of \p Ptr before the \p InsertPt.
+NullablePtr createDecrementBefore(SILValue ptr,
+ SILInstruction *insertpt);
+
+/// For each of the given instructions, if they are dead delete them
+/// along with their dead operands.
+///
+/// \param inst The ArrayRef of instructions to be deleted.
+/// \param force If Force is set, don't check if the top level instructions
+/// are considered dead - delete them regardless.
+/// \param callback a callback called whenever an instruction is deleted.
+void recursivelyDeleteTriviallyDeadInstructions(
+ ArrayRef inst, bool force = false,
+ llvm::function_ref callback = [](SILInstruction *) {
+ });
+
+/// If the given instruction is dead, delete it along with its dead
+/// operands.
+///
+/// \param inst The instruction to be deleted.
+/// \param force If Force is set, don't check if the top level instruction is
+/// considered dead - delete it regardless.
+/// \param callback a callback called whenever an instruction is deleted.
+void recursivelyDeleteTriviallyDeadInstructions(
+ SILInstruction *inst, bool force = false,
+ llvm::function_ref callback = [](SILInstruction *) {
+ });
+
+/// Perform a fast local check to see if the instruction is dead.
+///
+/// This routine only examines the state of the instruction at hand.
+bool isInstructionTriviallyDead(SILInstruction *inst);
+
+/// Return true if this is a release instruction that's not going to
+/// free the object.
+bool isIntermediateRelease(SILInstruction *inst, EpilogueARCFunctionInfo *erfi);
+
+/// Recursively collect all the uses and transitive uses of the
+/// instruction.
+void collectUsesOfValue(SILValue V,
+ llvm::SmallPtrSetImpl &Insts);
+
+/// Recursively erase all of the uses of the instruction (but not the
+/// instruction itself)
+void eraseUsesOfInstruction(
+ SILInstruction *inst, llvm::function_ref callback =
+ [](SILInstruction *) {});
+
+/// Recursively erase all of the uses of the value (but not the
+/// value itself)
+void eraseUsesOfValue(SILValue value);
+
+FullApplySite findApplyFromDevirtualizedResult(SILValue value);
+
+/// Cast a value into the expected, ABI compatible type if necessary.
+/// This may happen e.g. when:
+/// - a type of the return value is a subclass of the expected return type.
+/// - actual return type and expected return type differ in optionality.
+/// - both types are tuple-types and some of the elements need to be casted.
+SILValue castValueToABICompatibleType(SILBuilder *builder, SILLocation Loc,
+ SILValue value, SILType srcTy,
+ SILType destTy);
+/// Peek through trivial Enum initialization, typically for pointless
+/// Optionals.
+///
+/// The returned InitEnumDataAddr dominates the given
+/// UncheckedTakeEnumDataAddrInst.
+InitEnumDataAddrInst *
+findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *utedai);
+
+/// Returns a project_box if it is the next instruction after \p ABI and
+/// and has \p ABI as operand. Otherwise it creates a new project_box right
+/// after \p ABI and returns it.
+ProjectBoxInst *getOrCreateProjectBox(AllocBoxInst *abi, unsigned index);
+
+/// Return true if any call inside the given function may bind dynamic
+/// 'Self' to a generic argument of the callee.
+bool mayBindDynamicSelf(SILFunction *f);
+
+/// Check whether the \p addr is an address of a tail-allocated array element.
+bool isAddressOfArrayElement(SILValue addr);
+
+/// Move an ApplyInst's FuncRef so that it dominates the call site.
+void placeFuncRef(ApplyInst *ai, DominanceInfo *dt);
+
+/// Add an argument, \p val, to the branch-edge that is pointing into
+/// block \p Dest. Return a new instruction and do not erase the old
+/// instruction.
+TermInst *addArgumentToBranch(SILValue val, SILBasicBlock *dest,
+ TermInst *branch);
+
+/// Get the linkage to be used for specializations of a function with
+/// the given linkage.
+SILLinkage getSpecializedLinkage(SILFunction *f, SILLinkage linkage);
+
+/// Tries to optimize a given apply instruction if it is a concatenation of
+/// string literals. Returns a new instruction if optimization was possible.
+SingleValueInstruction *tryToConcatenateStrings(ApplyInst *ai,
+ SILBuilder &builder);
+
+/// Tries to perform jump-threading on all checked_cast_br instruction in
+/// function \p Fn.
+bool tryCheckedCastBrJumpThreading(
+ SILFunction *fn, DominanceInfo *dt,
+ SmallVectorImpl &blocksForWorklist);
+
+/// A structure containing callbacks that are called when an instruction is
+/// removed or added.
+struct InstModCallbacks {
+ using CallbackTy = std::function;
+ CallbackTy deleteInst = [](SILInstruction *inst) { inst->eraseFromParent(); };
+ CallbackTy createdNewInst = [](SILInstruction *) {};
+
+ InstModCallbacks(CallbackTy deleteInst, CallbackTy createdNewInst)
+ : deleteInst(deleteInst), createdNewInst(createdNewInst) {}
+ InstModCallbacks() = default;
+ ~InstModCallbacks() = default;
+ InstModCallbacks(const InstModCallbacks &) = default;
+ InstModCallbacks(InstModCallbacks &&) = default;
+};
+
+/// If Closure is a partial_apply or thin_to_thick_function with only local
+/// ref count users and a set of post-dominating releases:
+///
+/// 1. Remove all ref count operations and the closure.
+/// 2. Add each one of the last release locations insert releases for the
+/// captured args if we have a partial_apply.
+///
+/// In the future this should be extended to be less conservative with users.
+bool tryDeleteDeadClosure(SingleValueInstruction *closure,
+ InstModCallbacks callbacks = InstModCallbacks());
+
+/// Given a SILValue argument to a partial apply \p Arg and the associated
+/// parameter info for that argument, perform the necessary cleanups to Arg when
+/// one is attempting to delete the partial apply.
+void releasePartialApplyCapturedArg(
+ SILBuilder &builder, SILLocation loc, SILValue arg,
+ SILParameterInfo paramInfo,
+ InstModCallbacks callbacks = InstModCallbacks());
+
+/// Insert destroys of captured arguments of partial_apply [stack].
+void insertDestroyOfCapturedArguments(
+ PartialApplyInst *pai, SILBuilder &builder,
+ llvm::function_ref shouldInsertDestroy =
+ [](SILValue arg) -> bool { return true; });
+
+/// This iterator 'looks through' one level of builtin expect users exposing all
+/// users of the looked through builtin expect instruction i.e it presents a
+/// view that shows all users as if there were no builtin expect instructions
+/// interposed.
+class IgnoreExpectUseIterator
+ : public std::iterator {
+ ValueBaseUseIterator origUseChain;
+ ValueBaseUseIterator currentIter;
+
+ static BuiltinInst *isExpect(Operand *use) {
+ if (auto *bi = dyn_cast(use->getUser()))
+ if (bi->getIntrinsicInfo().ID == llvm::Intrinsic::expect)
+ return bi;
+ return nullptr;
+ }
+
+ // Advance through expect users to their users until we encounter a user that
+ // is not an expect.
+ void advanceThroughExpects() {
+ while (currentIter == origUseChain
+ && currentIter != ValueBaseUseIterator(nullptr)) {
+ auto *Expect = isExpect(*currentIter);
+ if (!Expect)
+ return;
+ currentIter = Expect->use_begin();
+ // Expect with no users advance to next item in original use chain.
+ if (currentIter == Expect->use_end())
+ currentIter = ++origUseChain;
+ }
+ }
+
+public:
+ IgnoreExpectUseIterator(ValueBase *value)
+ : origUseChain(value->use_begin()), currentIter(value->use_begin()) {
+ advanceThroughExpects();
+ }
+
+ IgnoreExpectUseIterator() = default;
+
+ Operand *operator*() const { return *currentIter; }
+ Operand *operator->() const { return *currentIter; }
+ SILInstruction *getUser() const { return currentIter->getUser(); }
+
+ IgnoreExpectUseIterator &operator++() {
+ assert(**this && "increment past end()!");
+ if (origUseChain == currentIter) {
+ // Use chain of the original value.
+ ++origUseChain;
+ ++currentIter;
+ // Ignore expects.
+ advanceThroughExpects();
+ } else {
+ // Use chain of an expect.
+ ++currentIter;
+ if (currentIter == ValueBaseUseIterator(nullptr)) {
+ // At the end of the use chain of an expect.
+ currentIter = ++origUseChain;
+ advanceThroughExpects();
+ }
+ }
+ return *this;
+ }
+
+ IgnoreExpectUseIterator operator++(int unused) {
+ IgnoreExpectUseIterator copy = *this;
+ ++*this;
+ return copy;
+ }
+ friend bool operator==(IgnoreExpectUseIterator lhs,
+ IgnoreExpectUseIterator rhs) {
+ return lhs.currentIter == rhs.currentIter;
+ }
+ friend bool operator!=(IgnoreExpectUseIterator lhs,
+ IgnoreExpectUseIterator rhs) {
+ return !(lhs == rhs);
+ }
+};
+
+inline iterator_range
+ignore_expect_uses(ValueBase *value) {
+ return make_range(IgnoreExpectUseIterator(value), IgnoreExpectUseIterator());
+}
+
+/// Run simplifyInstruction() on all of the instruction I's users if they only
+/// have one result (since simplifyInstruction assumes that). Replace all uses
+/// of the user with its simplification of we succeed. Returns true if we
+/// succeed and false otherwise.
+///
+/// An example of how this is useful is in cases where one is splitting up an
+/// aggregate and reforming it, the reformed aggregate may have extract
+/// operations from it. These can be simplified and removed.
+bool simplifyUsers(SingleValueInstruction *inst);
+
+/// True if a type can be expanded
+/// without a significant increase to code size.
+bool shouldExpand(SILModule &module, SILType ty);
+
+/// Check if the value of value is computed by means of a simple initialization.
+/// Store the actual SILValue into \p Val and the reversed list of instructions
+/// initializing it in \p Insns.
+/// The check is performed by recursively walking the computation of the
+/// SIL value being analyzed.
+bool analyzeStaticInitializer(SILValue value,
+ SmallVectorImpl &insns);
+
+/// Returns true if the below operation will succeed.
+bool canReplaceLoadSequence(SILInstruction *inst);
+
+/// Replace load sequence which may contain
+/// a chain of struct_element_addr followed by a load.
+/// The sequence is traversed inside out, i.e.
+/// starting with the innermost struct_element_addr
+void replaceLoadSequence(SILInstruction *inst, SILValue value);
+
+/// Do we have enough information to determine all callees that could
+/// be reached by calling the function represented by Decl?
+bool calleesAreStaticallyKnowable(SILModule &module, SILDeclRef decl);
+
+// Attempt to get the instance for , whose static type is the same as
+// its exact dynamic type, returning a null SILValue() if we cannot find it.
+// The information that a static type is the same as the exact dynamic,
+// can be derived e.g.:
+// - from a constructor or
+// - from a successful outcome of a checked_cast_br [exact] instruction.
+SILValue getInstanceWithExactDynamicType(SILValue instance,
+ ClassHierarchyAnalysis *cha);
+
+/// Try to determine the exact dynamic type of an object.
+/// returns the exact dynamic type of the object, or an empty type if the exact
+/// type could not be determined.
+SILType getExactDynamicType(SILValue instance, ClassHierarchyAnalysis *cha,
+ bool forUnderlyingObject = false);
+
+/// Try to statically determine the exact dynamic type of the underlying object.
+/// returns the exact dynamic type of the underlying object, or an empty SILType
+/// if the exact type could not be determined.
+SILType getExactDynamicTypeOfUnderlyingObject(SILValue instance,
+ ClassHierarchyAnalysis *cha);
+
+// Move only data structure that is the result of findLocalApplySite.
+///
+/// NOTE: Generally it is not suggested to have move only types that contain
+/// small vectors. Since our small vectors contain one element or a std::vector
+/// like data structure , this is ok since we will either just copy the single
+/// element when we do the move or perform a move of the vector type.
+struct LLVM_LIBRARY_VISIBILITY FindLocalApplySitesResult {
+ /// Contains the list of local non fully applied partial apply sites that we
+ /// found.
+ SmallVector partialApplySites;
+
+ /// Contains the list of full apply sites that we found.
+ SmallVector fullApplySites;
+
+ /// Set to true if the function_ref escapes into a use that our analysis does
+ /// not understand. Set to false if we found a use that had an actual
+ /// escape. Set to None if we did not find any call sites, but also didn't
+ /// find any "escaping uses" as well.
+ ///
+ /// The none case is so that we can distinguish in between saying that a value
+ /// did escape and saying that we did not find any conservative information.
+ bool escapes;
+
+ FindLocalApplySitesResult() = default;
+ FindLocalApplySitesResult(const FindLocalApplySitesResult &) = delete;
+ FindLocalApplySitesResult &
+ operator=(const FindLocalApplySitesResult &) = delete;
+ FindLocalApplySitesResult(FindLocalApplySitesResult &&) = default;
+ FindLocalApplySitesResult &operator=(FindLocalApplySitesResult &&) = default;
+ ~FindLocalApplySitesResult() = default;
+
+ /// Treat this function ref as escaping only if we found an actual user we
+ /// didn't understand. Do not treat it as escaping if we did not find any
+ /// users at all.
+ bool isEscaping() const { return escapes; }
+};
+
+/// Returns .some(FindLocalApplySitesResult) if we found any interesting
+/// information for the given function_ref. Otherwise, returns None.
+///
+/// We consider "interesting information" to mean inclusively that:
+///
+/// 1. We discovered that the function_ref never escapes.
+/// 2. We were able to find either a partial apply or a full apply site.
+Optional
+findLocalApplySites(FunctionRefBaseInst *fri);
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h
index 5613af10681..f11fbcd3042 100644
--- a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h
+++ b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h
@@ -33,7 +33,7 @@
#include "swift/SILOptimizer/Analysis/EscapeAnalysis.h"
#include "swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h"
#include "swift/SILOptimizer/Analysis/ValueTracking.h"
-#include "swift/SILOptimizer/Utils/Local.h"
+#include "swift/SILOptimizer/Utils/InstOptUtils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/Local.h
deleted file mode 100644
index c7a33d8afa0..00000000000
--- a/include/swift/SILOptimizer/Utils/Local.h
+++ /dev/null
@@ -1,684 +0,0 @@
-//===--- Local.h - Local SIL transformations. -------------------*- 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_SILOPTIMIZER_UTILS_LOCAL_H
-#define SWIFT_SILOPTIMIZER_UTILS_LOCAL_H
-
-#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
-#include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h"
-#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
-#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h"
-#include "swift/SIL/SILInstruction.h"
-#include "swift/SIL/SILBuilder.h"
-#include "swift/SIL/SILCloner.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Support/Allocator.h"
-#include
-#include
-
-namespace swift {
-
-class DominanceInfo;
-template class NullablePtr;
-
-/// Transform a Use Range (Operand*) into a User Range (SILInstruction*)
-using UserTransform = std::function;
-using ValueBaseUserRange =
- TransformRange, UserTransform>;
-
-inline ValueBaseUserRange makeUserRange(
- iterator_range R) {
- auto toUser = [](Operand *O) { return O->getUser(); };
- return makeTransformRange(makeIteratorRange(R.begin(), R.end()),
- UserTransform(toUser));
-}
-
-using DeadInstructionSet = llvm::SmallSetVector;
-
-/// Create a retain of \p Ptr before the \p InsertPt.
-NullablePtr