Merge pull request #12898 from sashabelonogov/sashabelonogov/SR-6361
[SR-6361] Fix Data.withUnsafeMutableBytes() for slices with length < range.lowerBound
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index a832224..5c2db0f 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -81,7 +81,9 @@
# HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM
# into swift. The use of this flag pollutes all targets, and we are not able
# to remove it on a per-target basis which breaks cross-compilation.
- string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+ string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+ endif()
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" PACKAGE_VERSION_MAJOR
diff --git a/docs/ContinuousIntegration.md b/docs/ContinuousIntegration.md
index e07f255..e037a74 100644
--- a/docs/ContinuousIntegration.md
+++ b/docs/ContinuousIntegration.md
@@ -9,7 +9,9 @@
- [Smoke Testing](#smoke-testing)
- [Validation Testing](#validation-testing)
- [Linting](#linting)
+ - [Source Compatibility Testing](#source-compatibility-testing)
- [Specific Preset Testing](#specific-preset-testing)
+ - [Testing Compiler Performance](#testing-compiler-performance)
- [Cross Repository Testing](#cross-repository-testing)
- [ci.swift.org bots](#ciswiftorg-bots)
@@ -31,6 +33,7 @@
4. Linting
5. Source Compatibility Testing
6. Specific Preset Testing
+7. Testing Compiler Performance
We describe each in detail below:
diff --git a/include/swift/AST/ASTNode.h b/include/swift/AST/ASTNode.h
index 078b5bc..5332fa7 100644
--- a/include/swift/AST/ASTNode.h
+++ b/include/swift/AST/ASTNode.h
@@ -18,7 +18,6 @@
#define SWIFT_AST_AST_NODE_H
#include "llvm/ADT/PointerUnion.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/TypeAlignments.h"
namespace swift {
@@ -48,9 +47,6 @@
void walk(ASTWalker &Walker);
void walk(ASTWalker &&walker) { walk(walker); }
- void walk(SourceEntityWalker &Walker);
- void walk(SourceEntityWalker &&walker) { walk(walker); }
-
/// \brief get the underlying entity as a decl context if it is one,
/// otherwise, return nullptr;
DeclContext *getAsDeclContext() const;
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index d9fc118..26e8b05 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -299,6 +299,10 @@
ImplicitlyUnwrappedOptional,
OnFunc | OnVar | OnSubscript | OnConstructor | RejectByParser, 72)
+DECL_ATTR(_optimize, Optimize,
+ OnFunc | OnConstructor | OnDestructor | OnSubscript | OnVar |
+ UserInaccessible, 73)
+
#undef TYPE_ATTR
#undef DECL_ATTR_ALIAS
#undef SIMPLE_DECL_ATTR
diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h
index 925aa7d..2db33d7 100644
--- a/include/swift/AST/Attr.h
+++ b/include/swift/AST/Attr.h
@@ -21,6 +21,7 @@
#include "swift/Basic/UUID.h"
#include "swift/Basic/STLExtras.h"
#include "swift/Basic/Range.h"
+#include "swift/Basic/OptimizationMode.h"
#include "swift/Basic/Version.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/AttrKind.h"
@@ -925,6 +926,23 @@
}
};
+/// Represents the optimize attribute.
+class OptimizeAttr : public DeclAttribute {
+ OptimizationMode Mode;
+public:
+ OptimizeAttr(SourceLoc atLoc, SourceRange range, OptimizationMode mode)
+ : DeclAttribute(DAK_Optimize, atLoc, range, /*Implicit=*/false),
+ Mode(mode) {}
+
+ OptimizeAttr(OptimizationMode mode)
+ : OptimizeAttr(SourceLoc(), SourceRange(), mode) {}
+
+ OptimizationMode getMode() const { return Mode; }
+ static bool classof(const DeclAttribute *DA) {
+ return DA->getKind() == DAK_Optimize;
+ }
+};
+
/// Represents the side effects attribute.
class EffectsAttr : public DeclAttribute {
EffectsKind Kind;
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index ab1b13a..5be9bbc 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -2225,6 +2225,10 @@
getFormalAccessScope(const DeclContext *useDC = nullptr,
bool respectVersionedAttr = false) const;
+
+ /// Copy the formal access level and @_versioned attribute from source.
+ void copyFormalAccessAndVersionedAttrFrom(ValueDecl *source);
+
/// Returns the access level that actually controls how a declaration should
/// be emitted and may be used.
///
@@ -3402,7 +3406,7 @@
/// Synthesize implicit, trivial destructor, add it to this ClassDecl
/// and return it.
- DestructorDecl *addImplicitDestructor();
+ void addImplicitDestructor();
/// Determine whether this class inherits the convenience initializers
/// from its superclass.
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 41c6cf4..570fc54 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1365,10 +1365,10 @@
ERROR(opened_attribute_expected_rparen,none,
"expected ')' after id value for 'opened' attribute", ())
-// inline
-ERROR(inline_attribute_expect_option,none,
- "expected '%0' option such as 'never'", (StringRef))
-ERROR(inline_attribute_unknown_option,none,
+// inline, optimize
+ERROR(optimization_attribute_expect_option,none,
+ "expected '%0' option such as '%1'", (StringRef, StringRef))
+ERROR(optimization_attribute_unknown_option,none,
"unknown option '%0' for attribute '%1'", (StringRef, StringRef))
// effects
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index e64b60b..fa41dab 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -474,6 +474,9 @@
"key path cannot reference tuple elements", ())
ERROR(expr_keypath_subscript_index_not_hashable, none,
"subscript index of type %0 in a key path must be Hashable", (Type))
+ERROR(expr_smart_keypath_application_type_mismatch,none,
+ "key path of type %0 cannot be applied to a base of type %1",
+ (Type, Type))
// Selector expressions.
ERROR(expr_selector_no_objc_runtime,none,
@@ -1024,8 +1027,6 @@
ERROR(static_functions_not_mutating,none,
"static functions must not be declared mutating", ())
-ERROR(transparent_stored_property,none,
- "@_transparent cannot be applied to stored properties", ())
ERROR(transparent_in_protocols_not_supported,none,
"@_transparent is not supported on declarations within protocols", ())
ERROR(transparent_in_classes_not_supported,none,
@@ -3705,8 +3706,8 @@
"'%select{@_transparent|@inline(__always)|@_inlineable|%error}1' and must "
"delegate to another initializer", (Type, unsigned))
-ERROR(inlineable_stored_property,
- none, "'@_inlineable' attribute cannot be applied to stored properties", ())
+ERROR(attribute_invalid_on_stored_property,
+ none, "@%0 cannot be applied to stored properties", (StringRef))
ERROR(inlineable_dynamic_not_supported,
none, "'@_inlineable' attribute cannot be applied to 'dynamic' declarations", ())
diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h
index a72fbc5..349f769 100644
--- a/include/swift/AST/IRGenOptions.h
+++ b/include/swift/AST/IRGenOptions.h
@@ -21,6 +21,7 @@
#include "swift/AST/LinkLibrary.h"
#include "swift/Basic/Sanitizers.h"
#include "swift/Basic/OptionSet.h"
+#include "swift/Basic/OptimizationMode.h"
// FIXME: This include is just for llvm::SanitizerCoverageOptions. We should
// split the header upstream so we don't include so much.
#include "llvm/Transforms/Instrumentation.h"
@@ -94,11 +95,7 @@
/// well-formed?
unsigned Verify : 1;
- /// Whether or not to run optimization passes.
- unsigned Optimize : 1;
-
- /// Whether or not to optimize for code size.
- unsigned OptimizeForSize : 1;
+ OptimizationMode OptMode;
/// Which sanitizer is turned on.
OptionSet<SanitizerKind> Sanitizers;
@@ -179,7 +176,7 @@
IRGenOptions()
: DWARFVersion(2), OutputKind(IRGenOutputKind::LLVMAssembly),
- Verify(true), Optimize(false), OptimizeForSize(false),
+ Verify(true), OptMode(OptimizationMode::NotSet),
Sanitizers(OptionSet<SanitizerKind>()),
DebugInfoKind(IRGenDebugInfoKind::None), UseJIT(false),
DisableLLVMOptzns(false), DisableLLVMARCOpts(false),
@@ -202,9 +199,7 @@
// Get a hash of all options which influence the llvm compilation but are not
// reflected in the llvm module itself.
unsigned getLLVMCodeGenOptionsHash() {
- unsigned Hash = 0;
- Hash = (Hash << 1) | Optimize;
- Hash = (Hash << 1) | OptimizeForSize;
+ unsigned Hash = (unsigned)OptMode;
Hash = (Hash << 1) | DisableLLVMOptzns;
Hash = (Hash << 1) | DisableLLVMARCOpts;
return Hash;
@@ -222,6 +217,14 @@
}
}
+ bool shouldOptimize() const {
+ return OptMode > OptimizationMode::NoOptimization;
+ }
+
+ bool optimizeForSize() const {
+ return OptMode == OptimizationMode::ForSize;
+ }
+
/// Return a hash code of any components from these options that should
/// contribute to a Swift Bridging PCH hash.
llvm::hash_code getPCHHashComponents() const {
diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h
index 3272e45..b434510 100644
--- a/include/swift/AST/PrintOptions.h
+++ b/include/swift/AST/PrintOptions.h
@@ -386,6 +386,7 @@
result.PrintImplicitAttrs = false;
result.ExcludeAttrList.push_back(DAK_Exported);
result.ExcludeAttrList.push_back(DAK_Inline);
+ result.ExcludeAttrList.push_back(DAK_Optimize);
result.ExcludeAttrList.push_back(DAK_Rethrows);
result.PrintOverrideKeyword = false;
result.AccessFilter = AccessLevel::Public;
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index bbd37b9..0c51835 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -20,6 +20,7 @@
#include "swift/Basic/Sanitizers.h"
#include "swift/Basic/OptionSet.h"
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include <string>
@@ -52,16 +53,6 @@
LinkAll
};
- /// Representation of optimization modes.
- enum class SILOptMode: unsigned {
- NotSet,
- None,
- Debug,
- Optimize,
- OptimizeForSize,
- OptimizeUnchecked
- };
-
/// Controls how to perform SIL linking.
LinkingMode LinkMode = LinkNormal;
@@ -91,7 +82,7 @@
bool EmitVerboseSIL = false;
/// Optimization mode being used.
- SILOptMode Optimization = SILOptMode::NotSet;
+ OptimizationMode OptMode = OptimizationMode::NotSet;
enum AssertConfiguration: unsigned {
// Used by standard library code to distinguish between a debug and release
@@ -167,6 +158,10 @@
llvm::hash_code getPCHHashComponents() const {
return llvm::hash_value(0);
}
+
+ bool shouldOptimize() const {
+ return OptMode > OptimizationMode::NoOptimization;
+ }
};
} // end namespace swift
diff --git a/include/swift/Basic/OptimizationMode.h b/include/swift/Basic/OptimizationMode.h
new file mode 100644
index 0000000..e57b8e6
--- /dev/null
+++ b/include/swift/Basic/OptimizationMode.h
@@ -0,0 +1,32 @@
+//===-------- OptimizationMode.h - Swift optimization modes -----*- C++ -*-===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_BASIC_OPTIMIZATIONMODE_H
+#define SWIFT_BASIC_OPTIMIZATIONMODE_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace swift {
+
+// The optimization mode specified on the command line or with function
+// attributes.
+enum class OptimizationMode : uint8_t {
+ NotSet = 0,
+ NoOptimization = 1, // -Onone
+ ForSpeed = 2, // -Ospeed == -O
+ ForSize = 3, // -Osize
+ LastMode = ForSize
+};
+
+} // end namespace swift
+
+#endif // SWIFT_BASIC_OPTIMIZATIONMODE_H
diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index 0bd2c66..576fa9c 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -309,6 +309,17 @@
}
return SourceFile::ImplicitModuleImportKind::Stdlib;
}
+
+ /// Performs input setup common to these tools:
+ /// sil-opt, sil-func-extractor, sil-llvm-gen, and sil-nm.
+ /// Return value includes the buffer so caller can keep it alive.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ setUpInputForSILTool(StringRef InputFilename, StringRef ModuleNameArg,
+ bool alwaysSetModuleToMain,
+ serialization::ExtendedValidationInfo &extendedInfo);
+ bool hasSerializedAST() {
+ return FrontendOpts.InputKind == InputFileKind::IFK_Swift_Library;
+ }
};
/// A class which manages the state and execution of the compiler.
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index db3c8f6..ce4b982 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -299,15 +299,15 @@
/// The module for which we should verify all of the generic signatures.
std::string VerifyGenericSignaturesInModule;
- enum ActionType {
- NoneAction, ///< No specific action
- Parse, ///< Parse only
- Typecheck, ///< Parse and type-check only
- DumpParse, ///< Parse only and dump AST
+ enum class ActionType {
+ NoneAction, ///< No specific action
+ Parse, ///< Parse only
+ Typecheck, ///< Parse and type-check only
+ DumpParse, ///< Parse only and dump AST
DumpInterfaceHash, ///< Parse and dump the interface token hash.
- EmitSyntax, ///< Parse and dump Syntax tree as JSON
- DumpAST, ///< Parse, type-check, and dump AST
- PrintAST, ///< Parse, type-check, and pretty-print AST
+ EmitSyntax, ///< Parse and dump Syntax tree as JSON
+ DumpAST, ///< Parse, type-check, and dump AST
+ PrintAST, ///< Parse, type-check, and pretty-print AST
/// Parse and dump scope map.
DumpScopeMaps,
@@ -316,30 +316,30 @@
DumpTypeRefinementContexts,
EmitImportedModules, ///< Emit the modules that this one imports
- EmitPCH, ///< Emit PCH of imported bridging header
+ EmitPCH, ///< Emit PCH of imported bridging header
EmitSILGen, ///< Emit raw SIL
- EmitSIL, ///< Emit canonical SIL
+ EmitSIL, ///< Emit canonical SIL
EmitModuleOnly, ///< Emit module only
- MergeModules, ///< Merge modules only
+ MergeModules, ///< Merge modules only
EmitSIBGen, ///< Emit serialized AST + raw SIL
- EmitSIB, ///< Emit serialized AST + canonical SIL
+ EmitSIB, ///< Emit serialized AST + canonical SIL
Immediate, ///< Immediate mode
- REPL, ///< REPL mode
+ REPL, ///< REPL mode
EmitAssembly, ///< Emit assembly
- EmitIR, ///< Emit LLVM IR
- EmitBC, ///< Emit LLVM BC
- EmitObject, ///< Emit object file
+ EmitIR, ///< Emit LLVM IR
+ EmitBC, ///< Emit LLVM BC
+ EmitObject, ///< Emit object file
};
- bool isCreatingSIL() { return RequestedAction >= EmitSILGen; }
+ bool isCreatingSIL() { return RequestedAction >= ActionType::EmitSILGen; }
/// Indicates the action the user requested that the frontend perform.
- ActionType RequestedAction = NoneAction;
+ ActionType RequestedAction = ActionType::NoneAction;
/// Indicates that the input(s) should be parsed as the Swift stdlib.
bool ParseStdlib = false;
diff --git a/include/swift/AST/SourceEntityWalker.h b/include/swift/IDE/SourceEntityWalker.h
similarity index 94%
rename from include/swift/AST/SourceEntityWalker.h
rename to include/swift/IDE/SourceEntityWalker.h
index fd33571..61f8cc5 100644
--- a/include/swift/AST/SourceEntityWalker.h
+++ b/include/swift/IDE/SourceEntityWalker.h
@@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef SWIFT_AST_SOURCE_ENTITY_WALKER_H
-#define SWIFT_AST_SOURCE_ENTITY_WALKER_H
+#ifndef SWIFT_IDE_SOURCE_ENTITY_WALKER_H
+#define SWIFT_IDE_SOURCE_ENTITY_WALKER_H
#include "swift/AST/ASTWalker.h"
#include "swift/Basic/LLVM.h"
@@ -36,6 +36,7 @@
class Stmt;
class Expr;
class Type;
+ struct ASTNode;
/// An abstract class used to traverse the AST and provide source information.
@@ -61,6 +62,9 @@
/// Walks the provided Expr.
/// \returns true if traversal was aborted, false otherwise.
bool walk(Expr *E);
+ /// Walks the provided ASTNode.
+ /// \returns true if traversal was aborted, false otherwise.
+ bool walk(ASTNode N);
/// This method is called when first visiting a decl, before walking into its
/// children. If it returns false, the subtree is skipped.
@@ -109,9 +113,11 @@
///
/// \param D the referenced decl.
/// \param Range the source range of the source reference.
+ /// \param AccKind whether this is a read, write or read/write access.
/// \param IsOpenBracket this is \c true when the method is called on an
/// open bracket.
virtual bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket);
/// This method is called for each keyword argument in a call expression.
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index 29ec7b3..4134871 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -19,7 +19,7 @@
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/Module.h"
#include "swift/AST/ASTPrinter.h"
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Token.h"
#include "llvm/ADT/StringRef.h"
#include <memory>
@@ -242,6 +242,7 @@
bool tryResolve(ModuleEntity Mod, SourceLoc Loc);
bool tryResolve(Stmt *St);
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override;
};
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 6631236..31e028f 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -577,16 +577,6 @@
return reinterpret_cast<SILFunction*>(Pointer);
}
- /// Returns true if this function is only serialized, but not necessarily
- /// code-gen'd. These are fragile transparent functions.
- bool isSILOnly() const {
- if (getKind() != Kind::SILFunction)
- return false;
-
- SILFunction *F = getSILFunction();
- return F->isTransparent() && F->isDefinition() && F->isSerialized();
- }
-
SILGlobalVariable *getSILGlobalVariable() const {
assert(getKind() == Kind::SILGlobalVariable);
return reinterpret_cast<SILGlobalVariable*>(Pointer);
@@ -681,7 +671,6 @@
static LinkInfo get(const UniversalLinkageInfo &linkInfo,
StringRef name,
SILLinkage linkage,
- bool isSILOnly,
ForDefinition_t isDefinition,
bool isWeakImported);
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index b6184c8..27a8a51 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -1237,6 +1237,16 @@
getModule(), getSILDebugLocation(Loc), Operand));
}
+ MultipleValueInstruction *emitDestructureValueOperation(SILLocation Loc,
+ SILValue Operand) {
+ SILType OpTy = Operand->getType();
+ if (OpTy.is<TupleType>())
+ return createDestructureTuple(Loc, Operand);
+ if (OpTy.getStructOrBoundGenericStruct())
+ return createDestructureStruct(Loc, Operand);
+ llvm_unreachable("Can not emit a destructure for this type of operand.");
+ }
+
ClassMethodInst *createClassMethod(SILLocation Loc, SILValue Operand,
SILDeclRef Member, SILType MethodTy) {
return insert(new (getModule()) ClassMethodInst(
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 572f2f3..efbd741 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -171,6 +171,10 @@
/// pre-specialization.
unsigned KeepAsPublic : 1;
+ /// If != OptimizationMode::NotSet, the optimization mode specified with an
+ /// function attribute.
+ OptimizationMode OptMode;
+
/// This is the number of uses of this SILFunction inside the SIL.
/// It does not include references from debug scopes.
unsigned RefCount = 0;
@@ -479,10 +483,26 @@
void addSpecializeAttr(SILSpecializeAttr *Attr);
+
+ /// Get this function's optimization mode or OptimizationMode::NotSet if it is
+ /// not set for this specific function.
+ OptimizationMode getOptimizationMode() const { return OptMode; }
+
+ /// Returns the optimization mode for the function. If no mode is set for the
+ /// function, returns the global mode, i.e. the mode of the module's options.
+ OptimizationMode getEffectiveOptimizationMode() const;
+
+ void setOptimizationMode(OptimizationMode mode) { OptMode = mode; }
+
/// \returns True if the function is optimizable (i.e. not marked as no-opt),
/// or is raw SIL (so that the mandatory passes still run).
bool shouldOptimize() const;
+ /// Returns true if this function should be optimized for size.
+ bool optimizeForSize() const {
+ return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
+ }
+
/// Returns true if this is a function that should have its ownership
/// verified.
bool shouldVerifyOwnership() const;
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index b87fdd4..d27792d 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -156,8 +156,14 @@
iterator begin() const;
iterator end() const;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ reverse_iterator rbegin() const;
+ reverse_iterator rend() const;
+
using range = llvm::iterator_range<iterator>;
range getValues() const;
+ using reverse_range = llvm::iterator_range<reverse_iterator>;
+ reverse_range getReversedValues() const;
using type_range = llvm::iterator_range<
llvm::mapped_iterator<iterator, std::function<SILType(SILValue)>>>;
@@ -200,9 +206,7 @@
}
};
-class SILInstructionResultArray::iterator
- : public std::iterator<std::bidirectional_iterator_tag, SILValue,
- ptrdiff_t> {
+class SILInstructionResultArray::iterator {
/// Our "parent" array.
///
/// This is actually a value type reference into a SILInstruction of some
@@ -214,14 +218,21 @@
Optional<unsigned> Index;
public:
+ using difference_type = int;
+ using value_type = SILValue;
+ using pointer = void;
+ using reference = SILValue;
+ using iterator_category = std::bidirectional_iterator_tag;
+
iterator() = default;
iterator(const SILInstructionResultArray &Parent,
Optional<unsigned> Index = 0)
: Parent(Parent), Index(Index) {}
SILValue operator*() const { return Parent[Index.getValue()]; }
-
+ SILValue operator*() { return Parent[Index.getValue()]; }
SILValue operator->() const { return operator*(); }
+ SILValue operator->() { return operator*(); }
iterator &operator++() {
++Index.getValue();
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index 75f1f4e..370b432 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -275,7 +275,11 @@
return TypeLowering::LoweringStyle::Shallow;
}
- /// Emit a lowered 'release_value' operation.
+ //===--------------------------------------------------------------------===//
+ // DestroyValue
+ //===--------------------------------------------------------------------===//
+
+ /// Emit a lowered destroy value operation.
///
/// This type must be loadable.
virtual void emitLoweredDestroyValue(SILBuilder &B, SILLocation loc,
@@ -290,7 +294,7 @@
return emitDestroyValue(B, loc, value);
}
- /// Emit a lowered 'release_value' operation.
+ /// Emit a lowered destroy value operation.
///
/// This type must be loadable.
void emitLoweredDestroyValueShallow(SILBuilder &B, SILLocation loc,
@@ -298,7 +302,7 @@
emitLoweredDestroyValue(B, loc, value, LoweringStyle::Shallow);
}
- /// Emit a lowered 'release_value' operation.
+ /// Emit a lowered destroy_value operation.
///
/// This type must be loadable.
void emitLoweredDestroyValueDeep(SILBuilder &B, SILLocation loc,
@@ -317,14 +321,18 @@
virtual void emitDestroyValue(SILBuilder &B, SILLocation loc,
SILValue value) const = 0;
- /// Emit a lowered 'retain_value' operation.
+ //===--------------------------------------------------------------------===//
+ // CopyValue
+ //===--------------------------------------------------------------------===//
+
+ /// Emit a lowered copy value operation.
///
/// This type must be loadable.
virtual SILValue emitLoweredCopyValue(SILBuilder &B, SILLocation loc,
SILValue value,
LoweringStyle style) const = 0;
- /// Emit a lowered 'retain_value' operation.
+ /// Emit a lowered copy value operation.
///
/// This type must be loadable.
SILValue emitLoweredCopyValueShallow(SILBuilder &B, SILLocation loc,
@@ -332,7 +340,7 @@
return emitLoweredCopyValue(B, loc, value, LoweringStyle::Shallow);
}
- /// Emit a lowered 'retain_value' operation.
+ /// Emit a lowered copy value operation.
///
/// This type must be loadable.
SILValue emitLoweredCopyValueDeep(SILBuilder &B, SILLocation loc,
diff --git a/include/swift/SILOptimizer/PassManager/PassManager.h b/include/swift/SILOptimizer/PassManager/PassManager.h
index 0324d10..7e7af25 100644
--- a/include/swift/SILOptimizer/PassManager/PassManager.h
+++ b/include/swift/SILOptimizer/PassManager/PassManager.h
@@ -97,6 +97,9 @@
/// same function.
bool RestartPipeline = false;
+ /// If true, passes are also run for functions which have
+ /// OptimizationMode::NoOptimization.
+ bool isMandatoryPipeline = false;
/// The IRGen SIL passes. These have to be dynamically added by IRGen.
llvm::DenseMap<unsigned, SILTransform *> IRGenPasses;
@@ -104,12 +107,17 @@
public:
/// C'tor. It creates and registers all analysis passes, which are defined
/// in Analysis.def.
- SILPassManager(SILModule *M, llvm::StringRef Stage = "");
+ ///
+ /// If \p isMandatoryPipeline is true, passes are also run for functions
+ /// which have OptimizationMode::NoOptimization.
+ SILPassManager(SILModule *M, llvm::StringRef Stage = "",
+ bool isMandatoryPipeline = false);
/// C'tor. It creates an IRGen pass manager. Passes can query for the
/// IRGenModule.
SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
- llvm::StringRef Stage = "");
+ llvm::StringRef Stage = "",
+ bool isMandatoryPipeline = false);
const SILOptions &getOptions() const;
diff --git a/include/swift/SILOptimizer/Utils/CFG.h b/include/swift/SILOptimizer/Utils/CFG.h
index 2ce5a80..44b781d 100644
--- a/include/swift/SILOptimizer/Utils/CFG.h
+++ b/include/swift/SILOptimizer/Utils/CFG.h
@@ -125,11 +125,52 @@
bool splitAllCriticalEdges(SILFunction &F, bool OnlyNonCondBr,
DominanceInfo *DT, SILLoopInfo *LI);
+/// \brief Split all cond_br critical edges with non-trivial arguments in the
+/// function updating the dominator tree and loop information (if they are not
+/// set to null).
+///
+/// A current invariant of Ownership SIL is that cond_br can only have critical
+/// edges with non-trivial arguments. This simplifies computation.
+bool splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &F,
+ DominanceInfo *DT,
+ SILLoopInfo *LI);
+
/// \brief Merge a basic block ending in a branch with its successor
/// if possible. If dominance information or loop info is non null update it.
/// Return true if block was merged.
bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT,
SILLoopInfo *LI);
+/// Given a list of \p UserBlocks and a list of \p DefBlocks, find a set of
+/// blocks that together with \p UserBlocks joint-postdominate \p
+/// DefBlocks. This is in a sense finding a set of blocks that "complete" \p
+/// UserBlocks with respect to \p DefBlocks. As an example, for the following
+/// CFG:
+///
+/// +-----+
+/// | Def |
+/// +-----+
+/// | |
+/// v v
+/// +-----+ +-----+
+/// | | | Use |
+/// +-----+ +-----+
+///
+/// the completion of the joint post-dominance set would be the empty
+/// block. This has two main uses:
+///
+/// 1. This can tell you the places where if you were to sink the Def one would
+/// need to insert "compensating code".
+///
+/// 2. It can be used to prove ownership correctness of @owned values by
+/// asserting that the set of UserBlocks has an empty completion, implying they
+/// jointly-post dominate the def.
+///
+/// *NOTE* This completion may not be unique.
+void completeJointPostDominanceSet(
+ ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
+ llvm::SmallVectorImpl<SILBasicBlock *> &Completion);
+
} // end namespace swift
+
#endif
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 7993440..38fb3d1 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 384; // Last change: begin_apply
+const uint16_t VERSION_MINOR = 385; // Last change: Optimization attribute
using DeclIDField = BCFixed<31>;
@@ -1401,6 +1401,11 @@
BCFixed<2> // inline value
>;
+ using OptimizeDeclAttrLayout = BCRecordLayout<
+ Optimize_DECL_ATTR,
+ BCFixed<2> // optimize value
+ >;
+
// Encodes a VersionTuple:
//
// Major
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index e79e188..e52f0ba 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -212,6 +212,8 @@
const SourcePresence Presence)
: Kind(Kind), Layout(Layout), Presence(Presence) {}
+ virtual ~RawSyntax() = default;
+
/// Returns a raw syntax node of the given Kind, specified Layout,
/// and source presence.
static RC<RawSyntax> make(const SyntaxKind Kind, const LayoutList Layout,
diff --git a/include/swift/Syntax/SyntaxFactory.h.gyb b/include/swift/Syntax/SyntaxFactory.h.gyb
index 08f8372..e9f7c09 100644
--- a/include/swift/Syntax/SyntaxFactory.h.gyb
+++ b/include/swift/Syntax/SyntaxFactory.h.gyb
@@ -54,6 +54,11 @@
static Optional<Syntax>
createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements);
+ /// Count the number of children for a given syntax node kind,
+ /// returning a pair of mininum and maximum count of children. The gap
+ /// between these two numbers is the number of optional children.
+ static std::pair<unsigned, unsigned> countChildren(SyntaxKind Kind);
+
static SyntaxKind getUnknownKind(SyntaxKind Kind);
static Syntax
diff --git a/lib/AST/ASTNode.cpp b/lib/AST/ASTNode.cpp
index e5f70b9..f182f01 100644
--- a/lib/AST/ASTNode.cpp
+++ b/lib/AST/ASTNode.cpp
@@ -76,16 +76,6 @@
else
llvm_unreachable("unsupported AST node");
}
-void ASTNode::walk(SourceEntityWalker &Walker) {
- if (auto *E = this->dyn_cast<Expr*>())
- Walker.walk(E);
- else if (auto *S = this->dyn_cast<Stmt*>())
- Walker.walk(S);
- else if (auto *D = this->dyn_cast<Decl*>())
- Walker.walk(D);
- else
- llvm_unreachable("unsupported AST node");
-}
#define FUNC(T) \
bool ASTNode::is##T(T##Kind Kind) const { \
diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp
index d723d43..5456345 100644
--- a/lib/AST/ASTVerifier.cpp
+++ b/lib/AST/ASTVerifier.cpp
@@ -1980,6 +1980,108 @@
abort();
}
}
+
+ void verifyChecked(KeyPathApplicationExpr *E) {
+ PrettyStackTraceExpr debugStack(
+ Ctx, "verifying KeyPathApplicationExpr", E);
+
+ auto baseTy = E->getBase()->getType();
+ auto keyPathTy = E->getKeyPath()->getType();
+ auto resultTy = E->getType();
+
+ if (auto nom = keyPathTy->getAs<NominalType>()) {
+ if (nom->getDecl() == Ctx.getAnyKeyPathDecl()) {
+ // AnyKeyPath application is <T> rvalue T -> rvalue Any?
+ if (baseTy->is<LValueType>()) {
+ Out << "AnyKeyPath application base is not an rvalue\n";
+ abort();
+ }
+ auto resultObjTy = resultTy->getOptionalObjectType();
+ if (!resultObjTy || !resultObjTy->isAny()) {
+ Out << "AnyKeyPath application result must be Any?\n";
+ abort();
+ }
+ return;
+ }
+ } else if (auto bgt = keyPathTy->getAs<BoundGenericType>()) {
+ if (bgt->getDecl() == Ctx.getPartialKeyPathDecl()) {
+ // PartialKeyPath<T> application is rvalue T -> rvalue Any
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "PartialKeyPath application base doesn't match type\n";
+ abort();
+ }
+ if (!resultTy->isAny()) {
+ Out << "PartialKeyPath application result must be Any?\n";
+ abort();
+ }
+ return;
+ } else if (bgt->getDecl() == Ctx.getKeyPathDecl()) {
+ // KeyPath<T, U> application is rvalue T -> rvalue U
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "KeyPath application base doesn't match type\n";
+ abort();
+ }
+ if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+ Out << "KeyPath application result doesn't match type\n";
+ abort();
+ }
+ return;
+ } else if (bgt->getDecl() == Ctx.getWritableKeyPathDecl()) {
+ // WritableKeyPath<T, U> application is
+ // lvalue T -> lvalue U
+ // or rvalue T -> rvalue U
+ if (baseTy->is<LValueType>()) {
+ if (!resultTy->is<LValueType>()) {
+ Out << "WritableKeyPath base and result don't match lvalue-ness\n";
+ abort();
+ }
+ baseTy = baseTy->getRValueType();
+ resultTy = resultTy->getRValueType();
+ }
+
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "WritableKeyPath application base doesn't match type\n";
+ abort();
+ }
+ if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+ Out << "WritableKeyPath application result doesn't match type\n";
+ abort();
+ }
+ return;
+ } else if (bgt->getDecl() == Ctx.getReferenceWritableKeyPathDecl()) {
+ // ReferenceWritableKeyPath<T, U> application is
+ // rvalue T -> lvalue U
+ // or lvalue T -> lvalue U
+ // or rvalue T -> rvalue U
+ if (baseTy->is<LValueType>()) {
+ if (!resultTy->is<LValueType>()) {
+ Out << "ReferenceWritableKeyPath base and result don't "
+ "match lvalue-ness\n";
+ abort();
+ }
+ baseTy = baseTy->getRValueType();
+ resultTy = resultTy->getRValueType();
+ } else {
+ resultTy = resultTy->getRValueType();
+ }
+
+ if (!baseTy->isEqual(bgt->getGenericArgs()[0])) {
+ Out << "ReferenceWritableKeyPath application base doesn't "
+ "match type\n";
+ abort();
+ }
+ if (!resultTy->isEqual(bgt->getGenericArgs()[1])) {
+ Out << "ReferenceWritableKeyPath application result doesn't "
+ "match type\n";
+ abort();
+ }
+ return;
+ }
+ }
+
+ Out << "invalid key path type\n";
+ abort();
+ }
static bool hasEnclosingFunctionContext(DeclContext *dc) {
switch (dc->getContextKind()) {
diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp
index e29a206..50d58a3 100644
--- a/lib/AST/Attr.cpp
+++ b/lib/AST/Attr.cpp
@@ -340,6 +340,7 @@
case DAK_AccessControl:
case DAK_Ownership:
case DAK_Effects:
+ case DAK_Optimize:
if (DeclAttribute::isDeclModifier(getKind())) {
Printer.printKeyword(getAttrName());
} else {
@@ -577,6 +578,18 @@
}
llvm_unreachable("Invalid inline kind");
}
+ case DAK_Optimize: {
+ switch (cast<OptimizeAttr>(this)->getMode()) {
+ case OptimizationMode::NoOptimization:
+ return "_optimize(none)";
+ case OptimizationMode::ForSpeed:
+ return "_optimize(speed)";
+ case OptimizationMode::ForSize:
+ return "_optimize(size)";
+ default:
+ llvm_unreachable("Invalid optimization kind");
+ }
+ }
case DAK_Effects:
switch (cast<EffectsAttr>(this)->getKind()) {
case EffectsKind::ReadNone:
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index df45aec..6cd7c59 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -48,7 +48,6 @@
SyntaxASTMap.cpp
SILLayout.cpp
Stmt.cpp
- SourceEntityWalker.cpp
Substitution.cpp
SubstitutionList.cpp
SubstitutionMap.cpp
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 483107a..4233676 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -2184,6 +2184,19 @@
llvm_unreachable("unknown access level");
}
+void ValueDecl::copyFormalAccessAndVersionedAttrFrom(ValueDecl *source) {
+ if (!hasAccess()) {
+ setAccess(source->getFormalAccess());
+ }
+
+ // Inherit the @_versioned attribute.
+ if (source->getAttrs().hasAttribute<VersionedAttr>()) {
+ auto &ctx = getASTContext();
+ auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
+ getAttrs().add(clonedAttr);
+ }
+}
+
Type TypeDecl::getDeclaredInterfaceType() const {
if (auto *NTD = dyn_cast<NominalTypeDecl>(this))
return NTD->getDeclaredInterfaceType();
@@ -2689,9 +2702,9 @@
return cast<DestructorDecl>(results.front());
}
-DestructorDecl *ClassDecl::addImplicitDestructor() {
+void ClassDecl::addImplicitDestructor() {
if (hasDestructor() || isInvalid())
- return nullptr;
+ return;
auto *selfDecl = ParamDecl::createSelf(getLoc(), this);
@@ -2699,12 +2712,36 @@
auto *DD = new (ctx) DestructorDecl(getLoc(), selfDecl, this);
DD->setImplicit();
+ DD->setValidationStarted();
// Create an empty body for the destructor.
DD->setBody(BraceStmt::create(ctx, getLoc(), { }, getLoc(), true));
addMember(DD);
setHasDestructor();
- return DD;
+
+ // Propagate access control and versioned-ness.
+ DD->copyFormalAccessAndVersionedAttrFrom(this);
+
+ // Wire up generic environment of DD.
+ DD->setGenericEnvironment(getGenericEnvironmentOfContext());
+
+ // Mark DD as ObjC, as all dtors are.
+ DD->setIsObjC(true);
+ recordObjCMethod(DD);
+
+ // Assign DD the interface type (Self) -> () -> ()
+ ArrayRef<AnyFunctionType::Param> noParams;
+ AnyFunctionType::ExtInfo info;
+ Type selfTy = selfDecl->getInterfaceType();
+ Type voidTy = TupleType::getEmpty(ctx);
+ Type funcTy = FunctionType::get(noParams, voidTy, info);
+ if (auto *sig = DD->getGenericSignature()) {
+ DD->setInterfaceType(
+ GenericFunctionType::get(sig, {selfTy}, funcTy, info));
+ } else {
+ DD->setInterfaceType(
+ FunctionType::get({selfTy}, funcTy, info));
+ }
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index df753e4..d27e118 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -3336,17 +3336,22 @@
Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
Type t(this);
+
+ if (!t->getAnyNominal()) {
+ if (auto archetype = t->getAs<ArchetypeType>()) {
+ t = archetype->getSuperclass();
+ } else if (auto dynamicSelfTy = t->getAs<DynamicSelfType>()) {
+ t = dynamicSelfTy->getSelfType();
+ } else if (auto compositionTy = t->getAs<ProtocolCompositionType>()) {
+ t = compositionTy->getExistentialLayout().superclass;
+ }
+ }
+
while (t) {
// If we have a class-constrained archetype or class-constrained
// existential, get the underlying superclass constraint.
auto *nominalDecl = t->getAnyNominal();
- if (!nominalDecl) {
- assert(t->is<ArchetypeType>() || t->isExistentialType() &&
- "expected a class, archetype or existential");
- t = t->getSuperclass();
- assert(t && "archetype or existential is not class constrained");
- continue;
- }
+ assert(nominalDecl && "expected nominal type here");
assert(isa<ClassDecl>(nominalDecl) && "expected a class here");
if (nominalDecl == baseClass)
@@ -3363,7 +3368,9 @@
assert(dc->isTypeContext());
Type baseTy(this);
- assert(!baseTy->hasLValueType() && !baseTy->is<AnyMetatypeType>());
+ assert(!baseTy->hasLValueType() &&
+ !baseTy->is<AnyMetatypeType>() &&
+ !baseTy->is<ErrorType>());
// The resulting set of substitutions. Always use this to ensure we
// don't miss out on NRVO anywhere.
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 40c58a4..3982bd6 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4254,7 +4254,7 @@
result->setCheckedInheritanceClause();
result->setAddedImplicitInitializers(); // suppress all initializers
addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
- Impl.registerExternalDecl(result);
+ result->addImplicitDestructor();
return result;
};
@@ -4274,7 +4274,6 @@
auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
nsObjectDecl->getDeclContext());
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
- result->addImplicitDestructor();
return result;
}
@@ -4359,7 +4358,6 @@
markMissingSwiftDecl(result);
if (decl->getAttr<clang::ObjCRuntimeVisibleAttr>()) {
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
- result->addImplicitDestructor();
}
// If this Objective-C class has a supertype, import it.
@@ -4392,7 +4390,6 @@
if (decl->getName() == "OS_object" ||
decl->getName() == "OS_os_log") {
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
- result->addImplicitDestructor();
}
// If the superclass is runtime-only, our class is also. This only
@@ -4420,9 +4417,7 @@
#include "InferredAttributes.def"
result->setMemberLoader(&Impl, 0);
-
- // Pass the class to the type checker to create an implicit destructor.
- Impl.registerExternalDecl(result);
+ result->addImplicitDestructor();
return result;
}
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index a32e4d9..336feda 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1414,8 +1414,9 @@
}
case types::TY_SwiftModuleFile:
case types::TY_SwiftModuleDocFile:
- if (OI.ShouldGenerateModule) {
- // When generating a .swiftmodule, treat .swiftmodule files as
+ if (OI.ShouldGenerateModule && !OI.shouldLink()) {
+ // When generating a .swiftmodule as a top-level output (as opposed
+ // to, for example, linking an image), treat .swiftmodule files as
// inputs to a MergeModule action.
AllModuleInputs.push_back(Current);
break;
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 9700939..2d1e878 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -238,39 +238,39 @@
if (const Arg *A = Args.getLastArg(OPT_modes_Group)) {
Option Opt = A->getOption();
if (Opt.matches(OPT_emit_object)) {
- Action = FrontendOptions::EmitObject;
+ Action = FrontendOptions::ActionType::EmitObject;
} else if (Opt.matches(OPT_emit_assembly)) {
- Action = FrontendOptions::EmitAssembly;
+ Action = FrontendOptions::ActionType::EmitAssembly;
} else if (Opt.matches(OPT_emit_ir)) {
- Action = FrontendOptions::EmitIR;
+ Action = FrontendOptions::ActionType::EmitIR;
} else if (Opt.matches(OPT_emit_bc)) {
- Action = FrontendOptions::EmitBC;
+ Action = FrontendOptions::ActionType::EmitBC;
} else if (Opt.matches(OPT_emit_sil)) {
- Action = FrontendOptions::EmitSIL;
+ Action = FrontendOptions::ActionType::EmitSIL;
} else if (Opt.matches(OPT_emit_silgen)) {
- Action = FrontendOptions::EmitSILGen;
+ Action = FrontendOptions::ActionType::EmitSILGen;
} else if (Opt.matches(OPT_emit_sib)) {
- Action = FrontendOptions::EmitSIB;
+ Action = FrontendOptions::ActionType::EmitSIB;
} else if (Opt.matches(OPT_emit_sibgen)) {
- Action = FrontendOptions::EmitSIBGen;
+ Action = FrontendOptions::ActionType::EmitSIBGen;
} else if (Opt.matches(OPT_emit_pch)) {
- Action = FrontendOptions::EmitPCH;
+ Action = FrontendOptions::ActionType::EmitPCH;
} else if (Opt.matches(OPT_emit_imported_modules)) {
- Action = FrontendOptions::EmitImportedModules;
+ Action = FrontendOptions::ActionType::EmitImportedModules;
} else if (Opt.matches(OPT_parse)) {
- Action = FrontendOptions::Parse;
+ Action = FrontendOptions::ActionType::Parse;
} else if (Opt.matches(OPT_typecheck)) {
- Action = FrontendOptions::Typecheck;
+ Action = FrontendOptions::ActionType::Typecheck;
} else if (Opt.matches(OPT_dump_parse)) {
- Action = FrontendOptions::DumpParse;
+ Action = FrontendOptions::ActionType::DumpParse;
} else if (Opt.matches(OPT_dump_ast)) {
- Action = FrontendOptions::DumpAST;
+ Action = FrontendOptions::ActionType::DumpAST;
} else if (Opt.matches(OPT_emit_syntax)) {
- Action = FrontendOptions::EmitSyntax;
+ Action = FrontendOptions::ActionType::EmitSyntax;
} else if (Opt.matches(OPT_merge_modules)) {
- Action = FrontendOptions::MergeModules;
+ Action = FrontendOptions::ActionType::MergeModules;
} else if (Opt.matches(OPT_dump_scope_maps)) {
- Action = FrontendOptions::DumpScopeMaps;
+ Action = FrontendOptions::ActionType::DumpScopeMaps;
StringRef value = A->getValue();
if (value == "expanded") {
@@ -300,16 +300,16 @@
Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
}
} else if (Opt.matches(OPT_dump_type_refinement_contexts)) {
- Action = FrontendOptions::DumpTypeRefinementContexts;
+ Action = FrontendOptions::ActionType::DumpTypeRefinementContexts;
} else if (Opt.matches(OPT_dump_interface_hash)) {
- Action = FrontendOptions::DumpInterfaceHash;
+ Action = FrontendOptions::ActionType::DumpInterfaceHash;
} else if (Opt.matches(OPT_print_ast)) {
- Action = FrontendOptions::PrintAST;
+ Action = FrontendOptions::ActionType::PrintAST;
} else if (Opt.matches(OPT_repl) ||
Opt.matches(OPT_deprecated_integrated_repl)) {
- Action = FrontendOptions::REPL;
+ Action = FrontendOptions::ActionType::REPL;
} else if (Opt.matches(OPT_interpret)) {
- Action = FrontendOptions::Immediate;
+ Action = FrontendOptions::ActionType::Immediate;
} else {
llvm_unreachable("Unhandled mode option");
}
@@ -319,11 +319,11 @@
// We've been told to emit a module, but have no other mode indicators.
// As a result, put the frontend into EmitModuleOnly mode.
// (Setting up module output will be handled below.)
- Action = FrontendOptions::EmitModuleOnly;
+ Action = FrontendOptions::ActionType::EmitModuleOnly;
}
}
- if (Opts.RequestedAction == FrontendOptions::Immediate &&
+ if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
Opts.Inputs.hasPrimaryInput()) {
Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
return true;
@@ -335,12 +335,13 @@
bool TreatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
if (Opts.Inputs.verifyInputs(
- Diags, TreatAsSIL, Opts.RequestedAction == FrontendOptions::REPL,
- Opts.RequestedAction == FrontendOptions::NoneAction)) {
+ Diags, TreatAsSIL,
+ Opts.RequestedAction == FrontendOptions::ActionType::REPL,
+ Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
return true;
}
- if (Opts.RequestedAction == FrontendOptions::Immediate) {
+ if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
Opts.ImmediateArgv.push_back(
Opts.Inputs.getFilenameOfFirstInput()); // argv[0]
if (const Arg *A = Args.getLastArg(OPT__DASH_DASH)) {
@@ -356,7 +357,7 @@
Opts.InputKind = InputFileKind::IFK_LLVM_IR;
else if (Args.hasArg(OPT_parse_as_library))
Opts.InputKind = InputFileKind::IFK_Swift_Library;
- else if (Action == FrontendOptions::REPL)
+ else if (Action == FrontendOptions::ActionType::REPL)
Opts.InputKind = InputFileKind::IFK_Swift_REPL;
else
Opts.InputKind = InputFileKind::IFK_Swift;
@@ -376,28 +377,28 @@
StringRef Suffix;
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
+ case FrontendOptions::ActionType::NoneAction:
break;
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
// Textual modes.
Opts.setOutputFilenameToStdout();
break;
- case FrontendOptions::EmitPCH:
+ case FrontendOptions::ActionType::EmitPCH:
Suffix = PCH_EXTENSION;
break;
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL: {
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL: {
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -405,23 +406,23 @@
break;
}
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
Suffix = SIB_EXTENSION;
break;
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
Suffix = SERIALIZED_MODULE_EXTENSION;
break;
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
// These modes have no frontend-generated output.
Opts.OutputFilenames.clear();
break;
- case FrontendOptions::EmitAssembly: {
+ case FrontendOptions::ActionType::EmitAssembly: {
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -429,7 +430,7 @@
break;
}
- case FrontendOptions::EmitIR: {
+ case FrontendOptions::ActionType::EmitIR: {
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -437,16 +438,16 @@
break;
}
- case FrontendOptions::EmitBC: {
+ case FrontendOptions::ActionType::EmitBC: {
Suffix = "bc";
break;
}
- case FrontendOptions::EmitObject:
+ case FrontendOptions::ActionType::EmitObject:
Suffix = "o";
break;
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::EmitImportedModules:
if (Opts.OutputFilenames.empty())
Opts.setOutputFilenameToStdout();
else
@@ -474,9 +475,9 @@
}
if (Opts.OutputFilenames.empty()) {
- if (Opts.RequestedAction != FrontendOptions::REPL &&
- Opts.RequestedAction != FrontendOptions::Immediate &&
- Opts.RequestedAction != FrontendOptions::NoneAction) {
+ if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
+ Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
+ Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
return true;
}
@@ -542,16 +543,16 @@
Opts.FixitsOutputPath = A->getValue();
}
- bool IsSIB =
- Opts.RequestedAction == FrontendOptions::EmitSIB ||
- Opts.RequestedAction == FrontendOptions::EmitSIBGen;
+ bool IsSIB = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB ||
+ Opts.RequestedAction == FrontendOptions::ActionType::EmitSIBGen;
bool canUseMainOutputForModule =
- Opts.RequestedAction == FrontendOptions::MergeModules ||
- Opts.RequestedAction == FrontendOptions::EmitModuleOnly ||
- IsSIB;
+ Opts.RequestedAction == FrontendOptions::ActionType::MergeModules ||
+ Opts.RequestedAction == FrontendOptions::ActionType::EmitModuleOnly ||
+ IsSIB;
auto ext = IsSIB ? SIB_EXTENSION : SERIALIZED_MODULE_EXTENSION;
- auto sibOpt = Opts.RequestedAction == FrontendOptions::EmitSIB ?
- OPT_emit_sib : OPT_emit_sibgen;
+ auto sibOpt = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB
+ ? OPT_emit_sib
+ : OPT_emit_sibgen;
determineOutputFilename(Opts.ModuleOutputPath,
IsSIB ? sibOpt : OPT_emit_module,
OPT_emit_module_path,
@@ -566,97 +567,97 @@
if (!Opts.DependenciesFilePath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_dependencies);
return true;
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
if (!Opts.ObjCHeaderOutputPath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
return true;
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
if (!Opts.LoadedModuleTracePath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::Parse:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
Diags.diagnose(SourceLoc(),
diag::error_mode_cannot_emit_loaded_module_trace);
return true;
- case FrontendOptions::Typecheck:
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
@@ -664,35 +665,35 @@
if (!Opts.ModuleOutputPath.empty() ||
!Opts.ModuleDocOutputPath.empty()) {
switch (Opts.RequestedAction) {
- case FrontendOptions::NoneAction:
- case FrontendOptions::Parse:
- case FrontendOptions::Typecheck:
- case FrontendOptions::DumpParse:
- case FrontendOptions::DumpInterfaceHash:
- case FrontendOptions::DumpAST:
- case FrontendOptions::EmitSyntax:
- case FrontendOptions::PrintAST:
- case FrontendOptions::EmitPCH:
- case FrontendOptions::DumpScopeMaps:
- case FrontendOptions::DumpTypeRefinementContexts:
- case FrontendOptions::EmitSILGen:
- case FrontendOptions::Immediate:
- case FrontendOptions::REPL:
+ case FrontendOptions::ActionType::NoneAction:
+ case FrontendOptions::ActionType::Parse:
+ case FrontendOptions::ActionType::Typecheck:
+ case FrontendOptions::ActionType::DumpParse:
+ case FrontendOptions::ActionType::DumpInterfaceHash:
+ case FrontendOptions::ActionType::DumpAST:
+ case FrontendOptions::ActionType::EmitSyntax:
+ case FrontendOptions::ActionType::PrintAST:
+ case FrontendOptions::ActionType::EmitPCH:
+ case FrontendOptions::ActionType::DumpScopeMaps:
+ case FrontendOptions::ActionType::DumpTypeRefinementContexts:
+ case FrontendOptions::ActionType::EmitSILGen:
+ case FrontendOptions::ActionType::Immediate:
+ case FrontendOptions::ActionType::REPL:
if (!Opts.ModuleOutputPath.empty())
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
else
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
return true;
- case FrontendOptions::MergeModules:
- case FrontendOptions::EmitModuleOnly:
- case FrontendOptions::EmitSIL:
- case FrontendOptions::EmitSIBGen:
- case FrontendOptions::EmitSIB:
- case FrontendOptions::EmitIR:
- case FrontendOptions::EmitBC:
- case FrontendOptions::EmitAssembly:
- case FrontendOptions::EmitObject:
- case FrontendOptions::EmitImportedModules:
+ case FrontendOptions::ActionType::MergeModules:
+ case FrontendOptions::ActionType::EmitModuleOnly:
+ case FrontendOptions::ActionType::EmitSIL:
+ case FrontendOptions::ActionType::EmitSIBGen:
+ case FrontendOptions::ActionType::EmitSIB:
+ case FrontendOptions::ActionType::EmitIR:
+ case FrontendOptions::ActionType::EmitBC:
+ case FrontendOptions::ActionType::EmitAssembly:
+ case FrontendOptions::ActionType::EmitObject:
+ case FrontendOptions::ActionType::EmitImportedModules:
break;
}
}
@@ -1169,8 +1170,7 @@
Diags.diagnose(SourceLoc(), diag::error_unsupported_option_argument,
A->getOption().getPrefixedName(), A->getValue());
}
- if (Opts.Optimization > SILOptions::SILOptMode::None
- && Opts.EnforceExclusivityDynamic) {
+ if (Opts.shouldOptimize() && Opts.EnforceExclusivityDynamic) {
Diags.diagnose(SourceLoc(),
diag::warning_argument_not_supported_with_optimization,
A->getOption().getPrefixedName() + A->getValue());
@@ -1229,40 +1229,31 @@
// Parse the optimization level.
// Default to Onone settings if no option is passed.
- IRGenOpts.Optimize = false;
- IRGenOpts.OptimizeForSize = false;
- Opts.Optimization = SILOptions::SILOptMode::None;
+ Opts.OptMode = OptimizationMode::NoOptimization;
if (const Arg *A = Args.getLastArg(OPT_O_Group)) {
if (A->getOption().matches(OPT_Onone)) {
// Already set.
} else if (A->getOption().matches(OPT_Ounchecked)) {
// Turn on optimizations and remove all runtime checks.
- IRGenOpts.Optimize = true;
- IRGenOpts.OptimizeForSize = false;
- Opts.Optimization = SILOptions::SILOptMode::OptimizeUnchecked;
+ Opts.OptMode = OptimizationMode::ForSpeed;
// Removal of cond_fail (overflow on binary operations).
Opts.RemoveRuntimeAsserts = true;
Opts.AssertConfig = SILOptions::Unchecked;
} else if (A->getOption().matches(OPT_Oplayground)) {
// For now -Oplayground is equivalent to -Onone.
- IRGenOpts.Optimize = false;
- IRGenOpts.OptimizeForSize = false;
- Opts.Optimization = SILOptions::SILOptMode::None;
+ Opts.OptMode = OptimizationMode::NoOptimization;
} else if (A->getOption().matches(OPT_Osize)) {
- IRGenOpts.Optimize = true;
- IRGenOpts.OptimizeForSize = true;
- Opts.Optimization = SILOptions::SILOptMode::OptimizeForSize;
+ Opts.OptMode = OptimizationMode::ForSize;
} else {
assert(A->getOption().matches(OPT_O));
- IRGenOpts.OptimizeForSize = false;
- IRGenOpts.Optimize = true;
- Opts.Optimization = SILOptions::SILOptMode::Optimize;
+ Opts.OptMode = OptimizationMode::ForSpeed;
}
- if (IRGenOpts.Optimize) {
+ if (Opts.shouldOptimize()) {
ClangOpts.Optimization = "-Os";
}
}
+ IRGenOpts.OptMode = Opts.OptMode;
if (Args.getLastArg(OPT_AssumeSingleThreaded)) {
Opts.AssumeSingleThreaded = true;
@@ -1292,7 +1283,7 @@
// Set the assert configuration according to the optimization level if it
// has not been set by the -Ounchecked flag.
Opts.AssertConfig =
- IRGenOpts.Optimize ? SILOptions::Release : SILOptions::Debug;
+ (IRGenOpts.shouldOptimize() ? SILOptions::Release : SILOptions::Debug);
}
// -Ounchecked might also set removal of runtime asserts (cond_fail).
@@ -1349,7 +1340,7 @@
IRGenOpts.Sanitizers = Opts.Sanitizers;
}
- if (Opts.Optimization > SILOptions::SILOptMode::None)
+ if (Opts.shouldOptimize())
Opts.EnforceExclusivityDynamic = false;
if (const Arg *A = Args.getLastArg(options::OPT_enforce_exclusivity_EQ)) {
parseExclusivityEnforcementOptions(A, Opts, Diags);
@@ -1707,3 +1698,39 @@
extendedInfo.getExtraClangImporterOptions().end());
return info.status;
}
+
+llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+CompilerInvocation::setUpInputForSILTool(
+ StringRef InputFilename, StringRef ModuleNameArg,
+ bool alwaysSetModuleToMain,
+ serialization::ExtendedValidationInfo &extendedInfo) {
+ // Load the input file.
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
+ llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ if (!FileBufOrErr) {
+ return FileBufOrErr;
+ }
+
+ // If it looks like we have an AST, set the source file kind to SIL and the
+ // name of the module to the file's name.
+ addInputBuffer(FileBufOrErr.get().get());
+
+ auto result = serialization::validateSerializedAST(
+ FileBufOrErr.get()->getBuffer(), &extendedInfo);
+ bool HasSerializedAST = result.status == serialization::Status::Valid;
+
+ if (HasSerializedAST) {
+ const StringRef Stem = !ModuleNameArg.empty()
+ ? ModuleNameArg
+ : llvm::sys::path::stem(InputFilename);
+ setModuleName(Stem);
+ setInputKind(InputFileKind::IFK_Swift_Library);
+ } else {
+ const StringRef Name = (alwaysSetModuleToMain || ModuleNameArg.empty())
+ ? "main"
+ : ModuleNameArg;
+ setModuleName(Name);
+ setInputKind(InputFileKind::IFK_SIL);
+ }
+ return FileBufOrErr;
+}
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index ff1791c..344595c 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -257,14 +257,14 @@
if (Invocation.getImplicitModuleImportKind() !=
SourceFile::ImplicitModuleImportKind::Stdlib)
return false;
- SILOptions::SILOptMode optimization = Invocation.getSILOptions().Optimization;
- if (optimization <= SILOptions::SILOptMode::None &&
- shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization(
+ if (Invocation.getSILOptions().shouldOptimize())
+ return false;
+
+ if (shouldImportSwiftOnoneModuleIfNoneOrImplicitOptimization(
Invocation.getFrontendOptions().RequestedAction)) {
return true;
}
- return optimization == SILOptions::SILOptMode::None &&
- Invocation.getFrontendOptions().isCreatingSIL();
+ return Invocation.getFrontendOptions().isCreatingSIL();
}
void CompilerInstance::performSema() {
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index c9cbe96..8bdca8f 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -170,33 +170,33 @@
bool FrontendOptions::actionHasOutput() const {
switch (RequestedAction) {
- case NoneAction:
- case Parse:
- case Typecheck:
- case DumpParse:
- case DumpAST:
- case EmitSyntax:
- case DumpInterfaceHash:
- case PrintAST:
- case DumpScopeMaps:
- case DumpTypeRefinementContexts:
+ case ActionType::NoneAction:
+ case ActionType::Parse:
+ case ActionType::Typecheck:
+ case ActionType::DumpParse:
+ case ActionType::DumpAST:
+ case ActionType::EmitSyntax:
+ case ActionType::DumpInterfaceHash:
+ case ActionType::PrintAST:
+ case ActionType::DumpScopeMaps:
+ case ActionType::DumpTypeRefinementContexts:
return false;
- case EmitPCH:
- case EmitSILGen:
- case EmitSIL:
- case EmitSIBGen:
- case EmitSIB:
- case EmitModuleOnly:
- case MergeModules:
+ case ActionType::EmitPCH:
+ case ActionType::EmitSILGen:
+ case ActionType::EmitSIL:
+ case ActionType::EmitSIBGen:
+ case ActionType::EmitSIB:
+ case ActionType::EmitModuleOnly:
+ case ActionType::MergeModules:
return true;
- case Immediate:
- case REPL:
+ case ActionType::Immediate:
+ case ActionType::REPL:
return false;
- case EmitAssembly:
- case EmitIR:
- case EmitBC:
- case EmitObject:
- case EmitImportedModules:
+ case ActionType::EmitAssembly:
+ case ActionType::EmitIR:
+ case ActionType::EmitBC:
+ case ActionType::EmitObject:
+ case ActionType::EmitImportedModules:
return true;
}
llvm_unreachable("Unknown ActionType");
@@ -204,32 +204,32 @@
bool FrontendOptions::actionIsImmediate() const {
switch (RequestedAction) {
- case NoneAction:
- case Parse:
- case Typecheck:
- case DumpParse:
- case DumpAST:
- case EmitSyntax:
- case DumpInterfaceHash:
- case PrintAST:
- case DumpScopeMaps:
- case DumpTypeRefinementContexts:
- case EmitPCH:
- case EmitSILGen:
- case EmitSIL:
- case EmitSIBGen:
- case EmitSIB:
- case EmitModuleOnly:
- case MergeModules:
+ case ActionType::NoneAction:
+ case ActionType::Parse:
+ case ActionType::Typecheck:
+ case ActionType::DumpParse:
+ case ActionType::DumpAST:
+ case ActionType::EmitSyntax:
+ case ActionType::DumpInterfaceHash:
+ case ActionType::PrintAST:
+ case ActionType::DumpScopeMaps:
+ case ActionType::DumpTypeRefinementContexts:
+ case ActionType::EmitPCH:
+ case ActionType::EmitSILGen:
+ case ActionType::EmitSIL:
+ case ActionType::EmitSIBGen:
+ case ActionType::EmitSIB:
+ case ActionType::EmitModuleOnly:
+ case ActionType::MergeModules:
return false;
- case Immediate:
- case REPL:
+ case ActionType::Immediate:
+ case ActionType::REPL:
return true;
- case EmitAssembly:
- case EmitIR:
- case EmitBC:
- case EmitObject:
- case EmitImportedModules:
+ case ActionType::EmitAssembly:
+ case ActionType::EmitIR:
+ case ActionType::EmitBC:
+ case ActionType::EmitObject:
+ case ActionType::EmitImportedModules:
return false;
}
llvm_unreachable("Unknown ActionType");
@@ -237,8 +237,8 @@
void FrontendOptions::forAllOutputPaths(
std::function<void(const std::string &)> fn) const {
- if (RequestedAction != FrontendOptions::EmitModuleOnly &&
- RequestedAction != FrontendOptions::MergeModules) {
+ if (RequestedAction != FrontendOptions::ActionType::EmitModuleOnly &&
+ RequestedAction != FrontendOptions::ActionType::MergeModules) {
for (const std::string &OutputFileName : OutputFilenames) {
fn(OutputFileName);
}
@@ -299,7 +299,7 @@
// Note: this code path will only be taken when running the frontend
// directly; the driver should always pass -module-name when invoking the
// frontend.
- if (RequestedAction == FrontendOptions::REPL) {
+ if (RequestedAction == FrontendOptions::ActionType::REPL) {
// Default to a module named "REPL" if we're in REPL mode.
return "REPL";
}
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index 90bd29a..d6acb03 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -319,15 +319,15 @@
/// Returns the OutputKind for the given Action.
static IRGenOutputKind getOutputKind(FrontendOptions::ActionType Action) {
switch (Action) {
- case FrontendOptions::EmitIR:
+ case FrontendOptions::ActionType::EmitIR:
return IRGenOutputKind::LLVMAssembly;
- case FrontendOptions::EmitBC:
+ case FrontendOptions::ActionType::EmitBC:
return IRGenOutputKind::LLVMBitcode;
- case FrontendOptions::EmitAssembly:
+ case FrontendOptions::ActionType::EmitAssembly:
return IRGenOutputKind::NativeAssembly;
- case FrontendOptions::EmitObject:
+ case FrontendOptions::ActionType::EmitObject:
return IRGenOutputKind::ObjectFile;
- case FrontendOptions::Immediate:
+ case FrontendOptions::ActionType::Immediate:
return IRGenOutputKind::Module;
default:
llvm_unreachable("Unknown ActionType which requires IRGen");
@@ -512,12 +512,12 @@
FrontendOptions opts = Invocation.getFrontendOptions();
FrontendOptions::ActionType Action = opts.RequestedAction;
- if (Action == FrontendOptions::EmitSyntax)
+ if (Action == FrontendOptions::ActionType::EmitSyntax)
Instance.getASTContext().LangOpts.KeepSyntaxInfoInSourceFile = true;
// We've been asked to precompile a bridging header; we want to
// avoid touching any other inputs and just parse, emit and exit.
- if (Action == FrontendOptions::EmitPCH) {
+ if (Action == FrontendOptions::ActionType::EmitPCH) {
auto clangImporter = static_cast<ClangImporter *>(
Instance.getASTContext().getClangModuleLoader());
auto &ImporterOpts = Invocation.getClangImporterOptions();
@@ -581,16 +581,16 @@
if (shouldTrackReferences)
Instance.setReferencedNameTracker(&nameTracker);
- if (Action == FrontendOptions::Parse ||
- Action == FrontendOptions::DumpParse ||
- Action == FrontendOptions::EmitSyntax ||
- Action == FrontendOptions::DumpInterfaceHash ||
- Action == FrontendOptions::EmitImportedModules)
+ if (Action == FrontendOptions::ActionType::Parse ||
+ Action == FrontendOptions::ActionType::DumpParse ||
+ Action == FrontendOptions::ActionType::EmitSyntax ||
+ Action == FrontendOptions::ActionType::DumpInterfaceHash ||
+ Action == FrontendOptions::ActionType::EmitImportedModules)
Instance.performParseOnly();
else
Instance.performSema();
- if (Action == FrontendOptions::Parse)
+ if (Action == FrontendOptions::ActionType::Parse)
return Instance.getASTContext().hadError();
if (observer) {
@@ -621,7 +621,7 @@
migrator::updateCodeAndEmitRemap(&Instance, Invocation);
}
- if (Action == FrontendOptions::REPL) {
+ if (Action == FrontendOptions::ActionType::REPL) {
runREPL(Instance, ProcessCmdLine(Args.begin(), Args.end()),
Invocation.getParseStdlib());
return Context.hadError();
@@ -632,21 +632,21 @@
// We've been told to dump the AST (either after parsing or type-checking,
// which is already differentiated in CompilerInstance::performSema()),
// so dump or print the main source file and return.
- if (Action == FrontendOptions::DumpParse ||
- Action == FrontendOptions::DumpAST ||
- Action == FrontendOptions::EmitSyntax ||
- Action == FrontendOptions::PrintAST ||
- Action == FrontendOptions::DumpScopeMaps ||
- Action == FrontendOptions::DumpTypeRefinementContexts ||
- Action == FrontendOptions::DumpInterfaceHash) {
+ if (Action == FrontendOptions::ActionType::DumpParse ||
+ Action == FrontendOptions::ActionType::DumpAST ||
+ Action == FrontendOptions::ActionType::EmitSyntax ||
+ Action == FrontendOptions::ActionType::PrintAST ||
+ Action == FrontendOptions::ActionType::DumpScopeMaps ||
+ Action == FrontendOptions::ActionType::DumpTypeRefinementContexts ||
+ Action == FrontendOptions::ActionType::DumpInterfaceHash) {
SourceFile *SF = PrimarySourceFile;
if (!SF) {
SourceFileKind Kind = Invocation.getSourceFileKind();
SF = &Instance.getMainModule()->getMainSourceFile(Kind);
}
- if (Action == FrontendOptions::PrintAST)
+ if (Action == FrontendOptions::ActionType::PrintAST)
SF->print(llvm::outs(), PrintOptions::printEverything());
- else if (Action == FrontendOptions::DumpScopeMaps) {
+ else if (Action == FrontendOptions::ActionType::DumpScopeMaps) {
ASTScope &scope = SF->getScope();
if (opts.DumpScopeMapLocations.empty()) {
@@ -690,17 +690,18 @@
// Print the resulting map.
scope.print(llvm::errs());
- } else if (Action == FrontendOptions::DumpTypeRefinementContexts)
+ } else if (Action ==
+ FrontendOptions::ActionType::DumpTypeRefinementContexts)
SF->getTypeRefinementContext()->dump(llvm::errs(), Context.SourceMgr);
- else if (Action == FrontendOptions::DumpInterfaceHash)
+ else if (Action == FrontendOptions::ActionType::DumpInterfaceHash)
SF->dumpInterfaceHash(llvm::errs());
- else if (Action == FrontendOptions::EmitSyntax) {
+ else if (Action == FrontendOptions::ActionType::EmitSyntax) {
emitSyntax(SF, Invocation.getLangOptions(), Instance.getSourceMgr(),
opts.getSingleOutputFilename());
} else
SF->dump();
return Context.hadError();
- } else if (Action == FrontendOptions::EmitImportedModules) {
+ } else if (Action == FrontendOptions::ActionType::EmitImportedModules) {
emitImportedModules(Context, Instance.getMainModule(), opts);
return Context.hadError();
}
@@ -740,7 +741,7 @@
!Context.LangOpts.EnableAppExtensionRestrictions;
// We've just been told to perform a typecheck, so we can return now.
- if (Action == FrontendOptions::Typecheck) {
+ if (Action == FrontendOptions::ActionType::Typecheck) {
if (!opts.ObjCHeaderOutputPath.empty())
return printAsObjC(opts.ObjCHeaderOutputPath, Instance.getMainModule(),
opts.ImplicitObjCHeaderPath, moduleIsPublic);
@@ -763,7 +764,7 @@
return true;
}
- assert(Action >= FrontendOptions::EmitSILGen &&
+ assert(Action >= FrontendOptions::ActionType::EmitSILGen &&
"All actions not requiring SILGen must have been handled!");
std::unique_ptr<SILModule> SM = Instance.takeSILModule();
@@ -802,7 +803,7 @@
}
// We've been told to emit SIL after SILGen, so write it now.
- if (Action == FrontendOptions::EmitSILGen) {
+ if (Action == FrontendOptions::ActionType::EmitSILGen) {
// If we are asked to link all, link all.
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
performSILLinking(SM.get(), true);
@@ -810,7 +811,7 @@
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
}
- if (Action == FrontendOptions::EmitSIBGen) {
+ if (Action == FrontendOptions::ActionType::EmitSIBGen) {
// If we are asked to link all, link all.
if (Invocation.getSILOptions().LinkMode == SILOptions::LinkAll)
performSILLinking(SM.get(), true);
@@ -836,7 +837,7 @@
std::move(OptRecordFile));
// Perform "stable" optimizations that are invariant across compiler versions.
- if (Action == FrontendOptions::MergeModules) {
+ if (Action == FrontendOptions::ActionType::MergeModules) {
// Don't run diagnostic passes at all.
} else if (!Invocation.getDiagnosticOptions().SkipDiagnosticPasses) {
if (runSILDiagnosticPasses(*SM))
@@ -908,9 +909,8 @@
// These may change across compiler versions.
{
SharedTimer timer("SIL optimization");
- if (Action != FrontendOptions::MergeModules &&
- Invocation.getSILOptions().Optimization >
- SILOptions::SILOptMode::None) {
+ if (Action != FrontendOptions::ActionType::MergeModules &&
+ Invocation.getSILOptions().shouldOptimize()) {
runSILOptPreparePasses(*SM);
@@ -956,7 +956,7 @@
opts.ImplicitObjCHeaderPath, moduleIsPublic);
}
- if (Action == FrontendOptions::EmitSIB) {
+ if (Action == FrontendOptions::ActionType::EmitSIB) {
auto DC = PrimarySourceFile ? ModuleOrSourceFile(PrimarySourceFile) :
Instance.getMainModule();
if (!opts.ModuleOutputPath.empty()) {
@@ -974,8 +974,8 @@
// Serialize the SILModule if it was not serialized yet.
if (!SM.get()->isSerialized())
SM.get()->serialize();
- if (Action == FrontendOptions::MergeModules ||
- Action == FrontendOptions::EmitModuleOnly) {
+ if (Action == FrontendOptions::ActionType::MergeModules ||
+ Action == FrontendOptions::ActionType::EmitModuleOnly) {
if (shouldIndex) {
if (emitIndexData(PrimarySourceFile, Invocation, Instance))
return true;
@@ -984,18 +984,18 @@
}
}
- assert(Action >= FrontendOptions::EmitSIL &&
+ assert(Action >= FrontendOptions::ActionType::EmitSIL &&
"All actions not requiring SILPasses must have been handled!");
// We've been told to write canonical SIL, so write it now.
- if (Action == FrontendOptions::EmitSIL) {
+ if (Action == FrontendOptions::ActionType::EmitSIL) {
return writeSIL(*SM, Instance.getMainModule(), opts.EmitVerboseSIL,
opts.getSingleOutputFilename(), opts.EmitSortedSIL);
}
- assert(Action >= FrontendOptions::Immediate &&
+ assert(Action >= FrontendOptions::ActionType::Immediate &&
"All actions not requiring IRGen must have been handled!");
- assert(Action != FrontendOptions::REPL &&
+ assert(Action != FrontendOptions::ActionType::REPL &&
"REPL mode must be handled immediately after Instance->performSema()");
// Check if we had any errors; if we did, don't proceed to IRGen.
@@ -1007,7 +1007,7 @@
// TODO: remove once the frontend understands what action it should perform
IRGenOpts.OutputKind = getOutputKind(Action);
- if (Action == FrontendOptions::Immediate) {
+ if (Action == FrontendOptions::ActionType::Immediate) {
assert(!PrimarySourceFile && "-i doesn't work in -primary-file mode");
IRGenOpts.UseJIT = true;
IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::Normal;
@@ -1109,15 +1109,13 @@
// paths as a fallback.
bool isDebugCompilation;
- switch (Invocation.getSILOptions().Optimization) {
- case SILOptions::SILOptMode::NotSet:
- case SILOptions::SILOptMode::None:
- case SILOptions::SILOptMode::Debug:
+ switch (Invocation.getSILOptions().OptMode) {
+ case OptimizationMode::NotSet:
+ case OptimizationMode::NoOptimization:
isDebugCompilation = true;
break;
- case SILOptions::SILOptMode::Optimize:
- case SILOptions::SILOptMode::OptimizeForSize:
- case SILOptions::SILOptMode::OptimizeUnchecked:
+ case OptimizationMode::ForSpeed:
+ case OptimizationMode::ForSize:
isDebugCompilation = false;
break;
}
@@ -1210,13 +1208,11 @@
}
static StringRef
-silOptModeArgStr(SILOptions::SILOptMode mode) {
+silOptModeArgStr(OptimizationMode mode) {
switch (mode) {
- case SILOptions::SILOptMode::Optimize:
+ case OptimizationMode::ForSpeed:
return "O";
- case SILOptions::SILOptMode::OptimizeUnchecked:
- return "Ounchecked";
- case SILOptions::SILOptMode::OptimizeForSize:
+ case OptimizationMode::ForSize:
return "Osize";
default:
return "Onone";
@@ -1326,7 +1322,7 @@
}
if (Invocation.getFrontendOptions().RequestedAction ==
- FrontendOptions::NoneAction) {
+ FrontendOptions::ActionType::NoneAction) {
Instance->getDiags().diagnose(SourceLoc(),
diag::error_missing_frontend_action);
return finishDiagProcessing(1);
@@ -1378,7 +1374,7 @@
auto &LangOpts = Invocation.getLangOptions();
auto &SILOpts = Invocation.getSILOptions();
StringRef InputName = FEOpts.Inputs.primaryInputFilenameIfAny();
- StringRef OptType = silOptModeArgStr(SILOpts.Optimization);
+ StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
StringRef OutFile = FEOpts.getSingleOutputFilename();
StringRef OutputType = llvm::sys::path::extension(OutFile);
std::string TripleName = LangOpts.Target.normalize();
diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt
index 90ec65a..e93742f 100644
--- a/lib/IDE/CMakeLists.txt
+++ b/lib/IDE/CMakeLists.txt
@@ -12,6 +12,7 @@
Utils.cpp
IDETypeChecking.cpp
APIDigesterData.cpp
+ SourceEntityWalker.cpp
DEPENDS
swift-syntax-generated-headers
LINK_LIBRARIES
diff --git a/lib/IDE/Formatting.cpp b/lib/IDE/Formatting.cpp
index 8a9c6e7..5b0059e 100644
--- a/lib/IDE/Formatting.cpp
+++ b/lib/IDE/Formatting.cpp
@@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTWalker.h"
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Parser.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Basic/SourceManager.h"
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index e2d42f7..b61ca6d 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -819,7 +819,7 @@
// We cannot extract expressions of l-value type.
if (auto Ty = RangeInfo.getType()) {
- if (Ty->hasLValueType() || Ty->getKind() == TypeKind::InOut)
+ if (Ty->hasLValueType() || Ty->is<InOutType>())
return ExtractCheckResult();
// Disallow extracting error type expressions/statements
@@ -941,7 +941,7 @@
static Type sanitizeType(Type Ty) {
// Transform lvalue type to inout type so that we can print it properly.
return Ty.transform([](Type Ty) {
- if (Ty->getKind() == TypeKind::LValue) {
+ if (Ty->is<LValueType>()) {
return Type(InOutType::get(Ty->getRValueType()->getCanonicalType()));
}
return Ty;
@@ -1163,7 +1163,7 @@
for (auto &RD : Parameters) {
// Inout argument needs "&".
- if (RD.Ty->getKind() == TypeKind::InOut)
+ if (RD.Ty->is<InOutType>())
OS << "&";
OS << RD.VD->getBaseName().userFacingName();
if (&RD != &Parameters.back())
diff --git a/lib/AST/SourceEntityWalker.cpp b/lib/IDE/SourceEntityWalker.cpp
similarity index 94%
rename from lib/AST/SourceEntityWalker.cpp
rename to lib/IDE/SourceEntityWalker.cpp
index 7b04710..6622bb9 100644
--- a/lib/AST/SourceEntityWalker.cpp
+++ b/lib/IDE/SourceEntityWalker.cpp
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
-#include "swift/AST/SourceEntityWalker.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Lexer.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTWalker.h"
@@ -65,7 +65,9 @@
bool passReference(ValueDecl *D, Type Ty, DeclNameLoc Loc, ReferenceMetaData Data);
bool passReference(ModuleEntity Mod, std::pair<Identifier, SourceLoc> IdLoc);
- bool passSubscriptReference(ValueDecl *D, SourceLoc Loc, bool IsOpenBracket);
+ bool passSubscriptReference(ValueDecl *D, SourceLoc Loc,
+ Optional<AccessKind> AccKind,
+ bool IsOpenBracket);
bool passCallArgNames(Expr *Fn, TupleExpr *TupleE);
@@ -297,7 +299,7 @@
SubscrD = SE->getDecl().getDecl();
if (SubscrD) {
- if (!passSubscriptReference(SubscrD, E->getLoc(), true))
+ if (!passSubscriptReference(SubscrD, E->getLoc(), OpAccess, true))
return { false, nullptr };
}
@@ -305,7 +307,7 @@
return { false, nullptr };
if (SubscrD) {
- if (!passSubscriptReference(SubscrD, E->getEndLoc(), false))
+ if (!passSubscriptReference(SubscrD, E->getEndLoc(), OpAccess, false))
return { false, nullptr };
}
@@ -434,12 +436,14 @@
}
bool SemaAnnotator::passSubscriptReference(ValueDecl *D, SourceLoc Loc,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) {
CharSourceRange Range = Loc.isValid()
? CharSourceRange(Loc, 1)
: CharSourceRange();
- bool Continue = SEWalker.visitSubscriptReference(D, Range, IsOpenBracket);
+ bool Continue = SEWalker.visitSubscriptReference(D, Range, AccKind,
+ IsOpenBracket);
if (!Continue)
Cancelled = true;
return Continue;
@@ -556,6 +560,17 @@
return DC->walkContext(Annotator);
}
+bool SourceEntityWalker::walk(ASTNode N) {
+ if (auto *E = N.dyn_cast<Expr*>())
+ return walk(E);
+ if (auto *S = N.dyn_cast<Stmt*>())
+ return walk(S);
+ if (auto *D = N.dyn_cast<Decl*>())
+ return walk(D);
+
+ llvm_unreachable("unsupported AST node");
+}
+
bool SourceEntityWalker::visitDeclReference(ValueDecl *D, CharSourceRange Range,
TypeDecl *CtorTyRef,
ExtensionDecl *ExtTyRef, Type T,
@@ -565,12 +580,13 @@
bool SourceEntityWalker::visitSubscriptReference(ValueDecl *D,
CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) {
// Most of the clients treat subscript reference the same way as a
// regular reference when called on the open bracket and
// ignore the closing one.
return IsOpenBracket ? visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None)) : true;
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind)) : true;
}
bool SourceEntityWalker::visitCallArgName(Identifier Name,
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index cbbf2d8..717e0c0 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -111,10 +111,11 @@
}
bool CursorInfoResolver::visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
- bool IsOpenBracket) {
+ Optional<AccessKind> AccKind,
+ bool IsOpenBracket) {
// We should treat both open and close brackets equally
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
ResolvedCursorInfo CursorInfoResolver::resolve(SourceLoc Loc) {
@@ -825,7 +826,7 @@
return Nodes.end() != std::find_if(Nodes.begin(), Nodes.end(), [](ASTNode N) {
ThrowingEntityAnalyzer Analyzer;
- N.walk(Analyzer);
+ Analyzer.walk(N);
return Analyzer.isThrowing();
});
}
@@ -1194,7 +1195,7 @@
void postAnalysis(ASTNode EndNode) {
// Visit the content of this node thoroughly, because the walker may
// abort early.
- EndNode.walk(CompleteWalker(this));
+ CompleteWalker(this).walk(EndNode);
// Analyze whether declared decls in the range is referenced outside of it.
FurtherReferenceWalker(this).walk(getImmediateContext());
@@ -1240,7 +1241,7 @@
};
for (auto N : Nodes) {
ControlFlowStmtSelector TheWalker;
- N.walk(TheWalker);
+ TheWalker.walk(N);
for (auto Pair : TheWalker.Ranges) {
// If the entire range does not include the target's range, we find
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 0cdd56d..0ddde22 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -73,7 +73,7 @@
bool IRGenerator::tryEnableLazyTypeMetadata(NominalTypeDecl *Nominal) {
// When compiling with -Onone keep all metadata for the debugger. Even if it
// is not used by the program itself.
- if (!Opts.Optimize)
+ if (!Opts.shouldOptimize())
return false;
switch (Nominal->getKind()) {
@@ -1329,7 +1329,7 @@
llvm::GlobalValue::VisibilityTypes,
llvm::GlobalValue::DLLStorageClassTypes>
getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
- bool isSILOnly, ForDefinition_t isDefinition,
+ ForDefinition_t isDefinition,
bool isWeakImported) {
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE) \
std::make_tuple(llvm::GlobalValue::LINKAGE##Linkage, \
@@ -1352,19 +1352,6 @@
switch (linkage) {
case SILLinkage::Public:
- // Don't code-gen transparent functions. Internal linkage will enable llvm
- // to delete transparent functions except they are referenced from somewhere
- // (i.e. the function pointer is taken).
- //
- // In case we are generating multiple LLVM modules, we still have to use
- // ExternalLinkage so that modules can cross-reference transparent
- // functions.
- //
- // TODO: In non-whole-module-opt the generated swiftmodules are "linked" and
- // this strips all serialized transparent functions. So we have to code-gen
- // transparent functions in non-whole-module-opt.
- if (isSILOnly && !info.HasMultipleIGMs && info.IsWholeModule)
- return RESULT(Internal, Default, Default);
return std::make_tuple(llvm::GlobalValue::ExternalLinkage,
PublicDefinitionVisibility, ExportedStorage);
@@ -1389,9 +1376,6 @@
case SILLinkage::PublicExternal: {
if (isDefinition) {
- // Transparent function are not available externally.
- if (isSILOnly)
- return RESULT(LinkOnceODR, Hidden, Default);
return std::make_tuple(llvm::GlobalValue::AvailableExternallyLinkage,
llvm::GlobalValue::DefaultVisibility,
ExportedStorage);
@@ -1426,7 +1410,6 @@
UniversalLinkageInfo linkInfo(IGM);
auto linkage =
getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
- entity.isSILOnly(),
ForDefinition, entity.isWeakImported(IGM.getSwiftModule()));
global->setLinkage(std::get<0>(linkage));
global->setVisibility(std::get<1>(linkage));
@@ -1458,7 +1441,6 @@
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
getIRLinkage(linkInfo, entity.getLinkage(isDefinition),
- entity.isSILOnly(),
isDefinition, entity.isWeakImported(swiftModule));
result.ForDefinition = isDefinition;
@@ -1469,14 +1451,13 @@
LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
StringRef name,
SILLinkage linkage,
- bool isSILOnly,
ForDefinition_t isDefinition,
bool isWeakImported) {
LinkInfo result;
result.Name += name;
std::tie(result.Linkage, result.Visibility, result.DLLStorageClass) =
- getIRLinkage(linkInfo, linkage, isSILOnly,
+ getIRLinkage(linkInfo, linkage,
isDefinition, isWeakImported);
result.ForDefinition = isDefinition;
return result;
@@ -1490,7 +1471,8 @@
llvm::Function *irgen::createFunction(IRGenModule &IGM,
LinkInfo &linkInfo,
const Signature &signature,
- llvm::Function *insertBefore) {
+ llvm::Function *insertBefore,
+ OptimizationMode FuncOptMode) {
auto name = linkInfo.getName();
llvm::Function *existing = IGM.Module.getFunction(name);
@@ -1519,7 +1501,7 @@
}
llvm::AttrBuilder initialAttrs;
- IGM.constructInitialFnAttributes(initialAttrs);
+ IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode);
// Merge initialAttrs with attrs.
auto updatedAttrs =
signature.getAttributes().addAttributes(IGM.getLLVMContext(),
@@ -1901,7 +1883,8 @@
llvm::AttributeList::FunctionIndex,
llvm::Attribute::ReadOnly);
}
- fn = createFunction(*this, link, signature, insertBefore);
+ fn = createFunction(*this, link, signature, insertBefore,
+ f->getOptimizationMode());
// If we have an order number for this function, set it up as appropriate.
if (hasOrderNumber) {
diff --git a/lib/IRGen/GenDecl.h b/lib/IRGen/GenDecl.h
index fd233bd..c394d76 100644
--- a/lib/IRGen/GenDecl.h
+++ b/lib/IRGen/GenDecl.h
@@ -17,6 +17,7 @@
#ifndef SWIFT_IRGEN_GENDECL_H
#define SWIFT_IRGEN_GENDECL_H
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/IR/CallingConv.h"
#include "DebugTypeInfo.h"
#include "IRGen.h"
@@ -35,8 +36,9 @@
llvm::Function *createFunction(IRGenModule &IGM,
LinkInfo &linkInfo,
const Signature &signature,
- llvm::Function *insertBefore = nullptr);
-
+ llvm::Function *insertBefore = nullptr,
+ OptimizationMode FuncOptMode =
+ OptimizationMode::NotSet);
llvm::GlobalVariable *createVariable(IRGenModule &IGM,
LinkInfo &linkInfo,
diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp
index 0cfc7e8..31d2549 100644
--- a/lib/IRGen/GenHeap.cpp
+++ b/lib/IRGen/GenHeap.cpp
@@ -1294,7 +1294,7 @@
/// optimizer not to touch this value.
void IRGenFunction::emitFixLifetime(llvm::Value *value) {
// If we aren't running the LLVM ARC optimizer, we don't need to emit this.
- if (!IGM.IRGen.Opts.Optimize || IGM.IRGen.Opts.DisableLLVMARCOpts)
+ if (!IGM.IRGen.Opts.shouldOptimize() || IGM.IRGen.Opts.DisableLLVMARCOpts)
return;
if (doesNotRequireRefCounting(value)) return;
emitUnaryRefCountCall(*this, IGM.getFixLifetimeFn(), value);
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index b025fe7..c2babaa 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -330,7 +330,6 @@
auto linkInfo = LinkInfo::get(IGM, "swift_keyPathGenericWitnessTable",
SILLinkage::PublicExternal,
- /*sil only*/ false,
NotForDefinition,
/*weak imported*/ false);
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index 24aef2f..ef8f1c8 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1388,7 +1388,7 @@
cacheVariable = cast<llvm::GlobalVariable>(
IGM.getAddrOfTypeMetadataLazyCacheVariable(type, ForDefinition));
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
}
@@ -1432,7 +1432,7 @@
if (!shouldDefine || !accessor->empty())
return accessor;
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
emitLazyCacheAccessFunction(IGM, accessor, /*cacheVariable=*/nullptr,
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index c8fe6a4..10d28c2 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -143,7 +143,7 @@
// If we're emitting optimized code, record the string in the module
// and let the late ARC pass insert it, but don't generate any calls
// right now.
- if (IRGen.Opts.Optimize) {
+ if (IRGen.Opts.shouldOptimize()) {
llvm::NamedMDNode *metadata =
Module.getOrInsertNamedMetadata(
"clang.arc.retainAutoreleasedReturnValueMarker");
diff --git a/lib/IRGen/GenOpaque.cpp b/lib/IRGen/GenOpaque.cpp
index e784a90..3338f58 100644
--- a/lib/IRGen/GenOpaque.cpp
+++ b/lib/IRGen/GenOpaque.cpp
@@ -735,7 +735,7 @@
SILType T,
llvm::Value *numEmptyCases,
Address destObject) {
- if (!IGF.IGM.getOptions().OptimizeForSize) {
+ if (!IGF.optimizeForSize()) {
llvm::Value *metadata;
auto fn = IGF.emitValueWitnessFunctionRef(
T, metadata, ValueWitness::GetEnumTagSinglePayload);
@@ -755,7 +755,7 @@
llvm::Value *irgen::emitStoreEnumTagSinglePayloadCall(
IRGenFunction &IGF, SILType T, llvm::Value *whichCase,
llvm::Value *numEmptyCases, Address destObject) {
- if (!IGF.IGM.getOptions().OptimizeForSize) {
+ if (!IGF.optimizeForSize()) {
llvm::Value *metadata;
auto fn = IGF.emitValueWitnessFunctionRef(
T, metadata, ValueWitness::StoreEnumTagSinglePayload);
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 9c1c074..d9bb28c 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -1109,7 +1109,7 @@
if (!accessor->empty())
return accessor;
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
// Okay, define the accessor.
@@ -1464,7 +1464,7 @@
llvm::Function *accessor =
IGM.getAddrOfAssociatedTypeMetadataAccessFunction(&Conformance,
requirement);
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
IRGenFunction IGF(IGM, accessor);
@@ -1570,7 +1570,7 @@
if (IGM.DebugInfo)
IGM.DebugInfo->emitArtificialFunction(IGF, accessor);
- if (IGM.getOptions().OptimizeForSize)
+ if (IGM.getOptions().optimizeForSize())
accessor->addFnAttr(llvm::Attribute::NoInline);
Explosion parameters = IGF.collectParameters();
diff --git a/lib/IRGen/IRGen.cpp b/lib/IRGen/IRGen.cpp
index 6861c81..ec76528 100644
--- a/lib/IRGen/IRGen.cpp
+++ b/lib/IRGen/IRGen.cpp
@@ -158,7 +158,7 @@
// Set up a pipeline.
PassManagerBuilderWrapper PMBuilder(Opts);
- if (Opts.Optimize && !Opts.DisableLLVMOptzns) {
+ if (Opts.shouldOptimize() && !Opts.DisableLLVMOptzns) {
PMBuilder.OptLevel = 2; // -Os
PMBuilder.SizeLevel = 1; // -Os
PMBuilder.Inliner = llvm::createFunctionInliningPass(200);
@@ -455,7 +455,7 @@
// rely on any other LLVM ARC transformations, but we do need ARC
// contraction to add the objc_retainAutoreleasedReturnValue
// assembly markers and remove clang.arc.used.
- if (Opts.Optimize && !DisableObjCARCContract)
+ if (Opts.shouldOptimize() && !DisableObjCARCContract)
EmitPasses.add(createObjCARCContractPass());
// Set up the final emission passes.
@@ -524,8 +524,9 @@
return nullptr;
}
- CodeGenOpt::Level OptLevel = Opts.Optimize ? CodeGenOpt::Default // -Os
- : CodeGenOpt::None;
+ CodeGenOpt::Level OptLevel = (Opts.shouldOptimize() ?
+ CodeGenOpt::Default // -Os
+ : CodeGenOpt::None);
// Set up TargetOptions and create the target features string.
TargetOptions TargetOpts;
@@ -684,7 +685,7 @@
/// IRGenModule.
static void runIRGenPreparePasses(SILModule &Module,
irgen::IRGenModule &IRModule) {
- SILPassManager PM(&Module, &IRModule);
+ SILPassManager PM(&Module, &IRModule, "irgen", /*isMandatoryPipeline=*/ true);
bool largeLoadable = Module.getOptions().EnableLargeLoadableTypes;
#define PASS(ID, Tag, Name)
#define IRGEN_PASS(ID, Tag, Name) \
diff --git a/lib/IRGen/IRGenDebugInfo.cpp b/lib/IRGen/IRGenDebugInfo.cpp
index d220ebe..1f35073 100644
--- a/lib/IRGen/IRGenDebugInfo.cpp
+++ b/lib/IRGen/IRGenDebugInfo.cpp
@@ -45,6 +45,7 @@
#include "llvm/Config/config.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -1478,7 +1479,6 @@
unsigned Lang = llvm::dwarf::DW_LANG_Swift;
std::string Producer = version::getSwiftFullVersion(
IGM.Context.LangOpts.EffectiveLanguageVersion);
- bool IsOptimized = Opts.Optimize;
StringRef Flags = Opts.DWARFDebugFlags;
unsigned Major, Minor;
std::tie(Major, Minor) = version::getSwiftNumericVersion();
@@ -1490,7 +1490,7 @@
// Clang is doing the same thing here.
TheCU = DBuilder.createCompileUnit(
Lang, DBuilder.createFile(AbsMainFile, Opts.DebugCompilationDir),
- Producer, IsOptimized, Flags, MajorRuntimeVersion, SplitName,
+ Producer, Opts.shouldOptimize(), Flags, MajorRuntimeVersion, SplitName,
Opts.DebugInfoKind > IRGenDebugInfoKind::LineTables
? llvm::DICompileUnit::FullDebug
: llvm::DICompileUnit::LineTablesOnly);
@@ -1803,7 +1803,6 @@
// Various flags.
bool IsLocalToUnit = Fn ? Fn->hasInternalLinkage() : true;
bool IsDefinition = true;
- bool IsOptimized = Opts.Optimize;
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
// Mark everything that is not visible from the source code (i.e.,
@@ -1838,7 +1837,7 @@
// Construct the DISubprogram.
llvm::DISubprogram *SP = DBuilder.createFunction(
Scope, Name, LinkageName, File, Line, DIFnTy, IsLocalToUnit, IsDefinition,
- ScopeLine, Flags, IsOptimized, TemplateParameters, Decl, Error);
+ ScopeLine, Flags, Opts.shouldOptimize(), TemplateParameters, Decl, Error);
if (Fn && !Fn->isDeclaration())
Fn->setSubprogram(SP);
@@ -1978,7 +1977,7 @@
auto *BB = Builder.GetInsertBlock();
// An alloca may only be described by exactly one dbg.declare.
- if (isa<llvm::AllocaInst>(Storage) && llvm::FindAllocaDbgDeclare(Storage))
+ if (isa<llvm::AllocaInst>(Storage) && !llvm::FindDbgAddrUses(Storage).empty())
return;
// A dbg.declare is only meaningful if there is a single alloca for
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index 3dd914d..d9e5e78 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -32,10 +32,12 @@
using namespace irgen;
IRGenFunction::IRGenFunction(IRGenModule &IGM, llvm::Function *Fn,
+ OptimizationMode OptMode,
const SILDebugScope *DbgScope,
Optional<SILLocation> DbgLoc)
: IGM(IGM), Builder(IGM.getLLVMContext(),
IGM.DebugInfo && !IGM.Context.LangOpts.DebuggerSupport),
+ OptMode(OptMode),
CurFn(Fn), DbgScope(DbgScope), inOutlinedFunction(false) {
// Make sure the instructions in this function are attached its debug scope.
@@ -60,6 +62,13 @@
if (LocalTypeData) destroyLocalTypeData();
}
+OptimizationMode IRGenFunction::getEffectiveOptimizationMode() const {
+ if (OptMode != OptimizationMode::NotSet)
+ return OptMode;
+
+ return IGM.getOptions().OptMode;
+}
+
ModuleDecl *IRGenFunction::getSwiftModule() const {
return IGM.getSwiftModule();
}
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index 507cddb..8d46cbf 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -66,6 +66,10 @@
IRGenModule &IGM;
IRBuilder Builder;
+ /// If != OptimizationMode::NotSet, the optimization mode specified with an
+ /// function attribute.
+ OptimizationMode OptMode;
+
llvm::Function *CurFn;
ModuleDecl *getSwiftModule() const;
SILModule &getSILModule() const;
@@ -73,6 +77,7 @@
const IRGenOptions &getOptions() const;
IRGenFunction(IRGenModule &IGM, llvm::Function *fn,
+ OptimizationMode Mode = OptimizationMode::NotSet,
const SILDebugScope *DbgScope = nullptr,
Optional<SILLocation> DbgLoc = None);
~IRGenFunction();
@@ -111,6 +116,16 @@
//--- Helper methods -----------------------------------------------------------
public:
+
+ /// Returns the optimization mode for the function. If no mode is set for the
+ /// function, returns the global mode, i.e. the mode in IRGenOptions.
+ OptimizationMode getEffectiveOptimizationMode() const;
+
+ /// Returns true if this function should be optimized for size.
+ bool optimizeForSize() const {
+ return getEffectiveOptimizationMode() == OptimizationMode::ForSize;
+ }
+
Address createAlloca(llvm::Type *ty, Alignment align,
const llvm::Twine &name);
Address createAlloca(llvm::Type *ty, llvm::Value *ArraySize, Alignment align,
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index aa697ff..e973c4f 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -88,7 +88,7 @@
auto &ClangContext = Importer->getClangASTContext();
auto &CGO = Importer->getClangCodeGenOpts();
- CGO.OptimizationLevel = Opts.Optimize ? 3 : 0;
+ CGO.OptimizationLevel = Opts.shouldOptimize() ? 3 : 0;
CGO.DisableFPElim = Opts.DisableFPElim;
CGO.DiscardValueNames = !Opts.shouldProvideValueNames();
switch (Opts.DebugInfoKind) {
@@ -818,7 +818,8 @@
}
/// Construct initial function attributes from options.
-void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs) {
+void IRGenModule::constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
+ OptimizationMode FuncOptMode) {
// Add DisableFPElim.
if (!IRGen.Opts.DisableFPElim) {
Attrs.addAttribute("no-frame-pointer-elim", "false");
@@ -851,7 +852,9 @@
});
Attrs.addAttribute("target-features", allFeatures);
}
- if (IRGen.Opts.OptimizeForSize)
+ if (FuncOptMode == OptimizationMode::NotSet)
+ FuncOptMode = IRGen.Opts.OptMode;
+ if (FuncOptMode == OptimizationMode::ForSize)
Attrs.addAttribute(llvm::Attribute::MinSize);
}
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 96337c0..6471f3e 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -24,6 +24,7 @@
#include "swift/Basic/LLVM.h"
#include "swift/Basic/ClusteredBitVector.h"
#include "swift/Basic/SuccessorMap.h"
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
@@ -957,7 +958,9 @@
/// invalid.
bool finalize();
- void constructInitialFnAttributes(llvm::AttrBuilder &Attrs);
+ void constructInitialFnAttributes(llvm::AttrBuilder &Attrs,
+ OptimizationMode FuncOptMode =
+ OptimizationMode::NotSet);
llvm::AttributeList constructInitialAttributes();
void emitProtocolDecl(ProtocolDecl *D);
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index 042b8ae..8d12c00 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -593,7 +593,7 @@
/// expression depending on the value in the blocks dominated by the
/// value.
void emitDebugVariableRangeExtension(const SILBasicBlock *CurBB) {
- if (IGM.IRGen.Opts.Optimize)
+ if (IGM.IRGen.Opts.shouldOptimize())
return;
for (auto &Variable : ValueDomPoints) {
auto VarDominancePoint = Variable.second;
@@ -671,7 +671,7 @@
Alignment Align = Alignment(0)) {
auto Ty = Storage->getType();
// Never emit shadow copies when optimizing, or if already on the stack.
- if (IGM.IRGen.Opts.Optimize ||
+ if (IGM.IRGen.Opts.shouldOptimize() ||
isa<llvm::AllocaInst>(Storage) ||
isa<llvm::UndefValue>(Storage) ||
Ty == IGM.RefCountedPtrTy) // No debug info is emitted for refcounts.
@@ -710,7 +710,7 @@
StringRef Name, unsigned ArgNo,
llvm::SmallVectorImpl<llvm::Value *> ©) {
// Only do this at -O0.
- if (IGM.IRGen.Opts.Optimize) {
+ if (IGM.IRGen.Opts.shouldOptimize()) {
copy.append(vals.begin(), vals.end());
return;
}
@@ -776,7 +776,7 @@
auto runtimeTy = getRuntimeReifiedType(IGM,
Ty.getType()->getCanonicalType());
- if (!IGM.IRGen.Opts.Optimize && runtimeTy->hasArchetype())
+ if (!IGM.IRGen.Opts.shouldOptimize() && runtimeTy->hasArchetype())
runtimeTy.visit([&](CanType t) {
if (auto archetype = dyn_cast<ArchetypeType>(t))
emitTypeMetadataRef(archetype);
@@ -1109,6 +1109,7 @@
IRGenSILFunction::IRGenSILFunction(IRGenModule &IGM,
SILFunction *f)
: IRGenFunction(IGM, IGM.getAddrOfSILFunction(f, ForDefinition),
+ f->getOptimizationMode(),
f->getDebugScope(), f->getLocation()),
CurSILFn(f) {
// Apply sanitizer attributes to the function.
@@ -5107,7 +5108,7 @@
Builder.CreateCondBr(cond, failBB, contBB);
Builder.emitBlock(failBB);
- if (IGM.IRGen.Opts.Optimize) {
+ if (IGM.IRGen.Opts.shouldOptimize()) {
// Emit unique side-effecting inline asm calls in order to eliminate
// the possibility that an LLVM optimization or code generation pass
// will merge these blocks back together again. We emit an empty asm
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
index fe2fc05..7b3aa73 100644
--- a/lib/IRGen/LocalTypeData.cpp
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -194,7 +194,7 @@
// At -O0, create an alloca to keep the type alive.
auto name = type->getFullName();
- if (!IGF.IGM.IRGen.Opts.Optimize) {
+ if (!IGF.IGM.IRGen.Opts.shouldOptimize()) {
auto temp = IGF.createAlloca(data->getType(), IGF.IGM.getPointerAlignment(),
name);
IGF.Builder.CreateStore(data, temp);
diff --git a/lib/Immediate/REPL.cpp b/lib/Immediate/REPL.cpp
index 31cc858..f2f1329 100644
--- a/lib/Immediate/REPL.cpp
+++ b/lib/Immediate/REPL.cpp
@@ -966,7 +966,7 @@
EE = builder.create();
IRGenOpts.OutputFilenames.clear();
- IRGenOpts.Optimize = false;
+ IRGenOpts.OptMode = OptimizationMode::NoOptimization;
IRGenOpts.OutputKind = IRGenOutputKind::Module;
IRGenOpts.UseJIT = true;
IRGenOpts.DebugInfoKind = IRGenDebugInfoKind::None;
diff --git a/lib/Index/Index.cpp b/lib/Index/Index.cpp
index 29ea715..5c6bd6b 100644
--- a/lib/Index/Index.cpp
+++ b/lib/Index/Index.cpp
@@ -19,11 +19,11 @@
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/Types.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Basic/StringExtras.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Markup/Markup.h"
#include "swift/Sema/IDETypeChecking.h"
#include "llvm/ADT/APInt.h"
@@ -352,9 +352,9 @@
IndexSymbol Info;
if (CtorTyRef)
- if (!reportRef(CtorTyRef, Loc, Info))
+ if (!reportRef(CtorTyRef, Loc, Info, Data.AccKind))
return false;
- if (!reportRef(D, Loc, Info))
+ if (!reportRef(D, Loc, Info, Data.AccKind))
return false;
return true;
@@ -397,7 +397,8 @@
bool report(ValueDecl *D);
bool reportExtension(ExtensionDecl *D);
- bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
+ bool reportRef(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info,
+ Optional<AccessKind> AccKind);
bool startEntity(Decl *D, IndexSymbol &Info);
bool startEntityDecl(ValueDecl *D);
@@ -435,7 +436,7 @@
bool initFuncDeclIndexSymbol(FuncDecl *D, IndexSymbol &Info);
bool initFuncRefIndexSymbol(ValueDecl *D, SourceLoc Loc, IndexSymbol &Info);
bool initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc,
- IndexSymbol &Info);
+ IndexSymbol &Info, Optional<AccessKind> AccKind);
bool indexComment(const Decl *D);
@@ -690,7 +691,7 @@
// don't report this ref again when visitDeclReference reports it
repressRefAtLoc(Loc);
- if (!reportRef(D, Loc, Info)) {
+ if (!reportRef(D, Loc, Info, None)) {
Cancelled = true;
return false;
}
@@ -716,7 +717,7 @@
if (auto *VD = Comps.back()->getBoundDecl()) {
if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
IndexSymbol Info;
- if (!reportRef(TAD, IdLoc, Info))
+ if (!reportRef(TAD, IdLoc, Info, None))
return false;
if (auto Ty = TAD->getUnderlyingTypeLoc().getType()) {
NTD = Ty->getAnyNominal();
@@ -934,7 +935,8 @@
}
bool IndexSwiftASTWalker::reportRef(ValueDecl *D, SourceLoc Loc,
- IndexSymbol &Info) {
+ IndexSymbol &Info,
+ Optional<AccessKind> AccKind) {
if (!shouldIndex(D, /*IsRef=*/true))
return true; // keep walking
@@ -942,7 +944,7 @@
if (initFuncRefIndexSymbol(D, Loc, Info))
return true;
} else if (isa<AbstractStorageDecl>(D)) {
- if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info))
+ if (initVarRefIndexSymbols(getCurrentExpr(), D, Loc, Info, AccKind))
return true;
} else {
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
@@ -1146,7 +1148,9 @@
return false;
}
-bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D, SourceLoc Loc, IndexSymbol &Info) {
+bool IndexSwiftASTWalker::initVarRefIndexSymbols(Expr *CurrentE, ValueDecl *D,
+ SourceLoc Loc, IndexSymbol &Info,
+ Optional<AccessKind> AccKind) {
if (initIndexSymbol(D, Loc, /*IsRef=*/true, Info))
return true;
@@ -1154,7 +1158,7 @@
if (!CurrentE)
return false;
- AccessKind Kind = CurrentE->hasLValueAccessKind() ? CurrentE->getLValueAccessKind() : AccessKind::Read;
+ AccessKind Kind = AccKind.hasValue() ? *AccKind : AccessKind::Read;
switch (Kind) {
case swift::AccessKind::Read:
Info.roles |= (unsigned)SymbolRole::Read;
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 360cbe4..717c120 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -15,6 +15,7 @@
#include "swift/AST/Module.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Migrator/ASTMigratorPass.h"
#include "swift/Parse/Lexer.h"
diff --git a/lib/Migrator/TypeOfMigratorPass.cpp b/lib/Migrator/TypeOfMigratorPass.cpp
index b7cb259..3697b9c 100644
--- a/lib/Migrator/TypeOfMigratorPass.cpp
+++ b/lib/Migrator/TypeOfMigratorPass.cpp
@@ -16,6 +16,7 @@
#include "swift/AST/NameLookup.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Migrator/ASTMigratorPass.h"
#include "swift/Parse/Lexer.h"
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cbc064f..5595983 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -613,7 +613,8 @@
}
if (Tok.isNot(tok::identifier)) {
- diagnose(Loc, diag::inline_attribute_expect_option, AttrName);
+ diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
+ "none");
return false;
}
@@ -623,7 +624,7 @@
else if (Tok.getText() == "__always")
kind = InlineKind::Always;
else {
- diagnose(Loc, diag::inline_attribute_unknown_option,
+ diagnose(Loc, diag::optimization_attribute_unknown_option,
Tok.getText(), AttrName);
return false;
}
@@ -642,6 +643,46 @@
break;
}
+ case DAK_Optimize: {
+ if (!consumeIf(tok::l_paren)) {
+ diagnose(Loc, diag::attr_expected_lparen, AttrName,
+ DeclAttribute::isDeclModifier(DK));
+ return false;
+ }
+
+ if (Tok.isNot(tok::identifier)) {
+ diagnose(Loc, diag::optimization_attribute_expect_option, AttrName,
+ "speed");
+ return false;
+ }
+
+ OptimizationMode optMode = OptimizationMode::NotSet;
+ if (Tok.getText() == "none")
+ optMode = OptimizationMode::NoOptimization;
+ else if (Tok.getText() == "speed")
+ optMode = OptimizationMode::ForSpeed;
+ else if (Tok.getText() == "size")
+ optMode = OptimizationMode::ForSize;
+ else {
+ diagnose(Loc, diag::optimization_attribute_unknown_option,
+ Tok.getText(), AttrName);
+ return false;
+ }
+ consumeToken(tok::identifier);
+ AttrRange = SourceRange(Loc, Tok.getRange().getStart());
+
+ if (!consumeIf(tok::r_paren)) {
+ diagnose(Loc, diag::attr_expected_rparen, AttrName,
+ DeclAttribute::isDeclModifier(DK));
+ return false;
+ }
+
+ if (!DiscardAttribute)
+ Attributes.add(new (Context) OptimizeAttr(AtLoc, AttrRange, optMode));
+
+ break;
+ }
+
case DAK_Ownership: {
// Handle weak/unowned/unowned(unsafe).
Ownership Kind = AttrName == "weak" ? Ownership::Weak : Ownership::Unowned;
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 79c1960..46bfa7d 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -165,9 +165,12 @@
ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
bool isExprBasic,
bool isForConditionalDirective) {
+ SyntaxParsingContextChild ExprSequnceContext(SyntaxContext,
+ SyntaxContextKind::Expr);
SmallVector<Expr*, 8> SequencedExprs;
SourceLoc startLoc = Tok.getLoc();
bool HasCodeCompletion = false;
+ bool PendingTernary = false;
while (true) {
if (isForConditionalDirective && Tok.isAtStartOfLine())
@@ -189,6 +192,12 @@
}
SequencedExprs.push_back(Primary.get());
+ // We know we can make a syntax node for ternary expression.
+ if (PendingTernary) {
+ SyntaxContext->makeNode(SyntaxKind::TernaryExpr, Tok.getLoc());
+ PendingTernary = false;
+ }
+
if (isForConditionalDirective && Tok.isAtStartOfLine())
break;
@@ -245,6 +254,10 @@
colonLoc);
SequencedExprs.push_back(unresolvedIf);
Message = diag::expected_expr_after_if_colon;
+
+ // Wait for the next expression to make a syntax node for ternary
+ // expression.
+ PendingTernary = true;
break;
}
@@ -368,6 +381,8 @@
/// sequence, but this isn't enforced until sequence-folding.
ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
bool isExprBasic) {
+ SyntaxParsingContextChild ElementContext(SyntaxContext,
+ SyntaxContextKind::Expr);
SourceLoc tryLoc;
bool hadTry = consumeIf(tok::kw_try, tryLoc);
Optional<Token> trySuffix;
@@ -1390,7 +1405,7 @@
case tok::integer_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
SourceLoc Loc = consumeToken(tok::integer_literal);
- SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Loc);
+ SyntaxContext->makeNode(SyntaxKind::IntegerLiteralExpr, Tok.getLoc());
Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
/*Implicit=*/false));
break;
@@ -1398,7 +1413,7 @@
case tok::floating_literal: {
StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
SourceLoc Loc = consumeToken(tok::floating_literal);
- SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Loc);
+ SyntaxContext->makeNode(SyntaxKind::FloatLiteralExpr, Tok.getLoc());
Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
/*Implicit=*/false));
break;
@@ -1428,6 +1443,8 @@
case tok::kw_true:
case tok::kw_false: {
+ SyntaxParsingContextChild BoolContext(SyntaxContext,
+ SyntaxKind::BooleanLiteralExpr);
bool isTrue = Tok.is(tok::kw_true);
Result = makeParserResult(
new (Context) BooleanLiteralExpr(isTrue, consumeToken()));
@@ -1811,7 +1828,7 @@
Token EntireTok = Tok;
// Create a syntax node for string literal.
- SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, Tok.getLoc());
+ SyntaxContext->makeNode(SyntaxKind::StringLiteralExpr, peekToken().getLoc());
// FIXME: Avoid creating syntax nodes for string interpolation.
SyntaxParsingContextChild LocalContext(SyntaxContext, /*disabled*/true);
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index 9ff7c0f..9721141 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include "swift/Parse/Parser.h"
+#include "swift/AST/ASTWalker.h"
#include "swift/AST/Attr.h"
#include "swift/AST/TypeLoc.h"
#include "swift/Parse/Lexer.h"
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index ee85135..675615d 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -878,7 +878,9 @@
static bool parseDeclSILOptional(bool *isTransparent,
IsSerialized_t *isSerialized,
IsThunk_t *isThunk, bool *isGlobalInit,
- Inline_t *inlineStrategy, bool *isLet,
+ Inline_t *inlineStrategy,
+ OptimizationMode *optimizationMode,
+ bool *isLet,
SmallVectorImpl<std::string> *Semantics,
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs,
ValueDecl **ClangDecl,
@@ -907,6 +909,12 @@
*isGlobalInit = true;
else if (inlineStrategy && SP.P.Tok.getText() == "noinline")
*inlineStrategy = NoInline;
+ else if (optimizationMode && SP.P.Tok.getText() == "Onone")
+ *optimizationMode = OptimizationMode::NoOptimization;
+ else if (optimizationMode && SP.P.Tok.getText() == "Ospeed")
+ *optimizationMode = OptimizationMode::ForSpeed;
+ else if (optimizationMode && SP.P.Tok.getText() == "Osize")
+ *optimizationMode = OptimizationMode::ForSize;
else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
*inlineStrategy = AlwaysInline;
else if (MRK && SP.P.Tok.getText() == "readnone")
@@ -5012,13 +5020,15 @@
IsThunk_t isThunk = IsNotThunk;
bool isGlobalInit = false;
Inline_t inlineStrategy = InlineDefault;
+ OptimizationMode optimizationMode = OptimizationMode::NotSet;
SmallVector<std::string, 1> Semantics;
SmallVector<ParsedSpecAttr, 4> SpecAttrs;
ValueDecl *ClangDecl = nullptr;
EffectsKind MRK = EffectsKind::Unspecified;
if (parseSILLinkage(FnLinkage, P) ||
parseDeclSILOptional(&isTransparent, &isSerialized, &isThunk, &isGlobalInit,
- &inlineStrategy, nullptr, &Semantics, &SpecAttrs,
+ &inlineStrategy, &optimizationMode, nullptr,
+ &Semantics, &SpecAttrs,
&ClangDecl, &MRK, FunctionState) ||
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
P.parseIdentifier(FnName, FnNameLoc, diag::expected_sil_function_name) ||
@@ -5045,6 +5055,7 @@
FunctionState.F->setThunk(IsThunk_t(isThunk));
FunctionState.F->setGlobalInit(isGlobalInit);
FunctionState.F->setInlineStrategy(inlineStrategy);
+ FunctionState.F->setOptimizationMode(optimizationMode);
FunctionState.F->setEffectsKind(MRK);
if (ClangDecl)
FunctionState.F->setClangNodeOwner(ClangDecl);
@@ -5173,7 +5184,7 @@
SILParser State(P);
if (parseSILLinkage(GlobalLinkage, P) ||
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
- nullptr, &isLet, nullptr, nullptr, nullptr,
+ nullptr, nullptr, &isLet, nullptr, nullptr, nullptr,
nullptr, State) ||
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
P.parseIdentifier(GlobalName, NameLoc, diag::expected_sil_value_name) ||
@@ -5216,7 +5227,7 @@
IsSerialized_t Serialized = IsNotSerialized;
if (parseDeclSILOptional(nullptr, &Serialized, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, VTableState))
return true;
@@ -5565,7 +5576,7 @@
IsSerialized_t isSerialized = IsNotSerialized;
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, WitnessState))
return true;
diff --git a/lib/SIL/SILFunction.cpp b/lib/SIL/SILFunction.cpp
index ec909fd..4212375 100644
--- a/lib/SIL/SILFunction.cpp
+++ b/lib/SIL/SILFunction.cpp
@@ -18,6 +18,7 @@
#include "swift/SIL/CFG.h"
#include "swift/SIL/PrettyStackTrace.h"
#include "swift/AST/GenericEnvironment.h"
+#include "swift/Basic/OptimizationMode.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/GraphWriter.h"
@@ -96,7 +97,8 @@
Serialized(isSerialized), Thunk(isThunk),
ClassSubclassScope(unsigned(classSubclassScope)), GlobalInitFlag(false),
InlineStrategy(inlineStrategy), Linkage(unsigned(Linkage)),
- HasCReferences(false), KeepAsPublic(false), EffectsKindAttr(E),
+ HasCReferences(false), KeepAsPublic(false),
+ OptMode(OptimizationMode::NotSet), EffectsKindAttr(E),
EntryCount(entryCount) {
if (InsertBefore)
Module.functions.insert(SILModule::iterator(InsertBefore), this);
@@ -168,10 +170,16 @@
return getModule().getASTContext();
}
+OptimizationMode SILFunction::getEffectiveOptimizationMode() const {
+ if (OptMode != OptimizationMode::NotSet)
+ return OptMode;
+
+ return getModule().getOptions().OptMode;
+}
+
bool SILFunction::shouldOptimize() const {
- if (Module.getStage() == SILStage::Raw)
- return true;
- return !hasSemanticsAttr("optimize.sil.never");
+ return !hasSemanticsAttr("optimize.sil.never") &&
+ getEffectiveOptimizationMode() != OptimizationMode::NoOptimization;
}
Type SILFunction::mapTypeIntoContext(Type type) const {
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index 589b5c1..2e247bf 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -1335,10 +1335,25 @@
return iterator(*this, getEndOffset());
}
+SILInstructionResultArray::reverse_iterator
+SILInstructionResultArray::rbegin() const {
+ return llvm::make_reverse_iterator(end());
+}
+
+SILInstructionResultArray::reverse_iterator
+SILInstructionResultArray::rend() const {
+ return llvm::make_reverse_iterator(begin());
+}
+
SILInstructionResultArray::range SILInstructionResultArray::getValues() const {
return {begin(), end()};
}
+SILInstructionResultArray::reverse_range
+SILInstructionResultArray::getReversedValues() const {
+ return {rbegin(), rend()};
+}
+
const ValueBase *SILInstructionResultArray::front() const {
assert(size() && "Can not access front of an empty result array");
return *begin();
diff --git a/lib/SIL/SILModule.cpp b/lib/SIL/SILModule.cpp
index 3a8b27a..2b41a69 100644
--- a/lib/SIL/SILModule.cpp
+++ b/lib/SIL/SILModule.cpp
@@ -280,6 +280,32 @@
PInfo.isGuaranteed() || PInfo.isIndirectMutating();
}
+static void addFunctionAttributes(SILFunction *F, DeclAttributes &Attrs,
+ SILModule &M) {
+ for (auto *A : Attrs.getAttributes<SemanticsAttr>())
+ F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
+
+ // Propagate @_specialize.
+ for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
+ auto *SA = cast<SpecializeAttr>(A);
+ auto kind = SA->getSpecializationKind() ==
+ SpecializeAttr::SpecializationKind::Full
+ ? SILSpecializeAttr::SpecializationKind::Full
+ : SILSpecializeAttr::SpecializationKind::Partial;
+ F->addSpecializeAttr(SILSpecializeAttr::create(
+ M, SA->getRequirements(), SA->isExported(), kind));
+ }
+
+ if (auto *OA = Attrs.getAttribute<OptimizeAttr>()) {
+ F->setOptimizationMode(OA->getMode());
+ }
+
+ // @_silgen_name and @_cdecl functions may be called from C code somewhere.
+ if (Attrs.hasAttribute<SILGenNameAttr>() ||
+ Attrs.hasAttribute<CDeclAttr>())
+ F->setHasCReferences(true);
+}
+
SILFunction *SILModule::getOrCreateFunction(SILLocation loc,
SILDeclRef constant,
ForDefinition_t forDefinition,
@@ -334,26 +360,12 @@
if (constant.isForeign && decl->hasClangNode())
F->setClangNodeOwner(decl);
- // Propagate @_semantics.
- auto Attrs = decl->getAttrs();
- for (auto *A : Attrs.getAttributes<SemanticsAttr>())
- F->addSemanticsAttr(cast<SemanticsAttr>(A)->Value);
-
- // Propagate @_specialize.
- for (auto *A : Attrs.getAttributes<SpecializeAttr>()) {
- auto *SA = cast<SpecializeAttr>(A);
- auto kind = SA->getSpecializationKind() ==
- SpecializeAttr::SpecializationKind::Full
- ? SILSpecializeAttr::SpecializationKind::Full
- : SILSpecializeAttr::SpecializationKind::Partial;
- F->addSpecializeAttr(SILSpecializeAttr::create(
- *this, SA->getRequirements(), SA->isExported(), kind));
+ if (auto *FDecl = dyn_cast<FuncDecl>(decl)) {
+ if (auto *StorageDecl = FDecl->getAccessorStorageDecl())
+ // Add attributes for e.g. computed properties.
+ addFunctionAttributes(F, StorageDecl->getAttrs(), *this);
}
-
- // @_silgen_name and @_cdecl functions may be called from C code somewhere.
- if (Attrs.hasAttribute<SILGenNameAttr>() ||
- Attrs.hasAttribute<CDeclAttr>())
- F->setHasCReferences(true);
+ addFunctionAttributes(F, decl->getAttrs(), *this);
}
// If this function has a self parameter, make sure that it has a +0 calling
@@ -513,8 +525,7 @@
// compilation, simply convert it into an external declaration,
// so that a compiled version from the shared library is used.
if (F->isDefinition() &&
- F->getModule().getOptions().Optimization <
- SILOptions::SILOptMode::Optimize) {
+ !F->getModule().getOptions().shouldOptimize()) {
F->convertToDeclaration();
}
if (F->isExternalDeclaration())
@@ -769,8 +780,7 @@
/// Returns true if it is the optimized OnoneSupport module.
bool SILModule::isOptimizedOnoneSupportModule() const {
- return getOptions().Optimization >= SILOptions::SILOptMode::Optimize &&
- isOnoneSupportModule();
+ return getOptions().shouldOptimize() && isOnoneSupportModule();
}
void SILModule::setSerializeSILAction(SILModule::ActionCallback Action) {
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index f633882..8a25896 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -2252,6 +2252,13 @@
case InlineDefault: break;
}
+ switch (getOptimizationMode()) {
+ case OptimizationMode::NoOptimization: OS << "[Onone] "; break;
+ case OptimizationMode::ForSpeed: OS << "[Ospeed] "; break;
+ case OptimizationMode::ForSize: OS << "[Osize] "; break;
+ default: break;
+ }
+
if (getEffectsKind() == EffectsKind::ReadOnly)
OS << "[readonly] ";
else if (getEffectsKind() == EffectsKind::ReadNone)
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index c48ce35..ae0d272 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -127,6 +127,16 @@
// Substitute into the witness function type.
witnessFnTy = witnessFnTy.substGenericArgs(SGF.SGM.M, typeSubMap);
+ // We might have to re-abstract the 'self' value if it is an
+ // Optional.
+ AbstractionPattern origSelfType(witness->getInterfaceType());
+ origSelfType = origSelfType.getFunctionInputType();
+
+ swiftValue = SGF.emitSubstToOrigValue(loc, swiftValue,
+ origSelfType,
+ swiftValueType,
+ SGFContext());
+
// The witness may be more abstract than the concrete value we're bridging,
// for instance, if the value is a concrete instantiation of a generic type.
//
@@ -345,6 +355,12 @@
return results;
}
+static CanAnyFunctionType getBridgedBlockType(SILGenModule &SGM,
+ CanAnyFunctionType blockType) {
+ return SGM.Types.getBridgedFunctionType(AbstractionPattern(blockType),
+ blockType, blockType->getExtInfo());
+}
+
static void buildFuncToBlockInvokeBody(SILGenFunction &SGF,
SILLocation loc,
CanAnyFunctionType formalFuncType,
@@ -358,10 +374,7 @@
SILFunctionConventions funcConv(funcTy, SGF.SGM.M);
// Make sure we lower the component types of the formal block type.
- formalBlockType =
- SGF.SGM.Types.getBridgedFunctionType(AbstractionPattern(formalBlockType),
- formalBlockType,
- formalBlockType->getExtInfo());
+ formalBlockType = getBridgedBlockType(SGF.SGM, formalBlockType);
// Set up the indirect result.
SILType blockResultTy = blockTy->getAllResultsType();
@@ -754,6 +767,9 @@
// Collect the native arguments, which should all be +1.
Scope scope(SGF.Cleanups, CleanupLocation::get(loc));
+ // Make sure we lower the component types of the formal block type.
+ formalBlockTy = getBridgedBlockType(SGF.SGM, formalBlockTy);
+
assert(blockTy->getNumParameters() == funcTy->getNumParameters()
&& "block and function types don't match");
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 3908a97..2252d6c 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -5080,37 +5080,25 @@
llvm::function_ref<void(Expr *)> emitSubExpr) {
Optional<FormalEvaluationScope> writebackScope;
- Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
-
// Emit the existential value.
- SILGenFunction::OpaqueValueState state;
-
- AccessKind accessKind;
if (E->getExistentialValue()->getType()->is<LValueType>()) {
- // Create a writeback scope for the access to the existential lvalue.
- writebackScope.emplace(*this);
+ bool inserted = OpaqueValueExprs.insert({E->getOpaqueValue(), E}).second;
+ (void)inserted;
+ assert(inserted && "already have this opened existential?");
- Type formalRValueType =
- E->getOpaqueValue()->getType()->getWithoutSpecifierType();
+ emitSubExpr(E->getSubExpr());
+ return;
+ }
- accessKind = E->getExistentialValue()->getLValueAccessKind();
- auto lv = emitLValue(E->getExistentialValue(), accessKind);
- lv = emitOpenExistentialLValue(E, std::move(lv),
- CanArchetypeType(E->getOpenedArchetype()),
- formalRValueType->getCanonicalType(),
- accessKind);
- auto addr = emitAddressOfLValue(E, std::move(lv), accessKind);
- state = {addr, false, false};
- } else {
- accessKind = AccessKind::Read;
- auto existentialValue = emitRValueAsSingleValue(
+ auto existentialValue = emitRValueAsSingleValue(
E->getExistentialValue(),
SGFContext::AllowGuaranteedPlusZero);
-
- state = emitOpenExistential(
+
+ Type opaqueValueType = E->getOpaqueValue()->getType()->getRValueType();
+ auto state = emitOpenExistential(
E, existentialValue, E->getOpenedArchetype(),
- getLoweredType(opaqueValueType), accessKind);
- }
+ getLoweredType(opaqueValueType),
+ AccessKind::Read);
// Register the opaque value for the projected existential.
SILGenFunction::OpaqueValueRAII opaqueValueRAII(
diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
index 24cc25a..518cec2 100644
--- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp
+++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp
@@ -84,16 +84,9 @@
auto *AllocBufferAI = dyn_cast<ApplyInst>(Arg0);
if (!AllocBufferAI)
return false;
-
auto *AllocFn = AllocBufferAI->getReferencedFunction();
- if (!AllocFn)
- return false;
-
- StringRef AllocFuncName = AllocFn->getName();
- if (AllocFuncName != "swift_bufferAllocate")
- return false;
-
- if (!hasOneNonDebugUse(AllocBufferAI))
+ if (!AllocFn || AllocFn->getName() != "swift_bufferAllocate" ||
+ !hasOneNonDebugUse(AllocBufferAI))
return false;
}
return true;
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index b302875..ac5d62e 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -405,6 +405,9 @@
if (PAI->hasSubstitutions()) {
if (Specialized->isExternalDeclaration())
return nullptr;
+ if (!Orig->shouldOptimize())
+ return nullptr;
+
// Perform a generic specialization of the Specialized function.
ReabstractionInfo ReInfo(ApplySite(), Specialized, PAI->getSubstitutions(),
/* ConvertIndirectToDirect */ false);
diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
index b7267e7..70fd6da 100644
--- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
+++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp
@@ -2316,8 +2316,7 @@
auto *Fn = getFunction();
// Don't hoist array property calls at Osize.
- auto OptMode = Fn->getModule().getOptions().Optimization;
- if (OptMode == SILOptions::SILOptMode::OptimizeForSize)
+ if (Fn->optimizeForSize())
return;
DominanceAnalysis *DA = PM->getAnalysis<DominanceAnalysis>();
diff --git a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
index 10e581c..f92c682 100644
--- a/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessEnforcementSelection.cpp
@@ -442,33 +442,56 @@
}
void SelectEnforcement::updateCapture(AddressCapture capture) {
+ auto captureIfEscaped = [&](SILInstruction *user) {
+ if (hasPotentiallyEscapedAt(user))
+ dynamicCaptures.recordCapture(capture);
+ };
llvm::SmallSetVector<SingleValueInstruction *, 8> worklist;
auto visitUse = [&](Operand *oper) {
auto *user = oper->getUser();
if (FullApplySite::isa(user)) {
// A call is considered a closure access regardless of whether it calls
// the closure or accepts the closure as an argument.
- if (hasPotentiallyEscapedAt(user)) {
- dynamicCaptures.recordCapture(capture);
- }
+ captureIfEscaped(user);
return;
}
- if (auto *CFI = dyn_cast<ConvertFunctionInst>(user)) {
- worklist.insert(CFI);
+ switch (user->getKind()) {
+ case SILInstructionKind::ConvertFunctionInst:
+ case SILInstructionKind::BeginBorrowInst:
+ case SILInstructionKind::CopyValueInst:
+ case SILInstructionKind::EnumInst:
+ case SILInstructionKind::StructInst:
+ case SILInstructionKind::TupleInst:
+ case SILInstructionKind::PartialApplyInst:
+ // Propagate the closure.
+ worklist.insert(cast<SingleValueInstruction>(user));
return;
- }
- if (auto *PAI = dyn_cast<PartialApplyInst>(user)) {
- assert(oper->get() != PAI->getCallee() && "cannot re-partially apply");
- // The closure is capture by another closure. Transitively consider any
- // calls to the parent closure as an access.
- worklist.insert(PAI);
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::DebugValueInst:
+ case SILInstructionKind::DestroyValueInst:
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::ReleaseValueInst:
+ case SILInstructionKind::EndBorrowInst:
+ // Benign use.
return;
+ case SILInstructionKind::TupleExtractInst:
+ case SILInstructionKind::StructExtractInst:
+ case SILInstructionKind::AssignInst:
+ case SILInstructionKind::BranchInst:
+ case SILInstructionKind::CondBranchInst:
+ case SILInstructionKind::ReturnInst:
+ case SILInstructionKind::StoreInst:
+ // These are all valid partial_apply users, however we don't expect them
+ // to occur with non-escaping closures. Handle them conservatively just in
+ // case they occur.
+ LLVM_FALLTHROUGH;
+ default:
+ DEBUG(llvm::dbgs() << " Unrecognized partial_apply user: " << *user);
+
+ // Handle unknown uses conservatively by assuming a capture.
+ captureIfEscaped(user);
}
- DEBUG(llvm::dbgs() << " Unrecognized partial_apply user: " << *user);
- // If this user has no results, then we can safely assume it doesn't pass
- // the closure to a call site. If it has results, then it might propagate
- // the closure, in which case it needs to be handled above.
- assert(user->getResults().empty());
};
SingleValueInstruction *PAIUser = dyn_cast<PartialApplyInst>(capture.site);
while (true) {
diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
index 674f560..1805c17 100644
--- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
+++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp
@@ -542,62 +542,70 @@
}
//===----------------------------------------------------------------------===//
-// Allocation Optimization
+// Available Value Dataflow
//===----------------------------------------------------------------------===//
namespace {
-/// This performs load promotion and deletes synthesized allocations if all
-/// loads can be removed.
-class AllocOptimize {
-
- SILModule &Module;
-
- /// This is either an alloc_box or alloc_stack instruction.
+/// Given a piece of memory, the memory's uses, and destroys perform a single
+/// round of optimistic dataflow switching to intersection when a back edge is
+/// encountered.
+class AvailableValueDataflowContext {
+ /// The base memory we are performing dataflow upon.
AllocationInst *TheMemory;
- /// This is the SILType of the memory object.
- SILType MemoryType;
-
- /// The number of primitive subelements across all elements of this memory
- /// value.
+ /// The number of sub elements of our memory.
unsigned NumMemorySubElements;
- SmallVectorImpl<DIMemoryUse> &Uses;
- SmallVectorImpl<SILInstruction *> &Releases;
+ /// The set of uses that we are tracking. This is only here so we can update
+ /// when exploding copy_addr. It would be great if we did not have to store
+ /// this.
+ llvm::SmallVectorImpl<DIMemoryUse> &Uses;
+ /// The set of blocks with local definitions.
+ ///
+ /// We use this to determine if we should visit a block or look at a block's
+ /// predecessors during dataflow.
llvm::SmallPtrSet<SILBasicBlock *, 32> HasLocalDefinition;
/// This is a map of uses that are not loads (i.e., they are Stores,
/// InOutUses, and Escapes), to their entry in Uses.
llvm::SmallDenseMap<SILInstruction *, unsigned, 16> NonLoadUses;
- /// Does this value escape anywhere in the function.
+ /// Does this value escape anywhere in the function. We use this very
+ /// conservatively.
bool HasAnyEscape = false;
public:
- AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<DIMemoryUse> &Uses,
- SmallVectorImpl<SILInstruction *> &Releases);
+ AvailableValueDataflowContext(AllocationInst *TheMemory,
+ unsigned NumMemorySubElements,
+ llvm::SmallVectorImpl<DIMemoryUse> &Uses);
- bool doIt();
+ /// Try to compute available values for "TheMemory" at the instruction \p
+ /// StartingFrom. We only compute the values for set bits in \p
+ /// RequiredElts. We return the vailable values in \p Result. If any available
+ /// values were found, return true. Otherwise, return false.
+ bool computeAvailableValues(SILInstruction *StartingFrom,
+ unsigned FirstEltOffset,
+ unsigned NumLoadSubElements,
+ llvm::SmallBitVector &RequiredElts,
+ SmallVectorImpl<AvailableValue> &Result);
+
+ /// Return true if the box has escaped at the specified instruction. We are
+ /// not
+ /// allowed to do load promotion in an escape region.
+ bool hasEscapedAt(SILInstruction *I);
+
+ /// Explode a copy_addr, updating the Uses at the same time.
+ void explodeCopyAddr(CopyAddrInst *CAI);
private:
- bool promoteLoad(SILInstruction *Inst);
- void promoteDestroyAddr(DestroyAddrInst *DAI,
- MutableArrayRef<AvailableValue> Values);
- bool
- canPromoteDestroyAddr(DestroyAddrInst *DAI,
- llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
+ SILModule &getModule() const { return TheMemory->getModule(); }
- // Load promotion.
- bool hasEscapedAt(SILInstruction *I);
void updateAvailableValues(SILInstruction *Inst,
llvm::SmallBitVector &RequiredElts,
SmallVectorImpl<AvailableValue> &Result,
llvm::SmallBitVector &ConflictingValues);
- void computeAvailableValues(SILInstruction *StartingFrom,
- llvm::SmallBitVector &RequiredElts,
- SmallVectorImpl<AvailableValue> &Result);
void computeAvailableValuesFrom(
SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
llvm::SmallBitVector &RequiredElts,
@@ -605,45 +613,26 @@
llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
&VisitedBlocks,
llvm::SmallBitVector &ConflictingValues);
-
- void explodeCopyAddr(CopyAddrInst *CAI);
-
- bool tryToRemoveDeadAllocation();
};
} // end anonymous namespace
-
-AllocOptimize::AllocOptimize(AllocationInst *TheMemory,
- SmallVectorImpl<DIMemoryUse> &Uses,
- SmallVectorImpl<SILInstruction*> &Releases)
-: Module(TheMemory->getModule()), TheMemory(TheMemory), Uses(Uses),
- Releases(Releases) {
-
- // Compute the type of the memory object.
- if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
- assert(ABI->getBoxType()->getLayout()->getFields().size() == 1
- && "optimizing multi-field boxes not implemented");
- MemoryType = ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
- } else {
- assert(isa<AllocStackInst>(TheMemory));
- MemoryType = cast<AllocStackInst>(TheMemory)->getElementType();
- }
-
- NumMemorySubElements = getNumSubElements(MemoryType, Module);
-
+AvailableValueDataflowContext::AvailableValueDataflowContext(
+ AllocationInst *InputTheMemory, unsigned NumMemorySubElements,
+ SmallVectorImpl<DIMemoryUse> &InputUses)
+ : TheMemory(InputTheMemory), NumMemorySubElements(NumMemorySubElements),
+ Uses(InputUses) {
// The first step of processing an element is to collect information about the
// element into data structures we use later.
- for (unsigned ui = 0, e = Uses.size(); ui != e; ++ui) {
+ for (unsigned ui : indices(Uses)) {
auto &Use = Uses[ui];
assert(Use.Inst && "No instruction identified?");
-
+
// Keep track of all the uses that aren't loads.
if (Use.Kind == DIUseKind::Load)
continue;
-
+
NonLoadUses[Use.Inst] = ui;
-
HasLocalDefinition.insert(Use.Inst->getParent());
if (Use.Kind == DIUseKind::Escape) {
@@ -659,35 +648,18 @@
HasLocalDefinition.insert(TheMemory->getParent());
}
-
-/// hasEscapedAt - Return true if the box has escaped at the specified
-/// instruction. We are not allowed to do load promotion in an escape region.
-bool AllocOptimize::hasEscapedAt(SILInstruction *I) {
- // FIXME: This is not an aggressive implementation. :)
-
- // TODO: At some point, we should special case closures that just *read* from
- // the escaped value (by looking at the body of the closure). They should not
- // prevent load promotion, and will allow promoting values like X in regions
- // dominated by "... && X != 0".
- return HasAnyEscape;
-}
-
-
-/// The specified instruction is a non-load access of the element being
-/// promoted. See if it provides a value or refines the demanded element mask
-/// used for load promotion.
-void AllocOptimize::updateAvailableValues(
+void AvailableValueDataflowContext::updateAvailableValues(
SILInstruction *Inst, llvm::SmallBitVector &RequiredElts,
SmallVectorImpl<AvailableValue> &Result,
llvm::SmallBitVector &ConflictingValues) {
-
- // Handle store and assign.
+ // Handle store.
if (auto *SI = dyn_cast<StoreInst>(Inst)) {
unsigned StartSubElt = computeSubelement(SI->getDest(), TheMemory);
assert(StartSubElt != ~0U && "Store within enum projection not handled");
SILType ValTy = SI->getSrc()->getType();
- for (unsigned i = 0, e = getNumSubElements(ValTy, Module); i != e; ++i) {
+ for (unsigned i = 0, e = getNumSubElements(ValTy, getModule()); i != e;
+ ++i) {
// If this element is not required, don't fill it in.
if (!RequiredElts[StartSubElt+i]) continue;
@@ -719,12 +691,13 @@
// to see if any loaded subelements are being used, and if so, explode the
// copy_addr to its individual pieces.
if (auto *CAI = dyn_cast<CopyAddrInst>(Inst)) {
- unsigned StartSubElt = computeSubelement(Inst->getOperand(1), TheMemory);
+ unsigned StartSubElt = computeSubelement(CAI->getDest(), TheMemory);
assert(StartSubElt != ~0U && "Store within enum projection not handled");
- SILType ValTy = Inst->getOperand(1)->getType();
-
+ SILType ValTy = CAI->getDest()->getType();
+
bool AnyRequired = false;
- for (unsigned i = 0, e = getNumSubElements(ValTy, Module); i != e; ++i) {
+ for (unsigned i = 0, e = getNumSubElements(ValTy, getModule()); i != e;
+ ++i) {
// If this element is not required, don't fill it in.
AnyRequired = RequiredElts[StartSubElt+i];
if (AnyRequired) break;
@@ -737,7 +710,7 @@
// If the copyaddr is of a non-loadable type, we can't promote it. Just
// consider it to be a clobber.
- if (CAI->getOperand(0)->getType().isLoadable(Module)) {
+ if (CAI->getSrc()->getType().isLoadable(getModule())) {
// Otherwise, some part of the copy_addr's value is demanded by a load, so
// we need to explode it to its component pieces. This only expands one
// level of the copyaddr.
@@ -748,11 +721,9 @@
return;
}
}
-
-
-
+
// TODO: inout apply's should only clobber pieces passed in.
-
+
// Otherwise, this is some unknown instruction, conservatively assume that all
// values are clobbered.
RequiredElts.clear();
@@ -760,16 +731,9 @@
return;
}
-
-/// Try to find available values of a set of subelements of the current value,
-/// starting right before the specified instruction.
-///
-/// The bitvector indicates which subelements we're interested in, and result
-/// captures the available value (plus an indicator of which subelement of that
-/// value is needed).
-///
-void AllocOptimize::computeAvailableValues(
- SILInstruction *StartingFrom, llvm::SmallBitVector &RequiredElts,
+bool AvailableValueDataflowContext::computeAvailableValues(
+ SILInstruction *StartingFrom, unsigned FirstEltOffset,
+ unsigned NumLoadSubElements, llvm::SmallBitVector &RequiredElts,
SmallVectorImpl<AvailableValue> &Result) {
llvm::SmallDenseMap<SILBasicBlock*, llvm::SmallBitVector, 32> VisitedBlocks;
llvm::SmallBitVector ConflictingValues(Result.size());
@@ -777,18 +741,44 @@
computeAvailableValuesFrom(StartingFrom->getIterator(),
StartingFrom->getParent(), RequiredElts, Result,
VisitedBlocks, ConflictingValues);
+ // If there are no values available at this load point, then we fail to
+ // promote this load and there is nothing to do.
+ llvm::SmallBitVector AvailableValueIsPresent(NumMemorySubElements);
- // If we have any conflicting values, explicitly mask them out of the result,
- // so we don't pick one arbitrary available value.
- if (!ConflictingValues.none())
- for (unsigned i = 0, e = Result.size(); i != e; ++i)
- if (ConflictingValues[i])
- Result[i] = {};
+ for (unsigned i :
+ range(FirstEltOffset, FirstEltOffset + NumLoadSubElements)) {
+ AvailableValueIsPresent[i] = Result[i].getValue();
+ }
- return;
+ // If we do not have any values available, bail.
+ if (AvailableValueIsPresent.none())
+ return false;
+
+ // Otherwise, if we have any conflicting values, explicitly mask them out of
+ // the result, so we don't pick one arbitrary available value.
+ if (ConflictingValues.none()) {
+ return true;
+ }
+
+ // At this point, we know that we have /some/ conflicting values and some
+ // available values.
+ if (AvailableValueIsPresent.reset(ConflictingValues).none())
+ return false;
+
+ // Otherwise, mask out the available values and return true. We have at least
+ // 1 available value.
+ int NextIter = ConflictingValues.find_first();
+ while (NextIter != -1) {
+ assert(NextIter >= 0 && "Int can not be represented?!");
+ unsigned Iter = NextIter;
+ Result[Iter] = {};
+ NextIter = ConflictingValues.find_next(Iter);
+ }
+
+ return true;
}
-void AllocOptimize::computeAvailableValuesFrom(
+void AvailableValueDataflowContext::computeAvailableValuesFrom(
SILBasicBlock::iterator StartingFrom, SILBasicBlock *BB,
llvm::SmallBitVector &RequiredElts, SmallVectorImpl<AvailableValue> &Result,
llvm::SmallDenseMap<SILBasicBlock *, llvm::SmallBitVector, 32>
@@ -862,6 +852,187 @@
}
}
+/// Explode a copy_addr instruction of a loadable type into lower level
+/// operations like loads, stores, retains, releases, retain_value, etc.
+void AvailableValueDataflowContext::explodeCopyAddr(CopyAddrInst *CAI) {
+ DEBUG(llvm::dbgs() << " -- Exploding copy_addr: " << *CAI << "\n");
+
+ SILType ValTy = CAI->getDest()->getType().getObjectType();
+ auto &TL = getModule().getTypeLowering(ValTy);
+
+ // Keep track of the new instructions emitted.
+ SmallVector<SILInstruction *, 4> NewInsts;
+ SILBuilder B(CAI, &NewInsts);
+ B.setCurrentDebugScope(CAI->getDebugScope());
+
+ // Use type lowering to lower the copyaddr into a load sequence + store
+ // sequence appropriate for the type.
+ SILValue StoredValue =
+ TL.emitLoadOfCopy(B, CAI->getLoc(), CAI->getSrc(), CAI->isTakeOfSrc());
+
+ TL.emitStoreOfCopy(B, CAI->getLoc(), StoredValue, CAI->getDest(),
+ CAI->isInitializationOfDest());
+
+ // Update our internal state for this being gone.
+ NonLoadUses.erase(CAI);
+
+ // Remove the copy_addr from Uses. A single copy_addr can appear multiple
+ // times if the source and dest are to elements within a single aggregate, but
+ // we only want to pick up the CopyAddrKind from the store.
+ DIMemoryUse LoadUse, StoreUse;
+ for (auto &Use : Uses) {
+ if (Use.Inst != CAI)
+ continue;
+
+ if (Use.Kind == DIUseKind::Load) {
+ assert(LoadUse.isInvalid());
+ LoadUse = Use;
+ } else {
+ assert(StoreUse.isInvalid());
+ StoreUse = Use;
+ }
+
+ Use.Inst = nullptr;
+
+ // Keep scanning in case the copy_addr appears multiple times.
+ }
+
+ assert((LoadUse.isValid() || StoreUse.isValid()) &&
+ "we should have a load or a store, possibly both");
+ assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
+ StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
+
+ // Now that we've emitted a bunch of instructions, including a load and store
+ // but also including other stuff, update the internal state of
+ // LifetimeChecker to reflect them.
+
+ // Update the instructions that touch the memory. NewInst can grow as this
+ // iterates, so we can't use a foreach loop.
+ for (auto *NewInst : NewInsts) {
+ switch (NewInst->getKind()) {
+ default:
+ NewInst->dump();
+ llvm_unreachable("Unknown instruction generated by copy_addr lowering");
+
+ case SILInstructionKind::StoreInst:
+ // If it is a store to the memory object (as oppose to a store to
+ // something else), track it as an access.
+ if (StoreUse.isValid()) {
+ StoreUse.Inst = NewInst;
+ NonLoadUses[NewInst] = Uses.size();
+ Uses.push_back(StoreUse);
+ }
+ continue;
+
+ case SILInstructionKind::LoadInst:
+ // If it is a load from the memory object (as oppose to a load from
+ // something else), track it as an access. We need to explicitly check to
+ // see if the load accesses "TheMemory" because it could either be a load
+ // for the copy_addr source, or it could be a load corresponding to the
+ // "assign" operation on the destination of the copyaddr.
+ if (LoadUse.isValid() &&
+ getAccessPathRoot(NewInst->getOperand(0)) == TheMemory) {
+ LoadUse.Inst = NewInst;
+ Uses.push_back(LoadUse);
+ }
+ continue;
+
+ case SILInstructionKind::RetainValueInst:
+ case SILInstructionKind::StrongRetainInst:
+ case SILInstructionKind::StrongReleaseInst:
+ case SILInstructionKind::UnownedRetainInst:
+ case SILInstructionKind::UnownedReleaseInst:
+ case SILInstructionKind::ReleaseValueInst: // Destroy overwritten value
+ // These are ignored.
+ continue;
+ }
+ }
+
+ // Next, remove the copy_addr itself.
+ CAI->eraseFromParent();
+}
+
+bool AvailableValueDataflowContext::hasEscapedAt(SILInstruction *I) {
+ // Return true if the box has escaped at the specified instruction. We are
+ // not allowed to do load promotion in an escape region.
+
+ // FIXME: This is not an aggressive implementation. :)
+
+ // TODO: At some point, we should special case closures that just *read* from
+ // the escaped value (by looking at the body of the closure). They should not
+ // prevent load promotion, and will allow promoting values like X in regions
+ // dominated by "... && X != 0".
+ return HasAnyEscape;
+}
+
+//===----------------------------------------------------------------------===//
+// Allocation Optimization
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+/// This performs load promotion and deletes synthesized allocations if all
+/// loads can be removed.
+class AllocOptimize {
+
+ SILModule &Module;
+
+ /// This is either an alloc_box or alloc_stack instruction.
+ AllocationInst *TheMemory;
+
+ /// This is the SILType of the memory object.
+ SILType MemoryType;
+
+ /// The number of primitive subelements across all elements of this memory
+ /// value.
+ unsigned NumMemorySubElements;
+
+ SmallVectorImpl<DIMemoryUse> &Uses;
+ SmallVectorImpl<SILInstruction *> &Releases;
+
+ /// A structure that we use to compute our available values.
+ AvailableValueDataflowContext DataflowContext;
+
+public:
+ AllocOptimize(AllocationInst *TheMemory, SmallVectorImpl<DIMemoryUse> &Uses,
+ SmallVectorImpl<SILInstruction *> &Releases);
+
+ bool doIt();
+
+private:
+ bool promoteLoad(SILInstruction *Inst);
+ void promoteDestroyAddr(DestroyAddrInst *DAI,
+ MutableArrayRef<AvailableValue> Values);
+ bool
+ canPromoteDestroyAddr(DestroyAddrInst *DAI,
+ llvm::SmallVectorImpl<AvailableValue> &AvailableValues);
+
+ bool tryToRemoveDeadAllocation();
+};
+
+} // end anonymous namespace
+
+static SILType getMemoryType(AllocationInst *TheMemory) {
+ // Compute the type of the memory object.
+ if (auto *ABI = dyn_cast<AllocBoxInst>(TheMemory)) {
+ assert(ABI->getBoxType()->getLayout()->getFields().size() == 1 &&
+ "optimizing multi-field boxes not implemented");
+ return ABI->getBoxType()->getFieldType(ABI->getModule(), 0);
+ } else {
+ assert(isa<AllocStackInst>(TheMemory));
+ return cast<AllocStackInst>(TheMemory)->getElementType();
+ }
+}
+
+AllocOptimize::AllocOptimize(AllocationInst *InputMemory,
+ SmallVectorImpl<DIMemoryUse> &InputUses,
+ SmallVectorImpl<SILInstruction *> &InputReleases)
+ : Module(InputMemory->getModule()), TheMemory(InputMemory),
+ MemoryType(getMemoryType(TheMemory)),
+ NumMemorySubElements(getNumSubElements(MemoryType, Module)),
+ Uses(InputUses), Releases(InputReleases),
+ DataflowContext(TheMemory, NumMemorySubElements, Uses) {}
+
/// If we are able to optimize \p Inst, return the source address that
/// instruction is loading from. If we can not optimize \p Inst, then just
/// return an empty SILValue.
@@ -899,7 +1070,7 @@
// If the box has escaped at this instruction, we can't safely promote the
// load.
- if (hasEscapedAt(Inst))
+ if (DataflowContext.hasEscapedAt(Inst))
return false;
SILType LoadTy = SrcAddr->getType().getObjectType();
@@ -925,28 +1096,17 @@
// Find out if we have any available values. If no bits are demanded, we
// trivially succeed. This can happen when there is a load of an empty struct.
- if (NumLoadSubElements != 0) {
- computeAvailableValues(Inst, RequiredElts, AvailableValues);
-
- // If there are no values available at this load point, then we fail to
- // promote this load and there is nothing to do.
- bool AnyAvailable = false;
- for (unsigned i = FirstElt, e = i+NumLoadSubElements; i != e; ++i)
- if (AvailableValues[i].getValue()) {
- AnyAvailable = true;
- break;
- }
-
- if (!AnyAvailable)
- return false;
- }
-
+ if (NumLoadSubElements != 0 &&
+ !DataflowContext.computeAvailableValues(
+ Inst, FirstElt, NumLoadSubElements, RequiredElts, AvailableValues))
+ return false;
+
// Ok, we have some available values. If we have a copy_addr, explode it now,
// exposing the load operation within it. Subsequent optimization passes will
// see the load and propagate the available values into it.
if (auto *CAI = dyn_cast<CopyAddrInst>(Inst)) {
- explodeCopyAddr(CAI);
-
+ DataflowContext.explodeCopyAddr(CAI);
+
// This is removing the copy_addr, but explodeCopyAddr takes care of
// removing the instruction from Uses for us, so we return false.
return false;
@@ -987,7 +1147,7 @@
// If the box has escaped at this instruction, we can't safely promote the
// load.
- if (hasEscapedAt(DAI))
+ if (DataflowContext.hasEscapedAt(DAI))
return false;
// Compute the access path down to the field so we can determine precise
@@ -1005,13 +1165,12 @@
if (NumLoadSubElements == 0)
return true;
+ // Compute our available values. If we do not have any available values,
+ // return false. We have nothing further to do.
llvm::SmallVector<AvailableValue, 8> TmpList;
TmpList.resize(NumMemorySubElements);
- computeAvailableValues(DAI, RequiredElts, TmpList);
-
- // If some value is not available at this load point, then we fail.
- if (llvm::any_of(range(FirstElt, FirstElt + NumLoadSubElements),
- [&](unsigned i) -> bool { return !TmpList[i]; }))
+ if (!DataflowContext.computeAvailableValues(DAI, FirstElt, NumLoadSubElements,
+ RequiredElts, TmpList))
return false;
// Now that we have our final list, move the temporary lists contents into
@@ -1051,105 +1210,6 @@
DAI->eraseFromParent();
}
-/// Explode a copy_addr instruction of a loadable type into lower level
-/// operations like loads, stores, retains, releases, retain_value, etc.
-void AllocOptimize::explodeCopyAddr(CopyAddrInst *CAI) {
- DEBUG(llvm::dbgs() << " -- Exploding copy_addr: " << *CAI << "\n");
-
- SILType ValTy = CAI->getDest()->getType().getObjectType();
- auto &TL = Module.getTypeLowering(ValTy);
-
- // Keep track of the new instructions emitted.
- SmallVector<SILInstruction*, 4> NewInsts;
- SILBuilder B(CAI, &NewInsts);
- B.setCurrentDebugScope(CAI->getDebugScope());
-
- // Use type lowering to lower the copyaddr into a load sequence + store
- // sequence appropriate for the type.
- SILValue StoredValue = TL.emitLoadOfCopy(B, CAI->getLoc(), CAI->getSrc(),
- CAI->isTakeOfSrc());
-
- TL.emitStoreOfCopy(B, CAI->getLoc(), StoredValue, CAI->getDest(),
- CAI->isInitializationOfDest());
-
- // Update our internal state for this being gone.
- NonLoadUses.erase(CAI);
-
- // Remove the copy_addr from Uses. A single copy_addr can appear multiple
- // times if the source and dest are to elements within a single aggregate, but
- // we only want to pick up the CopyAddrKind from the store.
- DIMemoryUse LoadUse, StoreUse;
- for (auto &Use : Uses) {
- if (Use.Inst != CAI) continue;
-
- if (Use.Kind == DIUseKind::Load) {
- assert(LoadUse.isInvalid());
- LoadUse = Use;
- } else {
- assert(StoreUse.isInvalid());
- StoreUse = Use;
- }
-
- Use.Inst = nullptr;
-
- // Keep scanning in case the copy_addr appears multiple times.
- }
-
- assert((LoadUse.isValid() || StoreUse.isValid()) &&
- "we should have a load or a store, possibly both");
- assert(StoreUse.isInvalid() || StoreUse.Kind == Assign ||
- StoreUse.Kind == PartialStore || StoreUse.Kind == Initialization);
-
- // Now that we've emitted a bunch of instructions, including a load and store
- // but also including other stuff, update the internal state of
- // LifetimeChecker to reflect them.
-
- // Update the instructions that touch the memory. NewInst can grow as this
- // iterates, so we can't use a foreach loop.
- for (auto *NewInst : NewInsts) {
- switch (NewInst->getKind()) {
- default:
- NewInst->dump();
- llvm_unreachable("Unknown instruction generated by copy_addr lowering");
-
- case SILInstructionKind::StoreInst:
- // If it is a store to the memory object (as oppose to a store to
- // something else), track it as an access.
- if (StoreUse.isValid()) {
- StoreUse.Inst = NewInst;
- NonLoadUses[NewInst] = Uses.size();
- Uses.push_back(StoreUse);
- }
- continue;
-
- case SILInstructionKind::LoadInst:
- // If it is a load from the memory object (as oppose to a load from
- // something else), track it as an access. We need to explicitly check to
- // see if the load accesses "TheMemory" because it could either be a load
- // for the copy_addr source, or it could be a load corresponding to the
- // "assign" operation on the destination of the copyaddr.
- if (LoadUse.isValid() &&
- getAccessPathRoot(NewInst->getOperand(0)) == TheMemory) {
- LoadUse.Inst = NewInst;
- Uses.push_back(LoadUse);
- }
- continue;
-
- case SILInstructionKind::RetainValueInst:
- case SILInstructionKind::StrongRetainInst:
- case SILInstructionKind::StrongReleaseInst:
- case SILInstructionKind::UnownedRetainInst:
- case SILInstructionKind::UnownedReleaseInst:
- case SILInstructionKind::ReleaseValueInst: // Destroy overwritten value
- // These are ignored.
- continue;
- }
- }
-
- // Next, remove the copy_addr itself.
- CAI->eraseFromParent();
-}
-
/// tryToRemoveDeadAllocation - If the allocation is an autogenerated allocation
/// that is only stored to (after load promotion) then remove it completely.
bool AllocOptimize::tryToRemoveDeadAllocation() {
diff --git a/lib/SILOptimizer/PassManager/PassManager.cpp b/lib/SILOptimizer/PassManager/PassManager.cpp
index 736ca54..9eb5407 100644
--- a/lib/SILOptimizer/PassManager/PassManager.cpp
+++ b/lib/SILOptimizer/PassManager/PassManager.cpp
@@ -236,8 +236,9 @@
};
-SILPassManager::SILPassManager(SILModule *M, llvm::StringRef Stage) :
- Mod(M), StageName(Stage) {
+SILPassManager::SILPassManager(SILModule *M, llvm::StringRef Stage,
+ bool isMandatoryPipeline) :
+ Mod(M), StageName(Stage), isMandatoryPipeline(isMandatoryPipeline) {
#define ANALYSIS(NAME) \
Analysis.push_back(create##NAME##Analysis(Mod));
@@ -250,14 +251,15 @@
}
SILPassManager::SILPassManager(SILModule *M, irgen::IRGenModule *IRMod,
- llvm::StringRef Stage)
- : SILPassManager(M, Stage) {
+ llvm::StringRef Stage, bool isMandatoryPipeline)
+ : SILPassManager(M, Stage, isMandatoryPipeline) {
this->IRMod = IRMod;
}
bool SILPassManager::continueTransforming() {
- return Mod->getStage() == SILStage::Raw ||
- NumPassesRun < SILNumOptPassesToRun;
+ if (isMandatoryPipeline)
+ return true;
+ return NumPassesRun < SILNumOptPassesToRun;
}
bool SILPassManager::analysesUnlocked() {
@@ -389,7 +391,7 @@
// Only include functions that are definitions, and which have not
// been intentionally excluded from optimization.
- if (F.isDefinition() && F.shouldOptimize())
+ if (F.isDefinition() && (isMandatoryPipeline || F.shouldOptimize()))
FunctionWorklist.push_back(*I);
}
@@ -554,8 +556,8 @@
void SILPassManager::addFunctionToWorklist(SILFunction *F,
SILFunction *DerivedFrom) {
- assert(F && F->isDefinition() && F->shouldOptimize() &&
- "Expected optimizable function definition!");
+ assert(F && F->isDefinition() && (isMandatoryPipeline || F->shouldOptimize())
+ && "Expected optimizable function definition!");
constexpr int MaxDeriveLevels = 10;
diff --git a/lib/SILOptimizer/PassManager/Passes.cpp b/lib/SILOptimizer/PassManager/Passes.cpp
index 94d74e7..761a044 100644
--- a/lib/SILOptimizer/PassManager/Passes.cpp
+++ b/lib/SILOptimizer/PassManager/Passes.cpp
@@ -51,7 +51,7 @@
auto &Ctx = Module.getASTContext();
- SILPassManager PM(&Module);
+ SILPassManager PM(&Module, "", /*isMandatoryPipeline=*/ true);
PM.executePassPipelinePlan(
SILPassPipelinePlan::getDiagnosticPassPipeline(Module.getOptions()));
@@ -119,7 +119,9 @@
if (Module.getOptions().VerifyAll)
Module.verify();
- SILPassManager PM(&Module, "Onone");
+ // We want to run the Onone passes also for function which have an explicit
+ // Onone attribute.
+ SILPassManager PM(&Module, "Onone", /*isMandatoryPipeline=*/ true);
PM.executePassPipelinePlan(SILPassPipelinePlan::getOnonePassPipeline());
// Verify the module, if required.
@@ -199,7 +201,7 @@
// convert it to a module pass to ensure that the SIL input is always at the
// same stage of lowering.
void swift::runSILLoweringPasses(SILModule &Module) {
- SILPassManager PM(&Module, "LoweringPasses");
+ SILPassManager PM(&Module, "LoweringPasses", /*isMandatoryPipeline=*/ true);
PM.executePassPipelinePlan(SILPassPipelinePlan::getLoweringPassPipeline());
assert(Module.getStage() == SILStage::Lowered);
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index e5f48b0..3fad2e2 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -489,13 +489,10 @@
assert(NewOpType.isAddress() && "Addresses should map to addresses.");
auto UAC = Builder.createUncheckedAddrCast(AI.getLoc(), Op, NewOpType);
Args.push_back(UAC);
- } else if (SILType::canRefCast(OldOpType, NewOpType, AI.getModule())) {
- auto URC = Builder.createUncheckedRefCast(AI.getLoc(), Op, NewOpType);
+ } else if (OldOpType.getSwiftRValueType() != NewOpType.getSwiftRValueType()) {
+ auto URC = Builder.createUncheckedBitCast(AI.getLoc(), Op, NewOpType);
Args.push_back(URC);
} else {
- assert((!OldOpType.isHeapObjectReferenceType()
- && !NewOpType.isHeapObjectReferenceType()) &&
- "ref argument types should map to refs.");
Args.push_back(Op);
}
}
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index f43224d..d1333cd 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -1148,8 +1148,7 @@
auto *F = getFunction();
// Don't run function signature optimizations at -Os.
- if (F->getModule().getOptions().Optimization ==
- SILOptions::SILOptMode::OptimizeForSize)
+ if (F->optimizeForSize())
return;
// Don't optimize callees that should not be optimized.
diff --git a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
index 20b88e9..51aff14 100644
--- a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
+++ b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp
@@ -84,6 +84,9 @@
SILFunction *Callee = Apply.getReferencedFunction();
assert(Callee && "Expected to have a known callee");
+ if (!Callee->shouldOptimize())
+ continue;
+
// We have a call that can potentially be specialized, so
// attempt to do so.
llvm::SmallVector<SILFunction *, 2> NewFunctions;
diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp
index abaed72..6b2687c 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -1289,8 +1289,7 @@
auto *Fun = getFunction();
// Only outline if we optimize for size.
- if (Fun->getModule().getOptions().Optimization !=
- SILOptions::SILOptMode::OptimizeForSize)
+ if (!Fun->optimizeForSize())
return;
// Dump function if requested.
diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
index 8190a3e..e7273a9 100644
--- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
+++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp
@@ -111,7 +111,7 @@
DefaultApplyLength = 10
};
- SILOptions::SILOptMode OptMode;
+ OptimizationMode OptMode;
#ifndef NDEBUG
SILFunction *LastPrintedCaller = nullptr;
@@ -161,7 +161,7 @@
public:
SILPerformanceInliner(InlineSelection WhatToInline, DominanceAnalysis *DA,
SILLoopAnalysis *LA, SideEffectAnalysis *SEA,
- SILOptions::SILOptMode OptMode, OptRemark::Emitter &ORE)
+ OptimizationMode OptMode, OptRemark::Emitter &ORE)
: WhatToInline(WhatToInline), DA(DA), LA(LA), SEA(SEA), CBI(DA), ORE(ORE),
OptMode(OptMode) {}
@@ -243,7 +243,7 @@
int BaseBenefit = RemovedCallBenefit;
// Osize heuristic.
- if (OptMode == SILOptions::SILOptMode::OptimizeForSize) {
+ if (OptMode == OptimizationMode::ForSize) {
// Don't inline into thunks.
if (AI.getFunction()->isThunk())
return false;
@@ -293,11 +293,6 @@
->getSubstitutionMap(AI.getSubstitutions());
}
- // For some reason -Ounchecked can accept a higher base benefit without
- // increasing the code size too much.
- if (OptMode == SILOptions::SILOptMode::OptimizeUnchecked)
- BaseBenefit *= 2;
-
CallerWeight.updateBenefit(Benefit, BaseBenefit);
// Benefit = 1;
@@ -443,7 +438,8 @@
ORE.emit([&]() {
using namespace OptRemark;
return RemarkMissed("NoInlinedCost", *AI.getInstruction())
- << "Not profitable to inline (cost = " << NV("Cost", CalleeCost)
+ << "Not profitable to inline function " << NV("Callee", Callee)
+ << " (cost = " << NV("Cost", CalleeCost)
<< ", benefit = " << NV("Benefit", Benefit) << ")";
});
return false;
@@ -905,7 +901,7 @@
return;
}
- auto OptMode = getFunction()->getModule().getOptions().Optimization;
+ auto OptMode = getFunction()->getEffectiveOptimizationMode();
SILPerformanceInliner Inliner(WhatToInline, DA, LA, SEA, OptMode, ORE);
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 801dd44..254c6b7 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -555,8 +555,7 @@
auto &CurFn = *getFunction();
// Don't perform speculative devirtualization at -Os.
- if (CurFn.getModule().getOptions().Optimization ==
- SILOptions::SILOptMode::OptimizeForSize)
+ if (CurFn.optimizeForSize())
return;
// Don't speculatively devirtualize calls inside thunks.
diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFG.cpp
index 9f419ba..261512d 100644
--- a/lib/SILOptimizer/Utils/CFG.cpp
+++ b/lib/SILOptimizer/Utils/CFG.cpp
@@ -848,3 +848,118 @@
}
llvm_unreachable("Destination block not found");
}
+
+void swift::completeJointPostDominanceSet(
+ ArrayRef<SILBasicBlock *> UserBlocks, ArrayRef<SILBasicBlock *> DefBlocks,
+ llvm::SmallVectorImpl<SILBasicBlock *> &Result) {
+ assert(!UserBlocks.empty() && "Must have at least 1 user block");
+ assert(!DefBlocks.empty() && "Must have at least 1 def block");
+
+ // If we have only one def block and one user block and they are the same
+ // block, then just return.
+ if (DefBlocks.size() == 1 && UserBlocks.size() == 1 &&
+ UserBlocks[0] == DefBlocks[0]) {
+ return;
+ }
+
+ // Some notes on the algorithm:
+ //
+ // 1. Our VisitedBlocks set just states that a value has been added to the
+ // worklist and should not be added to the worklist.
+ // 2. Our targets of the CFG block are DefBlockSet.
+ // 3. We find the missing post-domination blocks by finding successors of
+ // blocks on our walk that we have not visited by the end of the walk. For
+ // joint post-dominance to be true, no such successors should exist.
+
+ // Our set of target blocks where we stop walking.
+ llvm::SmallPtrSet<SILBasicBlock *, 8> DefBlockSet(DefBlocks.begin(),
+ DefBlocks.end());
+
+ // The set of successor blocks of blocks that we visit. Any blocks still in
+ // this set at the end of the walk act as a post-dominating closure around our
+ // UserBlock set.
+ llvm::SmallSetVector<SILBasicBlock *, 16> MustVisitSuccessorBlocks;
+
+ // Add our user and def blocks to the VisitedBlock set. We never want to find
+ // these in our worklist.
+ llvm::SmallPtrSet<SILBasicBlock *, 32> VisitedBlocks(UserBlocks.begin(),
+ UserBlocks.end());
+
+ // Finally setup our worklist by adding our user block predecessors. We only
+ // add the predecessors to the worklist once.
+ llvm::SmallVector<SILBasicBlock *, 32> Worklist;
+ for (auto *Block : UserBlocks) {
+ copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist),
+ [&](SILBasicBlock *PredBlock) -> bool {
+ return VisitedBlocks.insert(PredBlock).second;
+ });
+ }
+
+ // Then until we reach a fix point.
+ while (!Worklist.empty()) {
+ // Grab the next block from the worklist.
+ auto *Block = Worklist.pop_back_val();
+ assert(VisitedBlocks.count(Block) && "All blocks from worklist should be "
+ "in the visited blocks set.");
+
+ // Since we are visiting this block now, we know that this block can not be
+ // apart of a the post-dominance closure of our UseBlocks.
+ MustVisitSuccessorBlocks.remove(Block);
+
+ // Then add each successor block of Block that has not been visited yet to
+ // the MustVisitSuccessorBlocks set.
+ for (auto *SuccBlock : Block->getSuccessorBlocks()) {
+ if (!VisitedBlocks.count(SuccBlock)) {
+ MustVisitSuccessorBlocks.insert(SuccBlock);
+ }
+ }
+
+ // If this is a def block, then do not add its predecessors to the
+ // worklist.
+ if (DefBlockSet.count(Block))
+ continue;
+
+ // Otherwise add all unvisited predecessors to the worklist.
+ copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist),
+ [&](SILBasicBlock *Block) -> bool {
+ return VisitedBlocks.insert(Block).second;
+ });
+ }
+
+ // Now that we are done, add all remaining must visit blocks to our result
+ // list. These are the remaining parts of our joint post-dominance closure.
+ copy(MustVisitSuccessorBlocks, std::back_inserter(Result));
+}
+
+bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn,
+ DominanceInfo *DT,
+ SILLoopInfo *LI) {
+ // Find our targets.
+ llvm::SmallVector<std::pair<SILBasicBlock *, unsigned>, 8> Targets;
+ for (auto &Block : Fn) {
+ auto *CBI = dyn_cast<CondBranchInst>(Block.getTerminator());
+ if (!CBI)
+ continue;
+
+ // See if our true index is a critical edge. If so, add block to the list
+ // and continue. If the false edge is also critical, we will handle it at
+ // the same time.
+ if (isCriticalEdge(CBI, CondBranchInst::TrueIdx)) {
+ Targets.emplace_back(&Block, CondBranchInst::TrueIdx);
+ }
+
+ if (!isCriticalEdge(CBI, CondBranchInst::FalseIdx)) {
+ continue;
+ }
+
+ Targets.emplace_back(&Block, CondBranchInst::FalseIdx);
+ }
+
+ for (auto P : Targets) {
+ SILBasicBlock *Block = P.first;
+ unsigned Index = P.second;
+ auto *Result = splitCriticalEdge(Block->getTerminator(), Index, DT, LI);
+ (void)Result;
+ assert(Result);
+ }
+}
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index 9e854a8..a24e246 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -528,7 +528,10 @@
return false;
}
- if (!F->shouldOptimize()) {
+ // Mandatory inlining does class method devirtualization. I'm not sure if this
+ // is really needed, but some test rely on this.
+ // So even for Onone functions we have to do it if the SILStage is raw.
+ if (F->getModule().getStage() != SILStage::Raw && !F->shouldOptimize()) {
// Do not consider functions that should not be optimized.
DEBUG(llvm::dbgs() << " FAIL: Could not optimize function "
<< " because it is marked no-opt: " << F->getName()
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index eb69a59..5c49d9f 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -347,12 +347,6 @@
static bool shouldNotSpecializeCallee(SILFunction *Callee,
SubstitutionList Subs = {}) {
- if (!Callee->shouldOptimize()) {
- DEBUG(llvm::dbgs() << " Cannot specialize function " << Callee->getName()
- << " marked to be excluded from optimizations.\n");
- return true;
- }
-
if (Callee->hasSemanticsAttr("optimize.sil.specialize.generic.never"))
return true;
@@ -1841,12 +1835,10 @@
/// Create a new specialized function if possible, and cache it.
SILFunction *GenericFuncSpecializer::tryCreateSpecialization() {
// Do not create any new specializations at Onone.
- if (M.getOptions().Optimization <= SILOptions::SILOptMode::None)
+ if (!GenericFunc->shouldOptimize())
return nullptr;
- DEBUG(
- if (M.getOptions().Optimization <= SILOptions::SILOptMode::Debug) {
- llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n"; });
+ DEBUG(llvm::dbgs() << "Creating a specialization: " << ClonedName << "\n";);
ReInfo.verify();
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 72791f8..62d2bf6 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -89,7 +89,8 @@
// At Onone, consider all uses, including the debug_info.
// This way, debug_info is preserved at Onone.
if (I->hasUsesOfAnyResult() &&
- I->getModule().getOptions().Optimization <= SILOptions::SILOptMode::None)
+ I->getFunction()->getEffectiveOptimizationMode() <=
+ OptimizationMode::NoOptimization)
return false;
if (!onlyHaveDebugUsesOfAllResults(I) || isa<TermInst>(I))
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 2c4fded..8382876 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -474,9 +474,6 @@
tc.conformsToProtocol(baseTy, proto, cs.DC,
(ConformanceCheckFlags::InExpression|
ConformanceCheckFlags::Used));
- assert((!conformance ||
- conformance->getConditionalRequirements().empty()) &&
- "unhandled conditional conformance");
if (conformance && conformance->isConcrete()) {
if (auto witness =
conformance->getConcrete()->getWitnessDecl(decl, &tc)) {
@@ -1318,23 +1315,29 @@
// Apply a key path if we have one.
if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) {
+ auto applicationTy = simplifyType(selected->openedType)
+ ->castTo<FunctionType>();
+
index = cs.coerceToRValue(index);
// The index argument should be (keyPath: KeyPath<Root, Value>).
// Dig the key path expression out of the argument tuple.
auto indexKP = cast<TupleExpr>(index)->getElement(0);
- auto keyPathTTy = cs.getType(indexKP);
-
+ auto keyPathExprTy = cs.getType(indexKP);
+ auto keyPathTy = applicationTy->getInput()->castTo<TupleType>()
+ ->getElementType(0);
+
// Check for the KeyPath being an IUO
- if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathTTy)) {
- keyPathTTy = pathTy;
- indexKP = coerceImplicitlyUnwrappedOptionalToValue(indexKP, keyPathTTy, locator);
+ if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathExprTy)) {
+ keyPathExprTy = pathTy;
+ indexKP = coerceImplicitlyUnwrappedOptionalToValue(
+ indexKP, keyPathExprTy, locator);
}
Type valueTy;
Type baseTy;
bool resultIsLValue;
- if (auto nom = keyPathTTy->getAs<NominalType>()) {
+ if (auto nom = keyPathTy->getAs<NominalType>()) {
// AnyKeyPath is <T> rvalue T -> rvalue Any?
if (nom->getDecl() == cs.getASTContext().getAnyKeyPathDecl()) {
valueTy = ProtocolCompositionType::get(cs.getASTContext(), {},
@@ -1343,12 +1346,25 @@
resultIsLValue = false;
base = cs.coerceToRValue(base);
baseTy = cs.getType(base);
+ // We don't really want to attempt AnyKeyPath application
+ // if we know a more specific key path type is being applied.
+ if (!keyPathTy->isEqual(keyPathExprTy)) {
+ cs.TC.diagnose(base->getLoc(),
+ diag::expr_smart_keypath_application_type_mismatch,
+ keyPathExprTy,
+ baseTy)
+ .highlight(index->getSourceRange());
+ }
} else {
llvm_unreachable("unknown key path class!");
}
} else {
- auto keyPathBGT = keyPathTTy->castTo<BoundGenericType>();
+ auto keyPathBGT = keyPathTy->castTo<BoundGenericType>();
baseTy = keyPathBGT->getGenericArgs()[0];
+
+ // Coerce the base to the key path's expected base type.
+ if (!baseTy->isEqual(cs.getType(base)->getRValueType()))
+ base = coerceToType(base, baseTy, locator);
if (keyPathBGT->getDecl()
== cs.getASTContext().getPartialKeyPathDecl()) {
@@ -1377,12 +1393,6 @@
llvm_unreachable("unknown key path class!");
}
}
-
- // Coerce the base if its anticipated type doesn't match - say we're
- // applying a keypath with an existential base to a concrete base.
- if (baseTy->isExistentialType() && !cs.getType(base)->isExistentialType()) {
- base = coerceToType(base, baseTy, locator);
- }
}
if (resultIsLValue)
valueTy = LValueType::get(valueTy);
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index bf8f627..90f5bb9 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -4844,7 +4844,7 @@
AFD = dyn_cast<AbstractFunctionDecl>(candidate);
}
- if (!AFD || !AFD->isGeneric() || !AFD->hasInterfaceType())
+ if (!AFD || !AFD->getGenericSignature() || !AFD->hasInterfaceType())
return false;
auto env = AFD->getGenericEnvironment();
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index fecfb81..e14dae2 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -563,15 +563,6 @@
break;
}
- if (conformance) {
- assert(relationshipKind == SelfTypeRelationship::ConformsTo ||
- relationshipKind == SelfTypeRelationship::ConformedToBy);
-
- for (auto requirement : conformance->getConditionalRequirements()) {
- cs.addConstraint(requirement, locator);
- }
- }
-
bool fewerEffectiveParameters = false;
switch (checkKind) {
case CheckAll:
@@ -1045,16 +1036,6 @@
continue;
}
- // A concrete type is better than an archetype.
- // FIXME: Total hack.
- if (type1->is<ArchetypeType>() != type2->is<ArchetypeType>()) {
- if (type1->is<ArchetypeType>())
- ++score2;
- else
- ++score1;
- continue;
- }
-
// FIXME:
// This terrible hack is in place to support equality comparisons of non-
// equatable option types to 'nil'. Until we have a way to constrain a type
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 4e2d031..e5a406a 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -18,6 +18,7 @@
#include "ConstraintSystem.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/ParameterList.h"
+#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/StringExtras.h"
#include "swift/ClangImporter/ClangModule.h"
#include "llvm/Support/Compiler.h"
@@ -2606,11 +2607,19 @@
// This conformance may be conditional, in which case we need to consider
// those requirements as constraints too.
//
- // FIXME: this doesn't seem to be right; the requirements are sometimes
- // phrased in terms of the type's generic parameters, not type variables
- // in this context.
- for (auto req : conformance->getConditionalRequirements()) {
- addConstraint(req, locator);
+ // If we've got a normal conformance, we must've started with `type` in
+ // the context that declares the conformance, and so these requirements
+ // are automatically satisfied, and thus we can skip adding them. (This
+ // hacks around some representational problems caused by requirements
+ // being stored as interface types and the normal conformance's type being
+ // a contextual type. Once the latter is fixed and everything is interface
+ // types, this shouldn't be necessary.)
+ if (conformance->isConcrete() &&
+ conformance->getConcrete()->getKind() !=
+ ProtocolConformanceKind::Normal) {
+ for (auto req : conformance->getConditionalRequirements()) {
+ addConstraint(req, locator);
+ }
}
return SolutionKind::Solved;
}
@@ -4034,22 +4043,28 @@
// Try to match the root type.
rootTy = getFixedTypeRecursive(rootTy, flags, /*wantRValue=*/false);
- auto rootMatches = matchTypes(kpRootTy, rootTy,
- ConstraintKind::Equal,
- subflags, locator);
- switch (rootMatches) {
- case SolutionKind::Error:
- return SolutionKind::Error;
- case SolutionKind::Solved:
- break;
- case SolutionKind::Unsolved:
- llvm_unreachable("should have generated constraints");
- }
+
+ auto matchRoot = [&](ConstraintKind kind) -> bool {
+ auto rootMatches = matchTypes(rootTy, kpRootTy, kind,
+ subflags, locator);
+ switch (rootMatches) {
+ case SolutionKind::Error:
+ return false;
+ case SolutionKind::Solved:
+ return true;
+ case SolutionKind::Unsolved:
+ llvm_unreachable("should have generated constraints");
+ }
+ };
if (bgt->getDecl() == getASTContext().getPartialKeyPathDecl()) {
// Read-only keypath, whose projected value is upcast to `Any`.
auto resultTy = ProtocolCompositionType::get(getASTContext(), {},
/*explicit AnyObject*/ false);
+
+ if (!matchRoot(ConstraintKind::Conversion))
+ return SolutionKind::Error;
+
return matchTypes(resultTy, valueTy,
ConstraintKind::Bind, subflags, locator);
}
@@ -4060,6 +4075,7 @@
/// Solve for an rvalue base.
auto solveRValue = [&]() -> ConstraintSystem::SolutionKind {
+ // An rvalue base can be converted to a supertype.
return matchTypes(kpValueTy, valueTy,
ConstraintKind::Bind, subflags, locator);
};
@@ -4076,14 +4092,20 @@
return matchTypes(LValueType::get(kpValueTy), valueTy,
ConstraintKind::Bind, subflags, locator);
};
-
if (bgt->getDecl() == getASTContext().getKeyPathDecl()) {
// Read-only keypath.
+ if (!matchRoot(ConstraintKind::Conversion))
+ return SolutionKind::Error;
+
return solveRValue();
}
if (bgt->getDecl() == getASTContext().getWritableKeyPathDecl()) {
// Writable keypath. The result can be an lvalue if the root was.
+ // We can't convert the base without giving up lvalue-ness, though.
+ if (!matchRoot(ConstraintKind::Equal))
+ return SolutionKind::Error;
+
if (rootTy->is<LValueType>())
return solveLValue();
if (rootTy->isTypeVariableOrMember())
@@ -4092,6 +4114,9 @@
return solveRValue();
}
if (bgt->getDecl() == getASTContext().getReferenceWritableKeyPathDecl()) {
+ if (!matchRoot(ConstraintKind::Conversion))
+ return SolutionKind::Error;
+
// Reference-writable keypath. The result can always be an lvalue.
return solveLValue();
}
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 38d6a0d..882d537 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -2205,9 +2205,3 @@
return ctor;
}
-
-void TypeChecker::addImplicitDestructor(ClassDecl *CD) {
- auto *DD = CD->addImplicitDestructor();
- if (DD)
- typeCheckDecl(DD, /*isFirstPass=*/true);
-}
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 39c5ae6..8fbfe3d 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -390,14 +390,12 @@
ConstraintLocatorBuilder locator,
OpenedTypeMap &replacements) {
auto unboundDecl = unbound->getDecl();
- if (unboundDecl->isInvalid())
- return ErrorType::get(getASTContext());
// If the unbound decl hasn't been validated yet, we have a circular
// dependency that isn't being diagnosed properly.
if (!unboundDecl->getGenericSignature()) {
TC.diagnose(unboundDecl, diag::circular_reference);
- return ErrorType::get(unbound);
+ return Type();
}
auto parentTy = unbound->getParent();
@@ -458,7 +456,7 @@
if (!type->hasUnboundGenericType())
return type;
- return type.transform([&](Type type) -> Type {
+ type = type.transform([&](Type type) -> Type {
if (auto unbound = type->getAs<UnboundGenericType>()) {
OpenedTypeMap replacements;
return openUnboundGenericType(unbound, locator, replacements);
@@ -466,6 +464,11 @@
return type;
});
+
+ if (!type)
+ return ErrorType::get(getASTContext());
+
+ return type;
}
Type ConstraintSystem::openType(Type type, OpenedTypeMap &replacements) {
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 72124cc..fa3707a 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -671,7 +671,7 @@
FunctionType::ExtInfo());
}
eqDecl->setInterfaceType(interfaceTy);
- copyFormalAccess(eqDecl, typeDecl);
+ eqDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -1090,7 +1090,7 @@
AnyFunctionType::ExtInfo());
getterDecl->setInterfaceType(interfaceType);
- copyFormalAccess(getterDecl, typeDecl);
+ getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -1106,7 +1106,7 @@
hashValueDecl->setInterfaceType(intType);
hashValueDecl->makeComputed(SourceLoc(), getterDecl,
nullptr, nullptr, SourceLoc());
- copyFormalAccess(hashValueDecl, typeDecl);
+ hashValueDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
Pattern *hashValuePat = new (C) NamedPattern(hashValueDecl, /*implicit*/true);
hashValuePat->setType(intType);
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index c3fb22a..853e9ed 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -349,7 +349,7 @@
}
initDecl->setInterfaceType(allocIfaceType);
initDecl->setInitializerInterfaceType(initIfaceType);
- copyFormalAccess(initDecl, enumDecl);
+ initDecl->copyFormalAccessAndVersionedAttrFrom(enumDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp
index 0beaf5f..f2e6d36 100644
--- a/lib/Sema/DerivedConformances.cpp
+++ b/lib/Sema/DerivedConformances.cpp
@@ -251,7 +251,7 @@
interfaceType = FunctionType::get({selfParam}, interfaceType,
FunctionType::ExtInfo());
getterDecl->setInterfaceType(interfaceType);
- copyFormalAccess(getterDecl, typeDecl);
+ getterDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
// If the enum was not imported, the derived conformance is either from the
// enum itself or an extension, in which case we will emit the declaration
@@ -281,7 +281,7 @@
propDecl->setImplicit();
propDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
SourceLoc());
- copyFormalAccess(propDecl, typeDecl);
+ propDecl->copyFormalAccessAndVersionedAttrFrom(typeDecl);
propDecl->setInterfaceType(propertyInterfaceType);
// If this is supposed to be a final property, mark it as such.
@@ -304,14 +304,3 @@
return {propDecl, pbDecl};
}
-
-void DerivedConformance::copyFormalAccess(ValueDecl *dest, ValueDecl *source) {
- dest->setAccess(source->getFormalAccess());
-
- // Inherit the @_versioned attribute.
- if (source->getAttrs().hasAttribute<VersionedAttr>()) {
- auto &ctx = source->getASTContext();
- auto *clonedAttr = new (ctx) VersionedAttr(/*implicit=*/true);
- dest->getAttrs().add(clonedAttr);
- }
-}
diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h
index 0e6ab8b..2457971 100644
--- a/lib/Sema/DerivedConformances.h
+++ b/lib/Sema/DerivedConformances.h
@@ -185,9 +185,6 @@
/// Build a reference to the 'self' decl of a derived function.
DeclRefExpr *createSelfDeclRef(AbstractFunctionDecl *fn);
-/// Copy access from the source decl to the destination decl.
-void copyFormalAccess(ValueDecl *dest, ValueDecl *source);
-
}
}
diff --git a/lib/Sema/InstrumenterSupport.h b/lib/Sema/InstrumenterSupport.h
index dd4e71c..f223617 100644
--- a/lib/Sema/InstrumenterSupport.h
+++ b/lib/Sema/InstrumenterSupport.h
@@ -17,6 +17,8 @@
#include "TypeChecker.h"
+#include "swift/AST/ASTWalker.h"
+
namespace swift {
namespace instrumenter_support {
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 01d1832..27f2bff 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -1418,7 +1418,15 @@
/// x == nil // also !=
///
void checkOptionalPromotions(ApplyExpr *call) {
- auto DRE = dyn_cast<DeclRefExpr>(call->getSemanticFn());
+ // We only care about binary expressions.
+ if (!isa<BinaryExpr>(call)) return;
+
+ // Dig out the function we're calling.
+ auto fnExpr = call->getSemanticFn();
+ if (auto dotSyntax = dyn_cast<DotSyntaxCallExpr>(fnExpr))
+ fnExpr = dotSyntax->getSemanticFn();
+
+ auto DRE = dyn_cast<DeclRefExpr>(fnExpr);
auto args = dyn_cast<TupleExpr>(call->getArg());
if (!DRE || !DRE->getDecl()->isOperator() ||
!args || args->getNumElements() != 2)
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index c10325c..6d70db7 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -79,6 +79,7 @@
IGNORED_ATTR(FixedLayout)
IGNORED_ATTR(Infix)
IGNORED_ATTR(Inline)
+ IGNORED_ATTR(Optimize)
IGNORED_ATTR(Inlineable)
IGNORED_ATTR(NSApplicationMain)
IGNORED_ATTR(NSCopying)
@@ -279,7 +280,9 @@
if (auto *VD = dyn_cast<VarDecl>(D)) {
// Stored properties and variables can't be transparent.
if (VD->hasStorage())
- return diagnoseAndRemoveAttr(attr, diag::transparent_stored_property);
+ return diagnoseAndRemoveAttr(attr,
+ diag::attribute_invalid_on_stored_property,
+ attr->getAttrName());
}
}
@@ -866,7 +869,8 @@
void visitFixedLayoutAttr(FixedLayoutAttr *attr);
void visitVersionedAttr(VersionedAttr *attr);
void visitInlineableAttr(InlineableAttr *attr);
-
+ void visitOptimizeAttr(OptimizeAttr *attr);
+
void visitDiscardableResultAttr(DiscardableResultAttr *attr);
void visitImplementsAttr(ImplementsAttr *attr);
};
@@ -1914,7 +1918,8 @@
if (auto *VD = dyn_cast<VarDecl>(D)) {
if (VD->hasStorage() || VD->getAttrs().hasAttribute<LazyAttr>()) {
TC.diagnose(attr->getLocation(),
- diag::inlineable_stored_property)
+ diag::attribute_invalid_on_stored_property,
+ attr->getAttrName())
.fixItRemove(attr->getRangeWithAt());
attr->setInvalid();
return;
@@ -1947,6 +1952,19 @@
}
}
+void AttributeChecker::visitOptimizeAttr(OptimizeAttr *attr) {
+ if (auto *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->hasStorage()) {
+ TC.diagnose(attr->getLocation(),
+ diag::attribute_invalid_on_stored_property,
+ attr->getAttrName())
+ .fixItRemove(attr->getRangeWithAt());
+ attr->setInvalid();
+ return;
+ }
+ }
+}
+
void AttributeChecker::visitDiscardableResultAttr(DiscardableResultAttr *attr) {
if (auto *FD = dyn_cast<FuncDecl>(D)) {
if (auto result = FD->getResultInterfaceType()) {
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 04f0599..62f9cb5 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -4638,7 +4638,7 @@
if (!IsFirstPass)
TC.addImplicitConstructors(CD);
- TC.addImplicitDestructor(CD);
+ CD->addImplicitDestructor();
if (!IsFirstPass && !CD->isInvalid())
TC.checkConformancesInContext(CD, CD);
@@ -6381,6 +6381,7 @@
UNINTERESTING_ATTR(IBOutlet)
UNINTERESTING_ATTR(Indirect)
UNINTERESTING_ATTR(Inline)
+ UNINTERESTING_ATTR(Optimize)
UNINTERESTING_ATTR(Inlineable)
UNINTERESTING_ATTR(Effects)
UNINTERESTING_ATTR(FixedLayout)
@@ -7212,13 +7213,7 @@
&& "Decl parsing must prevent destructors outside of types!");
TC.checkDeclAttributesEarly(DD);
- if (!DD->hasAccess()) {
- DD->setAccess(enclosingClass->getFormalAccess());
- }
-
- if (enclosingClass->getAttrs().hasAttribute<VersionedAttr>()) {
- DD->getAttrs().add(new (TC.Context) VersionedAttr(/*implicit=*/true));
- }
+ DD->copyFormalAccessAndVersionedAttrFrom(enclosingClass);
configureImplicitSelf(TC, DD);
@@ -7962,7 +7957,7 @@
// class, you shouldn't have to know what the vtable layout is.
if (auto *CD = dyn_cast<ClassDecl>(nominal)) {
TC.addImplicitConstructors(CD);
- TC.addImplicitDestructor(CD);
+ CD->addImplicitDestructor();
}
// validateDeclForNameLookup will not trigger an immediate full
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index b5d3c2f..b75df46 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -69,7 +69,7 @@
addImplicitStructConformances(SD);
}
if (auto CD = dyn_cast<ClassDecl>(decl)) {
- addImplicitDestructor(CD);
+ CD->addImplicitDestructor();
}
if (auto ED = dyn_cast<EnumDecl>(decl)) {
addImplicitEnumConformances(ED);
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 1a22724..fa1ecae 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1511,10 +1511,6 @@
/// struct or class.
void addImplicitConstructors(NominalTypeDecl *typeDecl);
- /// \brief Add an implicitly-defined destructor, if there is no
- /// user-provided destructor.
- void addImplicitDestructor(ClassDecl *CD);
-
/// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an
/// imported NS_OPTIONS struct.
void addImplicitStructConformances(StructDecl *ED);
diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp
index eb824f1..0918a5b 100644
--- a/lib/Serialization/Deserialization.cpp
+++ b/lib/Serialization/Deserialization.cpp
@@ -1277,9 +1277,18 @@
DeclBaseName name = getDeclBaseName(IID);
pathTrace.addValue(name);
- Type filterTy = getType(TID);
- if (!isType)
+ Type filterTy;
+ if (!isType) {
+ auto maybeType = getTypeChecked(TID);
+ if (!maybeType) {
+ // FIXME: Don't throw away the inner error's information.
+ llvm::consumeError(maybeType.takeError());
+ return llvm::make_error<XRefError>("couldn't decode type",
+ pathTrace, name);
+ }
+ filterTy = maybeType.get();
pathTrace.addType(filterTy);
+ }
baseModule->lookupQualified(ModuleType::get(baseModule), name,
NL_QualifiedDefault | NL_KnownNoDependency,
@@ -1482,9 +1491,18 @@
pathTrace.addValue(memberName);
- Type filterTy = getType(TID);
- if (!isType)
+ Type filterTy;
+ if (!isType) {
+ auto maybeType = getTypeChecked(TID);
+ if (!maybeType) {
+ // FIXME: Don't throw away the inner error's information.
+ llvm::consumeError(maybeType.takeError());
+ return llvm::make_error<XRefError>("couldn't decode type",
+ pathTrace, memberName);
+ }
+ filterTy = maybeType.get();
pathTrace.addType(filterTy);
+ }
if (values.size() != 1) {
return llvm::make_error<XRefError>("multiple matching base values",
@@ -2318,6 +2336,14 @@
break;
}
+ case decls_block::Optimize_DECL_ATTR: {
+ unsigned kind;
+ serialization::decls_block::OptimizeDeclAttrLayout::readRecord(
+ scratch, kind);
+ Attr = new (ctx) OptimizeAttr((OptimizationMode)kind);
+ break;
+ }
+
case decls_block::Effects_DECL_ATTR: {
unsigned kind;
serialization::decls_block::EffectsDeclAttrLayout::readRecord(scratch,
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 1827119..d8e587f 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -407,10 +407,12 @@
TypeID funcTyID;
GenericEnvironmentID genericEnvID;
unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
- inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
+ inlineStrategy, optimizationMode, effect, numSpecAttrs,
+ hasQualifiedOwnership;
ArrayRef<uint64_t> SemanticsIDs;
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
- isThunk, isGlobal, inlineStrategy, effect,
+ isThunk, isGlobal, inlineStrategy,
+ optimizationMode, effect,
numSpecAttrs, hasQualifiedOwnership, funcTyID,
genericEnvID, clangNodeOwnerID, SemanticsIDs);
@@ -474,6 +476,7 @@
SubclassScope::NotApplicable, (Inline_t)inlineStrategy);
fn->setGlobalInit(isGlobal == 1);
fn->setEffectsKind((EffectsKind)effect);
+ fn->setOptimizationMode((OptimizationMode)optimizationMode);
if (clangNodeOwner)
fn->setClangNodeOwner(clangNodeOwner);
for (auto ID : SemanticsIDs) {
@@ -2373,10 +2376,12 @@
TypeID funcTyID;
GenericEnvironmentID genericEnvID;
unsigned rawLinkage, isTransparent, isSerialized, isThunk, isGlobal,
- inlineStrategy, effect, numSpecAttrs, hasQualifiedOwnership;
+ inlineStrategy, optimizationMode, effect, numSpecAttrs,
+ hasQualifiedOwnership;
ArrayRef<uint64_t> SemanticsIDs;
SILFunctionLayout::readRecord(scratch, rawLinkage, isTransparent, isSerialized,
- isThunk, isGlobal, inlineStrategy, effect,
+ isThunk, isGlobal, inlineStrategy,
+ optimizationMode, effect,
numSpecAttrs, hasQualifiedOwnership, funcTyID,
genericEnvID, clangOwnerID, SemanticsIDs);
auto linkage = fromStableSILLinkage(rawLinkage);
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index b861c32..55267a5 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -275,6 +275,7 @@
BCFixed<2>, // thunk/reabstraction_thunk
BCFixed<1>, // global_init
BCFixed<2>, // inlineStrategy
+ BCFixed<2>, // optimizationMode
BCFixed<2>, // side effect info.
BCVBR<8>, // number of specialize attributes
BCFixed<1>, // has qualified ownership
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index d8a586b..333ab8f 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2236,6 +2236,14 @@
return;
}
+ case DAK_Optimize: {
+ auto *theAttr = cast<OptimizeAttr>(DA);
+ auto abbrCode = DeclTypeAbbrCodes[OptimizeDeclAttrLayout::Code];
+ OptimizeDeclAttrLayout::emitRecord(Out, ScratchRecord, abbrCode,
+ (unsigned)theAttr->getMode());
+ return;
+ }
+
case DAK_Effects: {
auto *theAttr = cast<EffectsAttr>(DA);
auto abbrCode = DeclTypeAbbrCodes[EffectsDeclAttrLayout::Code];
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 5b76814..3ecaf0e 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -389,7 +389,8 @@
Out, ScratchRecord, abbrCode, toStableSILLinkage(Linkage),
(unsigned)F.isTransparent(), (unsigned)F.isSerialized(),
(unsigned)F.isThunk(), (unsigned)F.isGlobalInit(),
- (unsigned)F.getInlineStrategy(), (unsigned)F.getEffectsKind(),
+ (unsigned)F.getInlineStrategy(), (unsigned)F.getOptimizationMode(),
+ (unsigned)F.getEffectsKind(),
(unsigned)numSpecAttrs, (unsigned)F.hasQualifiedOwnership(), FnID,
genericEnvID, clangNodeOwnerID, SemanticsIDs);
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 1c80bee..4acef87 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -23,6 +23,8 @@
namespace {
static bool isTrivialSyntaxKind(SyntaxKind Kind) {
+ if (isUnknownKind(Kind))
+ return true;
if (isCollectionKind(Kind))
return true;
switch(Kind) {
diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb
index f57d2361..6a954e6 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -69,6 +69,20 @@
llvm_unreachable("not collection kind.");
}
+std::pair<unsigned, unsigned>
+SyntaxFactory::countChildren(SyntaxKind Kind){
+ switch(Kind) {
+% for node in SYNTAX_NODES:
+ case SyntaxKind::${node.syntax_kind}:
+% child_count = len(node.children)
+% non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.children)
+ return {${non_optional_child_count}, ${child_count}};
+% end
+ default:
+ llvm_unreachable("bad syntax kind.");
+ }
+}
+
Optional<Syntax>
SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements) {
switch(Kind) {
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index da98f2c..af28b2c 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -111,8 +111,8 @@
}
// Squash N syntax nodex from the back of the pending list into one.
- void createFromBackTokens(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
- unsigned N);
+ void createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
+ unsigned N);
void createWhole(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse);
std::vector<RawSyntaxInfo> collectAllSyntax(SourceLoc EndLoc);
ArrayRef<RawSyntaxInfo> allTokens() const { return Tokens; }
@@ -123,6 +123,7 @@
assert(Info.isImplicit() || PendingSyntax.empty() ||
PendingSyntax.back().getStartLoc().getOpaquePointerValue() <
Info.getStartLoc().getOpaquePointerValue());
+ assert(!Info.RawNode->isToken() && "Pending syntax should not have tokens");
PendingSyntax.push_back(Info);
}
@@ -212,11 +213,23 @@
}
void SyntaxParsingContext::ContextInfo::
-createFromBackTokens(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> UsedTokens,
- unsigned N) {
- auto Size = UsedTokens.size();
+createPartiallyFromBack(SyntaxKind Kind, ArrayRef<RawSyntaxInfo> NodesToUse,
+ unsigned N) {
+ auto Size = NodesToUse.size();
assert(N && Size >= N);
- auto Parts = llvm::makeArrayRef(UsedTokens).slice(Size - N);
+ auto Parts = llvm::makeArrayRef(NodesToUse).slice(Size - N);
+
+ // Count the parts from the pending syntax list.
+ unsigned UsedPending = std::accumulate(Parts.begin(), Parts.end(), 0,
+ [](unsigned Count, RawSyntaxInfo Info) {
+ return Count += Info.RawNode->isToken() ? 0 : 1;
+ });
+
+ // Remove all pending syntax ndoes that we used to create the new node.
+ for (unsigned I = 0; I < UsedPending; I ++)
+ PendingSyntax.pop_back();
+
+ // Add result to the pending syntax list.
addPendingSyntax(createSyntaxAs(Parts, Kind));
}
@@ -282,15 +295,15 @@
}
void SyntaxParsingContextChild::setSyntaxKind(SyntaxKind SKind) {
- assert(!ContextKind.hasValue());
- assert(!KnownSyntax.hasValue());
+ assert(!KnownSyntax.hasValue() && "reset");
KnownSyntax = SKind;
+ ContextKind = None;
}
void SyntaxParsingContextChild::setContextKind(SyntaxContextKind CKind) {
- assert(!ContextKind.hasValue());
- assert(!KnownSyntax.hasValue());
+ assert(!ContextKind.hasValue() && "reset");
ContextKind = CKind;
+ KnownSyntax = None;
}
SyntaxParsingContextChild::
@@ -300,12 +313,12 @@
disable();
}
-void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc LastTokLoc) {
+void SyntaxParsingContextChild::makeNode(SyntaxKind Kind, SourceLoc EndLoc) {
assert(isTopOfContextStack());
if (!ContextData.Enabled)
return;
- auto UsedTokens = ContextData.dropTokenAt(LastTokLoc);
- UsedTokens = llvm::makeArrayRef(UsedTokens.data(), UsedTokens.size() + 1);
+
+ auto AllNodes = ContextData.collectAllSyntax(EndLoc);
// Create syntax nodes according to the given kind.
switch (Kind) {
@@ -313,15 +326,17 @@
case SyntaxKind::IntegerLiteralExpr: {
// Integer may include the signs before the digits, so check if the sign
// exists and create.
- ContextData.createFromBackTokens(Kind, UsedTokens, ContextData.
- checkTokenFromBack(tok::oper_prefix, UsedTokens, 1) ? 2 : 1);
+ ContextData.createPartiallyFromBack(Kind, AllNodes, ContextData.
+ checkTokenFromBack(tok::oper_prefix, AllNodes, 1) ? 2 : 1);
break;
}
+ case SyntaxKind::TernaryExpr:
case SyntaxKind::StringLiteralExpr: {
- ContextData.createFromBackTokens(Kind, UsedTokens, 1);
+ auto Pair = SyntaxFactory::countChildren(Kind);
+ assert(Pair.first == Pair.second);
+ ContextData.createPartiallyFromBack(Kind, AllNodes, Pair.first);
break;
}
-
default:
llvm_unreachable("Unrecognized node kind.");
}
@@ -334,6 +349,7 @@
auto EndLoc = Tok.getLoc();
auto AllNodes = ContextData.collectAllSyntax(EndLoc);
switch (Kind) {
+ case SyntaxKind::BooleanLiteralExpr:
case SyntaxKind::NilLiteralExpr:
case SyntaxKind::DiscardAssignmentExpr:
case SyntaxKind::IdentifierExpr:
@@ -386,8 +402,21 @@
assert(RawNode->isStmt());
break;
}
- case SyntaxContextKind::Decl:
+ case SyntaxContextKind::Decl: {
+ if (!RawNode->isDecl()) {
+ RawNode = makeUnknownSyntax(SyntaxKind::UnknownDecl,
+ {make<Syntax>(RawNode)}).getRaw();
+ }
+ assert(RawNode->isDecl());
+ break;
+ }
+
case SyntaxContextKind::Expr:
+ if (!RawNode->isExpr()) {
+ RawNode = makeUnknownSyntax(SyntaxKind::UnknownExpr,
+ {make<Syntax>(RawNode)}).getRaw();
+ }
+ assert(RawNode->isExpr());
break;
}
}
diff --git a/stdlib/public/SDK/Foundation/JSONEncoder.swift b/stdlib/public/SDK/Foundation/JSONEncoder.swift
index 9901552..a8d5e6a 100644
--- a/stdlib/public/SDK/Foundation/JSONEncoder.swift
+++ b/stdlib/public/SDK/Foundation/JSONEncoder.swift
@@ -867,8 +867,8 @@
}
let decoder = _JSONDecoder(referencing: topLevel, options: self.options)
- guard let value = try decoder.unbox(topLevel, as: T.self) else {
- throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
+ guard let value = try decoder.unbox(topLevel, as: type) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
@@ -1236,7 +1236,7 @@
self.decoder.codingPath.append(key)
defer { self.decoder.codingPath.removeLast() }
- guard let value = try self.decoder.unbox(entry, as: T.self) else {
+ guard let value = try self.decoder.unbox(entry, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
}
@@ -1575,7 +1575,7 @@
self.decoder.codingPath.append(_JSONKey(index: self.currentIndex))
defer { self.decoder.codingPath.removeLast() }
- guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+ guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_JSONKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
@@ -1734,8 +1734,8 @@
}
public func decode<T : Decodable>(_ type: T.Type) throws -> T {
- try expectNonNull(T.self)
- return try self.unbox(self.storage.topContainer, as: T.self)!
+ try expectNonNull(type)
+ return try self.unbox(self.storage.topContainer, as: type)!
}
}
@@ -2094,13 +2094,13 @@
fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
let decoded: T
- if T.self == Date.self || T.self == NSDate.self {
+ if type == Date.self || type == NSDate.self {
guard let date = try self.unbox(value, as: Date.self) else { return nil }
decoded = date as! T
- } else if T.self == Data.self || T.self == NSData.self {
+ } else if type == Data.self || type == NSData.self {
guard let data = try self.unbox(value, as: Data.self) else { return nil }
decoded = data as! T
- } else if T.self == URL.self || T.self == NSURL.self {
+ } else if type == URL.self || type == NSURL.self {
guard let urlString = try self.unbox(value, as: String.self) else {
return nil
}
@@ -2111,12 +2111,12 @@
}
decoded = (url as! T)
- } else if T.self == Decimal.self || T.self == NSDecimalNumber.self {
+ } else if type == Decimal.self || type == NSDecimalNumber.self {
guard let decimal = try self.unbox(value, as: Decimal.self) else { return nil }
decoded = decimal as! T
} else {
self.storage.push(container: value)
- decoded = try T(from: self)
+ decoded = try type.init(from: self)
self.storage.popContainer()
}
diff --git a/stdlib/public/SDK/Foundation/PlistEncoder.swift b/stdlib/public/SDK/Foundation/PlistEncoder.swift
index 059e237..9544870 100644
--- a/stdlib/public/SDK/Foundation/PlistEncoder.swift
+++ b/stdlib/public/SDK/Foundation/PlistEncoder.swift
@@ -612,7 +612,7 @@
/// - throws: An error if any value throws an error during decoding.
open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
var format: PropertyListSerialization.PropertyListFormat = .binary
- return try decode(T.self, from: data, format: &format)
+ return try decode(type, from: data, format: &format)
}
/// Decodes a top-level value of the given type from the given property list representation.
@@ -631,7 +631,7 @@
throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not a valid property list.", underlyingError: error))
}
- return try decode(T.self, fromTopLevel: topLevel)
+ return try decode(type, fromTopLevel: topLevel)
}
/// Decodes a top-level value of the given type from the given property list container (top-level array or dictionary).
@@ -643,8 +643,8 @@
/// - throws: An error if any value throws an error during decoding.
internal func decode<T : Decodable>(_ type: T.Type, fromTopLevel container: Any) throws -> T {
let decoder = _PlistDecoder(referencing: container, options: self.options)
- guard let value = try decoder.unbox(container, as: T.self) else {
- throw DecodingError.valueNotFound(T.self, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
+ guard let value = try decoder.unbox(container, as: type) else {
+ throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: [], debugDescription: "The given data did not contain a top-level value."))
}
return value
@@ -1015,7 +1015,7 @@
self.decoder.codingPath.append(key)
defer { self.decoder.codingPath.removeLast() }
- guard let value = try self.decoder.unbox(entry, as: T.self) else {
+ guard let value = try self.decoder.unbox(entry, as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath, debugDescription: "Expected \(type) value but found null instead."))
}
@@ -1354,7 +1354,7 @@
self.decoder.codingPath.append(_PlistKey(index: self.currentIndex))
defer { self.decoder.codingPath.removeLast() }
- guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: T.self) else {
+ guard let decoded = try self.decoder.unbox(self.container[self.currentIndex], as: type) else {
throw DecodingError.valueNotFound(type, DecodingError.Context(codingPath: self.decoder.codingPath + [_PlistKey(index: self.currentIndex)], debugDescription: "Expected \(type) but found null instead."))
}
@@ -1516,8 +1516,8 @@
}
public func decode<T : Decodable>(_ type: T.Type) throws -> T {
- try expectNonNull(T.self)
- return try self.unbox(self.storage.topContainer, as: T.self)!
+ try expectNonNull(type)
+ return try self.unbox(self.storage.topContainer, as: type)!
}
}
@@ -1756,15 +1756,15 @@
fileprivate func unbox<T : Decodable>(_ value: Any, as type: T.Type) throws -> T? {
let decoded: T
- if T.self == Date.self || T.self == NSDate.self {
+ if type == Date.self || type == NSDate.self {
guard let date = try self.unbox(value, as: Date.self) else { return nil }
decoded = date as! T
- } else if T.self == Data.self || T.self == NSData.self {
+ } else if type == Data.self || type == NSData.self {
guard let data = try self.unbox(value, as: Data.self) else { return nil }
decoded = data as! T
} else {
self.storage.push(container: value)
- decoded = try T(from: self)
+ decoded = try type.init(from: self)
self.storage.popContainer()
}
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index 260d04e..6aa7709 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -1,3 +1,6 @@
+# HACK: Force this library to build with undefined symbols.
+string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
+
# libswiftRemoteMirror.dylib should not have runtime dependencies; it's
# always built as a shared library.
if(SWIFT_BUILD_DYNAMIC_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index 773e7fb..d80b233 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -2181,57 +2181,55 @@
// that are the same, e.g. Array<Int> and Array<Int>, not
// ArraySlice<Int> and Array<Int>.
-/// Returns `true` if these arrays contain the same elements.
-@_inlineable
-public func == <Element : Equatable>(
- lhs: ${Self}<Element>, rhs: ${Self}<Element>
-) -> Bool {
- let lhsCount = lhs.count
- if lhsCount != rhs.count {
- return false
- }
+extension ${Self} : Equatable where Element : Equatable {
+ /// Returns `true` if these arrays contain the same elements.
+ @_inlineable
+ public static func ==(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
+ let lhsCount = lhs.count
+ if lhsCount != rhs.count {
+ return false
+ }
- // Test referential equality.
- if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
+ // Test referential equality.
+ if lhsCount == 0 || lhs._buffer.identity == rhs._buffer.identity {
+ return true
+ }
+
+ %if Self == 'ArraySlice':
+
+ var streamLHS = lhs.makeIterator()
+ var streamRHS = rhs.makeIterator()
+
+ var nextLHS = streamLHS.next()
+ while nextLHS != nil {
+ let nextRHS = streamRHS.next()
+ if nextLHS != nextRHS {
+ return false
+ }
+ nextLHS = streamLHS.next()
+ }
+
+ %else:
+
+ _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
+ _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)
+
+ // We know that lhs.count == rhs.count, compare element wise.
+ for idx in 0..<lhsCount {
+ if lhs[idx] != rhs[idx] {
+ return false
+ }
+ }
+ %end
+
return true
}
-%if Self == 'ArraySlice':
-
- var streamLHS = lhs.makeIterator()
- var streamRHS = rhs.makeIterator()
-
- var nextLHS = streamLHS.next()
- while nextLHS != nil {
- let nextRHS = streamRHS.next()
- if nextLHS != nextRHS {
- return false
- }
- nextLHS = streamLHS.next()
+ /// Returns `true` if the arrays do not contain the same elements.
+ @_inlineable
+ public static func !=(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
+ return !(lhs == rhs)
}
-
-%else:
-
- _sanityCheck(lhs.startIndex == 0 && rhs.startIndex == 0)
- _sanityCheck(lhs.endIndex == lhsCount && rhs.endIndex == lhsCount)
-
- // We know that lhs.count == rhs.count, compare element wise.
- for idx in 0..<lhsCount {
- if lhs[idx] != rhs[idx] {
- return false
- }
- }
-%end
-
- return true
-}
-
-/// Returns `true` if the arrays do not contain the same elements.
-@_inlineable
-public func != <Element : Equatable>(
- lhs: ${Self}<Element>, rhs: ${Self}<Element>
-) -> Bool {
- return !(lhs == rhs)
}
extension ${Self} {
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 9526057..dcad518 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -18,8 +18,7 @@
where
// FIXME(ABI)#176 (Type checker)
// WORKAROUND rdar://25214598 - should be Bound : Strideable
- Bound : _Strideable & Comparable,
- Bound.Stride : BinaryInteger {
+ Bound : _Strideable & Comparable {
case pastEnd
case inRange(Bound)
}
@@ -36,7 +35,7 @@
// CountableClosedRange is not interchangeable with CountableRange in all
// contexts.
Bound : _Strideable & Comparable,
- Bound.Stride : SignedInteger {
+ Bound.Stride : SignedNumeric {
/// Creates the "past the end" position.
@_inlineable
@_versioned
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 3861ca5..79c021f 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -559,11 +559,11 @@
// in angles in the wrong quadrant if users aren't careful. This is
// not a problem for Double or Float80, as pi rounds down in both of
// those formats.
- return Float(0x1.921fb4p1)
+ return 0x1.921fb4p1
%elif bits == 64:
- return Double(0x1.921fb54442d18p1)
+ return 0x1.921fb54442d18p1
%elif bits == 80:
- return Float80(0x1.921fb54442d1846ap1)
+ return 0x1.921fb54442d1846ap1
%end
}
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/HashedCollections.swift.gyb
index 36f88c8..12433e3 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/HashedCollections.swift.gyb
@@ -2708,7 +2708,7 @@
}
}
-extension Dictionary where Value : Equatable {
+extension Dictionary : Equatable where Value : Equatable {
@_inlineable // FIXME(sil-serialize-all)
public static func == (lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
switch (lhs._variantBuffer, rhs._variantBuffer) {
diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift
index 72ce864..459b249 100644
--- a/stdlib/public/core/Optional.swift
+++ b/stdlib/public/core/Optional.swift
@@ -313,98 +313,100 @@
line: UInt(_line))
}
-/// Returns a Boolean value indicating whether two optional instances are
-/// equal.
-///
-/// Use this equal-to operator (`==`) to compare any two optional instances of
-/// a type that conforms to the `Equatable` protocol. The comparison returns
-/// `true` if both arguments are `nil` or if the two arguments wrap values
-/// that are equal. Conversely, the comparison returns `false` if only one of
-/// the arguments is `nil` or if the two arguments wrap values that are not
-/// equal.
-///
-/// let group1 = [1, 2, 3, 4, 5]
-/// let group2 = [1, 3, 5, 7, 9]
-/// if group1.first == group2.first {
-/// print("The two groups start the same.")
-/// }
-/// // Prints "The two groups start the same."
-///
-/// You can also use this operator to compare a non-optional value to an
-/// optional that wraps the same type. The non-optional value is wrapped as an
-/// optional before the comparison is made. In the following example, the
-/// `numberToMatch` constant is wrapped as an optional before comparing to the
-/// optional `numberFromString`:
-///
-/// let numberToFind: Int = 23
-/// let numberFromString: Int? = Int("23") // Optional(23)
-/// if numberToFind == numberFromString {
-/// print("It's a match!")
-/// }
-/// // Prints "It's a match!"
-///
-/// An instance that is expressed as a literal can also be used with this
-/// operator. In the next example, an integer literal is compared with the
-/// optional integer `numberFromString`. The literal `23` is inferred as an
-/// `Int` instance and then wrapped as an optional before the comparison is
-/// performed.
-///
-/// if 23 == numberFromString {
-/// print("It's a match!")
-/// }
-/// // Prints "It's a match!"
-///
-/// - Parameters:
-/// - lhs: An optional value to compare.
-/// - rhs: Another optional value to compare.
-@_inlineable
-public func == <T: Equatable>(lhs: T?, rhs: T?) -> Bool {
- switch (lhs, rhs) {
- case let (l?, r?):
- return l == r
- case (nil, nil):
- return true
- default:
- return false
+extension Optional : Equatable where Wrapped : Equatable {
+ /// Returns a Boolean value indicating whether two optional instances are
+ /// equal.
+ ///
+ /// Use this equal-to operator (`==`) to compare any two optional instances of
+ /// a type that conforms to the `Equatable` protocol. The comparison returns
+ /// `true` if both arguments are `nil` or if the two arguments wrap values
+ /// that are equal. Conversely, the comparison returns `false` if only one of
+ /// the arguments is `nil` or if the two arguments wrap values that are not
+ /// equal.
+ ///
+ /// let group1 = [1, 2, 3, 4, 5]
+ /// let group2 = [1, 3, 5, 7, 9]
+ /// if group1.first == group2.first {
+ /// print("The two groups start the same.")
+ /// }
+ /// // Prints "The two groups start the same."
+ ///
+ /// You can also use this operator to compare a non-optional value to an
+ /// optional that wraps the same type. The non-optional value is wrapped as an
+ /// optional before the comparison is made. In the following example, the
+ /// `numberToMatch` constant is wrapped as an optional before comparing to the
+ /// optional `numberFromString`:
+ ///
+ /// let numberToFind: Int = 23
+ /// let numberFromString: Int? = Int("23") // Optional(23)
+ /// if numberToFind == numberFromString {
+ /// print("It's a match!")
+ /// }
+ /// // Prints "It's a match!"
+ ///
+ /// An instance that is expressed as a literal can also be used with this
+ /// operator. In the next example, an integer literal is compared with the
+ /// optional integer `numberFromString`. The literal `23` is inferred as an
+ /// `Int` instance and then wrapped as an optional before the comparison is
+ /// performed.
+ ///
+ /// if 23 == numberFromString {
+ /// print("It's a match!")
+ /// }
+ /// // Prints "It's a match!"
+ ///
+ /// - Parameters:
+ /// - lhs: An optional value to compare.
+ /// - rhs: Another optional value to compare.
+ @_inlineable
+ public static func ==(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
+ switch (lhs, rhs) {
+ case let (l?, r?):
+ return l == r
+ case (nil, nil):
+ return true
+ default:
+ return false
+ }
}
-}
-
-/// Returns a Boolean value indicating whether two optional instances are not
-/// equal.
-///
-/// Use this not-equal-to operator (`!=`) to compare any two optional instances
-/// of a type that conforms to the `Equatable` protocol. The comparison
-/// returns `true` if only one of the arguments is `nil` or if the two
-/// arguments wrap values that are not equal. The comparison returns `false`
-/// if both arguments are `nil` or if the two arguments wrap values that are
-/// equal.
-///
-/// let group1 = [2, 4, 6, 8, 10]
-/// let group2 = [1, 3, 5, 7, 9]
-/// if group1.first != group2.first {
-/// print("The two groups start differently.")
-/// }
-/// // Prints "The two groups start differently."
-///
-/// You can also use this operator to compare a non-optional value to an
-/// optional that wraps the same type. The non-optional value is wrapped as an
-/// optional before the comparison is made. In this example, the
-/// `numberToMatch` constant is wrapped as an optional before comparing to the
-/// optional `numberFromString`:
-///
-/// let numberToFind: Int = 23
-/// let numberFromString: Int? = Int("not-a-number") // nil
-/// if numberToFind != numberFromString {
-/// print("No match.")
-/// }
-/// // Prints "No match."
-///
-/// - Parameters:
-/// - lhs: An optional value to compare.
-/// - rhs: Another optional value to compare.
-@_inlineable
-public func != <T : Equatable>(lhs: T?, rhs: T?) -> Bool {
- return !(lhs == rhs)
+
+ /// Returns a Boolean value indicating whether two optional instances are not
+ /// equal.
+ ///
+ /// Use this not-equal-to operator (`!=`) to compare any two optional instances
+ /// of a type that conforms to the `Equatable` protocol. The comparison
+ /// returns `true` if only one of the arguments is `nil` or if the two
+ /// arguments wrap values that are not equal. The comparison returns `false`
+ /// if both arguments are `nil` or if the two arguments wrap values that are
+ /// equal.
+ ///
+ /// let group1 = [2, 4, 6, 8, 10]
+ /// let group2 = [1, 3, 5, 7, 9]
+ /// if group1.first != group2.first {
+ /// print("The two groups start differently.")
+ /// }
+ /// // Prints "The two groups start differently."
+ ///
+ /// You can also use this operator to compare a non-optional value to an
+ /// optional that wraps the same type. The non-optional value is wrapped as an
+ /// optional before the comparison is made. In this example, the
+ /// `numberToMatch` constant is wrapped as an optional before comparing to the
+ /// optional `numberFromString`:
+ ///
+ /// let numberToFind: Int = 23
+ /// let numberFromString: Int? = Int("not-a-number") // nil
+ /// if numberToFind != numberFromString {
+ /// print("No match.")
+ /// }
+ /// // Prints "No match."
+ ///
+ /// - Parameters:
+ /// - lhs: An optional value to compare.
+ /// - rhs: Another optional value to compare.
+ @_inlineable
+ public static func !=(lhs: Wrapped?, rhs: Wrapped?) -> Bool {
+ return !(lhs == rhs)
+ }
}
// Enable pattern matching against the nil literal, even if the element type
@@ -418,175 +420,177 @@
}
}
-/// Returns a Boolean value indicating whether an argument matches `nil`.
-///
-/// You can use the pattern-matching operator (`~=`) to test whether an
-/// optional instance is `nil` even when the wrapped value's type does not
-/// conform to the `Equatable` protocol. The pattern-matching operator is used
-/// internally in `case` statements for pattern matching.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type, and then uses a `switch`
-/// statement to determine whether the stream is `nil` or has a configured
-/// value. When evaluating the `nil` case of the `switch` statement, this
-/// operator is called behind the scenes.
-///
-/// var stream: DataStream? = nil
-/// switch stream {
-/// case nil:
-/// print("No data stream is configured.")
-/// case let x?:
-/// print("The data stream has \(x.availableBytes) bytes available.")
-/// }
-/// // Prints "No data stream is configured."
-///
-/// - Note: To test whether an instance is `nil` in an `if` statement, use the
-/// equal-to operator (`==`) instead of the pattern-matching operator. The
-/// pattern-matching operator is primarily intended to enable `case`
-/// statement pattern matching.
-///
-/// - Parameters:
-/// - lhs: A `nil` literal.
-/// - rhs: A value to match against `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func ~= <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
- switch rhs {
- case .some(_):
- return false
- case .none:
- return true
+extension Optional {
+ /// Returns a Boolean value indicating whether an argument matches `nil`.
+ ///
+ /// You can use the pattern-matching operator (`~=`) to test whether an
+ /// optional instance is `nil` even when the wrapped value's type does not
+ /// conform to the `Equatable` protocol. The pattern-matching operator is used
+ /// internally in `case` statements for pattern matching.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type, and then uses a `switch`
+ /// statement to determine whether the stream is `nil` or has a configured
+ /// value. When evaluating the `nil` case of the `switch` statement, this
+ /// operator is called behind the scenes.
+ ///
+ /// var stream: DataStream? = nil
+ /// switch stream {
+ /// case nil:
+ /// print("No data stream is configured.")
+ /// case let x?:
+ /// print("The data stream has \(x.availableBytes) bytes available.")
+ /// }
+ /// // Prints "No data stream is configured."
+ ///
+ /// - Note: To test whether an instance is `nil` in an `if` statement, use the
+ /// equal-to operator (`==`) instead of the pattern-matching operator. The
+ /// pattern-matching operator is primarily intended to enable `case`
+ /// statement pattern matching.
+ ///
+ /// - Parameters:
+ /// - lhs: A `nil` literal.
+ /// - rhs: A value to match against `nil`.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func ~=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+ switch rhs {
+ case .some(_):
+ return false
+ case .none:
+ return true
+ }
}
-}
-// Enable equality comparisons against the nil literal, even if the
-// element type isn't equatable
+ // Enable equality comparisons against the nil literal, even if the
+ // element type isn't equatable
-/// Returns a Boolean value indicating whether the left-hand-side argument is
-/// `nil`.
-///
-/// You can use this equal-to operator (`==`) to test whether an optional
-/// instance is `nil` even when the wrapped value's type does not conform to
-/// the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` is
-/// `nil`.
-///
-/// var stream: DataStream? = nil
-/// if stream == nil {
-/// print("No data stream is configured.")
-/// }
-/// // Prints "No data stream is configured."
-///
-/// - Parameters:
-/// - lhs: A value to compare to `nil`.
-/// - rhs: A `nil` literal.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func == <T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {
- switch lhs {
- case .some(_):
- return false
- case .none:
- return true
+ /// Returns a Boolean value indicating whether the left-hand-side argument is
+ /// `nil`.
+ ///
+ /// You can use this equal-to operator (`==`) to test whether an optional
+ /// instance is `nil` even when the wrapped value's type does not conform to
+ /// the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` is
+ /// `nil`.
+ ///
+ /// var stream: DataStream? = nil
+ /// if stream == nil {
+ /// print("No data stream is configured.")
+ /// }
+ /// // Prints "No data stream is configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A value to compare to `nil`.
+ /// - rhs: A `nil` literal.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func ==(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool {
+ switch lhs {
+ case .some(_):
+ return false
+ case .none:
+ return true
+ }
}
-}
-/// Returns a Boolean value indicating whether the left-hand-side argument is
-/// not `nil`.
-///
-/// You can use this not-equal-to operator (`!=`) to test whether an optional
-/// instance is not `nil` even when the wrapped value's type does not conform
-/// to the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` wraps
-/// a value and is therefore not `nil`.
-///
-/// var stream: DataStream? = fetchDataStream()
-/// if stream != nil {
-/// print("The data stream has been configured.")
-/// }
-/// // Prints "The data stream has been configured."
-///
-/// - Parameters:
-/// - lhs: A value to compare to `nil`.
-/// - rhs: A `nil` literal.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func != <T>(lhs: T?, rhs: _OptionalNilComparisonType) -> Bool {
- switch lhs {
- case .some(_):
- return true
- case .none:
- return false
+ /// Returns a Boolean value indicating whether the left-hand-side argument is
+ /// not `nil`.
+ ///
+ /// You can use this not-equal-to operator (`!=`) to test whether an optional
+ /// instance is not `nil` even when the wrapped value's type does not conform
+ /// to the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` wraps
+ /// a value and is therefore not `nil`.
+ ///
+ /// var stream: DataStream? = fetchDataStream()
+ /// if stream != nil {
+ /// print("The data stream has been configured.")
+ /// }
+ /// // Prints "The data stream has been configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A value to compare to `nil`.
+ /// - rhs: A `nil` literal.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func !=(lhs: Wrapped?, rhs: _OptionalNilComparisonType) -> Bool {
+ switch lhs {
+ case .some(_):
+ return true
+ case .none:
+ return false
+ }
}
-}
-/// Returns a Boolean value indicating whether the right-hand-side argument is
-/// `nil`.
-///
-/// You can use this equal-to operator (`==`) to test whether an optional
-/// instance is `nil` even when the wrapped value's type does not conform to
-/// the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` is
-/// `nil`.
-///
-/// var stream: DataStream? = nil
-/// if nil == stream {
-/// print("No data stream is configured.")
-/// }
-/// // Prints "No data stream is configured."
-///
-/// - Parameters:
-/// - lhs: A `nil` literal.
-/// - rhs: A value to compare to `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func == <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
- switch rhs {
- case .some(_):
- return false
- case .none:
- return true
+ /// Returns a Boolean value indicating whether the right-hand-side argument is
+ /// `nil`.
+ ///
+ /// You can use this equal-to operator (`==`) to test whether an optional
+ /// instance is `nil` even when the wrapped value's type does not conform to
+ /// the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` is
+ /// `nil`.
+ ///
+ /// var stream: DataStream? = nil
+ /// if nil == stream {
+ /// print("No data stream is configured.")
+ /// }
+ /// // Prints "No data stream is configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A `nil` literal.
+ /// - rhs: A value to compare to `nil`.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func ==(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+ switch rhs {
+ case .some(_):
+ return false
+ case .none:
+ return true
+ }
}
-}
-/// Returns a Boolean value indicating whether the right-hand-side argument is
-/// not `nil`.
-///
-/// You can use this not-equal-to operator (`!=`) to test whether an optional
-/// instance is not `nil` even when the wrapped value's type does not conform
-/// to the `Equatable` protocol.
-///
-/// The following example declares the `stream` variable as an optional
-/// instance of a hypothetical `DataStream` type. Although `DataStream` is not
-/// an `Equatable` type, this operator allows checking whether `stream` wraps
-/// a value and is therefore not `nil`.
-///
-/// var stream: DataStream? = fetchDataStream()
-/// if nil != stream {
-/// print("The data stream has been configured.")
-/// }
-/// // Prints "The data stream has been configured."
-///
-/// - Parameters:
-/// - lhs: A `nil` literal.
-/// - rhs: A value to compare to `nil`.
-@_inlineable // FIXME(sil-serialize-all)
-@_transparent
-public func != <T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool {
- switch rhs {
- case .some(_):
- return true
- case .none:
- return false
+ /// Returns a Boolean value indicating whether the right-hand-side argument is
+ /// not `nil`.
+ ///
+ /// You can use this not-equal-to operator (`!=`) to test whether an optional
+ /// instance is not `nil` even when the wrapped value's type does not conform
+ /// to the `Equatable` protocol.
+ ///
+ /// The following example declares the `stream` variable as an optional
+ /// instance of a hypothetical `DataStream` type. Although `DataStream` is not
+ /// an `Equatable` type, this operator allows checking whether `stream` wraps
+ /// a value and is therefore not `nil`.
+ ///
+ /// var stream: DataStream? = fetchDataStream()
+ /// if nil != stream {
+ /// print("The data stream has been configured.")
+ /// }
+ /// // Prints "The data stream has been configured."
+ ///
+ /// - Parameters:
+ /// - lhs: A `nil` literal.
+ /// - rhs: A value to compare to `nil`.
+ @_inlineable // FIXME(sil-serialize-all)
+ @_transparent
+ static public func !=(lhs: _OptionalNilComparisonType, rhs: Wrapped?) -> Bool {
+ switch rhs {
+ case .some(_):
+ return true
+ case .none:
+ return false
+ }
}
}
diff --git a/stdlib/public/core/Stride.swift.gyb b/stdlib/public/core/Stride.swift.gyb
index 74792b6..40e2298 100644
--- a/stdlib/public/core/Stride.swift.gyb
+++ b/stdlib/public/core/Stride.swift.gyb
@@ -274,8 +274,126 @@
public var customMirror: Mirror {
return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
}
+
+ // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+ // here until a proper Collection conformance is possible
+ @_inlineable
+ public var underestimatedCount: Int {
+ var it = self.makeIterator()
+ var count = 0
+ while it.next() != nil {
+ count += 1
+ }
+ return count
+ }
}
+// FIXME(conditional-conformances): these extra types can easily be turned into
+// conditional extensions to StrideTo type
+% for Self, ElementConstraint, Where in [
+% ('IntegerStrideToCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
+% ('FloatingPointStrideToCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
+% ]:
+% ElementIsInteger = ElementConstraint == 'BinaryInteger'
+
+internal struct ${Self}<
+ Element : ${ElementConstraint}
+> : RandomAccessCollection, CustomReflectable
+where ${Where} {
+
+//===----------------------------------------------------------------------===//
+// This block is copied from StrideTo struct definition //
+//===----------------------------------------------------------------------===//
+ @_inlineable
+ public func makeIterator() -> StrideToIterator<Element> {
+ return StrideToIterator(_start: _start, end: _end, stride: _stride)
+ }
+
+ @_inlineable
+ public func _customContainsEquatableElement(
+ _ element: Element
+ ) -> Bool? {
+ if element < _start || _end <= element {
+ return false
+ }
+ return nil
+ }
+
+ @_inlineable
+ @_versioned
+ internal init(_start: Element, end: Element, stride: Element.Stride) {
+ _precondition(stride != 0, "Stride size must not be zero")
+ // At start, striding away from end is allowed; it just makes for an
+ // already-empty Sequence.
+ self._start = _start
+ self._end = end
+ self._stride = stride
+ }
+
+ @_versioned
+ internal let _start: Element
+
+ @_versioned
+ internal let _end: Element
+
+ @_versioned
+ internal let _stride: Element.Stride
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public var customMirror: Mirror {
+ return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
+ }
+//===----------------------------------------------------------------------===//
+// The end of the copied block
+//===----------------------------------------------------------------------===//
+
+ // RandomAccessCollection conformance
+ public typealias Index = Int
+ public typealias SubSequence = RandomAccessSlice<${Self}>
+ public typealias Indices = CountableRange<Int>
+
+ public var startIndex: Index { return 0 }
+ public var endIndex: Index { return count }
+
+ public var count: Int {
+ let (start, end, stride) =
+ (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
+% if ElementIsInteger:
+ return Int((start.distance(to: end) - 1) / stride) + 1
+% else:
+ let nonExactCount = (start.distance(to: end)) / stride
+ return Int(nonExactCount.rounded(.toNearestOrAwayFromZero))
+% end
+ }
+
+ public subscript(position: Index) -> Element {
+ _failEarlyRangeCheck(position, bounds: startIndex ..< endIndex)
+ return _indexToElement(position)
+ }
+
+ public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+ _failEarlyRangeCheck(bounds, bounds: startIndex ..< endIndex)
+ return RandomAccessSlice(base: self, bounds: bounds)
+ }
+
+ public func index(after i: Index) -> Index {
+ _failEarlyRangeCheck(i, bounds: startIndex-1 ..< endIndex)
+ return i+1
+ }
+
+ public func index(before i: Index) -> Index {
+ _failEarlyRangeCheck(i, bounds: startIndex+1 ... endIndex)
+ return i-1
+ }
+
+ @inline(__always)
+ internal func _indexToElement(_ i: Index) -> Element {
+ return _start.advanced(by: Element.Stride(i) * _stride)
+ }
+}
+
+% end
+
/// Returns the sequence of values (`self`, `self + stride`, `self +
/// 2 * stride`, ... *last*) where *last* is the last value in the
/// progression that is less than `end`.
@@ -388,8 +506,148 @@
return Mirror(self,
children: ["from": _start, "through": _end, "by": _stride])
}
+
+ // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+ // here until a proper Collection conformance is possible
+ @_inlineable
+ public var underestimatedCount: Int {
+ var it = self.makeIterator()
+ var count = 0
+ while it.next() != nil {
+ count += 1
+ }
+ return count
+ }
}
+// FIXME(conditional-conformances): these extra types can easily be turned into
+// conditional extensions to StrideThrough type
+% for Self, ElementConstraint, Where in [
+% ('IntegerStrideThroughCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
+% ('FloatingPointStrideThroughCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
+% ]:
+% ElementIsInteger = ElementConstraint == 'BinaryInteger'
+
+internal struct ${Self}<
+ Element : ${ElementConstraint}
+> : RandomAccessCollection, CustomReflectable
+where ${Where} {
+
+//===----------------------------------------------------------------------===//
+// This block is copied from StrideThrough struct definition //
+//===----------------------------------------------------------------------===//
+ /// Returns an iterator over the elements of this sequence.
+ ///
+ /// - Complexity: O(1).
+ @_inlineable
+ public func makeIterator() -> StrideThroughIterator<Element> {
+ return StrideThroughIterator(_start: _start, end: _end, stride: _stride)
+ }
+
+ @_inlineable
+ public func _customContainsEquatableElement(
+ _ element: Element
+ ) -> Bool? {
+ if element < _start || _end < element {
+ return false
+ }
+ return nil
+ }
+
+ @_inlineable
+ @_versioned
+ internal init(_start: Element, end: Element, stride: Element.Stride) {
+ _precondition(stride != 0, "Stride size must not be zero")
+ self._start = _start
+ self._end = end
+ self._stride = stride
+ }
+
+ @_versioned
+ internal let _start: Element
+ @_versioned
+ internal let _end: Element
+ @_versioned
+ internal let _stride: Element.Stride
+
+ @_inlineable // FIXME(sil-serialize-all)
+ public var customMirror: Mirror {
+ return Mirror(self,
+ children: ["from": _start, "through": _end, "by": _stride])
+ }
+//===----------------------------------------------------------------------===//
+// The end of the copied block
+//===----------------------------------------------------------------------===//
+
+ // RandomAccessCollection conformance
+ public typealias Index = ClosedRangeIndex<Int>
+ public typealias IndexDistance = Int
+ public typealias SubSequence = RandomAccessSlice<${Self}>
+
+ @_inlineable
+ public var startIndex: Index { return ClosedRangeIndex(0) }
+ @_inlineable
+ public var endIndex: Index { return ClosedRangeIndex() }
+
+ @_inlineable
+ public var count: Int {
+ let (start, end, stride) =
+ (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
+% if ElementIsInteger:
+ return Int(start.distance(to: end) / stride) + 1
+% else:
+ let nonExactCount = start.distance(to: end) / stride
+ return Int(nonExactCount.rounded(.toNearestOrAwayFromZero)) + 1
+% end
+ }
+
+ public subscript(position: Index) -> Element {
+ let offset = Element.Stride(position._dereferenced) * _stride
+ return _start.advanced(by: offset)
+ }
+
+ public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+ return RandomAccessSlice(base: self, bounds: bounds)
+ }
+
+ @_inlineable
+ public func index(before i: Index) -> Index {
+ switch i._value {
+ case .inRange(let n):
+ _precondition(n > 0, "Incrementing past start index")
+ return ClosedRangeIndex(n - 1)
+ case .pastEnd:
+ _precondition(_end >= _start, "Incrementing past start index")
+ return ClosedRangeIndex(count - 1)
+ }
+ }
+
+ @_inlineable
+ public func index(after i: Index) -> Index {
+ switch i._value {
+ case .inRange(let n):
+ return n == (count - 1)
+ ? ClosedRangeIndex()
+ : ClosedRangeIndex(n + 1)
+ case .pastEnd:
+ _preconditionFailure("Incrementing past end index")
+ }
+ }
+
+ // FIXME(ABI)#175 (Type checker)
+ @_inlineable
+ public // WORKAROUND: needed because of rdar://25584401
+ var indices: DefaultRandomAccessIndices<${Self}> {
+ return DefaultRandomAccessIndices(
+ _elements: self,
+ startIndex: self.startIndex,
+ endIndex: self.endIndex)
+ }
+
+}
+
+% end
+
/// Returns the sequence of values (`self`, `self + stride`, `self +
/// 2 * stride`, ... *last*) where *last* is the last value in the
/// progression less than or equal to `end`.
@@ -401,3 +659,4 @@
) -> StrideThrough<T> {
return StrideThrough(_start: start, end: end, stride: stride)
}
+
diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift
index 5b52394..1ba1e45 100644
--- a/test/Constraints/bridging.swift
+++ b/test/Constraints/bridging.swift
@@ -181,8 +181,9 @@
struct NotEquatable {}
func notEquatableError(_ d: Dictionary<Int, NotEquatable>) -> Bool {
// FIXME: Another awful diagnostic.
- return d == d // expected-error{{binary operator '==' cannot be applied to two 'Dictionary<Int, NotEquatable>' operands}}
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+ return d == d // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+ // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+ // expected-note @-2 {{requirement from conditional conformance of 'Dictionary<Int, NotEquatable>' to 'Equatable'}}
}
// NSString -> String
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index b56e228..022c4e1 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -163,9 +163,8 @@
default: break
}
-// <rdar://problem/21995744> QoI: Binary operator '~=' cannot be applied to operands of type 'String' and 'String?'
switch ("foo" as String?) {
-case "what": break // expected-error{{expression pattern of type 'String' cannot match values of type 'String?'}} {{12-12=?}}
+case "what": break
default: break
}
diff --git a/test/Driver/actions.swift b/test/Driver/actions.swift
index cc8ee4d..3e21f12 100644
--- a/test/Driver/actions.swift
+++ b/test/Driver/actions.swift
@@ -28,6 +28,19 @@
// BASICMODULE: 1: compile, {0}, swiftmodule
// BASICMODULE: 2: merge-module, {1}, swiftmodule
+// RUN: touch %t/a.swiftmodule
+// RUN: %swiftc_driver -driver-print-actions -emit-module -module-name foo %s %t/a.swiftmodule 2>&1 | %FileCheck %s -check-prefix=SWIFTMODULE-INPUT
+// SWIFTMODULE-INPUT: 0: input, "{{.*}}actions.swift", swift
+// SWIFTMODULE-INPUT: 1: compile, {0}, swiftmodule
+// SWIFTMODULE-INPUT: 2: input, "{{.*}}a.swiftmodule", swift
+// SWIFTMODULE-INPUT: 3: merge-module, {1, 2}, swiftmodule
+
+// RUN: %swiftc_driver -driver-print-actions -g -emit-module -module-name foo %s %t/a.swiftmodule 2>&1 | %FileCheck %s -check-prefix=SWIFTMODULE-INPUT
+// SWIFTMODULE-DEBUG-INPUT: 0: input, "{{.*}}actions.swift", swift
+// SWIFTMODULE-DEBUG-INPUT: 1: compile, {0}, swiftmodule
+// SWIFTMODULE-DEBUG-INPUT: 2: input, "{{.*}}a.swiftmodule", swift
+// SWIFTMODULE-DEBUG-INPUT: 3: merge-module, {1, 2}, swiftmodule
+
// RUN: %swiftc_driver -driver-print-actions -emit-executable -emit-module %s 2>&1 | %FileCheck %s -check-prefix=EXEC-AND-MODULE
// EXEC-AND-MODULE: 0: input, "{{.*}}actions.swift", swift
// EXEC-AND-MODULE: 1: compile, {0}, object
@@ -114,9 +127,8 @@
// DEBUG-LINK-ONLY: 1: input, "{{.*}}/b.o", object
// DEBUG-LINK-ONLY: 2: input, "{{.*}}/a.swiftmodule", swiftmodule
// DEBUG-LINK-ONLY: 3: input, "{{.*}}/b.swiftmodule", swiftmodule
-// DEBUG-LINK-ONLY: 4: merge-module, {2, 3}, swiftmodule
-// DEBUG-LINK-ONLY: 5: link, {0, 1, 4}, image
-// DEBUG-LINK-ONLY: 6: generate-dSYM, {5}, dSYM
+// DEBUG-LINK-ONLY: 4: link, {0, 1, 2, 3}, image
+// DEBUG-LINK-ONLY: 5: generate-dSYM, {4}, dSYM
// RUN: touch %t/c.swift
// RUN: %swiftc_driver -driver-print-actions %t/c.swift %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=LINK-SWIFTMODULES
@@ -128,6 +140,16 @@
// LINK-SWIFTMODULES: 5: input, "{{.*}}/b.swiftmodule", swiftmodule
// LINK-SWIFTMODULES: 6: link, {1, 2, 3, 4, 5}, image
+// RUN: %swiftc_driver -driver-print-actions -g %t/c.swift %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=LINK-DEBUG-SWIFTMODULES
+// LINK-DEBUG-SWIFTMODULES: 0: input, "{{.*}}/c.swift", swift
+// LINK-DEBUG-SWIFTMODULES: 1: compile, {0}, object
+// LINK-DEBUG-SWIFTMODULES: 2: input, "{{.*}}/a.o", object
+// LINK-DEBUG-SWIFTMODULES: 3: input, "{{.*}}/b.o", object
+// LINK-DEBUG-SWIFTMODULES: 4: input, "{{.*}}/a.swiftmodule", swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 5: input, "{{.*}}/b.swiftmodule", swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 6: merge-module, {1}, swiftmodule
+// LINK-DEBUG-SWIFTMODULES: 7: link, {1, 2, 3, 4, 5, 6}, image
+
// RUN: touch %t/a.o %t/b.o
// RUN: %swiftc_driver -driver-print-actions %t/a.o %s -o main 2>&1 | %FileCheck %s -check-prefix=COMPILE-PLUS-OBJECT
// COMPILE-PLUS-OBJECT: 0: input, "{{.*}}/a.o", object
diff --git a/test/Driver/bindings.swift b/test/Driver/bindings.swift
index 423c61b..c516545 100644
--- a/test/Driver/bindings.swift
+++ b/test/Driver/bindings.swift
@@ -50,5 +50,5 @@
// RUN: touch %t/a.swiftmodule %t/b.swiftmodule
// RUN: %swiftc_driver -driver-print-bindings -target x86_64-apple-macosx10.9 -g %t/a.o %t/b.o %t/a.swiftmodule %t/b.swiftmodule -o main 2>&1 | %FileCheck %s -check-prefix=DEBUG-LINK-ONLY
-// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "swift", inputs: ["{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {swiftmodule: "[[MERGED:.+\.swiftmodule]]", swiftdoc: "{{.+}}.swiftdoc"}
-// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "[[MERGED]]"], output: {image: "main"}
+// DEBUG-LINK-ONLY-NOT: "swift"
+// DEBUG-LINK-ONLY: # "x86_64-apple-macosx10.9" - "ld", inputs: ["{{.*}}/a.o", "{{.*}}/b.o", "{{.*}}/a.swiftmodule", "{{.*}}/b.swiftmodule"], output: {image: "main"}
diff --git a/test/Driver/filelists.swift b/test/Driver/filelists.swift
index a5e605d..6d9132e 100644
--- a/test/Driver/filelists.swift
+++ b/test/Driver/filelists.swift
@@ -42,8 +42,8 @@
// RUN: ls %t/tmp-crash/sources-* %t/tmp-crash/outputs-*
-// RUN: (cd %t && env PATH=%t/bin/:$PATH %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
-// RUN: (cd %t && env PATH=%t/bin/:$PATH %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json -force-single-frontend-invocation -num-threads 1 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
+// RUN: (cd %t && env PATH="%t/bin/:$PATH" %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
+// RUN: (cd %t && env PATH="%t/bin/:$PATH" %swiftc_driver_plain -driver-use-frontend-path %S/Inputs/filelists/check-filelist-abc.py -emit-library ./a.swift ./b.swift ./c.swift -module-name main -target x86_64-apple-macosx10.9 -driver-use-filelists -output-file-map=%S/Inputs/filelists/output.json -force-single-frontend-invocation -num-threads 1 2>&1 | %FileCheck -check-prefix=CHECK-LINK %s)
// CHECK-LINK: Handled link
diff --git a/test/Driver/opt-remark.swift b/test/Driver/opt-remark.swift
index 433a607..aa2fb52 100644
--- a/test/Driver/opt-remark.swift
+++ b/test/Driver/opt-remark.swift
@@ -38,7 +38,7 @@
func foo() {
// REMARK_MISSED-NOT: remark: {{.*}} inlined
- // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline (cost = {{.*}}, benefit = {{.*}})
+ // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline function "big()" (cost = {{.*}}, benefit = {{.*}})
// REMARK_MISSED-NOT: remark: {{.*}} inlined
big()
// REMARK_PASSED-NOT: remark: Not profitable
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 3e206bd..6e32e9c 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -15,7 +15,7 @@
protocol Assoc { associatedtype AT }
func takes_P2<X: P2>(_: X) {}
-// expected-note@-1{{in call to function 'takes_P2'}}
+
// expected-note@-2{{candidate requires that the types 'U' and 'V' be equivalent (requirement specified as 'U' == 'V')}}
// expected-note@-3{{requirement from conditional conformance of 'SameTypeGeneric<U, V>' to 'P2'}}
// expected-note@-4{{candidate requires that the types 'U' and 'Int' be equivalent (requirement specified as 'U' == 'Int')}}
@@ -91,13 +91,8 @@
// CHECK-NEXT: (normal_conformance type=SameType<Int> protocol=P2
// CHECK-NEXT: same_type: τ_0_0 Int)
extension SameType: P2 where T == Int {}
-// FIXME: the compiler gets this... exactly backwards. :( For the incorrectly
-// accepted cases, it seems the compiler ends up with a (specialized_conformance
-// type=SameType<Float> ... same_type: Int Int ...) for the (normal_conformance
-// type=SameType<Int> ...).
func same_type_good() {
takes_P2(SameType<Int>())
- // expected-error@-1{{generic parameter 'X' could not be inferred}}
}
func same_type_bad<U>(_: U) {
takes_P2(SameType<U>())
diff --git a/test/Generics/conditional_conformances_operators.swift b/test/Generics/conditional_conformances_operators.swift
new file mode 100644
index 0000000..91b6a54
--- /dev/null
+++ b/test/Generics/conditional_conformances_operators.swift
@@ -0,0 +1,17 @@
+// RUN: %target-typecheck-verify-swift -typecheck %s -verify
+
+// rdar://problem/35480952
+
+postfix operator %%%
+protocol P {
+ static postfix func %%%(lhs: Self)
+}
+protocol Q {}
+struct Foo<T> {}
+extension Foo: P where T : Q {
+ static postfix func %%%(lhs: Foo<T>) {}
+}
+
+func useIt<T: Q>(_: T.Type) {
+ Foo<T>()%%%
+}
diff --git a/test/IRGen/sil_linkage.sil b/test/IRGen/sil_linkage.sil
index f0f3149..0fdbe7a 100644
--- a/test/IRGen/sil_linkage.sil
+++ b/test/IRGen/sil_linkage.sil
@@ -3,7 +3,7 @@
sil_stage canonical
// CHECK: define{{( protected)?}} swiftcc void @public_fragile_function_test() {{.*}} {
-// CHECK: define{{( protected)?}} internal swiftcc void @public_transparent_fragile_function_test() {{.*}} {
+// CHECK: define{{( protected)?}} swiftcc void @public_transparent_fragile_function_test() {{.*}} {
// CHECK: define{{( protected)?}} swiftcc void @public_transparent_function_test() {{.*}} {
// CHECK: define{{( hidden)?}} swiftcc void @hidden_fragile_function_test() {{.*}} {
// CHECK: define linkonce_odr hidden swiftcc void @shared_fragile_function_test() {{.*}} {
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index 6bc6a0d..dd3f35f 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -144,7 +144,7 @@
}
enum ExpressibleByRawTypeNotLiteral : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
- // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}} expected-error@-1 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
+ // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
case Ladd, Elliott, Sixteenth, Harrison
}
diff --git a/test/Parse/pointer_conversion.swift.gyb b/test/Parse/pointer_conversion.swift.gyb
index dae6ff8..69741eb 100644
--- a/test/Parse/pointer_conversion.swift.gyb
+++ b/test/Parse/pointer_conversion.swift.gyb
@@ -291,8 +291,10 @@
func arrayComparison(_ x: [NotEquatable], y: [NotEquatable], p: UnsafeMutablePointer<NotEquatable>) {
var x = x
// Don't allow implicit array-to-pointer conversions in operators.
- let a: Bool = x == y // expected-error{{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists:}}
+ // FIXME: The use of <Self: Equatable> in this diagnostic is awful.
+ let a: Bool = x == y // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+ // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+ // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
let _: Bool = p == &x // Allowed!
}
diff --git a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
index 2d59069..456b446 100644
--- a/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
+++ b/test/SILGen/Inputs/usr/include/BridgeTestFoundation.h
@@ -93,3 +93,5 @@
@interface ObjectWithSplitProperty : NSObject
@property (nonatomic, setter=private_setFlagForSomething:) BOOL flagForSomething;
@end
+
+extern NSString * __nonnull (^ const __nonnull GlobalBlock)(NSString * __nonnull);
diff --git a/test/SILGen/functions.swift b/test/SILGen/functions.swift
index 300bf99..d8d9294 100644
--- a/test/SILGen/functions.swift
+++ b/test/SILGen/functions.swift
@@ -452,6 +452,37 @@
func alwaysInlined() {}
}
+// CHECK-LABEL: sil hidden [Onone] @_T09functions10onone_funcyyF : $@convention(thin) () -> ()
+@_optimize(none)
+func onone_func() {}
+
+// CHECK-LABEL: sil hidden [Ospeed] @_T09functions11ospeed_funcyyF : $@convention(thin) () -> ()
+@_optimize(speed)
+func ospeed_func() {}
+
+// CHECK-LABEL: sil hidden [Osize] @_T09functions10osize_funcyyF : $@convention(thin) () -> ()
+@_optimize(size)
+func osize_func() {}
+
+struct OptmodeTestStruct {
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructV3fooyyF :
+ @_optimize(speed)
+ func foo() { }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructVACycfC :
+ @_optimize(speed)
+ init() { }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructV1xBi64_vg :
+ @_optimize(speed)
+ var x: Int { return getInt() }
+
+ // CHECK-LABEL: sil hidden [Ospeed] @_T09functions17OptmodeTestStructVBi64_Bi64_cig :
+ @_optimize(speed)
+ subscript(l: Int) -> Int { return getInt() }
+}
+
// CHECK-LABEL: sil hidden [_semantics "foo"] @_T09functions9semanticsyyF : $@convention(thin) () -> ()
@_semantics("foo")
func semantics() {}
diff --git a/test/SILGen/objc_blocks_bridging.swift b/test/SILGen/objc_blocks_bridging.swift
index cb3ef59..08b07c3 100644
--- a/test/SILGen/objc_blocks_bridging.swift
+++ b/test/SILGen/objc_blocks_bridging.swift
@@ -188,3 +188,11 @@
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0Ix_Ixx_IyB_IyBy_TR : $@convention(c) (@inout_aliasable @block_storage @noescape @callee_owned (@owned @noescape @callee_owned () -> ()) -> (), @convention(block) @noescape () -> ()) -> ()
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] @_T0IyB_Ix_TR : $@convention(thin) (@owned @convention(block) @noescape () -> ()) -> ()
+// rdar://35402696
+func takeOptStringFunction(fn: (String) -> String?) {}
+func testGlobalBlock() {
+ takeOptStringFunction(fn: GlobalBlock)
+}
+// CHECK-LABEL: sil hidden @_T020objc_blocks_bridging15testGlobalBlockyyF
+// CHECK: global_addr @GlobalBlock : $*@convention(block) (NSString) -> @autoreleased Optional<NSString>
+// CHECK: function_ref @_T0So8NSStringCABSgIeyBya_S2SIexxo_TR : $@convention(thin) (@owned String, @owned @convention(block) (NSString) -> @autoreleased Optional<NSString>) -> @owned String
diff --git a/test/SILGen/objc_bridging_any.swift b/test/SILGen/objc_bridging_any.swift
index d45f33c..4b1006a 100644
--- a/test/SILGen/objc_bridging_any.swift
+++ b/test/SILGen/objc_bridging_any.swift
@@ -738,6 +738,16 @@
}
}
+// CHECK-LABEL: sil hidden @_T017objc_bridging_any33bridgeOptionalFunctionToAnyObjectyXlyycSg2fn_tF : $@convention(thin) (@owned Optional<@callee_owned () -> ()>) -> @owned AnyObject
+// CHECK: [[BRIDGE:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
+// CHECK: [[FN:%.*]] = function_ref @_T0Iex_ytytIexir_TR
+// CHECK: partial_apply [[FN]]
+// CHECK: [[SELF:%.*]] = alloc_stack $Optional<@callee_owned (@in ()) -> @out ()>
+// CHECK: apply [[BRIDGE]]<() -> ()>([[SELF]])
+func bridgeOptionalFunctionToAnyObject(fn: (() -> ())?) -> AnyObject {
+ return fn as AnyObject
+}
+
// CHECK-LABEL: sil_witness_table shared [serialized] GenericOption: Hashable module objc_generics {
// CHECK-NEXT: base_protocol Equatable: GenericOption: Equatable module objc_generics
// CHECK-NEXT: method #Hashable.hashValue!getter.1: {{.*}} : @_T0SC13GenericOptionVs8Hashable13objc_genericssACP9hashValueSivgTW
diff --git a/test/SILGen/protocols.swift b/test/SILGen/protocols.swift
index 2f6570d..17af5ad 100644
--- a/test/SILGen/protocols.swift
+++ b/test/SILGen/protocols.swift
@@ -26,10 +26,10 @@
// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*SubscriptableGet to $*[[OPENED:@opened(.*) SubscriptableGet]]
// CHECK: [[ALLOCSTACK:%[0-9]+]] = alloc_stack $[[OPENED]]
// CHECK: copy_addr [[PROJ]] to [initialization] [[ALLOCSTACK]] : $*[[OPENED]]
+// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGet
// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #SubscriptableGet.subscript!getter.1
// CHECK-NEXT: [[RESULT:%[0-9]+]] = apply [[METH]]<[[OPENED]]>(%0, [[ALLOCSTACK]])
// CHECK-NEXT: destroy_addr [[ALLOCSTACK]]
-// CHECK-NEXT: end_access [[READ]] : $*SubscriptableGet
// CHECK-NEXT: dealloc_stack [[ALLOCSTACK]] : $*[[OPENED]]
// CHECK-NEXT: return [[RESULT]]
@@ -133,6 +133,7 @@
// CHECK: [[PROJ:%[0-9]+]] = open_existential_addr immutable_access [[READ]] : $*PropertyWithGetter to $*[[OPENED:@opened(.*) PropertyWithGetter]]
// CHECK: [[COPY:%.*]] = alloc_stack $[[OPENED]]
// CHECK-NEXT: copy_addr [[PROJ]] to [initialization] [[COPY]] : $*[[OPENED]]
+// CHECK-NEXT: end_access [[READ]] : $*PropertyWithGetter
// CHECK-NEXT: [[METH:%[0-9]+]] = witness_method $[[OPENED]], #PropertyWithGetter.a!getter.1
// CHECK-NEXT: apply [[METH]]<[[OPENED]]>([[COPY]])
diff --git a/test/SILOptimizer/access_enforcement_selection.sil b/test/SILOptimizer/access_enforcement_selection.sil
index dbf440e..ed69a81 100644
--- a/test/SILOptimizer/access_enforcement_selection.sil
+++ b/test/SILOptimizer/access_enforcement_selection.sil
@@ -180,3 +180,39 @@
%closure = partial_apply %f(%var) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
unreachable
}
+
+// Borrowed closure can be statically checked.
+//
+// CHECK-LABEL: sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+// CHECK: begin_access [read] [static]
+// CHECK-LABEL: } // end sil function 'borrowedClosure'
+sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
+bb0(%0 : $*Builtin.Int64):
+ %access = begin_access [read] [unknown] %0 : $*Builtin.Int64
+ %val = load [trivial] %access : $*Builtin.Int64
+ end_access %access : $*Builtin.Int64
+ %empty = tuple ()
+ return %empty : $()
+}
+
+// Borrow an escaping closure. The closure body will be dynamically checked.
+sil @borrowClosure : $@convention(thin) () -> () {
+ %box = alloc_box ${ var Builtin.Int64 }, var, name "x"
+ %addr = project_box %box : ${ var Builtin.Int64 }, 0
+ // box escapes.
+ %copy = copy_value %box : ${ var Builtin.Int64 }
+
+ %f = function_ref @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+ %closure = partial_apply %f(%addr) : $@convention(thin) (@inout_aliasable Builtin.Int64) -> ()
+
+ // closure is borrowed.
+ %borrow = begin_borrow %closure : $@callee_owned () -> ()
+ %closure_copy = copy_value %borrow : $@callee_owned () -> ()
+ end_borrow %borrow from %closure : $@callee_owned () -> (), $@callee_owned () -> ()
+
+ destroy_value %closure_copy : $@callee_owned () -> ()
+ destroy_value %copy : ${ var Builtin.Int64 }
+ destroy_value %box : ${ var Builtin.Int64 }
+ %empty = tuple ()
+ return %empty : $()
+}
diff --git a/test/SILOptimizer/devirt_static_covariant_return.swift b/test/SILOptimizer/devirt_static_covariant_return.swift
new file mode 100644
index 0000000..fa52598
--- /dev/null
+++ b/test/SILOptimizer/devirt_static_covariant_return.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -O -whole-module-optimization %s -emit-sil -sil-verify-all | %FileCheck %s
+
+// CHECK-NOT: class_method
+
+// Static method returning Self in generic class
+public class Factory<T> {
+ public required init() {}
+
+ @inline(never) class func bar() -> Self {
+ return self.init()
+ }
+
+ @inline(never) class func foo() -> Self {
+ return bar()
+ }
+}
+
+public func foo(m: Factory<Int>.Type) {
+ m.foo()
+}
diff --git a/test/SILOptimizer/inliner_coldblocks.sil b/test/SILOptimizer/inliner_coldblocks.sil
index 6b378df..58d5c68 100644
--- a/test/SILOptimizer/inliner_coldblocks.sil
+++ b/test/SILOptimizer/inliner_coldblocks.sil
@@ -233,17 +233,23 @@
sil @dont_inline_regular_large_callee : $@convention(thin) () -> () {
bb0:
%f = function_ref @regular_large_callee : $@convention(thin) () -> ()
- // REMARKS_MISSED: inliner_coldblocks.sil:252:8: remark: Not profitable to inline (cost = {{.*}}, benefit = {{.*}})
+ // REMARKS_MISSED: inliner_coldblocks.sil:258:8: remark: Not profitable to inline function "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
// YAML: --- !Missed
// YAML-NEXT: Pass: sil-inliner
// YAML-NEXT: Name: NoInlinedCost
// YAML-NEXT: DebugLoc:
// YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
- // YAML-NEXT: Line: 252
+ // YAML-NEXT: Line: 258
// YAML-NEXT: Column: 8
// YAML-NEXT: Function: dont_inline_regular_large_callee
// YAML-NEXT: Args:
- // YAML-NEXT: - String: 'Not profitable to inline (cost = '
+ // YAML-NEXT: - String: 'Not profitable to inline function '
+ // YAML-NEXT: - Callee: '"regular_large_callee"'
+ // YAML-NEXT: DebugLoc:
+ // YAML-NEXT: File: {{.*}}inliner_coldblocks.sil
+ // YAML-NEXT: Line: 162
+ // YAML-NEXT: Column: 6
+ // YAML-NEXT: - String: ' (cost = '
// YAML-NEXT: - Cost: '{{.*}}'
// YAML-NEXT: - String: ', benefit = '
// YAML-NEXT: - Benefit: '{{.*}}'
diff --git a/test/SILOptimizer/mandatory_nil_comparison_inlining.swift b/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
index 425d4a6..8a4665b 100644
--- a/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
+++ b/test/SILOptimizer/mandatory_nil_comparison_inlining.swift
@@ -1,5 +1,6 @@
// RUN: %target-swift-frontend -enable-sil-ownership -sil-verify-all -primary-file %s -module-name=test -emit-sil -o - -verify | %FileCheck %s
+struct X { }
// CHECK-LABEL: sil {{.*}} @{{.*}}generic_func
// CHECK: switch_enum_addr
@@ -11,28 +12,28 @@
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_rhs_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_rhs_nil(x: [Int]?) -> Bool {
+func array_func_rhs_nil(x: [X]?) -> Bool {
return x == nil
}
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_lhs_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_lhs_nil(x: [Int]?) -> Bool {
+func array_func_lhs_nil(x: [X]?) -> Bool {
return nil == x
}
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_rhs_non_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_rhs_non_nil(x: [Int]?) -> Bool {
+func array_func_rhs_non_nil(x: [X]?) -> Bool {
return x != nil
}
// CHECK-LABEL: sil {{.*}} @{{.*}}array_func_lhs_non_nil
// CHECK: switch_enum_addr
// CHECK: return
-func array_func_lhs_non_nil(x: [Int]?) -> Bool {
+func array_func_lhs_non_nil(x: [X]?) -> Bool {
return nil != x
}
diff --git a/test/SILOptimizer/opt_mode.swift b/test/SILOptimizer/opt_mode.swift
new file mode 100644
index 0000000..d2257d7
--- /dev/null
+++ b/test/SILOptimizer/opt_mode.swift
@@ -0,0 +1,51 @@
+// RUN: %target-swift-frontend -primary-file %s -O -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend -primary-file %s -Osize -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend -primary-file %s -O -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
+// RUN: %target-swift-frontend -primary-file %s -Osize -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
+// REQUIRES: swift_stdlib_no_asserts,optimized_stdlib
+
+class A {
+ func foo(_ x: Int) -> Int { return x }
+}
+
+class B : A {
+ override func foo(_ x: Int) -> Int { return x + 1 }
+}
+
+
+func donothing(_ x: Int) -> Int { return x }
+
+// CHECK-LABEL: sil {{.*}} [Ospeed] @{{.*}}test_ospeed
+// CHECK: checked_cast_br
+// CHECK: checked_cast_br
+// CHECK: }
+// CHECK-IR: define hidden {{.*}}test_ospeed{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
+@_optimize(speed)
+func test_ospeed(_ a: A) -> Int {
+ return donothing(a.foo(27))
+}
+
+// CHECK-LABEL: sil {{.*}} [Osize] @{{.*}}test_osize
+// CHECK: [[M:%[0-9]+]] = class_method
+// CHECK: [[A:%[0-9]+]] = apply [[M]]
+// CHECK: return [[A]]
+// CHECK-IR: define hidden {{.*}}test_osize{{.*}} [[SIZE_ATTR:#[0-9]+]]
+@_optimize(size)
+func test_osize(_ a: A) -> Int {
+ return donothing(a.foo(27))
+}
+
+// CHECK-LABEL: sil {{.*}} [Onone] @{{.*}}test_onone
+// CHECK: [[M:%[0-9]+]] = class_method
+// CHECK: [[A:%[0-9]+]] = apply [[M]]
+// CHECK: [[A2:%[0-9]+]] = apply
+// CHECK: return [[A2]]
+// CHECK-IR: define hidden {{.*}}test_onone{{.*}} [[NOSIZE_ATTR:#[0-9]+]]
+@_optimize(none)
+func test_onone(_ a: A) -> Int {
+ return donothing(a.foo(27))
+}
+
+
+// CHECK-IR: attributes [[NOSIZE_ATTR]] = { "
+// CHECK-IR: attributes [[SIZE_ATTR]] = { minsize "
diff --git a/test/SILOptimizer/sil_combine_apply.sil b/test/SILOptimizer/sil_combine_apply.sil
index b7873c1..9751347 100644
--- a/test/SILOptimizer/sil_combine_apply.sil
+++ b/test/SILOptimizer/sil_combine_apply.sil
@@ -497,3 +497,25 @@
bb99:
return %closure : $@callee_guaranteed (@guaranteed C) -> @error Error
}
+
+// Make sure convert_function -> apply does the right thing with metatypes
+class Base {}
+class Derived {}
+
+sil @takesMetatype : $@convention(thin) (@thick Base.Type) -> ()
+
+// CHECK-LABEL: sil @passesMetatype
+// CHECK: [[METATYPE:%.*]] = metatype $@thick Derived.Type
+// CHECK: [[FN:%.*]] = function_ref @takesMetatype
+// CHECK: [[CONVERTED:%.*]] = unchecked_trivial_bit_cast [[METATYPE]] : $@thick Derived.Type to $@thick Base.Type
+// CHECK: [[RESULT:%.*]] = apply [[FN]]([[CONVERTED]])
+
+sil @passesMetatype : $@convention(thin) () -> () {
+bb0:
+ %metatype = metatype $@thick Derived.Type
+ %fn = function_ref @takesMetatype : $@convention(thin) (@thick Base.Type) -> ()
+ %converted = convert_function %fn : $@convention(thin) (@thick Base.Type) -> () to $@convention(thin) (@thick Derived.Type) -> ()
+ %result = apply %converted(%metatype) : $@convention(thin) (@thick Derived.Type) -> ()
+ %return = tuple ()
+ return %return : $()
+}
diff --git a/test/Sema/enum_equatable_hashable.swift b/test/Sema/enum_equatable_hashable.swift
index b5c334d..a915449 100644
--- a/test/Sema/enum_equatable_hashable.swift
+++ b/test/Sema/enum_equatable_hashable.swift
@@ -226,6 +226,18 @@
case end(Int)
}
+// Check the use of conditional conformances.
+enum ArrayOfEquatables : Equatable {
+case only([Int])
+}
+
+struct NotEquatable { }
+
+// FIXME: rdar://problem/35518088 this should fail.
+enum ArrayOfNotEquatables : Equatable {
+case only([NotEquatable])
+}
+
// FIXME: Remove -verify-ignore-unknown.
// <unknown>:0: error: unexpected error produced: invalid redeclaration of 'hashValue'
// <unknown>:0: error: unexpected note produced: candidate has non-matching type '(Foo, Foo) -> Bool'
diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift
index 138f9a9..9793e58 100644
--- a/test/Sema/enum_raw_representable.swift
+++ b/test/Sema/enum_raw_representable.swift
@@ -78,8 +78,6 @@
let a: Int = E.a // expected-error {{cannot convert value of type 'Outer.E' to specified type 'Int'}}
enum E : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
- // expected-error@-1 {{'Outer.E' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
- // expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
case a
}
}
@@ -146,3 +144,10 @@
let _ = choice == "bar"
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{11-11=}} {{17-17=.rawValue}}
}
+
+
+struct NotEquatable { }
+
+enum ArrayOfNewEquatable : Array<NotEquatable> { }
+// expected-error@-1{{raw type 'Array<NotEquatable>' is not expressible by any literal}}
+// expected-error@-2{{'ArrayOfNewEquatable' declares raw type 'Array<NotEquatable>', but does not conform to RawRepresentable and conformance could not be synthesized}}
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 3e8cbdd..60104ea 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -920,6 +920,27 @@
return %2 : $()
}
+// CHECK-LABEL: [Onone] @test_onone : $@convention(thin) () -> ()
+sil [serialized] [Onone] @test_onone : $@convention(thin) () -> () {
+bb0:
+ %2 = tuple ()
+ return %2 : $()
+}
+
+// CHECK-LABEL: [Ospeed] @test_ospeed : $@convention(thin) () -> ()
+sil [serialized] [Ospeed] @test_ospeed : $@convention(thin) () -> () {
+bb0:
+ %2 = tuple ()
+ return %2 : $()
+}
+
+// CHECK-LABEL: [Osize] @test_osize : $@convention(thin) () -> ()
+sil [serialized] [Osize] @test_osize : $@convention(thin) () -> () {
+bb0:
+ %2 = tuple ()
+ return %2 : $()
+}
+
sil [serialized] @takes_unnamed_closure : $@convention(thin) (@callee_owned () -> Int) -> @callee_owned () -> @callee_owned () -> Int
sil [serialized] @takes_int64_float32 : $@convention(thin) (Int, Float32) -> ()
@@ -1420,6 +1441,9 @@
%130 = function_ref @noinline_callee : $@convention(thin) () -> Int
%132 = function_ref @always_inline_callee : $@convention(thin) () -> Int
%131 = function_ref @test_semantics : $@convention(thin) () -> ()
+ %136 = function_ref @test_onone : $@convention(thin) () -> ()
+ %137 = function_ref @test_ospeed : $@convention(thin) () -> ()
+ %138 = function_ref @test_osize : $@convention(thin) () -> ()
%111 = function_ref @test_partial_apply : $@convention(thin) Float32 -> @callee_owned Int -> ()
%113 = function_ref @test_dynamic_lookup_br : $@convention(thin) (AnyObject) -> ()
%115 = function_ref @test_mark_fn_escape : $@convention(thin) () -> ()
diff --git a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
index 7bf9c7a..6eaf68c 100644
--- a/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
+++ b/test/Serialization/Recovery/Inputs/custom-modules/Overrides.h
@@ -115,3 +115,22 @@
//- (nonnull instancetype)initWithValue:(long)value;
#endif
@end
+
+
+#if !BAD
+struct BoxedInt {
+ int value;
+};
+#endif
+
+@interface MethodWithDisappearingType : Object
+#if !BAD
+- (struct BoxedInt)boxItUp;
+#endif
+@end
+
+@interface InitializerWithDisappearingType : Object
+#if !BAD
+- (nonnull instancetype)initWithBoxedInt:(struct BoxedInt)box;
+#endif
+@end
diff --git a/test/Serialization/Recovery/overrides.swift b/test/Serialization/Recovery/overrides.swift
index c0b7b25..486f6c0 100644
--- a/test/Serialization/Recovery/overrides.swift
+++ b/test/Serialization/Recovery/overrides.swift
@@ -311,4 +311,33 @@
// CHECK-RECOVERY-NEXT: /* placeholder for init(value:) */
// CHECK-RECOVERY-NEXT: {{^}$}}
+public class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+ public override func boxItUp() -> BoxedInt { fatalError() }
+}
+
+// CHECK-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-NEXT: override func boxItUp() -> BoxedInt
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E1_MethodWithDisappearingType : MethodWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
+public class E2_InitializerStub : InitializerWithDisappearingType {
+ public init(unrelatedValue: Int) { fatalError() }
+}
+
+// CHECK-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-NEXT: init(unrelatedValue: Int)
+// CHECK-NEXT: init(boxedInt box: BoxedInt)
+// CHECK-NEXT: init()
+// CHECK-NEXT: {{^}$}}
+
+// CHECK-RECOVERY-LABEL: class E2_InitializerStub : InitializerWithDisappearingType {
+// CHECK-RECOVERY-NEXT: init(unrelatedValue: Int)
+// CHECK-RECOVERY-NEXT: /* placeholder for init(boxedInt:) */
+// CHECK-RECOVERY-NEXT: init()
+// CHECK-RECOVERY-NEXT: {{^}$}}
+
#endif // TEST
diff --git a/test/Serialization/serialize_attr.swift b/test/Serialization/serialize_attr.swift
index a062448..0fc5004 100644
--- a/test/Serialization/serialize_attr.swift
+++ b/test/Serialization/serialize_attr.swift
@@ -13,6 +13,27 @@
@_versioned
@_semantics("crazy") func foo() -> Int { return 5}
+// @_optimize
+// -----------------------------------------------------------------------------
+
+//CHECK-DAG: @_optimize(none) func test_onone()
+@_inlineable
+@_versioned
+@_optimize(none)
+func test_onone() -> Int { return 5}
+
+//CHECK-DAG: @_optimize(speed) func test_ospeed()
+@_inlineable
+@_versioned
+@_optimize(speed)
+func test_ospeed() -> Int { return 5}
+
+//CHECK-DAG: @_optimize(size) func test_osize()
+@_inlineable
+@_versioned
+@_optimize(size)
+func test_osize() -> Int { return 5}
+
// @_specialize
// -----------------------------------------------------------------------------
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index e429365..3eb5364 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -1,36 +1,43 @@
-<UnknownDecl>// RUN: %swift-syntax-test -input-source-filename %s -parse-gen > %t
+// RUN: %swift-syntax-test -input-source-filename %s -parse-gen > %t
// RUN: diff -u %s %t
// RUN: %swift-syntax-test -input-source-filename %s -parse-gen -print-node-kind > %t.withkinds
// RUN: diff -u %S/Outputs/round_trip_parse_gen.swift.withkinds %t.withkinds
-class C {<UnknownDecl>
- func bar(_ a: Int) <CodeBlock>{}</CodeBlock></UnknownDecl><UnknownDecl>
- func bar1(_ a: Float) -> Float <CodeBlock>{ <UnknownStmt>return <UnknownExpr><FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr></UnknownExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
- func bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
- func bar3(a: Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
- func bar4(_ a: Int) -> Int <CodeBlock>{ <UnknownStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></UnknownStmt>}</CodeBlock></UnknownDecl><UnknownDecl>
- func foo() <CodeBlock>{<UnknownDecl>
- var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr></UnknownDecl><UnknownDecl>
- var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr></UnknownDecl><UnknownExpr><IdentifierExpr>
- bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
- bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
- bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
- bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><IdentifierExpr>
- bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownDecl>
- var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr></UnknownDecl><UnknownExpr><IdentifierExpr>
- foo</IdentifierExpr>()</UnknownExpr>
- }</CodeBlock></UnknownDecl><UnknownDecl>
+class C {
+ func bar(_ a: Int) <CodeBlock>{}</CodeBlock>
+ func bar1(_ a: Float) -> Float <CodeBlock>{ return <FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr>}</CodeBlock>
+ func bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+ func bar3(a: Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+ func bar4(_ a: Int) -> Int <CodeBlock>{ return <IntegerLiteralExpr>1 </IntegerLiteralExpr>}</CodeBlock>
+ func foo() <CodeBlock>{
+ var a = /*comment*/<StringLiteralExpr>"abc"/*comment*/</StringLiteralExpr>
+ var b = /*comment*/<IntegerLiteralExpr>+2/*comment*/</IntegerLiteralExpr><IdentifierExpr>
+ bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+ bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)
+ var f = /*comments*/<FloatLiteralExpr>+0.1/*comments*/</FloatLiteralExpr><IdentifierExpr>
+ foo</IdentifierExpr>()
+ }</CodeBlock>
- func foo1() <CodeBlock>{<UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<UnknownExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr></UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>b:<UnknownExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>c:<UnknownExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <UnknownExpr><IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><UnknownExpr><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><UnknownExpr><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr></FunctionCallArgument>)</UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr></UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><IntegerLiteralExpr>1</IntegerLiteralExpr>:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>2</IntegerLiteralExpr>:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>3</IntegerLiteralExpr>:<IntegerLiteralExpr>3</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>4</IntegerLiteralExpr>:<IntegerLiteralExpr>4</IntegerLiteralExpr></DictionaryElement>]</DictionaryExpr></UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </ArrayElement><ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </ArrayElement><ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </ArrayElement><ArrayElement><UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></ArrayElement>]</ArrayExpr></UnknownExpr><UnknownExpr><DiscardAssignmentExpr>
- _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr>, </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <UnknownExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</UnknownExpr></DictionaryElement>]</DictionaryExpr></UnknownExpr><UnknownExpr><IdentifierExpr>
- foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)</UnknownExpr>
- }</CodeBlock></UnknownDecl>
-}</UnknownDecl>
+ func foo1() <CodeBlock>{<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>), </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><IntegerLiteralExpr>1</IntegerLiteralExpr>:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>2</IntegerLiteralExpr>:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>3</IntegerLiteralExpr>:<IntegerLiteralExpr>3</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>4</IntegerLiteralExpr>:<IntegerLiteralExpr>4</IntegerLiteralExpr></DictionaryElement>]</DictionaryExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</DictionaryElement>]</DictionaryExpr><IdentifierExpr>
+ foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)
+ }</CodeBlock>
+ func boolAnd() -> Bool <CodeBlock>{ return <BooleanLiteralExpr>true </BooleanLiteralExpr>&& <BooleanLiteralExpr>false </BooleanLiteralExpr>}</CodeBlock>
+ func boolOr() -> Bool <CodeBlock>{ return <BooleanLiteralExpr>true </BooleanLiteralExpr>|| <BooleanLiteralExpr>false </BooleanLiteralExpr>}</CodeBlock>
+
+ func foo2() <CodeBlock>{<DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr><DiscardAssignmentExpr>
+ _ </DiscardAssignmentExpr>= <TernaryExpr>(<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) ? (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) : (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>)</TernaryExpr>
+ }</CodeBlock>
+}
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 010c211..a9d72bb 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -33,4 +33,11 @@
_ = ["a": bar3(a:1), "b": bar3(a:1), "c": bar3(a:1), "d": bar3(a:1)]
foo(nil, nil, nil)
}
+ func boolAnd() -> Bool { return true && false }
+ func boolOr() -> Bool { return true || false }
+
+ func foo2() {
+ _ = true ? 1 : 0
+ _ = (true ? 1 : 0) ? (true ? 1 : 0) : (true ? 1 : 0)
+ }
}
diff --git a/test/attr/attr_inlineable.swift b/test/attr/attr_inlineable.swift
index d675917..4dc3a491 100644
--- a/test/attr/attr_inlineable.swift
+++ b/test/attr/attr_inlineable.swift
@@ -24,10 +24,10 @@
public init() {}
@_inlineable public var storedProperty: Int
- // expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
+ // expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
@_inlineable public lazy var lazyProperty: Int = 0
- // expected-error@-1 {{'@_inlineable' attribute cannot be applied to stored properties}}
+ // expected-error@-1 {{@_inlineable cannot be applied to stored properties}}
}
public struct Struct {
diff --git a/test/attr/attributes.swift b/test/attr/attributes.swift
index 966ae39..993b5fe 100644
--- a/test/attr/attributes.swift
+++ b/test/attr/attributes.swift
@@ -215,6 +215,11 @@
@inline(__always) class FooClass2 { // expected-error {{@inline(__always) cannot be applied to this declaration}} {{1-19=}}
}
+@_optimize(speed) func OspeedFunc() {}
+@_optimize(speed) var OpeedVar : Int // expected-error {{@_optimize(speed) cannot be applied to stored properties}} {{1-19=}}
+@_optimize(speed) class OspeedClass { // expected-error {{@_optimize(speed) cannot be applied to this declaration}} {{1-19=}}
+}
+
class A {
@inline(never) init(a : Int) {}
var b : Int {
@@ -237,6 +242,18 @@
}
}
+class C {
+ @_optimize(speed) init(a : Int) {}
+ var b : Int {
+ @_optimize(none) get {
+ return 42
+ }
+ @_optimize(size) set {
+ }
+ }
+ @_optimize(size) var c : Int // expected-error {{@_optimize(size) cannot be applied to stored properties}}
+}
+
class SILStored {
@sil_stored var x : Int = 42 // expected-error {{'sil_stored' only allowed in SIL modules}}
}
diff --git a/test/expr/unary/keypath/keypath.swift b/test/expr/unary/keypath/keypath.swift
index 066556c..2498292 100644
--- a/test/expr/unary/keypath/keypath.swift
+++ b/test/expr/unary/keypath/keypath.swift
@@ -269,7 +269,10 @@
subscript(keyPath kp: PartialKeyPath<ZwithSubscript>) -> Any { return 0 }
}
+struct NotZ {}
+
func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscript,
+ wrongType: inout NotZ,
kp: KeyPath<ZwithSubscript, Int>,
wkp: WritableKeyPath<ZwithSubscript, Int>,
rkp: ReferenceWritableKeyPath<ZwithSubscript, Int>) {
@@ -312,6 +315,12 @@
readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign to immutable}}
// FIXME: silently falls back to keypath application, which seems inconsistent
writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}}
+
+ _ = wrongType[keyPath: kp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: wkp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: rkp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: pkp] // expected-error{{cannot be applied}}
+ _ = wrongType[keyPath: akp]
}
func testKeyPathSubscriptMetatype(readonly: Z.Type, writable: inout Z.Type,
@@ -358,10 +367,33 @@
_ = base[keyPath: kp]
}
-func testKeyPathSubscriptExistentialBase(base: B, kp: KeyPath<P, String>) {
- _ = base[keyPath: kp]
-}
+func testKeyPathSubscriptExistentialBase(concreteBase: inout B,
+ existentialBase: inout P,
+ kp: KeyPath<P, String>,
+ wkp: WritableKeyPath<P, String>,
+ rkp: ReferenceWritableKeyPath<P, String>,
+ pkp: PartialKeyPath<P>,
+ s: String) {
+ _ = concreteBase[keyPath: kp]
+ _ = concreteBase[keyPath: wkp]
+ _ = concreteBase[keyPath: rkp]
+ _ = concreteBase[keyPath: pkp]
+ concreteBase[keyPath: kp] = s // expected-error{{}}
+ concreteBase[keyPath: wkp] = s // expected-error{{}}
+ concreteBase[keyPath: rkp] = s
+ concreteBase[keyPath: pkp] = s // expected-error{{}}
+
+ _ = existentialBase[keyPath: kp]
+ _ = existentialBase[keyPath: wkp]
+ _ = existentialBase[keyPath: rkp]
+ _ = existentialBase[keyPath: pkp]
+
+ existentialBase[keyPath: kp] = s // expected-error{{}}
+ existentialBase[keyPath: wkp] = s
+ existentialBase[keyPath: rkp] = s
+ existentialBase[keyPath: pkp] = s // expected-error{{}}
+}
struct AA {
subscript(x: Int) -> Int { return x }
diff --git a/test/expr/unary/keypath/salvage-with-other-type-errors.swift b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
index e035613..7a6af78 100644
--- a/test/expr/unary/keypath/salvage-with-other-type-errors.swift
+++ b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
@@ -52,6 +52,7 @@
extension Bindable {
func test<Value>(to targetKeyPath: ReferenceWritableKeyPath<Self, Value>, change: Value?) {
if self[keyPath:targetKeyPath] != change { // expected-error{{}}
+ // expected-note@-1{{overloads for '!=' exist with these partially matching parameter lists: (Self, Self), (_OptionalNilComparisonType, Wrapped?)}}
self[keyPath: targetKeyPath] = change!
}
}
diff --git a/test/expr/unary/selector/selector.swift b/test/expr/unary/selector/selector.swift
index 127d1cf..7b7a468 100644
--- a/test/expr/unary/selector/selector.swift
+++ b/test/expr/unary/selector/selector.swift
@@ -134,7 +134,7 @@
}
switch optionalSel {
-case #selector(SR1827.bar): // expected-error{{expression pattern of type 'Selector' cannot match values of type 'Selector?'}} {{27-27=?}}
+case #selector(SR1827.bar):
break
case #selector(SR1827.bar)!: // expected-error{{cannot force unwrap value of non-optional type 'Selector'}}
break
diff --git a/test/stdlib/ArrayDiagnostics.swift b/test/stdlib/ArrayDiagnostics.swift
index d1f6f6b..144a107 100644
--- a/test/stdlib/ArrayDiagnostics.swift
+++ b/test/stdlib/ArrayDiagnostics.swift
@@ -5,7 +5,8 @@
func test_ArrayOfNotEquatableIsNotEquatable() {
var a = [ NotEquatable(), NotEquatable() ]
// FIXME: This is an awful error.
- if a == a {} // expected-error {{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
- // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+ if a == a {} // expected-error {{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+ // expected-note @-1 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+ // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
}
diff --git a/test/stdlib/Intents.swift b/test/stdlib/Intents.swift
index de7a3fd..d0b19bf 100644
--- a/test/stdlib/Intents.swift
+++ b/test/stdlib/Intents.swift
@@ -75,4 +75,32 @@
}
#endif
+#if os(iOS)
+if #available(iOS 11.0, *) {
+ IntentsTestSuite.test("INSetProfileInCarIntent Initializers/\(swiftVersion)") {
+#if swift(>=4)
+ _ = INSetProfileInCarIntent()
+ _ = INSetProfileInCarIntent(isDefaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileName: nil)
+ _ = INSetProfileInCarIntent(profileName: nil, isDefaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, isDefaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, profileName: nil)
+ _ = INSetProfileInCarIntent(
+ profileNumber: nil, profileName: nil, isDefaultProfile: nil)
+#else
+ _ = INSetProfileInCarIntent()
+ _ = INSetProfileInCarIntent(defaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileName: nil)
+ _ = INSetProfileInCarIntent(profileName: nil, defaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, defaultProfile: nil)
+ _ = INSetProfileInCarIntent(profileNumber: nil, profileName: nil)
+ _ = INSetProfileInCarIntent(
+ profileNumber: nil, profileName: nil, defaultProfile: nil)
+#endif
+ }
+}
+#endif
+
runAllTests()
diff --git a/test/stdlib/TestJSONEncoder.swift b/test/stdlib/TestJSONEncoder.swift
index 5ed50b8..b0bf177 100644
--- a/test/stdlib/TestJSONEncoder.swift
+++ b/test/stdlib/TestJSONEncoder.swift
@@ -478,6 +478,22 @@
_testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self)
}
+ func testDecodingConcreteTypeParameter() {
+ let encoder = JSONEncoder()
+ guard let json = try? encoder.encode(Employee.testValue) else {
+ expectUnreachable("Unable to encode Employee.")
+ return
+ }
+
+ let decoder = JSONDecoder()
+ guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: json) else {
+ expectUnreachable("Failed to decode Employee as Person from JSON.")
+ return
+ }
+
+ expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.")
+ }
+
// MARK: - Helper Functions
private var _jsonEmptyDictionary: Data {
return "{}".data(using: .utf8)!
@@ -1104,5 +1120,6 @@
JSONEncoderTests.test("testInterceptDecimal") { TestJSONEncoder().testInterceptDecimal() }
JSONEncoderTests.test("testInterceptURL") { TestJSONEncoder().testInterceptURL() }
JSONEncoderTests.test("testTypeCoercion") { TestJSONEncoder().testTypeCoercion() }
+JSONEncoderTests.test("testDecodingConcreteTypeParameter") { TestJSONEncoder().testDecodingConcreteTypeParameter() }
runAllTests()
#endif
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index 1638226..489261a 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -522,7 +522,7 @@
let float = (number!) as? Float
let expectedFloat = Float(uint32!)
// these are disabled because of https://bugs.swift.org/browse/SR-4634
- if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+ if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
testFloat(expectedFloat, float)
}
diff --git a/test/stdlib/TestPlistEncoder.swift b/test/stdlib/TestPlistEncoder.swift
index d7b037b..d38ef76 100644
--- a/test/stdlib/TestPlistEncoder.swift
+++ b/test/stdlib/TestPlistEncoder.swift
@@ -198,6 +198,22 @@
_testRoundTripTypeCoercionFailure(of: [0.0, 1.0] as [Double], as: [Bool].self)
}
+ func testDecodingConcreteTypeParameter() {
+ let encoder = PropertyListEncoder()
+ guard let plist = try? encoder.encode(Employee.testValue) else {
+ expectUnreachable("Unable to encode Employee.")
+ return
+ }
+
+ let decoder = PropertyListDecoder()
+ guard let decoded = try? decoder.decode(Employee.self as Person.Type, from: plist) else {
+ expectUnreachable("Failed to decode Employee as Person from plist.")
+ return
+ }
+
+ expectEqual(type(of: decoded), Employee.self, "Expected decoded value to be of type Employee; got \(type(of: decoded)) instead.")
+ }
+
// MARK: - Helper Functions
private var _plistEmptyDictionaryBinary: Data {
return Data(base64Encoded: "YnBsaXN0MDDQCAAAAAAAAAEBAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAJ")!
@@ -731,5 +747,6 @@
PropertyListEncoderTests.test("testInterceptData") { TestPropertyListEncoder().testInterceptData() }
PropertyListEncoderTests.test("testInterceptDate") { TestPropertyListEncoder().testInterceptDate() }
PropertyListEncoderTests.test("testTypeCoercion") { TestPropertyListEncoder().testTypeCoercion() }
+PropertyListEncoderTests.test("testDecodingConcreteTypeParameter") { TestPropertyListEncoder().testDecodingConcreteTypeParameter() }
runAllTests()
#endif
diff --git a/test/stdlib/UnsafeRawBufferPointer.swift b/test/stdlib/UnsafeRawBufferPointer.swift
index a5f5897..442f6fc 100644
--- a/test/stdlib/UnsafeRawBufferPointer.swift
+++ b/test/stdlib/UnsafeRawBufferPointer.swift
@@ -100,7 +100,10 @@
let buffer = UnsafeMutableRawBufferPointer.allocate(count: 30)
defer { buffer.deallocate() }
let source = stride(from: 5 as Int64, to: 0, by: -1)
- var (it,bound) = buffer.initializeMemory(as: Int64.self, from: source)
+ if _isDebugAssertConfiguration() {
+ expectCrashLater()
+ }
+ var (it, bound) = buffer.initializeMemory(as: Int64.self, from: source)
let idx = bound.endIndex * MemoryLayout<Int64>.stride
expectEqual(it.next()!, 2)
expectEqual(idx, 24)
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 616f4f8..9be32b6 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -21,11 +21,11 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTWalker.h"
#include "swift/AST/GenericSignature.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/IDE/Refactoring.h"
// This is included only for createLazyResolver(). Move to different header ?
@@ -1041,10 +1041,11 @@
}
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override {
// Treat both open and close brackets equally
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
bool isLocal(Decl *D) const {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
index 397f25b..4471725 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp
@@ -23,7 +23,6 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/ASTWalker.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/DiagnosticsClangImporter.h"
#include "swift/AST/DiagnosticsParse.h"
#include "swift/Basic/SourceManager.h"
@@ -33,6 +32,7 @@
#include "swift/IDE/CodeCompletion.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/Formatting.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/Subsystems.h"
@@ -876,10 +876,11 @@
}
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override {
// We should treat both open and close brackets equally
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
void annotate(const Decl *D, bool IsRef, CharSourceRange Range) {
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 5f30a16..a96492b 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -19,13 +19,13 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Decl.h"
#include "swift/AST/NameLookup.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/SwiftNameTranslation.h"
#include "swift/Basic/SourceManager.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/Utils.h"
#include "swift/IDE/Refactoring.h"
#include "swift/Markup/XMLUtils.h"
diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp
index 701113a..0a812af 100644
--- a/tools/sil-func-extractor/SILFunctionExtractor.cpp
+++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp
@@ -254,34 +254,15 @@
Invocation.getLangOptions().EnableAccessControl = false;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size()
- ? StringRef(ModuleName)
- : llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- Invocation.setModuleName("main");
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
SILOptions &SILOpts = Invocation.getSILOptions();
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
@@ -300,7 +281,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(
diff --git a/tools/sil-llvm-gen/SILLLVMGen.cpp b/tools/sil-llvm-gen/SILLLVMGen.cpp
index c04f619..5498216 100644
--- a/tools/sil-llvm-gen/SILLLVMGen.cpp
+++ b/tools/sil-llvm-gen/SILLLVMGen.cpp
@@ -167,35 +167,15 @@
Opts.OutputFilenames.push_back(OutputFilename);
Opts.OutputKind = OutputKind;
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size()
- ? StringRef(ModuleName)
- : llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
- Invocation.setModuleName(Name);
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
CompilerInstance CI;
PrintingDiagnosticConsumer PrintDiags;
CI.addDiagnosticConsumer(&PrintDiags);
@@ -216,7 +196,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(SILModule::createEmptyModule(
diff --git a/tools/sil-nm/SILNM.cpp b/tools/sil-nm/SILNM.cpp
index ec5df3c..b3eddc9 100644
--- a/tools/sil-nm/SILNM.cpp
+++ b/tools/sil-nm/SILNM.cpp
@@ -168,34 +168,15 @@
Invocation.getLangOptions().EnableAccessControl = false;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size()
- ? StringRef(ModuleName)
- : llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- Invocation.setModuleName("main");
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
SILOptions &SILOpts = Invocation.getSILOptions();
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
@@ -214,7 +195,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index d7d5e66..b222dcd 100644
--- a/tools/sil-opt/SILOpt.cpp
+++ b/tools/sil-opt/SILOpt.cpp
@@ -311,7 +311,7 @@
SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts;
SILOpts.AssertConfig = AssertConfId;
if (OptimizationGroup != OptGroup::Diagnostics)
- SILOpts.Optimization = SILOptions::SILOptMode::Optimize;
+ SILOpts.OptMode = OptimizationMode::ForSpeed;
SILOpts.EnableSILOwnership = EnableSILOwnershipOpt;
SILOpts.AssumeUnqualifiedOwnershipWhenParsing =
AssumeUnqualifiedOwnershipWhenParsing;
@@ -342,35 +342,15 @@
}
}
- // Load the input file.
+ serialization::ExtendedValidationInfo extendedInfo;
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
- llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
+ Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
+ extendedInfo);
if (!FileBufOrErr) {
fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
exit(-1);
}
- // If it looks like we have an AST, set the source file kind to SIL and the
- // name of the module to the file's name.
- Invocation.addInputBuffer(FileBufOrErr.get().get());
-
- serialization::ExtendedValidationInfo extendedInfo;
- auto result = serialization::validateSerializedAST(
- FileBufOrErr.get()->getBuffer(), &extendedInfo);
- bool HasSerializedAST = result.status == serialization::Status::Valid;
-
- if (HasSerializedAST) {
- const StringRef Stem = ModuleName.size() ?
- StringRef(ModuleName) :
- llvm::sys::path::stem(InputFilename);
- Invocation.setModuleName(Stem);
- Invocation.setInputKind(InputFileKind::IFK_Swift_Library);
- } else {
- const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main";
- Invocation.setModuleName(Name);
- Invocation.setInputKind(InputFileKind::IFK_SIL);
- }
-
CompilerInstance CI;
PrintingDiagnosticConsumer PrintDiags;
CI.addDiagnosticConsumer(&PrintDiags);
@@ -391,7 +371,7 @@
// Load the SIL if we have a module. We have to do this after SILParse
// creating the unfortunate double if statement.
- if (HasSerializedAST) {
+ if (Invocation.hasSerializedAST()) {
assert(!CI.hasSILModule() &&
"performSema() should not create a SILModule.");
CI.setSILModule(SILModule::createEmptyModule(
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index a04751b..93fce76 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -22,7 +22,6 @@
#include "swift/AST/ASTMangler.h"
#include "swift/AST/PrintOptions.h"
#include "swift/AST/RawComment.h"
-#include "swift/AST/SourceEntityWalker.h"
#include "swift/AST/USRGeneration.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Basic/LangOptions.h"
@@ -35,6 +34,7 @@
#include "swift/IDE/CommentConversion.h"
#include "swift/IDE/ModuleInterfacePrinting.h"
#include "swift/IDE/REPLCodeCompletion.h"
+#include "swift/IDE/SourceEntityWalker.h"
#include "swift/IDE/SyntaxModel.h"
#include "swift/IDE/Utils.h"
#include "swift/Index/Index.h"
@@ -1254,9 +1254,10 @@
}
bool visitSubscriptReference(ValueDecl *D, CharSourceRange Range,
+ Optional<AccessKind> AccKind,
bool IsOpenBracket) override {
return visitDeclReference(D, Range, nullptr, nullptr, Type(),
- ReferenceMetaData(SemaReferenceKind::SubscriptRef, None));
+ ReferenceMetaData(SemaReferenceKind::SubscriptRef, AccKind));
}
bool visitCallArgName(Identifier Name, CharSourceRange Range,
diff --git a/tools/swift-llvm-opt/LLVMOpt.cpp b/tools/swift-llvm-opt/LLVMOpt.cpp
index d3d9f05..cba627f 100644
--- a/tools/swift-llvm-opt/LLVMOpt.cpp
+++ b/tools/swift-llvm-opt/LLVMOpt.cpp
@@ -302,7 +302,7 @@
if (Optimized) {
IRGenOptions Opts;
- Opts.Optimize = true;
+ Opts.OptMode = OptimizationMode::ForSpeed;
// Then perform the optimizations.
performLLVMOptimizations(Opts, M.get(), TM.get());
diff --git a/utils/dev-scripts/split-cmdline b/utils/dev-scripts/split-cmdline
index 364009e..736b1a2 100755
--- a/utils/dev-scripts/split-cmdline
+++ b/utils/dev-scripts/split-cmdline
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# splitcmdline - Split swift compiler command lines -------------*- python -*-
+# split-cmdline - Split swift compiler command lines ------------*- python -*-
#
# This source file is part of the Swift.org open source project
#
@@ -14,7 +14,19 @@
# Split swift compiler command lines into multiple lines.
#
# Reads the command line from stdin an outputs the split line to stdout.
+# Example:
#
+# $ swiftc -c hello.swift -### | split-cmdline
+# /path-to-swift/bin/swift \
+# -frontend \
+# -c \
+# -primary-file hello.swift \
+# -target x86_64-apple-macosx10.9 \
+# -enable-objc-interop \
+# -color-diagnostics \
+# -module-name hello \
+# -o hello.o
+#
# Example usage in vim:
# *) make sure that split-cmdline is in the $PATH
# *) copy-paste the swift command line the text buffer
@@ -29,16 +41,15 @@
import re
import sys
import os
-
+import shlex
def main():
for line in sys.stdin:
first = True
is_arg_param = False
# Handle escaped spaces
- args = re.sub('\\\\ ', '@#space#@', line).split()
+ args = shlex.split(line)
for arg in args:
- arg = re.sub('@#space#@', '\\ ', arg)
if arg == '':
continue
if not first:
@@ -59,7 +70,10 @@
first = True
continue
- print(arg, end='')
+ if ' ' in arg:
+ print('"' + arg + '"', end='')
+ else:
+ print(arg, end='')
# A hard-coded list of options which expect a parameter
is_arg_param = (arg in [
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index fcf4122..d6c57e1 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -171,5 +171,25 @@
Node('StringLiteralExpr', kind='Expr',
children=[
Child("StringLiteral", kind='StringLiteralToken')
- ])
+ ]),
+
+ # true or false
+ Node('BooleanLiteralExpr', kind='Expr',
+ children=[
+ Child("BooleanLiteral", kind='Token',
+ token_choices=[
+ 'TrueToken',
+ 'FalseToken',
+ ])
+ ]),
+
+ # a ? 1 : 0
+ Node('TernaryExpr', kind='Expr',
+ children=[
+ Child("ConditionExpression", kind='Expr'),
+ Child("QuestionMark", kind='InfixQuestionMarkToken'),
+ Child("FirstChoice", kind='Expr'),
+ Child("ColonMark", kind='ColonToken'),
+ Child("SecondChoice", kind='Expr')
+ ]),
]
diff --git a/utils/update_checkout.py b/utils/update_checkout.py
index df10b57..8221365 100755
--- a/utils/update_checkout.py
+++ b/utils/update_checkout.py
@@ -479,6 +479,14 @@
skip_history,
skip_repo_list)
+ # Quick check whether somebody is calling update in an empty directory
+ directory_contents = os.listdir(SWIFT_SOURCE_ROOT)
+ if not ('cmark' in directory_contents or
+ 'llvm' in directory_contents or
+ 'clang' in directory_contents):
+ print("You don't have all swift sources. "
+ "Call this script with --clone to get them.")
+
update_results = update_all_repositories(args, config, scheme,
cross_repos_pr)
fail_count = 0
diff --git a/validation-test/Evolution/test_superclass_methods.swift b/validation-test/Evolution/test_superclass_methods.swift
index e09e8f2..d2434c7 100644
--- a/validation-test/Evolution/test_superclass_methods.swift
+++ b/validation-test/Evolution/test_superclass_methods.swift
@@ -1,9 +1,6 @@
// RUN: %target-resilience-test
// REQUIRES: executable_test
-// rdar://35492775
-// REQUIRES: swift_test_mode_optimize_none
-
import StdlibUnittest
import superclass_methods
diff --git a/validation-test/Evolution/test_superclass_properties.swift b/validation-test/Evolution/test_superclass_properties.swift
index bc30df2..81cdf5c 100644
--- a/validation-test/Evolution/test_superclass_properties.swift
+++ b/validation-test/Evolution/test_superclass_properties.swift
@@ -1,9 +1,6 @@
// RUN: %target-resilience-test
// REQUIRES: executable_test
-// rdar://35492775
-// REQUIRES: swift_test_mode_optimize_none
-
import StdlibUnittest
import superclass_properties
diff --git a/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift b/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
index ec99b6a..b4378e9 100644
--- a/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
+++ b/validation-test/compiler_crashers_fixed/26725-llvm-smallvectorimpl-swift-diagnosticargument-operator.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
class a<T where g:d{class A{class A<T>:A{init(){T{
diff --git a/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift b/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
index e48931e..359453f 100644
--- a/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
+++ b/validation-test/compiler_crashers_fixed/28350-swift-typechecker-performtypocorrection.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
struct c{class A:A{}var f=A.s
diff --git a/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift b/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
index 63fe9ac..dcbf097 100644
--- a/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
+++ b/validation-test/compiler_crashers_fixed/28389-swift-lookupvisibledecls.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -typecheck
-// REQUIRES: asserts
struct B{let d=A.b}class A:A{let a=V
diff --git a/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift b/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
index 00f45d8..f65282f 100644
--- a/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
+++ b/validation-test/compiler_crashers_fixed/28482-hasaccessibility-accessibility-not-computed-yet.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
{guard let{protocol A{extension{let d}}}let f=d
diff --git a/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift b/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
index e546946..73f5994 100644
--- a/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
+++ b/validation-test/compiler_crashers_fixed/28626-objectty-is-lvaluetype-objectty-is-inouttype-cannot-have-inout-or-lvalue-wrapped.swift
@@ -6,5 +6,4 @@
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
// RUN: not %target-swift-frontend %s -emit-ir
-// REQUIRES: asserts
&[_=(&_
diff --git a/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift b/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
index 8be1db1..5d42a2b 100644
--- a/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
+++ b/validation-test/compiler_crashers_fixed/28706-conformance-failed-to-find-pas-conformance-to-known-protocol.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{let c{}typealias e:RangeReplaceableCollection}extension P{typealias e:a
diff --git a/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift b/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
index 8f0ba7d..ee5d02c 100644
--- a/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
+++ b/validation-test/compiler_crashers_fixed/28728-d-isbeingvalidated-d-hasvalidsignature.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
typealias e:a
struct A:a{}typealias a=A
diff --git a/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift b/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
index 9b66b76..9e30b6b 100644
--- a/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
+++ b/validation-test/compiler_crashers_fixed/28733-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{class a:Self.a
diff --git a/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift b/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
index f54117f..297f82b 100644
--- a/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
+++ b/validation-test/compiler_crashers_fixed/28738-impl-genericparams-empty-key-depth-impl-genericparams-back-getdepth-key-index-im.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P}extension P{{}typealias a:P}extension P.a{protocol P
diff --git a/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift b/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
index f9d112f..d9dc8bd 100644
--- a/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
+++ b/validation-test/compiler_crashers_fixed/28745-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
&{LazyFilterIndex{
diff --git a/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift b/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
index 8d68e87..fea557c 100644
--- a/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
+++ b/validation-test/compiler_crashers_fixed/28748-genericenv-nullptr-too-much-circularity.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:a{{}typealias e:a}{}class a:A{typealias e:b
diff --git a/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift b/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
index d8cfda1..0c7cab3 100644
--- a/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
+++ b/validation-test/compiler_crashers_fixed/28750-false-should-have-found-context-by-now.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{struct A}class a:P{class a:A
diff --git a/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift b/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
index da91b69..87061d5 100644
--- a/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
+++ b/validation-test/compiler_crashers_fixed/28751-membertype-missing-type-witness.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
{class a:P{{}typealias a:Self.a}protocol P{typealias a
diff --git a/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift b/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
index 675bf9e..4ee8994 100644
--- a/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
+++ b/validation-test/compiler_crashers_fixed/28752-hasinterfacetype-no-interface-type-was-set.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
@objc protocol P{typealias e:P{}var a}{}extension P{typealias e:P
diff --git a/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift b/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
index f14b655..6827b5d 100644
--- a/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
+++ b/validation-test/compiler_crashers_fixed/28753-conforms-equivclass-conformsto-end.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:A{{}class a{let ca{a{
diff --git a/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift b/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
index 06b5bb10..b1db627 100644
--- a/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
+++ b/validation-test/compiler_crashers_fixed/28754-value-openexistentials-end-didnt-see-this-ove-in-a-containing-openexistentialexp.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:RangeReplaceableCollection
typealias e:a._=A.init(
diff --git a/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift b/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
index 24269e6..3edd0b70 100644
--- a/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
+++ b/validation-test/compiler_crashers_fixed/28756-isobjc-cannot-get-root-type-of-objc-keypath.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
guard#keyPath($
diff --git a/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift b/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
index 441f3f5..0a37d63 100644
--- a/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
+++ b/validation-test/compiler_crashers_fixed/28759-activediagnostic-already-have-an-active-diagnostic.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension in($A
diff --git a/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift b/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
index 80bca15..db1c2fe 100644
--- a/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
+++ b/validation-test/compiler_crashers_fixed/28760-dist-0-nested-type-should-have-matched-associated-type.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias e:P{}class a{{}func a:Self.a.e
diff --git a/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift b/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
index eb3ce30..07b3cad 100644
--- a/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
+++ b/validation-test/compiler_crashers_fixed/28761-allowoverwrite-e-haslvalueaccesskind-l-value-access-kind-has-already-been-set.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
&_ is Character
diff --git a/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift b/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
index 963d2de..2549064 100644
--- a/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
+++ b/validation-test/compiler_crashers_fixed/28762-valuetype-hasunboundgenerictype-valuetype-hastypeparameter.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
guard let f==A:UnfoldSequence
diff --git a/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift b/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
index a50bb7f..5c7f0d2 100644
--- a/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
+++ b/validation-test/compiler_crashers_fixed/28765-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{{}class a:A{}protocol A:P.a{typealias a{}func a:a
diff --git a/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift b/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
index 5eba003..e22a1c3 100644
--- a/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
+++ b/validation-test/compiler_crashers_fixed/28767-ty-getnominalorboundgenericnominal-ty-is-dynamicselftype-ty-isexistentialtype-ty.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
@objc protocol P{struct B{var f=_=a{}}class a{}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift b/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
index 5b4f0e4..1686b88 100644
--- a/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
+++ b/validation-test/compiler_crashers_fixed/28768-isactuallycanonicalornull-forming-a-cantype-out-of-a-non-canonical-type.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
Indexable
& ManagedBuffer
diff --git a/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift b/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
index 8c2d8ea..1404712 100644
--- a/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
+++ b/validation-test/compiler_crashers_fixed/28770-selfty-isequal-proto-getselfinterfacetype.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{protocol b:P{{}typealias e:a.a}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift b/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
index 615f29c..769a13a 100644
--- a/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
+++ b/validation-test/compiler_crashers_fixed/28772-loc-isvalid-diagnosing-attribute-with-invalid-location.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a{@objc@dynamic
let d
diff --git a/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 33a3375..36a9536 100644
--- a/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28775-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{{}protocol A{typealias e{}}typealias a=A}extension P.a{protocol P
diff --git a/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift b/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
index 26b3ac3..9421946 100644
--- a/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
+++ b/validation-test/compiler_crashers_fixed/28776-type-should-have-type-checked-inheritance-clause-by-now.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias a{}class a
{}typealias a{}class a
diff --git a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 1900ef7..57f8aaf 100644
--- a/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers_fixed/28783-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a:A
protocol A:a{
diff --git a/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift b/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
index af99a3f..34901f3 100644
--- a/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
+++ b/validation-test/compiler_crashers_fixed/28784-genericsigorenv-isnull-getgenericsignature-getcanonicalsignature-genericenv-getg.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension P{{}}protocol P{protocol P{protocol A{{}typealias a{}}typealias e:A.a}typealias e:P
diff --git a/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift b/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
index f0e4bf6..08c38fe 100644
--- a/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
+++ b/validation-test/compiler_crashers_fixed/28788-conformance-isconcrete-concrete-isexistentialtype.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{
typealias e:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift b/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
index 7fd018a..aa5c573 100644
--- a/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
+++ b/validation-test/compiler_crashers_fixed/28792-conforms-equivclass-conformsto-end.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:A{struct B{{}var a{class a{class ss:a
diff --git a/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index efc3af8..0374eed 100644
--- a/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28793-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:RangeReplaceableCollection
protocol P{
diff --git a/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift b/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
index 1714776..54eafc3 100644
--- a/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
+++ b/validation-test/compiler_crashers_fixed/28795-inprotocol-isrequirementsignaturecomputed-missing-signature.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:A.b{func 丏
protocol b:Collection
diff --git a/validation-test/compiler_crashers_fixed/28796-result-second.swift b/validation-test/compiler_crashers_fixed/28796-result-second.swift
index 316ac8c..41a241c 100644
--- a/validation-test/compiler_crashers_fixed/28796-result-second.swift
+++ b/validation-test/compiler_crashers_fixed/28796-result-second.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{{{}}func b{extension{class a<a{{}class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift b/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
index df54499..76fd112b 100644
--- a/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
+++ b/validation-test/compiler_crashers_fixed/28802-constrainttype-missing-constraint-type.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{protocol A{protocol A{}typealias e where f:A
diff --git a/validation-test/compiler_crashers_fixed/28804-second.swift b/validation-test/compiler_crashers_fixed/28804-second.swift
index edcddea..d2d91d8 100644
--- a/validation-test/compiler_crashers_fixed/28804-second.swift
+++ b/validation-test/compiler_crashers_fixed/28804-second.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{
protocol A{{}typealias e where f=A
diff --git a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
index 3902655..84fc444 100644
--- a/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
+++ b/validation-test/compiler_crashers_fixed/28807-parentequiv-conformsto-count-proto-0-no-conformance-requirement.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a:RangeReplaceableCollection}protocol P{{}typealias e:a{{}}typealias e:Collection
diff --git a/validation-test/compiler_crashers_fixed/28808-hasval.swift b/validation-test/compiler_crashers_fixed/28808-hasval.swift
index af52480..d930ac5 100644
--- a/validation-test/compiler_crashers_fixed/28808-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28808-hasval.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias a
protocol A:P{
diff --git a/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 70a1cc5..d951e40 100644
--- a/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28811-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
{<a.h=a
class a<H
diff --git a/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift b/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
index cebc195..28c2d36 100644
--- a/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
+++ b/validation-test/compiler_crashers_fixed/28820-fl-isinout-caller-did-not-set-flags-correctly.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
.a.i(t:&_
diff --git a/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift b/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
index ac9a4e6..5320203 100644
--- a/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
+++ b/validation-test/compiler_crashers_fixed/28821-isa-protocoldecl-nominal-cannot-be-a-protocol.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A{{}protocol A{func a:Self.a}typealias e:A.a
diff --git a/validation-test/compiler_crashers_fixed/28824-hasval.swift b/validation-test/compiler_crashers_fixed/28824-hasval.swift
index 59b31af..a920a03 100644
--- a/validation-test/compiler_crashers_fixed/28824-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28824-hasval.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension CountableRange{protocol b{typealias a:RangeReplaceableCollection
protocol P{}
diff --git a/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift b/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
index 1aa2114..71601aa 100644
--- a/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
+++ b/validation-test/compiler_crashers_fixed/28825-isa-classdecl-nominaldecl-expected-a-class-here.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol b:a{init(t:a}class a{class a
diff --git a/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index cd7ff73..cd937d6 100644
--- a/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ b/validation-test/compiler_crashers_fixed/28827-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
[(Int
(t:&_
diff --git a/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
index 5ee0ca9..768a520 100644
--- a/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
+++ b/validation-test/compiler_crashers_fixed/28831-type-ismaterializable-argument-to-setmustbematerializablerecursive-may-not-be-in.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
[(Int
(Int
diff --git a/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift b/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
index 73776c4..522b887 100644
--- a/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
+++ b/validation-test/compiler_crashers_fixed/28832-superclass-superclass-hasarchetype-superclass-must-be-interface-type.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
extension CountableRange{{}class a:a&a.a{func a
diff --git a/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
index f0dbe14..c20b4e1 100644
--- a/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
+++ b/validation-test/compiler_crashers_fixed/28835-type-hastypeparameter-already-have-an-interface-type.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
class a<a{
class a:RangeReplaceableCollection
diff --git a/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift b/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
index 392b757..b7b0294 100644
--- a/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
+++ b/validation-test/compiler_crashers_fixed/28838-gpdecl-getdepth-generictypeparamdecl-invaliddepth-parameter-hasnt-been-validated.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias e:A
protocol A:P{}typealias a
diff --git a/validation-test/compiler_crashers_fixed/28842-hasval.swift b/validation-test/compiler_crashers_fixed/28842-hasval.swift
index 0a745b8..12fd071 100644
--- a/validation-test/compiler_crashers_fixed/28842-hasval.swift
+++ b/validation-test/compiler_crashers_fixed/28842-hasval.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{{}typealias a:A{}class a
protocol a protocol A:P{typealias a
diff --git a/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift b/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
index 504f8d5..2acdaaa 100644
--- a/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
+++ b/validation-test/compiler_crashers_fixed/28848-iscanonicaltypeincontext-result-builder.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{typealias a{}func a:a.a{}class a{{}protocol 0
diff --git a/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift b/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
index 350c824..3b62d6e 100644
--- a/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
+++ b/validation-test/compiler_crashers_fixed/28851-hasconformanceinsignature-inprotocol-getrequirementsignature-subjecttype-conform.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:a{{}typealias a=a{}func a{}typealias a}class a:A{func a
diff --git a/validation-test/compiler_crashers_fixed/28853-result-second.swift b/validation-test/compiler_crashers_fixed/28853-result-second.swift
index 122c6ef..d2c10e9 100644
--- a/validation-test/compiler_crashers_fixed/28853-result-second.swift
+++ b/validation-test/compiler_crashers_fixed/28853-result-second.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
func a<a{
extension{{}
diff --git a/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
index 14d2e3d..fcf87c7 100644
--- a/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
+++ b/validation-test/compiler_crashers_fixed/28857-nestedpabyname-didnt-find-the-associated-type-we-wanted.swift
@@ -5,6 +5,5 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol A:RangeReplaceableCollection&a:class a:A
diff --git a/validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift b/validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
similarity index 83%
rename from validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift
rename to validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
index 026a0b1..f05671c 100644
--- a/validation-test/compiler_crashers/28858-val-isa-used-on-a-null-pointer.swift
+++ b/validation-test/compiler_crashers_fixed/28858-val-isa-used-on-a-null-pointer.swift
@@ -5,8 +5,7 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
func a
class a<b}let d=a?as?CVarArg
& a
diff --git a/validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift b/validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
similarity index 84%
rename from validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
rename to validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
index 0442f6c..ca51a8b 100644
--- a/validation-test/compiler_crashers/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
+++ b/validation-test/compiler_crashers_fixed/28863-t-is-archetypetype-t-isexistentialtype-expected-a-class-archetype-or-existential.swift
@@ -5,8 +5,7 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
class a
class a<a{{}class a<a{var f=a
& ManagedBuffer
diff --git a/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift b/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
index 40f673d..f78be0e 100644
--- a/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
+++ b/validation-test/compiler_crashers_fixed/28864-bool-typesig-bool-extensionsig-unexpected-generic-ness-mismatch-on-conformance.swift
@@ -5,7 +5,6 @@
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
-// REQUIRES: asserts
// RUN: not %target-swift-frontend %s -emit-ir
protocol P{class a}protocol A:P
extension P.a:A
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 61255c4..29eae21 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -516,7 +516,7 @@
let float = (number!) as? Float
let expectedFloat = Float(uint32!)
// these are disabled because of https://bugs.swift.org/browse/SR-4634
- if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+ if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
testFloat(expectedFloat, float)
}