diff --git a/CMakeLists.txt b/CMakeLists.txt index d699d69d04a50..18cf581a64f03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -413,6 +413,8 @@ endif() if(MSVC OR "${CMAKE_SIMULATE_ID}" STREQUAL MSVC) include(ClangClCompileRules) +elseif(UNIX) + include(UnixCompileRules) endif() if(CMAKE_C_COMPILER_ID MATCHES Clang) @@ -432,19 +434,6 @@ if(SWIFT_BUILD_SYNTAXPARSERLIB OR SWIFT_BUILD_SOURCEKIT) endif() endif() -# -# Assume a new enough ar to generate the index at construction time. This avoids -# having to invoke ranlib as a secondary command. -# - -set(CMAKE_C_ARCHIVE_CREATE " crs ") -set(CMAKE_C_ARCHIVE_APPEND " qs ") -set(CMAKE_C_ARCHIVE_FINISH "") - -set(CMAKE_CXX_ARCHIVE_CREATE " crs ") -set(CMAKE_CXX_ARCHIVE_APPEND " qs ") -set(CMAKE_CXX_ARCHIVE_FINISH "") - # # Include CMake modules # diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index ff24b14198b4a..6ac3c62315c9f 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -517,7 +517,6 @@ function(add_swift_host_library name) endif() set_target_properties(${name} PROPERTIES - CXX_STANDARD 14 NO_SONAME YES) endif() diff --git a/cmake/modules/UnixCompileRules.cmake b/cmake/modules/UnixCompileRules.cmake new file mode 100644 index 0000000000000..1f1bd57ce10db --- /dev/null +++ b/cmake/modules/UnixCompileRules.cmake @@ -0,0 +1,13 @@ + +# +# Assume a new enough ar to generate the index at construction time. This avoids +# having to invoke ranlib as a secondary command. +# + +set(CMAKE_C_ARCHIVE_CREATE " crs ") +set(CMAKE_C_ARCHIVE_APPEND " qs ") +set(CMAKE_C_ARCHIVE_FINISH "") + +set(CMAKE_CXX_ARCHIVE_CREATE " crs ") +set(CMAKE_CXX_ARCHIVE_APPEND " qs ") +set(CMAKE_CXX_ARCHIVE_FINISH "") diff --git a/include/swift/AST/ASTPrinter.h b/include/swift/AST/ASTPrinter.h index 6e110646a1142..0e5a17c9dcef7 100644 --- a/include/swift/AST/ASTPrinter.h +++ b/include/swift/AST/ASTPrinter.h @@ -17,6 +17,7 @@ #include "swift/Basic/QuotedString.h" #include "swift/Basic/UUID.h" #include "swift/AST/Identifier.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Support/raw_ostream.h" diff --git a/include/swift/AST/AnyFunctionRef.h b/include/swift/AST/AnyFunctionRef.h index bc57d7ae7ba8b..9c0ebe122e03c 100644 --- a/include/swift/AST/AnyFunctionRef.h +++ b/include/swift/AST/AnyFunctionRef.h @@ -89,6 +89,20 @@ class AnyFunctionRef { return TheFunction.get()->getSingleExpressionBody(); } + void setSingleExpressionBody(Expr *expr) { + if (auto *AFD = TheFunction.dyn_cast()) { + AFD->setSingleExpressionBody(expr); + return; + } + + auto ACE = TheFunction.get(); + if (auto CE = dyn_cast(ACE)) { + CE->setSingleExpressionBody(expr); + } else { + cast(ACE)->setBody(expr); + } + } + Type getType() const { if (auto *AFD = TheFunction.dyn_cast()) return AFD->getInterfaceType(); @@ -123,6 +137,21 @@ class AnyFunctionRef { return cast(ACE)->getBody(); } + void setBody(BraceStmt *stmt, bool isSingleExpression) { + if (auto *AFD = TheFunction.dyn_cast()) { + AFD->setBody(stmt); + AFD->setHasSingleExpressionBody(isSingleExpression); + return; + } + + auto *ACE = TheFunction.get(); + if (auto *CE = dyn_cast(ACE)) { + return CE->setBody(stmt, isSingleExpression); + } + + llvm_unreachable("autoclosures don't have statement bodies"); + } + DeclContext *getAsDeclContext() const { if (auto *AFD = TheFunction.dyn_cast()) return AFD; diff --git a/include/swift/AST/AnyRequest.h b/include/swift/AST/AnyRequest.h index 669174e3bf978..c886986363e4b 100644 --- a/include/swift/AST/AnyRequest.h +++ b/include/swift/AST/AnyRequest.h @@ -22,6 +22,7 @@ #include "swift/Basic/TypeID.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/PointerIntPair.h" #include namespace llvm { diff --git a/include/swift/AST/CaptureInfo.h b/include/swift/AST/CaptureInfo.h index 6d2eb20735229..4203c80eaf338 100644 --- a/include/swift/AST/CaptureInfo.h +++ b/include/swift/AST/CaptureInfo.h @@ -22,7 +22,6 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/TrailingObjects.h" -#include namespace swift { class CapturedValue; diff --git a/include/swift/AST/ConcreteDeclRef.h b/include/swift/AST/ConcreteDeclRef.h index 9049e438e245a..1ef420d98248f 100644 --- a/include/swift/AST/ConcreteDeclRef.h +++ b/include/swift/AST/ConcreteDeclRef.h @@ -21,7 +21,6 @@ #include "swift/Basic/LLVM.h" #include "swift/AST/SubstitutionMap.h" #include "swift/AST/TypeAlignments.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Compiler.h" #include diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 08634bec519fb..78e04e69598cf 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -41,7 +41,6 @@ #include "swift/Basic/OptionalEnum.h" #include "swift/Basic/Range.h" #include "swift/Basic/Located.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/Support/TrailingObjects.h" #include diff --git a/include/swift/AST/ExistentialLayout.h b/include/swift/AST/ExistentialLayout.h index 50f0cca77ca15..9f08d03cf8101 100644 --- a/include/swift/AST/ExistentialLayout.h +++ b/include/swift/AST/ExistentialLayout.h @@ -20,7 +20,6 @@ #include "swift/Basic/ArrayRefView.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Type.h" -#include "llvm/ADT/SmallVector.h" namespace swift { class ProtocolDecl; diff --git a/include/swift/AST/FileUnit.h b/include/swift/AST/FileUnit.h index 574c55f3ebb69..e15a56560fcf6 100644 --- a/include/swift/AST/FileUnit.h +++ b/include/swift/AST/FileUnit.h @@ -107,8 +107,8 @@ class FileUnit : public DeclContext { /// Find all SPI names imported from \p importedModule by this module, /// collecting the identifiers in \p spiGroups. virtual void lookupImportedSPIGroups( - const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const {}; + const ModuleDecl *importedModule, + SmallSetVector &spiGroups) const {}; protected: /// Look up an operator declaration. Do not call directly, use diff --git a/include/swift/AST/GenericParamKey.h b/include/swift/AST/GenericParamKey.h index 081c47a8aa571..f8590f8c4e124 100644 --- a/include/swift/AST/GenericParamKey.h +++ b/include/swift/AST/GenericParamKey.h @@ -14,7 +14,6 @@ #define SWIFT_AST_GENERICPARAMKEY_H #include "llvm/ADT/DenseMapInfo.h" -#include "llvm/ADT/ArrayRef.h" #include "swift/AST/Type.h" namespace swift { diff --git a/include/swift/AST/GenericSignatureBuilder.h b/include/swift/AST/GenericSignatureBuilder.h index 21b9c60d65a04..abb790e466a14 100644 --- a/include/swift/AST/GenericSignatureBuilder.h +++ b/include/swift/AST/GenericSignatureBuilder.h @@ -30,7 +30,6 @@ #include "swift/AST/TypeRepr.h" #include "swift/Basic/Debug.h" #include "swift/Basic/LLVM.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/PointerUnion.h" diff --git a/include/swift/AST/LinkLibrary.h b/include/swift/AST/LinkLibrary.h index 44a5d9c7e3ede..c40cc6f024348 100644 --- a/include/swift/AST/LinkLibrary.h +++ b/include/swift/AST/LinkLibrary.h @@ -14,7 +14,7 @@ #define SWIFT_AST_LINKLIBRARY_H #include "swift/Basic/LLVM.h" -#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include namespace swift { diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h index 667871022b8df..a83c89a7f003c 100644 --- a/include/swift/AST/Module.h +++ b/include/swift/AST/Module.h @@ -28,15 +28,12 @@ #include "swift/Basic/STLExtras.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" +#include namespace clang { class Module; @@ -646,8 +643,9 @@ class ModuleDecl : public DeclContext, public TypeDecl { /// Find all SPI names imported from \p importedModule by this module, /// collecting the identifiers in \p spiGroups. - void lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const; + void lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const; /// \sa getImportedModules enum class ImportFilterKind { diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index e169eff011f79..196c69c237cad 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -20,7 +20,6 @@ #include "swift/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSet.h" #include diff --git a/include/swift/AST/ModuleLoader.h b/include/swift/AST/ModuleLoader.h index bec885cb58739..6abeebcb8b8ba 100644 --- a/include/swift/AST/ModuleLoader.h +++ b/include/swift/AST/ModuleLoader.h @@ -22,8 +22,6 @@ #include "swift/Basic/Located.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "swift/AST/ModuleDependencies.h" diff --git a/include/swift/AST/NameLookup.h b/include/swift/AST/NameLookup.h index 544b5b9bdf54c..9d6a68516c494 100644 --- a/include/swift/AST/NameLookup.h +++ b/include/swift/AST/NameLookup.h @@ -17,7 +17,6 @@ #ifndef SWIFT_AST_NAME_LOOKUP_H #define SWIFT_AST_NAME_LOOKUP_H -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/Identifier.h" diff --git a/include/swift/AST/ProtocolConformance.h b/include/swift/AST/ProtocolConformance.h index f5fa29f0f6be4..1136fb5be73cd 100644 --- a/include/swift/AST/ProtocolConformance.h +++ b/include/swift/AST/ProtocolConformance.h @@ -27,8 +27,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/TinyPtrVector.h" #include namespace swift { diff --git a/include/swift/AST/SourceFile.h b/include/swift/AST/SourceFile.h index 7265512843e73..fb68e8564a44f 100644 --- a/include/swift/AST/SourceFile.h +++ b/include/swift/AST/SourceFile.h @@ -16,6 +16,8 @@ #include "swift/AST/FileUnit.h" #include "swift/AST/SynthesizedFileUnit.h" #include "swift/Basic/Debug.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallPtrSet.h" namespace swift { @@ -338,8 +340,9 @@ class SourceFile final : public FileUnit { /// Find all SPI names imported from \p importedModule by this file, /// collecting the identifiers in \p spiGroups. virtual void - lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const override; + lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const override; // Is \p targetDecl accessible as an explictly imported SPI from this file? bool isImportedAsSPI(const ValueDecl *targetDecl) const; diff --git a/include/swift/AST/Stmt.h b/include/swift/AST/Stmt.h index 17e013dbbcfc0..513be8e40d774 100644 --- a/include/swift/AST/Stmt.h +++ b/include/swift/AST/Stmt.h @@ -25,7 +25,6 @@ #include "swift/AST/TypeAlignments.h" #include "swift/Basic/Debug.h" #include "swift/Basic/NullablePtr.h" -#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/TrailingObjects.h" namespace swift { diff --git a/include/swift/Basic/OutputFileMap.h b/include/swift/Basic/OutputFileMap.h index 8f3235c05e247..363288f25b704 100644 --- a/include/swift/Basic/OutputFileMap.h +++ b/include/swift/Basic/OutputFileMap.h @@ -17,7 +17,6 @@ #include "swift/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" diff --git a/include/swift/Basic/SourceManager.h b/include/swift/Basic/SourceManager.h index b424dc6acbf6d..e26e44e78cef9 100644 --- a/include/swift/Basic/SourceManager.h +++ b/include/swift/Basic/SourceManager.h @@ -17,7 +17,6 @@ #include "swift/Basic/SourceLoc.h" #include "clang/Basic/FileManager.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringMap.h" #include "llvm/Support/SourceMgr.h" #include diff --git a/include/swift/Basic/SupplementaryOutputPaths.h b/include/swift/Basic/SupplementaryOutputPaths.h index d24d94822bafb..c1d0494a95891 100644 --- a/include/swift/Basic/SupplementaryOutputPaths.h +++ b/include/swift/Basic/SupplementaryOutputPaths.h @@ -14,7 +14,6 @@ #define SWIFT_FRONTEND_SUPPLEMENTARYOUTPUTPATHS_H #include "swift/Basic/LLVM.h" -#include "llvm/ADT/Optional.h" #include diff --git a/include/swift/Basic/TypeID.h b/include/swift/Basic/TypeID.h index 49e66bb5457cb..b7a4cc2bbc6ec 100644 --- a/include/swift/Basic/TypeID.h +++ b/include/swift/Basic/TypeID.h @@ -19,9 +19,12 @@ #ifndef SWIFT_BASIC_TYPEID_H #define SWIFT_BASIC_TYPEID_H -#include "llvm/ADT/StringRef.h" +// NOTE: Most of these includes are for CTypeIDZone.def and DefineTypeIDZone.h. +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/StringRef.h" #include +#include #include #include diff --git a/include/swift/Basic/UUID.h b/include/swift/Basic/UUID.h index a39202e688db2..1aa508fd6209c 100644 --- a/include/swift/Basic/UUID.h +++ b/include/swift/Basic/UUID.h @@ -21,8 +21,6 @@ #include "swift/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" #include diff --git a/include/swift/Driver/Action.h b/include/swift/Driver/Action.h index 3f4e5c4edec14..02801d8aece66 100644 --- a/include/swift/Driver/Action.h +++ b/include/swift/Driver/Action.h @@ -17,7 +17,6 @@ #include "swift/Basic/LLVM.h" #include "swift/Driver/Util.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Chrono.h" diff --git a/include/swift/Driver/Compilation.h b/include/swift/Driver/Compilation.h index 57baeb81db99e..840681c69e868 100644 --- a/include/swift/Driver/Compilation.h +++ b/include/swift/Driver/Compilation.h @@ -26,7 +26,6 @@ #include "swift/Driver/Driver.h" #include "swift/Driver/Job.h" #include "swift/Driver/Util.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Chrono.h" diff --git a/include/swift/Driver/Driver.h b/include/swift/Driver/Driver.h index 9723f4527ced4..5e055359d6346 100644 --- a/include/swift/Driver/Driver.h +++ b/include/swift/Driver/Driver.h @@ -25,7 +25,6 @@ #include "swift/Basic/Sanitizers.h" #include "swift/Driver/Util.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include diff --git a/include/swift/Driver/FineGrainedDependencyDriverGraph.h b/include/swift/Driver/FineGrainedDependencyDriverGraph.h index 1f04df6ec93ac..16f9a70dea984 100644 --- a/include/swift/Driver/FineGrainedDependencyDriverGraph.h +++ b/include/swift/Driver/FineGrainedDependencyDriverGraph.h @@ -19,12 +19,8 @@ #include "swift/Basic/OptionSet.h" #include "swift/Driver/Job.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Path.h" #include "llvm/Support/PointerLikeTypeTraits.h" diff --git a/include/swift/Driver/Job.h b/include/swift/Driver/Job.h index e57952545bb64..52ba51aafa1fe 100644 --- a/include/swift/Driver/Job.h +++ b/include/swift/Driver/Job.h @@ -20,7 +20,6 @@ #include "swift/Driver/Action.h" #include "swift/Driver/Util.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/swift/Frontend/FrontendInputsAndOutputs.h b/include/swift/Frontend/FrontendInputsAndOutputs.h index ccc699e211e30..76f5ef125bc14 100644 --- a/include/swift/Frontend/FrontendInputsAndOutputs.h +++ b/include/swift/Frontend/FrontendInputsAndOutputs.h @@ -17,7 +17,6 @@ #include "swift/Basic/SupplementaryOutputPaths.h" #include "swift/Frontend/InputFile.h" #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/MapVector.h" #include #include diff --git a/include/swift/Frontend/InputFile.h b/include/swift/Frontend/InputFile.h index 52678c9a2e951..bd9e24808f60e 100644 --- a/include/swift/Frontend/InputFile.h +++ b/include/swift/Frontend/InputFile.h @@ -17,7 +17,6 @@ #include "swift/Basic/SupplementaryOutputPaths.h" #include "llvm/Support/MemoryBuffer.h" #include -#include namespace swift { diff --git a/include/swift/IDE/CompletionInstance.h b/include/swift/IDE/CompletionInstance.h index 8eb345fee94da..3dfcf56b31299 100644 --- a/include/swift/IDE/CompletionInstance.h +++ b/include/swift/IDE/CompletionInstance.h @@ -16,7 +16,6 @@ #include "swift/Frontend/Frontend.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/MemoryBuffer.h" diff --git a/include/swift/IDE/SourceEntityWalker.h b/include/swift/IDE/SourceEntityWalker.h index 08d7e1580fe4b..1a6facca4d74a 100644 --- a/include/swift/IDE/SourceEntityWalker.h +++ b/include/swift/IDE/SourceEntityWalker.h @@ -17,7 +17,6 @@ #include "swift/Basic/LLVM.h" #include "swift/Basic/SourceLoc.h" #include "llvm/ADT/PointerUnion.h" -#include namespace clang { class Module; diff --git a/include/swift/Index/IndexSymbol.h b/include/swift/Index/IndexSymbol.h index c086e2a4ac283..338c906a960ae 100644 --- a/include/swift/Index/IndexSymbol.h +++ b/include/swift/Index/IndexSymbol.h @@ -15,7 +15,6 @@ #include "swift/Basic/LLVM.h" #include "clang/Index/IndexSymbol.h" -#include "llvm/ADT/SmallString.h" namespace swift { class Decl; diff --git a/include/swift/Migrator/FixitApplyDiagnosticConsumer.h b/include/swift/Migrator/FixitApplyDiagnosticConsumer.h index 4db9bb78ddfba..4937a881b827d 100644 --- a/include/swift/Migrator/FixitApplyDiagnosticConsumer.h +++ b/include/swift/Migrator/FixitApplyDiagnosticConsumer.h @@ -22,7 +22,7 @@ #include "swift/Migrator/Migrator.h" #include "swift/Migrator/Replacement.h" #include "clang/Rewrite/Core/RewriteBuffer.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallSet.h" namespace swift { diff --git a/include/swift/Parse/ParsedRawSyntaxNode.h b/include/swift/Parse/ParsedRawSyntaxNode.h index 00a1dc93381af..916e3d816703b 100644 --- a/include/swift/Parse/ParsedRawSyntaxNode.h +++ b/include/swift/Parse/ParsedRawSyntaxNode.h @@ -18,7 +18,6 @@ #include "swift/Parse/ParsedTrivia.h" #include "swift/Parse/Token.h" #include "swift/Syntax/SyntaxKind.h" -#include namespace swift { diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h index 71e2f1819b2ae..72a89ea2762a7 100644 --- a/include/swift/Parse/Parser.h +++ b/include/swift/Parse/Parser.h @@ -35,7 +35,6 @@ #include "swift/Parse/SyntaxParsingContext.h" #include "swift/Syntax/References.h" #include "swift/Config.h" -#include "llvm/ADT/SetVector.h" namespace llvm { template class PointerUnion; diff --git a/include/swift/Parse/PersistentParserState.h b/include/swift/Parse/PersistentParserState.h index cbbf82159e84c..0879674a33492 100644 --- a/include/swift/Parse/PersistentParserState.h +++ b/include/swift/Parse/PersistentParserState.h @@ -20,7 +20,6 @@ #include "swift/Basic/SourceLoc.h" #include "swift/Parse/LocalContext.h" #include "swift/Parse/Scope.h" -#include "llvm/ADT/DenseMap.h" namespace swift { diff --git a/include/swift/Parse/Scope.h b/include/swift/Parse/Scope.h index 0e77904dbc2ff..c58443d335384 100644 --- a/include/swift/Parse/Scope.h +++ b/include/swift/Parse/Scope.h @@ -21,7 +21,6 @@ #include "swift/AST/Identifier.h" #include "swift/Basic/Debug.h" #include "swift/Basic/TreeScopedHashTable.h" -#include "llvm/ADT/SmallVector.h" namespace swift { class ValueDecl; diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h index a469f26450572..f7fe5a78398b0 100644 --- a/include/swift/Reflection/ReflectionContext.h +++ b/include/swift/Reflection/ReflectionContext.h @@ -27,6 +27,7 @@ #include "swift/Remote/MemoryReader.h" #include "swift/Remote/MetadataReader.h" #include "swift/Reflection/Records.h" +#include "swift/Reflection/RuntimeInternals.h" #include "swift/Reflection/TypeLowering.h" #include "swift/Reflection/TypeRef.h" #include "swift/Reflection/TypeRefBuilder.h" @@ -104,7 +105,10 @@ class ReflectionContext using super::readMetadataAndValueOpaqueExistential; using super::readMetadataFromInstance; using super::readTypeFromMetadata; + using super::stripSignedPointer; using typename super::StoredPointer; + using typename super::StoredSignedPointer; + using typename super::StoredSize; explicit ReflectionContext(std::shared_ptr reader) : super(std::move(reader), *this) @@ -768,6 +772,156 @@ class ReflectionContext } } + /// Iterate the protocol conformance cache tree rooted at NodePtr, calling + /// Call with the type and protocol in each node. + void iterateConformanceTree(StoredPointer NodePtr, + std::function Call) { + if (!NodePtr) + return; + auto NodeBytes = getReader().readBytes(RemoteAddress(NodePtr), sizeof(Node)); + auto NodeData = + reinterpret_cast *>(NodeBytes.get()); + if (!NodeData) + return; + Call(NodeData->Type, NodeData->Proto); + iterateConformanceTree(NodeData->Left, Call); + iterateConformanceTree(NodeData->Right, Call); + } + + /// Iterate the protocol conformance cache in the target process, calling Call + /// with the type and protocol of each conformance. Returns None on success, + /// and a string describing the error on failure. + llvm::Optional iterateConformances( + std::function Call) { + std::string ConformancesPointerName = + "__swift_debug_protocolConformanceStatePointer"; + auto ConformancesAddrAddr = + getReader().getSymbolAddress(ConformancesPointerName); + if (!ConformancesAddrAddr) + return "unable to look up debug variable " + ConformancesPointerName; + + auto ConformancesAddr = + getReader().readPointer(ConformancesAddrAddr, sizeof(StoredPointer)); + if (!ConformancesAddr) + return "unable to read value of " + ConformancesPointerName; + + auto Root = getReader().readPointer(ConformancesAddr->getResolvedAddress(), + sizeof(StoredPointer)); + iterateConformanceTree(Root->getResolvedAddress().getAddressData(), Call); + return llvm::None; + } + + /// Fetch the metadata pointer from a metadata allocation, or 0 if this + /// allocation's tag is not handled or an error occurred. + StoredPointer allocationMetadataPointer( + MetadataAllocation Allocation) { + if (Allocation.Tag == GenericMetadataCacheTag) { + struct GenericMetadataCacheEntry { + StoredPointer Left, Right; + StoredPointer LockedStorage; + uint8_t LockedStorageKind; + uint8_t TrackingInfo; + uint16_t NumKeyParameters; + uint16_t NumWitnessTables; + uint32_t Hash; + StoredPointer Value; + }; + auto AllocationBytes = + getReader().readBytes(RemoteAddress(Allocation.Ptr), + Allocation.Size); + auto Entry = reinterpret_cast( + AllocationBytes.get()); + if (!Entry) + return 0; + return Entry->Value; + } + return 0; + } + + /// Iterate the metadata allocations in the target process, calling Call with + /// each allocation found. Returns None on success, and a string describing + /// the error on failure. + llvm::Optional iterateMetadataAllocations( + std::function)> Call) { + std::string IterationEnabledName = + "__swift_debug_metadataAllocationIterationEnabled"; + std::string AllocationPoolPointerName = + "__swift_debug_allocationPoolPointer"; + + auto IterationEnabledAddr = + getReader().getSymbolAddress(IterationEnabledName); + if (!IterationEnabledAddr) + return "unable to look up debug variable " + IterationEnabledName; + char IterationEnabled; + if (!getReader().readInteger(IterationEnabledAddr, &IterationEnabled)) + return "failed to read value of " + IterationEnabledName; + if (!IterationEnabled) + return std::string("remote process does not have metadata allocation " + "iteration enabled"); + + auto AllocationPoolAddrAddr = + getReader().getSymbolAddress(AllocationPoolPointerName); + if (!AllocationPoolAddrAddr) + return "unable to look up debug variable " + AllocationPoolPointerName; + auto AllocationPoolAddr = + getReader().readPointer(AllocationPoolAddrAddr, sizeof(StoredPointer)); + if (!AllocationPoolAddr) + return "failed to read value of " + AllocationPoolPointerName; + + struct PoolRange { + StoredPointer Begin; + StoredSize Remaining; + }; + struct PoolTrailer { + StoredPointer PrevTrailer; + StoredSize PoolSize; + }; + struct alignas(StoredPointer) AllocationHeader { + uint16_t Size; + uint16_t Tag; + }; + + auto PoolBytes = getReader() + .readBytes(AllocationPoolAddr->getResolvedAddress(), sizeof(PoolRange)); + auto Pool = reinterpret_cast(PoolBytes.get()); + if (!Pool) + return std::string("failure reading allocation pool contents"); + + auto TrailerPtr = Pool->Begin + Pool->Remaining; + while (TrailerPtr) { + auto TrailerBytes = getReader() + .readBytes(RemoteAddress(TrailerPtr), sizeof(PoolTrailer)); + auto Trailer = reinterpret_cast(TrailerBytes.get()); + if (!Trailer) + break; + auto PoolStart = TrailerPtr - Trailer->PoolSize; + auto PoolBytes = getReader() + .readBytes(RemoteAddress(PoolStart), Trailer->PoolSize); + auto PoolPtr = (const char *)PoolBytes.get(); + if (!PoolPtr) + break; + + uintptr_t Offset = 0; + while (Offset < Trailer->PoolSize) { + auto AllocationPtr = PoolPtr + Offset; + auto Header = (const AllocationHeader *)AllocationPtr; + if (Header->Size == 0) + break; + auto RemoteAddr = PoolStart + Offset + sizeof(AllocationHeader); + MetadataAllocation Allocation; + Allocation.Tag = Header->Tag; + Allocation.Ptr = RemoteAddr; + Allocation.Size = Header->Size; + Call(Allocation); + + Offset += sizeof(AllocationHeader) + Header->Size; + } + + TrailerPtr = Trailer->PrevTrailer; + } + return llvm::None; + } + private: const TypeInfo *getClosureContextInfo(StoredPointer Context, const ClosureContextInfo &Info) { diff --git a/include/swift/Reflection/RuntimeInternals.h b/include/swift/Reflection/RuntimeInternals.h new file mode 100644 index 0000000000000..0fa056360e9c6 --- /dev/null +++ b/include/swift/Reflection/RuntimeInternals.h @@ -0,0 +1,47 @@ +//===--- RuntimeInternals.h - Runtime Internal Structures -------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// +// +// Runtime data structures that Reflection inspects externally. +// +// FIXME: Ideally the original definitions would be templatized on a Runtime +// parameter and we could use the original definitions in both the runtime and +// in Reflection. +// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_REFLECTION_RUNTIME_INTERNALS_H +#define SWIFT_REFLECTION_RUNTIME_INTERNALS_H + +namespace swift { + +namespace reflection { + +template +struct ConformanceNode { + typename Runtime::StoredPointer Left, Right; + typename Runtime::StoredPointer Type; + typename Runtime::StoredPointer Proto; + typename Runtime::StoredPointer Description; + typename Runtime::StoredSize FailureGeneration; +}; + +template +struct MetadataAllocation { + uint16_t Tag; + typename Runtime::StoredPointer Ptr; + unsigned Size; +}; + +} // end namespace reflection +} // end namespace swift + +#endif // SWIFT_REFLECTION_RUNTIME_INTERNALS_H diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h index cb7b3393735fc..1f091dfd66065 100644 --- a/include/swift/Remote/MetadataReader.h +++ b/include/swift/Remote/MetadataReader.h @@ -2192,6 +2192,8 @@ class MetadataReader { readMangledName(RemoteAddress(extendedContextAddress), MangledNameKind::Type, dem); + if (!demangledExtendedContext) + return nullptr; auto demangling = dem.createNode(Node::Kind::Extension); demangling->addChild(parentDemangling, dem); diff --git a/include/swift/RemoteAST/RemoteAST.h b/include/swift/RemoteAST/RemoteAST.h index e5de3b46c8157..ba3d83200c296 100644 --- a/include/swift/RemoteAST/RemoteAST.h +++ b/include/swift/RemoteAST/RemoteAST.h @@ -24,7 +24,6 @@ #include "swift/Basic/LLVM.h" #include "swift/ABI/MetadataValues.h" #include "swift/AST/Type.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include diff --git a/include/swift/Runtime/Debug.h b/include/swift/Runtime/Debug.h index e4e77cb81f1d0..4ffc3e31174c8 100644 --- a/include/swift/Runtime/Debug.h +++ b/include/swift/Runtime/Debug.h @@ -231,6 +231,14 @@ bool _swift_reportFatalErrorsToDebugger; SWIFT_RUNTIME_STDLIB_SPI bool _swift_shouldReportFatalErrorsToDebugger(); +SWIFT_RUNTIME_STDLIB_SPI +bool _swift_debug_metadataAllocationIterationEnabled; + +SWIFT_RUNTIME_STDLIB_SPI +const void * const _swift_debug_allocationPoolPointer; + +SWIFT_RUNTIME_STDLIB_SPI +const void * const _swift_debug_protocolConformanceStatePointer; SWIFT_RUNTIME_ATTRIBUTE_ALWAYS_INLINE inline static int swift_asprintf(char **strp, const char *fmt, ...) { diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h index 720f03ae3dc09..6f4cefcdc35ed 100644 --- a/include/swift/Runtime/Metadata.h +++ b/include/swift/Runtime/Metadata.h @@ -25,6 +25,35 @@ namespace swift { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wreturn-type-c-linkage" +// Tags used to denote different kinds of allocations made with the metadata +// allocator. This is encoded in a header on each allocation when metadata +// iteration is enabled, and allows tools to know where each allocation came +// from. +// +// Some of these values are also declared in SwiftRemoteMirrorTypes.h. Those +// values must be kept stable to preserve compatibility. +enum MetadataAllocatorTags : uint16_t { + UnusedTag = 0, + BoxesTag, + ObjCClassWrappersTag, + FunctionTypesTag, + MetatypeTypesTag, + ExistentialMetatypeValueWitnessTablesTag, + ExistentialMetatypesTag, + ExistentialTypesTag, + OpaqueExistentialValueWitnessTablesTag, + ClassExistentialValueWitnessTablesTag, + ForeignWitnessTablesTag, + ResilientMetadataAllocatorTag, + MetadataTag, + TupleCacheTag, + GenericMetadataCacheTag, + ForeignMetadataCacheTag, + GenericWitnessTableCacheTag, + GenericClassMetadataTag, + GenericValueMetadataTag, +}; + /// The buffer used by a yield-once coroutine (such as the generalized /// accessors `read` and `modify`). struct YieldOnceBuffer { diff --git a/include/swift/SIL/LinearLifetimeChecker.h b/include/swift/SIL/LinearLifetimeChecker.h index eb71517c21d1c..88ad7909113dd 100644 --- a/include/swift/SIL/LinearLifetimeChecker.h +++ b/include/swift/SIL/LinearLifetimeChecker.h @@ -19,7 +19,6 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILValue.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" namespace swift { diff --git a/include/swift/SIL/Projection.h b/include/swift/SIL/Projection.h index b8d66d7983634..16c9c192e0236 100644 --- a/include/swift/SIL/Projection.h +++ b/include/swift/SIL/Projection.h @@ -33,7 +33,6 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/SetVector.h" #include "llvm/Support/Allocator.h" namespace swift { diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h index 4253ca79b39cd..ae3f940d21ad4 100644 --- a/include/swift/SIL/SILFunction.h +++ b/include/swift/SIL/SILFunction.h @@ -26,7 +26,6 @@ #include "swift/SIL/SILDeclRef.h" #include "swift/SIL/SILLinkage.h" #include "swift/SIL/SILPrintContext.h" -#include "llvm/ADT/StringMap.h" /// The symbol name used for the program entry point function. #define SWIFT_ENTRY_POINT_FUNCTION "main" diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index 86183e7a8ea1f..c3869a1ff7a0c 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -40,7 +40,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/ilist.h" diff --git a/include/swift/SIL/SILWitnessTable.h b/include/swift/SIL/SILWitnessTable.h index 12967cb9b4b4a..0c17fd7ff5757 100644 --- a/include/swift/SIL/SILWitnessTable.h +++ b/include/swift/SIL/SILWitnessTable.h @@ -28,7 +28,6 @@ #include "swift/AST/ProtocolConformanceRef.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/ilist.h" -#include namespace swift { diff --git a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h index 459bca52e6b5e..393e74efedd77 100644 --- a/include/swift/SILOptimizer/Analysis/ARCAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/ARCAnalysis.h @@ -20,10 +20,7 @@ #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/TinyPtrVector.h" namespace swift { diff --git a/include/swift/SILOptimizer/Analysis/Analysis.h b/include/swift/SILOptimizer/Analysis/Analysis.h index bb1ad1de2cf20..938f4f9e1a2b8 100644 --- a/include/swift/SILOptimizer/Analysis/Analysis.h +++ b/include/swift/SILOptimizer/Analysis/Analysis.h @@ -16,11 +16,7 @@ #include "swift/Basic/NullablePtr.h" #include "swift/SIL/Notifications.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" -#include namespace swift { diff --git a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h index 0896695bc80a5..16fbe53a89895 100644 --- a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h @@ -18,10 +18,8 @@ #include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/TinyPtrVector.h" namespace swift { diff --git a/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h b/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h index 16801ed1184fa..e2a3230a85544 100644 --- a/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h @@ -17,7 +17,6 @@ #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILValue.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Debug.h" diff --git a/include/swift/SILOptimizer/Analysis/DominanceAnalysis.h b/include/swift/SILOptimizer/Analysis/DominanceAnalysis.h index 40e1f6e419ec3..2b3b5d121756b 100644 --- a/include/swift/SILOptimizer/Analysis/DominanceAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/DominanceAnalysis.h @@ -16,7 +16,6 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/Dominance.h" #include "swift/SILOptimizer/Analysis/Analysis.h" -#include "llvm/ADT/DenseMap.h" namespace swift { class SILModule; diff --git a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h index 93c726dc0adcf..d1fa89e98b633 100644 --- a/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/EscapeAnalysis.h @@ -164,7 +164,6 @@ #include "swift/SILOptimizer/Analysis/BottomUpIPAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/swift/SILOptimizer/Analysis/LoopAnalysis.h b/include/swift/SILOptimizer/Analysis/LoopAnalysis.h index 2e7bc60471251..5819e04137fcf 100644 --- a/include/swift/SILOptimizer/Analysis/LoopAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/LoopAnalysis.h @@ -17,7 +17,6 @@ #include "swift/SIL/LoopInfo.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SILOptimizer/Analysis/Analysis.h" -#include "llvm/ADT/DenseMap.h" namespace swift { class DominanceInfo; diff --git a/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h b/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h index e86eaadfaa6e9..2e845c1829882 100644 --- a/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/PassManagerVerifierAnalysis.h @@ -15,7 +15,6 @@ #include "swift/SIL/SILFunction.h" #include "swift/SILOptimizer/Analysis/Analysis.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringSet.h" namespace swift { diff --git a/include/swift/SILOptimizer/Analysis/PostOrderAnalysis.h b/include/swift/SILOptimizer/Analysis/PostOrderAnalysis.h index e8dfea7ea206c..689bbc7bda3c7 100644 --- a/include/swift/SILOptimizer/Analysis/PostOrderAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/PostOrderAnalysis.h @@ -19,10 +19,8 @@ #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILFunction.h" #include "swift/SILOptimizer/Analysis/Analysis.h" -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/iterator_range.h" -#include namespace swift { diff --git a/include/swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h b/include/swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h index d6ab10d569a49..7bdae666b09ca 100644 --- a/include/swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h @@ -21,7 +21,6 @@ #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" diff --git a/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h b/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h index 45dba16761af2..f75e577b41052 100644 --- a/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/SideEffectAnalysis.h @@ -19,7 +19,6 @@ #include "swift/SILOptimizer/Analysis/BottomUpIPAnalysis.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" namespace swift { diff --git a/include/swift/SILOptimizer/PassManager/PassManager.h b/include/swift/SILOptimizer/PassManager/PassManager.h index da2b912d4c74e..b72969c96a01b 100644 --- a/include/swift/SILOptimizer/PassManager/PassManager.h +++ b/include/swift/SILOptimizer/PassManager/PassManager.h @@ -14,7 +14,6 @@ #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/PassManager/PassPipeline.h" #include "swift/SILOptimizer/PassManager/Passes.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Casting.h" diff --git a/include/swift/SILOptimizer/PassManager/PassPipeline.h b/include/swift/SILOptimizer/PassManager/PassPipeline.h index 7df29dc559183..e9ecc77e7a078 100644 --- a/include/swift/SILOptimizer/PassManager/PassPipeline.h +++ b/include/swift/SILOptimizer/PassManager/PassPipeline.h @@ -26,7 +26,6 @@ #define SWIFT_SILOPTIMIZER_PASSMANAGER_PASSPIPELINE_H #include "swift/Basic/LLVM.h" -#include "swift/SILOptimizer/PassManager/PassPipeline.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "llvm/ADT/Hashing.h" #include diff --git a/include/swift/SILOptimizer/Utils/CastOptimizer.h b/include/swift/SILOptimizer/Utils/CastOptimizer.h index f741459d0f191..b80938b972ac1 100644 --- a/include/swift/SILOptimizer/Utils/CastOptimizer.h +++ b/include/swift/SILOptimizer/Utils/CastOptimizer.h @@ -22,7 +22,6 @@ #include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h" #include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" #include #include diff --git a/include/swift/SILOptimizer/Utils/GenericCloner.h b/include/swift/SILOptimizer/Utils/GenericCloner.h index ea0d3aa617d79..7b5a2c424e74c 100644 --- a/include/swift/SILOptimizer/Utils/GenericCloner.h +++ b/include/swift/SILOptimizer/Utils/GenericCloner.h @@ -24,7 +24,6 @@ #include "swift/SIL/TypeSubstCloner.h" #include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" #include "swift/SILOptimizer/Utils/Generics.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include diff --git a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h index b3be068d40051..39b3c6ffa9ad1 100644 --- a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h +++ b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h @@ -35,7 +35,6 @@ #include "swift/SILOptimizer/Analysis/ValueTracking.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" diff --git a/include/swift/SILOptimizer/Utils/SILInliner.h b/include/swift/SILOptimizer/Utils/SILInliner.h index 87a0370450346..0db94ad5f85b9 100644 --- a/include/swift/SILOptimizer/Utils/SILInliner.h +++ b/include/swift/SILOptimizer/Utils/SILInliner.h @@ -22,7 +22,6 @@ #include "swift/SIL/ApplySite.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILOpenedArchetypesTracker.h" -#include "llvm/ADT/DenseMap.h" #include namespace swift { diff --git a/include/swift/Sema/IDETypeChecking.h b/include/swift/Sema/IDETypeChecking.h index 91edfc0ae81b5..6ca626a75f608 100644 --- a/include/swift/Sema/IDETypeChecking.h +++ b/include/swift/Sema/IDETypeChecking.h @@ -19,7 +19,6 @@ #ifndef SWIFT_SEMA_IDETYPECHECKING_H #define SWIFT_SEMA_IDETYPECHECKING_H -#include "llvm/ADT/MapVector.h" #include "swift/AST/Identifier.h" #include "swift/Basic/SourceLoc.h" #include diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index bc4d084dda017..83af39e5fc41a 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -368,8 +368,9 @@ class SerializedASTFile final : public LoadedFile { SmallVectorImpl &results) const override; virtual void - lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const override; + lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const override; Optional getCommentForDecl(const Decl *D) const override; diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h index 35f5131046cfa..09f746dfe1d7e 100644 --- a/include/swift/Subsystems.h +++ b/include/swift/Subsystems.h @@ -22,7 +22,6 @@ #include "swift/Basic/PrimarySpecificPaths.h" #include "swift/Basic/Version.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Mutex.h" diff --git a/include/swift/SwiftRemoteMirror/CMakeLists.txt b/include/swift/SwiftRemoteMirror/CMakeLists.txt index bf259082c1828..64b802099ee49 100644 --- a/include/swift/SwiftRemoteMirror/CMakeLists.txt +++ b/include/swift/SwiftRemoteMirror/CMakeLists.txt @@ -3,7 +3,8 @@ list(APPEND swift_remote_mirror_headers MemoryReaderInterface.h Platform.h SwiftRemoteMirror.h - SwiftRemoteMirrorTypes.h) + SwiftRemoteMirrorTypes.h + module.modulemap) swift_install_in_component(FILES ${swift_remote_mirror_headers} DESTINATION diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h index 4961ef3f0f941..80a448a735f9c 100644 --- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h +++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirror.h @@ -159,6 +159,11 @@ char * swift_reflection_copyDemangledNameForTypeRef( SwiftReflectionContextRef ContextRef, swift_typeref_t OpaqueTypeRef); +SWIFT_REMOTE_MIRROR_LINKAGE +char * +swift_reflection_copyDemangledNameForProtocolDescriptor( + SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto); + /// Returns a structure describing the layout of a value of a typeref. /// For classes, this returns the reference value itself. SWIFT_REMOTE_MIRROR_LINKAGE @@ -283,6 +288,49 @@ SWIFT_REMOTE_MIRROR_LINKAGE size_t swift_reflection_demangle(const char *MangledName, size_t Length, char *OutDemangledName, size_t MaxLength); +/// Iterate over the process's protocol conformance cache. +/// +/// Calls the passed in Call function for each protocol conformance found in +/// the conformance cache. The function is passed the type which conforms and +/// the protocol it conforms to. The ContextPtr is passed through unchanged. +/// +/// Returns NULL on success. On error, returns a pointer to a C string +/// describing the error. This pointer remains valid until the next +/// swift_reflection call on the given context. +SWIFT_REMOTE_MIRROR_LINKAGE +const char *swift_reflection_iterateConformanceCache( + SwiftReflectionContextRef ContextRef, + void (*Call)(swift_reflection_ptr_t Type, + swift_reflection_ptr_t Proto, + void *ContextPtr), + void *ContextPtr); + +/// Iterate over the process's metadata allocations. +/// +/// Calls the passed in Call function for each metadata allocation. The function +/// is passed a structure that describes the allocation. The ContextPtr is +/// passed through unchanged. +/// +/// Returns NULL on success. On error, returns a pointer to a C string +/// describing the error. This pointer remains valid until the next +/// swift_reflection call on the given context. +SWIFT_REMOTE_MIRROR_LINKAGE +const char *swift_reflection_iterateMetadataAllocations( + SwiftReflectionContextRef ContextRef, + void (*Call)(swift_metadata_allocation_t Allocation, + void *ContextPtr), + void *ContextPtr); + +/// Given a metadata allocation, return the metadata it points to. Returns NULL +/// on failure. Despite the name, not all allocations point to metadata. +/// Currently, this will return a metadata only for allocations with tag +/// SWIFT_GENERIC_METADATA_CACHE_ALLOCATION. Support for additional tags may be +/// added in the future. The caller must gracefully handle failure. +SWIFT_REMOTE_MIRROR_LINKAGE +swift_reflection_ptr_t swift_reflection_allocationMetadataPointer( + SwiftReflectionContextRef ContextRef, + swift_metadata_allocation_t Allocation); + #ifdef __cplusplus } // extern "C" #endif diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h index 36393c6c45d68..73ff685ac0e19 100644 --- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h +++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h @@ -141,6 +141,27 @@ typedef struct swift_childinfo { swift_typeref_t TR; } swift_childinfo_t; +// Values here match the values from MetadataAllocatorTags in Metadata.h. +enum swift_metadata_allocation_tag { + SWIFT_GENERIC_METADATA_CACHE_ALLOCATION = 14, +}; + +typedef int swift_metadata_allocation_tag_t; + +/// A metadata allocation made by the Swift runtime. +typedef struct swift_metadata_allocation { + /// The allocation's tag, which describes what kind of allocation it is. This + /// may be one of the values in swift_metadata_allocation_tag, or something + /// else, in which case the tag should be considered unknown. + swift_metadata_allocation_tag_t Tag; + + /// A pointer to the start of the allocation in the remote process. + swift_reflection_ptr_t Ptr; + + /// The size of the allocation in bytes. + unsigned Size; +} swift_metadata_allocation_t; + /// An opaque pointer to a context which maintains state and /// caching of reflection structure for heap instances. typedef struct SwiftReflectionContext *SwiftReflectionContextRef; diff --git a/include/swift/SwiftRemoteMirror/module.modulemap b/include/swift/SwiftRemoteMirror/module.modulemap new file mode 100644 index 0000000000000..61cf3b0fb808b --- /dev/null +++ b/include/swift/SwiftRemoteMirror/module.modulemap @@ -0,0 +1,4 @@ +module SwiftRemoteMirror { + header "SwiftRemoteMirror.h" + export * +} diff --git a/include/swift/Syntax/UnknownSyntax.h b/include/swift/Syntax/UnknownSyntax.h index 1ca339b5db156..4a1e77508498b 100644 --- a/include/swift/Syntax/UnknownSyntax.h +++ b/include/swift/Syntax/UnknownSyntax.h @@ -16,8 +16,6 @@ #include "swift/Syntax/SyntaxData.h" #include "swift/Syntax/Syntax.h" -#include - namespace swift { namespace syntax { diff --git a/include/swift/TBDGen/TBDGen.h b/include/swift/TBDGen/TBDGen.h index c11a81a467d41..1da2386d3132a 100644 --- a/include/swift/TBDGen/TBDGen.h +++ b/include/swift/TBDGen/TBDGen.h @@ -13,7 +13,6 @@ #define SWIFT_IRGEN_TBDGEN_H #include "llvm/ADT/Hashing.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "swift/Basic/Version.h" #include diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 4ad4df3636fc2..979f6ffcbaa35 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -46,8 +46,9 @@ #include "swift/AST/SwiftNameTranslation.h" #include "swift/Parse/Lexer.h" #include "clang/Lex/MacroInfo.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" @@ -6114,8 +6115,8 @@ ParamDecl::ParamDecl(SourceLoc specifierLoc, ParamDecl *ParamDecl::cloneWithoutType(const ASTContext &Ctx, ParamDecl *PD) { auto *Clone = new (Ctx) ParamDecl( - PD->getSpecifierLoc(), PD->getArgumentNameLoc(), PD->getArgumentName(), - PD->getArgumentNameLoc(), PD->getParameterName(), PD->getDeclContext()); + SourceLoc(), SourceLoc(), PD->getArgumentName(), + SourceLoc(), PD->getParameterName(), PD->getDeclContext()); Clone->DefaultValueAndFlags.setPointerAndInt( nullptr, PD->DefaultValueAndFlags.getInt()); Clone->Bits.ParamDecl.defaultArgumentKind = diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6ab5da2eb5810..79ea2455f9eb0 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1889,16 +1889,23 @@ FORWARD_SOURCE_LOCS_TO(ClosureExpr, Body.getPointer()) Expr *ClosureExpr::getSingleExpressionBody() const { assert(hasSingleExpressionBody() && "Not a single-expression body"); auto body = getBody()->getFirstElement(); - if (body.is()) - return cast(body.get())->getResult(); + if (auto stmt = body.dyn_cast()) { + if (auto braceStmt = dyn_cast(stmt)) + return braceStmt->getFirstElement().get(); + + return cast(stmt)->getResult(); + } return body.get(); } void ClosureExpr::setSingleExpressionBody(Expr *NewBody) { assert(hasSingleExpressionBody() && "Not a single-expression body"); auto body = getBody()->getFirstElement(); - if (body.is()) { - cast(body.get())->setResult(NewBody); + if (auto stmt = body.dyn_cast()) { + if (auto braceStmt = dyn_cast(stmt)) + braceStmt->getFirstElement() = NewBody; + else + cast(stmt)->setResult(NewBody); return; } getBody()->setFirstElement(NewBody); diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index c8d4463477ef3..ee348386c1007 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -40,6 +40,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" diff --git a/lib/AST/Module.cpp b/lib/AST/Module.cpp index 68beaa0b785f6..6b1ae78787496 100644 --- a/lib/AST/Module.cpp +++ b/lib/AST/Module.cpp @@ -648,8 +648,9 @@ void ModuleDecl::lookupObjCMethods( FORWARD(lookupObjCMethods, (selector, results)); } -void ModuleDecl::lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const { +void ModuleDecl::lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const { FORWARD(lookupImportedSPIGroups, (importedModule, spiGroups)); } @@ -1933,31 +1934,29 @@ bool SourceFile::isImportedImplementationOnly(const ModuleDecl *module) const { return !imports.isImportedBy(module, getParentModule()); } -void SourceFile::lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const { +void SourceFile::lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const { for (auto &import : *Imports) { if (import.importOptions.contains(ImportFlags::SPIAccessControl) && importedModule == import.module.importedModule) { auto importedSpis = import.spiGroups; - spiGroups.append(importedSpis.begin(), importedSpis.end()); + spiGroups.insert(importedSpis.begin(), importedSpis.end()); } } } bool SourceFile::isImportedAsSPI(const ValueDecl *targetDecl) const { auto targetModule = targetDecl->getModuleContext(); - SmallVector importedSPIGroups; + llvm::SmallSetVector importedSPIGroups; lookupImportedSPIGroups(targetModule, importedSPIGroups); if (importedSPIGroups.empty()) return false; auto declSPIGroups = targetDecl->getSPIGroups(); - // Note: If we reach a point where there are many SPI imports or SPI groups - // on decls we could optimize this further by using a set. - for (auto importedSPI : importedSPIGroups) - for (auto declSPI : declSPIGroups) - if (importedSPI == declSPI) - return true; + for (auto declSPI : declSPIGroups) + if (importedSPIGroups.count(declSPI)) + return true; return false; } diff --git a/lib/Basic/UUID.cpp b/lib/Basic/UUID.cpp index ad90e55810d46..e896aa4cbfe6c 100644 --- a/lib/Basic/UUID.cpp +++ b/lib/Basic/UUID.cpp @@ -16,6 +16,7 @@ //===----------------------------------------------------------------------===// #include "swift/Basic/UUID.h" +#include "llvm/ADT/SmallString.h" // WIN32 doesn't natively support . Instead, we use Win32 APIs. #if defined(_WIN32) diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp index 3c8832acac374..f5a19356b5223 100644 --- a/lib/Demangling/Remangler.cpp +++ b/lib/Demangling/Remangler.cpp @@ -268,8 +268,8 @@ class Remangler : public RemanglerBase { } void mangleChildNode(Node *node, unsigned index) { - assert(index < node->getNumChildren()); - mangle(node->begin()[index]); + if (index < node->getNumChildren()) + mangle(node->begin()[index]); } void manglePureProtocol(Node *Proto) { diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 90065e3fe2aa3..d41a07c1485f6 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -25,6 +25,7 @@ #include "swift/Option/Options.h" #include "clang/Basic/Version.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" diff --git a/lib/Frontend/ModuleInterfaceSupport.cpp b/lib/Frontend/ModuleInterfaceSupport.cpp index 39694452f81d6..27d4c8ec30d3c 100644 --- a/lib/Frontend/ModuleInterfaceSupport.cpp +++ b/lib/Frontend/ModuleInterfaceSupport.cpp @@ -28,6 +28,7 @@ #include "swift/Serialization/Validation.h" #include "clang/Basic/Module.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Path.h" #include "llvm/Support/Regex.h" @@ -130,7 +131,7 @@ static void printImports(raw_ostream &out, // SPI attribute on imports if (Opts.PrintSPIs) { - SmallVector spis; + llvm::SmallSetVector spis; M->lookupImportedSPIGroups(importedModule, spis); for (auto spiName : spis) out << "@_spi(" << spiName << ") "; diff --git a/lib/IDE/ExprContextAnalysis.cpp b/lib/IDE/ExprContextAnalysis.cpp index 9b906ec2a8e74..a4d2914f3b4fd 100644 --- a/lib/IDE/ExprContextAnalysis.cpp +++ b/lib/IDE/ExprContextAnalysis.cpp @@ -32,6 +32,7 @@ #include "swift/Subsystems.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "llvm/ADT/SmallSet.h" using namespace swift; using namespace ide; diff --git a/lib/IDE/TypeContextInfo.cpp b/lib/IDE/TypeContextInfo.cpp index 68e7b672c92d8..1bd6be37e8e5d 100644 --- a/lib/IDE/TypeContextInfo.cpp +++ b/lib/IDE/TypeContextInfo.cpp @@ -19,6 +19,7 @@ #include "swift/Sema/IDETypeChecking.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "llvm/ADT/SmallSet.h" using namespace swift; using namespace ide; diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp index 28060ae9313ec..ef6e5ab9dad33 100644 --- a/lib/IRGen/MetadataRequest.cpp +++ b/lib/IRGen/MetadataRequest.cpp @@ -41,6 +41,7 @@ #include "swift/IRGen/Linking.h" #include "swift/SIL/FormalLinkage.h" #include "swift/SIL/TypeLowering.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Constant.h" #include "llvm/Support/Debug.h" diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 67b02a28ceeb8..6cd20d3dfbf4f 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1503,8 +1503,13 @@ Parser::parseStmtConditionElement(SmallVectorImpl &result, } ThePattern = parseOptionalPatternTypeAnnotation(ThePattern); - if (ThePattern.hasCodeCompletion()) + if (ThePattern.hasCodeCompletion()) { Status.setHasCodeCompletion(); + + // Skip to '=' so that the completion can see the expected type of the + // pattern which is determined by the initializer. + skipUntilDeclStmtRBrace(tok::equal, tok::l_brace); + } if (ThePattern.isNull()) { // Recover by creating AnyPattern. diff --git a/lib/SIL/Verifier/SILVerifier.cpp b/lib/SIL/Verifier/SILVerifier.cpp index 7c666a3bd0886..fdcd178603e18 100644 --- a/lib/SIL/Verifier/SILVerifier.cpp +++ b/lib/SIL/Verifier/SILVerifier.cpp @@ -42,6 +42,7 @@ #include "swift/SIL/TypeLowering.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp index f36705d985435..2f2adfe656bae 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp @@ -63,6 +63,7 @@ #include "swift/SIL/Projection.h" #include "swift/SIL/LoopInfo.h" #include "swift/SIL/SILCloner.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Mandatory/Differentiation.cpp b/lib/SILOptimizer/Mandatory/Differentiation.cpp index 3914cc3380e2f..b05e8a6550e28 100644 --- a/lib/SILOptimizer/Mandatory/Differentiation.cpp +++ b/lib/SILOptimizer/Mandatory/Differentiation.cpp @@ -46,6 +46,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/BreadthFirstIterator.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/CommandLine.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/PhiArgumentOptimizations.cpp b/lib/SILOptimizer/Transforms/PhiArgumentOptimizations.cpp index 1890fcc6f2372..817cdd5eab72a 100644 --- a/lib/SILOptimizer/Transforms/PhiArgumentOptimizations.cpp +++ b/lib/SILOptimizer/Transforms/PhiArgumentOptimizations.cpp @@ -20,6 +20,7 @@ #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILFunction.h" #include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index 498a4ea2d3b59..88c1f6681573b 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -27,7 +27,6 @@ #include "swift/SIL/SILValue.h" #include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" #include "swift/SILOptimizer/Utils/InstOptUtils.h" -#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Casting.h" diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 64f16ddf7040f..f9bedcbee6a0b 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -2,6 +2,7 @@ add_swift_host_library(swiftSema STATIC BuilderTransform.cpp CSApply.cpp CSBindings.cpp + CSClosure.cpp CSGen.cpp CSRanking.cpp CSSimplify.cpp diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 6cacdd41d8a97..78232a90851c2 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -1504,30 +1504,6 @@ namespace { } public: - - - /// Coerce a closure expression with a non-Void return type to a - /// contextual function type with a Void return type. - /// - /// This operation cannot fail. - /// - /// \param expr The closure expression to coerce. - /// - /// \returns The coerced closure expression. - /// - ClosureExpr *coerceClosureExprToVoid(ClosureExpr *expr); - - /// Coerce a closure expression with a Never return type to a - /// contextual function type with some other return type. - /// - /// This operation cannot fail. - /// - /// \param expr The closure expression to coerce. - /// - /// \returns The coerced closure expression. - /// - ClosureExpr *coerceClosureExprFromNever(ClosureExpr *expr); - /// Coerce the given expression to the given type. /// /// This operation cannot fail. @@ -4994,14 +4970,6 @@ namespace { return result; } - const AppliedBuilderTransform *getAppliedBuilderTransform( - AnyFunctionRef fn) { - auto known = solution.functionBuilderTransformed.find(fn); - return known != solution.functionBuilderTransformed.end() - ? &known->second - : nullptr; - } - void finalize() { assert(ExprStack.empty()); assert(OpenedExistentials.empty()); @@ -5831,83 +5799,6 @@ static bool applyTypeToClosureExpr(ConstraintSystem &cs, return false; } -ClosureExpr *ExprRewriter::coerceClosureExprToVoid(ClosureExpr *closureExpr) { - auto &ctx = cs.getASTContext(); - - // Re-write the single-expression closure to return '()' - assert(closureExpr->hasSingleExpressionBody()); - - // A single-expression body contains a single return statement - // prior to this transformation. - auto member = closureExpr->getBody()->getFirstElement(); - - if (member.is()) { - auto returnStmt = cast(member.get()); - auto singleExpr = returnStmt->getResult(); - auto voidExpr = cs.cacheType(TupleExpr::createEmpty( - ctx, singleExpr->getStartLoc(), singleExpr->getEndLoc(), - /*implicit*/ true)); - returnStmt->setResult(voidExpr); - - // For l-value types, reset to the object type. This might not be strictly - // necessary any more, but it's probably still a good idea. - if (cs.getType(singleExpr)->is()) - cs.setType(singleExpr, - cs.getType(singleExpr)->getWithoutSpecifierType()); - - solution.setExprTypes(singleExpr); - TypeChecker::checkIgnoredExpr(singleExpr); - - SmallVector elements; - elements.push_back(singleExpr); - elements.push_back(returnStmt); - - auto braceStmt = BraceStmt::create(ctx, closureExpr->getStartLoc(), - elements, closureExpr->getEndLoc(), - /*implicit*/ true); - - closureExpr->setImplicit(); - closureExpr->setBody(braceStmt, /*isSingleExpression*/true); - } - - // Finally, compute the proper type for the closure. - auto fnType = cs.getType(closureExpr)->getAs(); - auto newClosureType = FunctionType::get( - fnType->getParams(), ctx.TheEmptyTupleType, fnType->getExtInfo()); - cs.setType(closureExpr, newClosureType); - return closureExpr; -} - -ClosureExpr *ExprRewriter::coerceClosureExprFromNever(ClosureExpr *closureExpr) { - // Re-write the single-expression closure to drop the 'return'. - assert(closureExpr->hasSingleExpressionBody()); - - // A single-expression body contains a single return statement - // prior to this transformation. - auto member = closureExpr->getBody()->getFirstElement(); - - if (member.is()) { - auto returnStmt = cast(member.get()); - auto singleExpr = returnStmt->getResult(); - - solution.setExprTypes(singleExpr); - TypeChecker::checkIgnoredExpr(singleExpr); - - SmallVector elements; - elements.push_back(singleExpr); - - auto braceStmt = - BraceStmt::create(cs.getASTContext(), closureExpr->getStartLoc(), - elements, closureExpr->getEndLoc(), - /*implicit*/ true); - - closureExpr->setImplicit(); - closureExpr->setBody(braceStmt, /*isSingleExpression*/true); - } - - return closureExpr; -} - // Look through sugar and DotSyntaxBaseIgnoredExprs. static Expr * getSemanticExprForDeclOrMemberRef(Expr *expr) { @@ -7721,80 +7612,7 @@ namespace { std::pair walkToExprPre(Expr *expr) override { // For closures, update the parameter types and check the body. if (auto closure = dyn_cast(expr)) { - Rewriter.simplifyExprType(expr); - auto &cs = Rewriter.getConstraintSystem(); - - // Coerce the pattern, in case we resolved something. - auto fnType = cs.getType(closure)->castTo(); - auto *params = closure->getParameters(); - TypeChecker::coerceParameterListToType(params, closure, fnType); - - if (closure->hasExplicitResultType()) { - closure->setExplicitResultType(fnType->getResult()); - } - - if (auto transform = - Rewriter.getAppliedBuilderTransform(closure)) { - // Apply the function builder to the closure. We want to be in the - // context of the closure for subsequent transforms. - llvm::SaveAndRestore savedDC(Rewriter.dc, closure); - auto newBody = applyFunctionBuilderTransform( - Rewriter.solution, *transform, closure->getBody(), closure, - [&](SolutionApplicationTarget target) { - auto resultTarget = rewriteTarget(target); - if (resultTarget) { - if (auto expr = resultTarget->getAsExpr()) - Rewriter.solution.setExprTypes(expr); - } - - return resultTarget; - }); - closure->setBody(newBody, /*isSingleExpression=*/false); - closure->setAppliedFunctionBuilder(); - - Rewriter.solution.setExprTypes(closure); - } else if (closure->hasSingleExpressionBody()) { - // If this is a single-expression closure, convert the expression - // in the body to the result type of the closure. - - // Enter the context of the closure when type-checking the body. - llvm::SaveAndRestore savedDC(Rewriter.dc, closure); - Expr *body = closure->getSingleExpressionBody()->walk(*this); - if (!body) - return { false, nullptr }; - - if (body != closure->getSingleExpressionBody()) - closure->setSingleExpressionBody(body); - - if (body) { - // A single-expression closure with a non-Void expression type - // coerces to a Void-returning function type. - if (fnType->getResult()->isVoid() && !cs.getType(body)->isVoid()) { - closure = Rewriter.coerceClosureExprToVoid(closure); - // A single-expression closure with a Never expression type - // coerces to any other function type. - } else if (cs.getType(body)->isUninhabited()) { - closure = Rewriter.coerceClosureExprFromNever(closure); - } else { - - body = Rewriter.coerceToType(body, - fnType->getResult(), - cs.getConstraintLocator( - closure, - ConstraintLocator::ClosureResult)); - if (!body) - return { false, nullptr }; - - closure->setSingleExpressionBody(body); - } - } - } else { - // For other closures, type-check the body once we've finished with - // the expression. - Rewriter.solution.setExprTypes(closure); - ClosuresToTypeCheck.push_back(closure); - } - + rewriteFunction(closure); return { false, closure }; } @@ -7823,6 +7641,37 @@ namespace { /// Rewrite the target, producing a new target. Optional rewriteTarget(SolutionApplicationTarget target); + + /// Rewrite the function for the given solution. + /// + /// \returns true if an error occurred. + bool rewriteFunction(AnyFunctionRef fn) { + auto result = Rewriter.cs.applySolution( + Rewriter.solution, fn, Rewriter.dc, + [&](SolutionApplicationTarget target) { + auto resultTarget = rewriteTarget(target); + if (resultTarget) { + if (auto expr = resultTarget->getAsExpr()) + Rewriter.solution.setExprTypes(expr); + } + + return resultTarget; + }); + + switch (result) { + case SolutionApplicationToFunctionResult::Success: + return false; + + case SolutionApplicationToFunctionResult::Failure: + return true; + + case SolutionApplicationToFunctionResult::Delay: { + auto closure = cast(fn.getAbstractClosureExpr()); + ClosuresToTypeCheck.push_back(closure); + return false; + } + } + } }; } // end anonymous namespace @@ -8256,28 +8105,10 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { return target; } else { auto fn = *target.getAsFunction(); - - // Dig out the function builder transformation we applied. - auto transform = Rewriter.getAppliedBuilderTransform(fn); - assert(transform); - - auto newBody = applyFunctionBuilderTransform( - solution, *transform, fn.getBody(), fn.getAsDeclContext(), - [&](SolutionApplicationTarget target) { - auto resultTarget = rewriteTarget(target); - if (resultTarget) { - if (auto expr = resultTarget->getAsExpr()) - solution.setExprTypes(expr); - } - - return resultTarget; - }); - - if (!newBody) + if (rewriteFunction(fn)) return None; - result.setFunctionBody(newBody); - fn.getAbstractFunctionDecl()->setHasSingleExpressionBody(false); + result.setFunctionBody(fn.getBody()); } // Follow-up tasks. diff --git a/lib/Sema/CSClosure.cpp b/lib/Sema/CSClosure.cpp new file mode 100644 index 0000000000000..592fca0024441 --- /dev/null +++ b/lib/Sema/CSClosure.cpp @@ -0,0 +1,352 @@ +//===--- CSClosure.cpp - Closures -----------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2018 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements constraint generation and solution application for +// closures. It provides part of the implementation of the ConstraintSystem +// class. +// +//===----------------------------------------------------------------------===// + +#include "ConstraintSystem.h" +using namespace swift; +using namespace swift::constraints; + +namespace { + +// MARK: Constraint generation + +/// Statement visitor that generates constraints for a given closure body. +class ClosureConstraintGenerator + : public StmtVisitor { + friend StmtVisitor; + + ConstraintSystem &cs; + ClosureExpr *closure; + Type closureResultType; + +public: + /// Whether an error was encountered while generating constraints. + bool hadError = false; + + ClosureConstraintGenerator(ConstraintSystem &cs, ClosureExpr *closure, + Type closureResultType) + : cs(cs), closure(closure), closureResultType(closureResultType) { } + +private: + void visitDecl(Decl *decl) { + // Just ignore #if; the chosen children should appear in the + // surrounding context. This isn't good for source tools but it + // at least works. + if (isa(decl)) + return; + + // Skip #warning/#error; we'll handle them when applying the closure. + if (isa(decl)) + return; + + // Ignore variable declarations, because they're always handled within + // their enclosing pattern bindings. + if (isa(decl)) + return; + + llvm_unreachable("Unimplemented case for closure body"); + } + + void visitBraceStmt(BraceStmt *braceStmt) { + for (auto node : braceStmt->getElements()) { + if (auto expr = node.dyn_cast()) { + auto generatedExpr = cs.generateConstraints( + expr, closure, /*isInputExpression=*/false); + if (!generatedExpr) { + hadError = true; + } + } else if (auto stmt = node.dyn_cast()) { + visit(stmt); + } else { + visitDecl(node.get()); + } + } + } + + void visitReturnStmt(ReturnStmt *returnStmt) { + auto expr = returnStmt->getResult(); + + // FIXME: Implies Void return? + if (!expr) + return; + + expr = cs.generateConstraints(expr, closure, /*isInputExpression=*/false); + if (!expr) { + hadError = true; + return; + } + + // FIXME: Locator should point at the return statement? + bool hasReturn = hasExplicitResult(closure); + cs.addConstraint( + ConstraintKind::Conversion, cs.getType(expr), + closureResultType, + cs.getConstraintLocator( + closure, LocatorPathElt::ClosureBody(hasReturn))); + } + +#define UNSUPPORTED_STMT(STMT) void visit##STMT##Stmt(STMT##Stmt *) { \ + llvm_unreachable("Unsupported statement kind " #STMT); \ + } + UNSUPPORTED_STMT(Yield) + UNSUPPORTED_STMT(Defer) + UNSUPPORTED_STMT(If) + UNSUPPORTED_STMT(Guard) + UNSUPPORTED_STMT(While) + UNSUPPORTED_STMT(Do) + UNSUPPORTED_STMT(DoCatch) + UNSUPPORTED_STMT(RepeatWhile) + UNSUPPORTED_STMT(ForEach) + UNSUPPORTED_STMT(Switch) + UNSUPPORTED_STMT(Case) + UNSUPPORTED_STMT(Break) + UNSUPPORTED_STMT(Continue) + UNSUPPORTED_STMT(Fallthrough) + UNSUPPORTED_STMT(Fail) + UNSUPPORTED_STMT(Throw) + UNSUPPORTED_STMT(PoundAssert) +#undef UNSUPPORTED_STMT +}; + +} + +bool ConstraintSystem::generateConstraints( + ClosureExpr *closure, Type resultType) { + ClosureConstraintGenerator generator(*this, closure, resultType); + generator.visit(closure->getBody()); + return generator.hadError; +} + +// MARK: Solution application + +namespace { + +/// Statement visitor that applies constraints for a given closure body. +class ClosureConstraintApplication + : public StmtVisitor { + friend StmtVisitor; + + Solution &solution; + ClosureExpr *closure; + Type resultType; + RewriteTargetFn rewriteTarget; + bool isSingleExpression; + +public: + /// Whether an error was encountered while generating constraints. + bool hadError = false; + + ClosureConstraintApplication( + Solution &solution, ClosureExpr *closure, Type resultType, + RewriteTargetFn rewriteTarget) + : solution(solution), closure(closure), resultType(resultType), + rewriteTarget(rewriteTarget), + isSingleExpression(closure->hasSingleExpressionBody()) { } + +private: + /// Rewrite an expression without any particularly special context. + Expr *rewriteExpr(Expr *expr) { + auto result = rewriteTarget( + SolutionApplicationTarget(expr, closure, CTP_Unused, Type(), + /*isDiscarded=*/false)); + if (result) + return result->getAsExpr(); + + return nullptr; + } + + void visitDecl(Decl *decl) { + llvm_unreachable("Declarations not supported"); + } + + ASTNode visitBraceStmt(BraceStmt *braceStmt) { + for (auto &node : braceStmt->getElements()) { + if (auto expr = node.dyn_cast()) { + // Rewrite the expression. + if (auto rewrittenExpr = rewriteExpr(expr)) + node = expr; + else + hadError = true; + } else if (auto stmt = node.dyn_cast()) { + node = visit(stmt); + } else { + visitDecl(node.get()); + } + } + + return braceStmt; + } + + ASTNode visitReturnStmt(ReturnStmt *returnStmt) { + auto resultExpr = returnStmt->getResult(); + if (!resultExpr) + return returnStmt; + + enum { + convertToResult, + coerceToVoid, + coerceFromNever, + } mode; + + auto resultExprType = + solution.simplifyType(solution.getType(resultExpr))->getRValueType(); + // A closure with a non-void return expression can coerce to a closure + // that returns Void. + if (resultType->isVoid() && !resultExprType->isVoid()) { + mode = coerceToVoid; + + // A single-expression closure with a Never expression type + // coerces to any other function type. + } else if (isSingleExpression && resultExprType->isUninhabited()) { + mode = coerceFromNever; + + // Normal rule is to coerce to the return expression to the closure type. + } else { + mode = convertToResult; + } + + SolutionApplicationTarget resultTarget( + resultExpr, closure, + mode == convertToResult ? CTP_ReturnStmt : CTP_Unused, + mode == convertToResult ? resultType : Type(), + /*isDiscarded=*/false); + if (auto newResultTarget = rewriteTarget(resultTarget)) + resultExpr = newResultTarget->getAsExpr(); + + switch (mode) { + case convertToResult: + // Record the coerced expression. + returnStmt->setResult(resultExpr); + return returnStmt; + + case coerceToVoid: { + // Evaluate the expression, then produce a return statement that + // returns nothing. + TypeChecker::checkIgnoredExpr(resultExpr); + auto &ctx = solution.getConstraintSystem().getASTContext(); + auto newReturnStmt = + new (ctx) ReturnStmt( + returnStmt->getStartLoc(), nullptr, /*implicit=*/true); + ASTNode elements[2] = { resultExpr, newReturnStmt }; + return BraceStmt::create(ctx, returnStmt->getStartLoc(), + elements, returnStmt->getEndLoc(), + /*implicit*/ true); + } + + case coerceFromNever: + // Replace the return statement with its expression, so that the + // expression is evaluated directly. This only works because coercion + // from never is limited to single-expression closures. + return resultExpr; + } + + return returnStmt; + } + +#define UNSUPPORTED_STMT(STMT) ASTNode visit##STMT##Stmt(STMT##Stmt *) { \ + llvm_unreachable("Unsupported statement kind " #STMT); \ + } + UNSUPPORTED_STMT(Yield) + UNSUPPORTED_STMT(Defer) + UNSUPPORTED_STMT(If) + UNSUPPORTED_STMT(Guard) + UNSUPPORTED_STMT(While) + UNSUPPORTED_STMT(Do) + UNSUPPORTED_STMT(DoCatch) + UNSUPPORTED_STMT(RepeatWhile) + UNSUPPORTED_STMT(ForEach) + UNSUPPORTED_STMT(Switch) + UNSUPPORTED_STMT(Case) + UNSUPPORTED_STMT(Break) + UNSUPPORTED_STMT(Continue) + UNSUPPORTED_STMT(Fallthrough) + UNSUPPORTED_STMT(Fail) + UNSUPPORTED_STMT(Throw) + UNSUPPORTED_STMT(PoundAssert) +#undef UNSUPPORTED_STMT + +}; + +} + +SolutionApplicationToFunctionResult ConstraintSystem::applySolution( + Solution &solution, AnyFunctionRef fn, + DeclContext *¤tDC, + RewriteTargetFn rewriteTarget) { + auto &cs = solution.getConstraintSystem(); + auto closure = dyn_cast_or_null(fn.getAbstractClosureExpr()); + FunctionType *closureFnType = nullptr; + if (closure) { + // Update the closure's type. + auto closureType = solution.simplifyType(cs.getType(closure)); + cs.setType(closure, closureType); + + // Coerce the parameter types. + closureFnType = closureType->castTo(); + auto *params = closure->getParameters(); + TypeChecker::coerceParameterListToType(params, closure, closureFnType); + + // Coerce the result type, if it was written explicitly. + if (closure->hasExplicitResultType()) { + closure->setExplicitResultType(closureFnType->getResult()); + } + } + + // Enter the context of the function before performing any additional + // transformations. + llvm::SaveAndRestore savedDC(currentDC, fn.getAsDeclContext()); + + // Apply the function builder transform, if there is one. + if (auto transform = solution.getAppliedBuilderTransform(fn)) { + // Apply the function builder to the closure. We want to be in the + // context of the closure for subsequent transforms. + auto newBody = applyFunctionBuilderTransform( + solution, *transform, fn.getBody(), fn.getAsDeclContext(), + [&](SolutionApplicationTarget target) { + auto resultTarget = rewriteTarget(target); + if (resultTarget) { + if (auto expr = resultTarget->getAsExpr()) + solution.setExprTypes(expr); + } + + return resultTarget; + }); + if (!newBody) + return SolutionApplicationToFunctionResult::Failure; + + fn.setBody(newBody, /*isSingleExpression=*/false); + if (closure) { + closure->setAppliedFunctionBuilder(); + solution.setExprTypes(closure); + } + + return SolutionApplicationToFunctionResult::Success; + } + + // If there is a single-expression body, transform that body now. + if (fn.hasSingleExpressionBody()) { + ClosureConstraintApplication application( + solution, closure, closureFnType->getResult(), rewriteTarget); + application.visit(fn.getBody()); + + return SolutionApplicationToFunctionResult::Success; + } + + // Otherwise, we need to delay type checking of the closure until later. + solution.setExprTypes(closure); + return SolutionApplicationToFunctionResult::Delay; +} diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index ff51ff4097f70..3fabb0505b120 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -28,6 +28,7 @@ #include "swift/Subsystems.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include @@ -4418,14 +4419,10 @@ bool ConstraintSystem::generateConstraints( llvm_unreachable("BOOM"); } -Expr *ConstraintSystem::generateConstraints(ClosureExpr *closure) { - assert(closure->hasSingleExpressionBody()); - return generateConstraintsFor(*this, closure->getSingleExpressionBody(), - closure); -} - -Expr *ConstraintSystem::generateConstraints(Expr *expr, DeclContext *dc) { - InputExprs.insert(expr); +Expr *ConstraintSystem::generateConstraints( + Expr *expr, DeclContext *dc, bool isInputExpression) { + if (isInputExpression) + InputExprs.insert(expr); return generateConstraintsFor(*this, expr, dc); } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 51bc765d50ed6..f3a146f9ba32a 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7162,14 +7162,8 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar, // If this is a multi-statement closure its body doesn't participate // in type-checking. if (closure->hasSingleExpressionBody()) { - auto *closureBody = generateConstraints(closure); - if (!closureBody) + if (generateConstraints(closure, closureType->getResult())) return false; - - addConstraint( - ConstraintKind::Conversion, getType(closureBody), - closureType->getResult(), - getConstraintLocator(closure, LocatorPathElt::ClosureBody(hasReturn))); } else if (!hasReturn) { // If this closure has an empty body and no explicit result type // let's bind result type to `Void` since that's the only type empty body diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index cf30977daf891..4c8f4c977ecd4 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -22,6 +22,7 @@ #include "swift/AST/TypeWalker.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/SaveAndRestore.h" diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 40ad7edae7db1..9e112c9aab259 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -27,6 +27,7 @@ #include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/Statistic.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Format.h" diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 28b68e4779354..60cf395ea1fda 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -1043,6 +1043,15 @@ class Solution { Optional getFunctionArgApplyInfo(ConstraintLocator *) const; + /// Retrieve the builder transform that was applied to this function, if any. + const AppliedBuilderTransform *getAppliedBuilderTransform( + AnyFunctionRef fn) const { + auto known = functionBuilderTransformed.find(fn); + return known != functionBuilderTransformed.end() + ? &known->second + : nullptr; + } + SWIFT_DEBUG_DUMP; /// Dump this solution. @@ -1616,6 +1625,11 @@ class SolutionApplicationTarget { SolutionApplicationTarget walk(ASTWalker &walker); }; +/// A function that rewrites a solution application target in the context +/// of solution application. +using RewriteTargetFn = std::function< + Optional (SolutionApplicationTarget)>; + enum class ConstraintSystemPhase { ConstraintGeneration, Solving, @@ -1623,6 +1637,18 @@ enum class ConstraintSystemPhase { Finalization }; +/// Describes the result of applying a solution to a given function. +enum class SolutionApplicationToFunctionResult { + /// Application of the solution succeeded. + Success, + /// Application of the solution failed. + /// TODO: This should probably go away entirely. + Failure, + /// The solution could not be applied immediately, and type checking for + /// this function should be delayed until later. + Delay, +}; + /// Describes a system of constraints on type variables, the /// solution of which assigns concrete types to each of the type variables. /// Constraint systems are typically generated given an (untyped) expression. @@ -3576,15 +3602,19 @@ class ConstraintSystem { bool generateConstraints(SolutionApplicationTarget &target, FreeTypeVariableBinding allowFreeTypeVariables); - /// Generate constraints for the body of the given single-statement closure. + /// Generate constraints for the body of the given closure. /// - /// \returns a possibly-sanitized expression, or null if an error occurred. - Expr *generateConstraints(ClosureExpr *closure); + /// \param closure the closure expression + /// \param resultType the closure's result type + /// + /// \returns \c true if constraint generation failed, \c false otherwise + bool generateConstraints(ClosureExpr *closure, Type resultType); /// Generate constraints for the given (unchecked) expression. /// /// \returns a possibly-sanitized expression, or null if an error occurred. - Expr *generateConstraints(Expr *E, DeclContext *dc); + Expr *generateConstraints(Expr *E, DeclContext *dc, + bool isInputExpression = true); /// Generate constraints for binding the given pattern to the /// value of the given expression. @@ -4677,6 +4707,23 @@ class ConstraintSystem { Optional applySolution( Solution &solution, StmtCondition condition, DeclContext *dc); + /// Apply the given solution to the given function's body and, for + /// closure expressions, the expression itself. + /// + /// \param solution The solution to apply. + /// \param fn The function to which the solution is being applied. + /// \param currentDC The declaration context in which transformations + /// will be applied. + /// \param rewriteTarget Function that performs a rewrite of any + /// solution application target within the context. + /// + SolutionApplicationToFunctionResult applySolution( + Solution &solution, AnyFunctionRef fn, + DeclContext *¤tDC, + std::function< + Optional (SolutionApplicationTarget)> + rewriteTarget); + /// Reorder the disjunctive clauses for a given expression to /// increase the likelihood that a favored constraint will be successfully /// resolved before any others. diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 3ca81535d1f60..dd26ab5e44062 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -2663,13 +2663,14 @@ void ModuleFile::lookupObjCMethods( } } -void ModuleFile::lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const { +void ModuleFile::lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const { for (auto &dep : Dependencies) { auto depSpis = dep.spiGroups; if (dep.Import.hasValue() && dep.Import->importedModule == importedModule && !depSpis.empty()) { - spiGroups.append(depSpis.begin(), depSpis.end()); + spiGroups.insert(depSpis.begin(), depSpis.end()); } } } diff --git a/lib/Serialization/ModuleFile.h b/lib/Serialization/ModuleFile.h index 72d25041af509..0b239c86cbbcc 100644 --- a/lib/Serialization/ModuleFile.h +++ b/lib/Serialization/ModuleFile.h @@ -26,6 +26,7 @@ #include "clang/AST/Type.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Bitstream/BitstreamReader.h" #include "llvm/Support/Error.h" @@ -812,8 +813,9 @@ class ModuleFile /// Find all SPI names imported from \p importedModule by this module, /// collecting the identifiers in \p spiGroups. - void lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const; + void lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const; /// Reports all link-time dependencies. void collectLinkLibraries(ModuleDecl::LinkLibraryCallback callback) const; diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 24992f2b4b051..445399bc36c90 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1082,7 +1082,7 @@ void Serializer::writeInputBlock(const SerializationOptions &options) { else stableImportControl = ImportControl::ImplementationOnly; - SmallVector spis; + llvm::SmallSetVector spis; M->lookupImportedSPIGroups(import.importedModule, spis); ImportedModule.emit(ScratchRecord, diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index ed67fda78129d..e8ce91f5936ae 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -1176,8 +1176,9 @@ void SerializedASTFile::lookupObjCMethods( File.lookupObjCMethods(selector, results); } -void SerializedASTFile::lookupImportedSPIGroups(const ModuleDecl *importedModule, - SmallVectorImpl &spiGroups) const { +void SerializedASTFile::lookupImportedSPIGroups( + const ModuleDecl *importedModule, + llvm::SmallSetVector &spiGroups) const { File.lookupImportedSPIGroups(importedModule, spiGroups); } diff --git a/stdlib/public/CMakeLists.txt b/stdlib/public/CMakeLists.txt index 731bbfba4d0b2..7cf3ab11b0b0b 100644 --- a/stdlib/public/CMakeLists.txt +++ b/stdlib/public/CMakeLists.txt @@ -50,6 +50,34 @@ endif() add_subdirectory(SwiftShims) +# This static library is shared across swiftCore and swiftReflection +if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR) + # TODO: due to the use of `add_swift_target_library` rather than `add_library` + # we cannot use `target_sources` and thus must resort to list manipulations to + # adjust the source list. + set(swiftDemanglingSources + "${SWIFT_SOURCE_DIR}/lib/Demangling/Context.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/Demangler.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/ManglingUtils.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/NodePrinter.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/OldDemangler.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/OldRemangler.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/Punycode.cpp" + "${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp") + + # When we're building with assertions, include the demangle node dumper to aid + # in debugging. + if(LLVM_ENABLE_ASSERTIONS) + list(APPEND swiftDemanglingSources + "${SWIFT_SOURCE_DIR}/lib/Demangling/NodeDumper.cpp") + endif() + + add_swift_target_library(swiftDemangling OBJECT_LIBRARY + ${swiftDemanglingSources} + C_COMPILE_FLAGS -DswiftCore_EXPORTS + INSTALL_IN_COMPONENT never_install) +endif() + if(SWIFT_BUILD_STDLIB) # These must be kept in dependency order so that any referenced targets # exist at the time we look for them in add_swift_*. diff --git a/stdlib/public/Darwin/Foundation/NSStringAPI.swift b/stdlib/public/Darwin/Foundation/NSStringAPI.swift index b906126193a5e..b8c087687aeeb 100644 --- a/stdlib/public/Darwin/Foundation/NSStringAPI.swift +++ b/stdlib/public/Darwin/Foundation/NSStringAPI.swift @@ -73,10 +73,10 @@ internal func _persistCString(_ p: UnsafePointer?) -> [CChar]? { guard let cString = p else { return nil } - let len = UTF8._nullCodeUnitOffset(in: cString) - var result = [CChar](repeating: 0, count: len + 1) - for i in 0..>>; +using Runtime = External>; +using NativeReflectionContext = swift::reflection::ReflectionContext; struct SwiftReflectionContext { NativeReflectionContext *nativeContext; std::vector> freeFuncs; std::vector> dataSegments; + std::string lastError; SwiftReflectionContext(MemoryReaderImpl impl) { auto Reader = std::make_shared(impl); @@ -280,6 +281,18 @@ swift_reflection_copyDemangledNameForTypeRef( return strdup(Name.c_str()); } +SWIFT_REMOTE_MIRROR_LINKAGE +char * +swift_reflection_copyDemangledNameForProtocolDescriptor( + SwiftReflectionContextRef ContextRef, swift_reflection_ptr_t Proto) { + auto Context = ContextRef->nativeContext; + + Demangle::Demangler Dem; + auto Demangling = Context->readDemanglingForContextDescriptor(Proto, Dem); + auto Name = nodeToString(Demangling); + return strdup(Name.c_str()); +} + swift_typeref_t swift_reflection_genericArgumentOfTypeRef(swift_typeref_t OpaqueTypeRef, unsigned Index) { @@ -410,6 +423,15 @@ static swift_childinfo_t convertChild(const TypeInfo *TI, unsigned Index) { }; } +static const char *convertError(SwiftReflectionContextRef ContextRef, + llvm::Optional Error) { + if (Error) { + ContextRef->lastError = *Error; + return ContextRef->lastError.c_str(); + } + return nullptr; +} + swift_typeinfo_t swift_reflection_infoForTypeRef(SwiftReflectionContextRef ContextRef, swift_typeref_t OpaqueTypeRef) { @@ -572,3 +594,44 @@ size_t swift_reflection_demangle(const char *MangledName, size_t Length, strncpy(OutDemangledName, Demangled.c_str(), MaxLength); return Demangled.size(); } + +const char *swift_reflection_iterateConformanceCache( + SwiftReflectionContextRef ContextRef, + void (*Call)(swift_reflection_ptr_t Type, + swift_reflection_ptr_t Proto, + void *ContextPtr), + void *ContextPtr) { + auto Context = ContextRef->nativeContext; + auto Error = Context->iterateConformances([&](auto Type, auto Proto) { + Call(Type, Proto, ContextPtr); + }); + return convertError(ContextRef, Error); +} + +const char *swift_reflection_iterateMetadataAllocations( + SwiftReflectionContextRef ContextRef, + void (*Call)(swift_metadata_allocation_t Allocation, + void *ContextPtr), + void *ContextPtr) { + auto Context = ContextRef->nativeContext; + auto Error = Context->iterateMetadataAllocations([&](auto Allocation) { + swift_metadata_allocation CAllocation; + CAllocation.Tag = Allocation.Tag; + CAllocation.Ptr = Allocation.Ptr; + CAllocation.Size = Allocation.Size; + Call(CAllocation, ContextPtr); + }); + return convertError(ContextRef, Error); +} + +SWIFT_REMOTE_MIRROR_LINKAGE +swift_reflection_ptr_t swift_reflection_allocationMetadataPointer( + SwiftReflectionContextRef ContextRef, + swift_metadata_allocation_t Allocation) { + auto Context = ContextRef->nativeContext; + MetadataAllocation NativeAllocation; + NativeAllocation.Tag = Allocation.Tag; + NativeAllocation.Ptr = Allocation.Ptr; + NativeAllocation.Size = Allocation.Size; + return Context->allocationMetadataPointer(NativeAllocation); +} diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index a54ae587ff4ee..2d33bc1769fbe 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -321,7 +321,7 @@ add_swift_target_library(swiftCore PRIVATE_LINK_LIBRARIES ${swift_core_private_link_libraries} INCORPORATE_OBJECT_LIBRARIES - swiftRuntime swiftLLVMSupport swiftStdlibStubs + swiftRuntime swiftLLVMSupport swiftDemangling swiftStdlibStubs FRAMEWORK_DEPENDS ${swift_core_framework_depends} INSTALL_IN_COMPONENT diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb index 844286bfdeddc..393f7924aca79 100644 --- a/stdlib/public/core/FloatingPointTypes.swift.gyb +++ b/stdlib/public/core/FloatingPointTypes.swift.gyb @@ -13,6 +13,7 @@ import SwiftShims %{ +from __future__ import division from SwiftIntTypes import all_integer_types from SwiftFloatingPointTypes import all_floating_point_types @@ -981,7 +982,7 @@ extension ${Self}: Hashable { %elif bits == 64: return Hasher._hash(seed: seed, v.bitPattern) %elif bits < 64: - return Hasher._hash(seed: seed, bytes: UInt64(v.bitPattern), count: ${bits/8}) + return Hasher._hash(seed: seed, bytes: UInt64(v.bitPattern), count: ${bits//8}) %else: #error("Unimplemented") %end diff --git a/stdlib/public/core/IntegerTypes.swift.gyb b/stdlib/public/core/IntegerTypes.swift.gyb index 4cdb3348e9a3d..34c1ae509c660 100644 --- a/stdlib/public/core/IntegerTypes.swift.gyb +++ b/stdlib/public/core/IntegerTypes.swift.gyb @@ -14,10 +14,10 @@ # Utility code for later in this template # +from __future__ import division from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init from SwiftFloatingPointTypes import getFtoIBounds -from string import maketrans, capitalize from itertools import chain # Number of bits in the Builtin.Word type @@ -1658,7 +1658,7 @@ extension ${Self}: Hashable { return Hasher._hash( seed: seed, bytes: UInt64(truncatingIfNeeded: ${U}${Self}(_value)), - count: ${bits / 8}) + count: ${bits // 8}) % end } } diff --git a/stdlib/public/core/SIMDVectorTypes.swift.gyb b/stdlib/public/core/SIMDVectorTypes.swift.gyb index 925253a92854b..ba887ed6f81be 100644 --- a/stdlib/public/core/SIMDVectorTypes.swift.gyb +++ b/stdlib/public/core/SIMDVectorTypes.swift.gyb @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// %{ +from __future__ import division from SwiftIntTypes import all_integer_types word_bits = int(CMAKE_SIZEOF_VOID_P) * 8 storagescalarCounts = [2,4,8,16,32,64] @@ -90,17 +91,17 @@ public struct SIMD${n}: SIMD where Scalar: SIMDScalar { % if n >= 4: /// Creates a new vector from two half-length vectors. @_transparent - public init(lowHalf: SIMD${n/2}, highHalf: SIMD${n/2}) { + public init(lowHalf: SIMD${n//2}, highHalf: SIMD${n//2}) { self.init() self.lowHalf = lowHalf self.highHalf = highHalf } -% for (half,indx) in [('low','i'), ('high',str(n/2)+'+i'), ('even','2*i'), ('odd','2*i+1')]: +% for (half,indx) in [('low','i'), ('high',str(n//2)+'+i'), ('even','2*i'), ('odd','2*i+1')]: /// A half-length vector made up of the ${half} elements of the vector. - public var ${half}Half: SIMD${n/2} { + public var ${half}Half: SIMD${n//2} { @inlinable get { - var result = SIMD${n/2}() + var result = SIMD${n//2}() for i in result.indices { result[i] = self[${indx}] } return result } @@ -159,7 +160,7 @@ extension SIMD${n}: CustomDebugStringConvertible { public var debugDescription: String { return "SIMD${n}<\(Scalar.self)>(${', '.join(map(lambda c: '\\(self['+ str(c) + '])', - xrange(n)))})" + range(n)))})" } } @@ -212,7 +213,7 @@ extension ${Self}: SIMDScalar { public typealias SIMDMaskScalar = ${Mask} % for n in storagescalarCounts: -% bytes = n * self_type.bits / 8 +% bytes = n * self_type.bits // 8 /// Storage for a vector of ${spelledNumbers[n]} integers. @frozen @_alignment(${bytes if bytes <= 16 else 16}) @@ -260,7 +261,7 @@ extension ${Self} : SIMDScalar { public typealias SIMDMaskScalar = Int${bits} % for n in storagescalarCounts: -% bytes = n * bits / 8 +% bytes = n * bits // 8 /// Storage for a vector of ${spelledNumbers[n]} floating-point values. @frozen @_alignment(${bytes if bytes <= 16 else 16}) diff --git a/stdlib/public/core/Tuple.swift.gyb b/stdlib/public/core/Tuple.swift.gyb index 29548c92d0e17..63d7ee25f0c96 100644 --- a/stdlib/public/core/Tuple.swift.gyb +++ b/stdlib/public/core/Tuple.swift.gyb @@ -111,7 +111,7 @@ public func >=(lhs: (), rhs: ()) -> Bool { % equatableTypeParams = ", ".join(["{}: Equatable".format(c) for c in typeParams]) % originalTuple = "(\"a\", {})".format(", ".join(map(str, range(1, arity)))) -% greaterTuple = "(\"a\", {})".format(", ".join(map(str, range(1, arity - 1) + [arity]))) +% greaterTuple = "(\"a\", {})".format(", ".join(map(str, list(range(1, arity - 1)) + [arity]))) /// Returns a Boolean value indicating whether the corresponding components of /// two tuples are equal. diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt index eaf77fe23e015..c73961205828d 100644 --- a/stdlib/public/runtime/CMakeLists.txt +++ b/stdlib/public/runtime/CMakeLists.txt @@ -23,10 +23,7 @@ set(swift_runtime_objc_sources SwiftObject.mm SwiftValue.mm ReflectionMirror.mm - ObjCRuntimeGetImageNameFromClass.mm - "${SWIFT_SOURCE_DIR}/lib/Demangling/OldRemangler.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/Remangler.cpp" - ) + ObjCRuntimeGetImageNameFromClass.mm) set(swift_runtime_sources AnyHashableSupport.cpp @@ -62,19 +59,7 @@ set(swift_runtime_sources ProtocolConformance.cpp RefCount.cpp RuntimeInvocationsTracking.cpp - SwiftDtoa.cpp - "${SWIFT_SOURCE_DIR}/lib/Demangling/OldDemangler.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/Demangler.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/NodePrinter.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/Context.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/ManglingUtils.cpp" - "${SWIFT_SOURCE_DIR}/lib/Demangling/Punycode.cpp") - -# When we're building with assertions, include the demangle node dumper to aid -# in debugging. -if (LLVM_ENABLE_ASSERTIONS) - list(APPEND swift_runtime_sources "${SWIFT_SOURCE_DIR}/lib/Demangling/NodeDumper.cpp") -endif(LLVM_ENABLE_ASSERTIONS) + SwiftDtoa.cpp) # Acknowledge that the following sources are known. set(LLVM_OPTIONAL_SOURCES @@ -174,7 +159,6 @@ add_swift_target_library(swiftRuntime OBJECT_LIBRARY ${swift_runtime_library_compile_flags} ${_RUNTIME_NONATOMIC_FLAGS} LINK_FLAGS ${swift_runtime_linker_flags} - INCORPORATE_OBJECT_LIBRARIES swiftLLVMSupport SWIFT_COMPILE_FLAGS ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS} INSTALL_IN_COMPONENT never_install) diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp index 2db36a4671c66..9c38b5ed1d5e5 100644 --- a/stdlib/public/runtime/HeapObject.cpp +++ b/stdlib/public/runtime/HeapObject.cpp @@ -243,7 +243,7 @@ class BoxCacheEntry { } // end anonymous namespace -static SimpleGlobalCache Boxes; +static SimpleGlobalCache Boxes; BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type, size_t alignMask) { diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp index b520ebbbdb326..fbafd97872c12 100644 --- a/stdlib/public/runtime/Metadata.cpp +++ b/stdlib/public/runtime/Metadata.cpp @@ -331,7 +331,8 @@ namespace { } // end anonymous namespace namespace { - class GenericMetadataCache : public MetadataCache { + class GenericMetadataCache : + public MetadataCache { public: uint16_t NumKeyParameters; uint16_t NumWitnessTables; @@ -585,8 +586,8 @@ swift::swift_allocateGenericClassMetadata(const ClassDescriptor *description, } auto bytes = (char*) - cache.getAllocator().Allocate(allocationBounds.getTotalSizeInBytes(), - alignof(void*)); + cache.getAllocator().withTag(GenericClassMetadataTag) + .Allocate(allocationBounds.getTotalSizeInBytes(), alignof(void*)); auto addressPoint = bytes + allocationBounds.getAddressPointInBytes(); auto metadata = reinterpret_cast(addressPoint); @@ -658,7 +659,8 @@ swift::swift_allocateGenericValueMetadata(const ValueTypeDescriptor *description size_t totalSize = sizeof(FullMetadata) + extraDataSize; - auto bytes = (char*) cache.getAllocator().Allocate(totalSize, alignof(void*)); + auto bytes = (char*) cache.getAllocator().withTag(GenericValueMetadataTag) + .Allocate(totalSize, alignof(void*)); #ifndef NDEBUG // Fill the metadata record with garbage. @@ -887,7 +889,8 @@ namespace { } /// The uniquing structure for ObjC class-wrapper metadata. -static SimpleGlobalCache ObjCClassWrappers; +static SimpleGlobalCache + ObjCClassWrappers; const Metadata * swift::swift_getObjCClassMetadata(const ClassMetadata *theClass) { @@ -1018,7 +1021,7 @@ class FunctionCacheEntry { } // end anonymous namespace /// The uniquing structure for function type metadata. -static SimpleGlobalCache FunctionTypes; +static SimpleGlobalCache FunctionTypes; const FunctionTypeMetadata * swift::swift_getFunctionTypeMetadata0(FunctionTypeFlags flags, @@ -1212,7 +1215,7 @@ class TupleCacheEntry }; class TupleCacheStorage : - public LockingConcurrentMapStorage { + public LockingConcurrentMapStorage { public: // FIXME: https://bugs.swift.org/browse/SR-1155 #pragma clang diagnostic push @@ -2133,7 +2136,7 @@ void swift::swift_initStructMetadata(StructMetadata *structType, static MetadataAllocator &getResilientMetadataAllocator() { // This should be constant-initialized, but this is safe. - static MetadataAllocator allocator; + static MetadataAllocator allocator(ResilientMetadataAllocatorTag); return allocator; } @@ -3124,7 +3127,7 @@ namespace { } // end anonymous namespace /// The uniquing structure for metatype type metadata. -static SimpleGlobalCache MetatypeTypes; +static SimpleGlobalCache MetatypeTypes; /// Fetch a uniqued metadata for a metatype type. SWIFT_RUNTIME_EXPORT @@ -3192,11 +3195,13 @@ class ExistentialMetatypeCacheEntry { } // end anonymous namespace /// The uniquing structure for existential metatype value witness tables. -static SimpleGlobalCache +static SimpleGlobalCache ExistentialMetatypeValueWitnessTables; /// The uniquing structure for existential metatype type metadata. -static SimpleGlobalCache ExistentialMetatypes; +static SimpleGlobalCache ExistentialMetatypes; static const ValueWitnessTable ExistentialMetatypeValueWitnesses_1 = @@ -3390,7 +3395,7 @@ class ClassExistentialValueWitnessTableCacheEntry { } // end anonymous namespace /// The uniquing structure for existential type metadata. -static SimpleGlobalCache ExistentialTypes; +static SimpleGlobalCache ExistentialTypes; static const ValueWitnessTable OpaqueExistentialValueWitnesses_0 = @@ -3430,7 +3435,8 @@ METADATA_SYM(ANYOBJECT_MANGLING) = { }; /// The uniquing structure for opaque existential value witness tables. -static SimpleGlobalCache +static SimpleGlobalCache OpaqueExistentialValueWitnessTables; /// Instantiate a value witness table for an opaque existential container with @@ -3476,7 +3482,8 @@ static const ValueWitnessTable ClassExistentialValueWitnesses_2 = ValueWitnessTableForBox>::table; /// The uniquing structure for class existential value witness tables. -static SimpleGlobalCache +static SimpleGlobalCache ClassExistentialValueWitnessTables; /// Instantiate a value witness table for a class-constrained existential @@ -3974,7 +3981,8 @@ class ForeignMetadataCacheEntry } // end anonymous namespace -static Lazy> ForeignMetadata; +static Lazy> ForeignMetadata; MetadataResponse swift::swift_getForeignTypeMetadata(MetadataRequest request, @@ -4021,7 +4029,8 @@ namespace { }; } -static SimpleGlobalCache ForeignWitnessTables; +static SimpleGlobalCache ForeignWitnessTables; static const WitnessTable *_getForeignWitnessTable( const WitnessTable *witnessTableCandidate, @@ -4283,7 +4292,8 @@ class WitnessTableCacheEntry : } // end anonymous namespace using GenericWitnessTableCache = - MetadataCache; + MetadataCache; using LazyGenericWitnessTableCache = Lazy; /// Fetch the cache for a generic witness-table structure. @@ -5464,24 +5474,70 @@ namespace { /// The number of bytes remaining. size_t Remaining; }; + + /// The trailer placed at the end of each pool allocation, used when + /// SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION is on. + struct PoolTrailer { + void *PrevTrailer; + size_t PoolSize; + }; + + static constexpr size_t InitialPoolSize = 64 * 1024; + + /// The header placed before each allocation, used when + /// SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION is on. + struct alignas(void *) AllocationHeader { + uint16_t Size; + uint16_t Tag; + }; } // end anonymous namespace // A statically-allocated pool. It's zero-initialized, so this // doesn't cost us anything in binary size. -alignas(void *) static char InitialAllocationPool[64 * 1024]; +alignas(void *) static struct { + char Pool[InitialPoolSize]; +} InitialAllocationPool; static std::atomic -AllocationPool{PoolRange{InitialAllocationPool, - sizeof(InitialAllocationPool)}}; +AllocationPool{PoolRange{InitialAllocationPool.Pool, + sizeof(InitialAllocationPool.Pool)}}; + +bool swift::_swift_debug_metadataAllocationIterationEnabled = false; +const void * const swift::_swift_debug_allocationPoolPointer = &AllocationPool; + +static void checkAllocatorDebugEnvironmentVariable(void *context) { + const char *value = + getenv("SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION"); + if (value && (value[0] == '1' || value[0] == 'y' || value[0] == 'Y')) { + _swift_debug_metadataAllocationIterationEnabled = true; + // Write a PoolTrailer to the end of InitialAllocationPool and shrink + // the pool accordingly. + auto poolCopy = AllocationPool.load(std::memory_order_relaxed); + assert(poolCopy.Begin == InitialAllocationPool.Pool); + size_t newPoolSize = InitialPoolSize - sizeof(PoolTrailer); + PoolTrailer trailer = { nullptr, newPoolSize }; + memcpy(InitialAllocationPool.Pool + newPoolSize, &trailer, + sizeof(trailer)); + poolCopy.Remaining = newPoolSize; + AllocationPool.store(poolCopy, std::memory_order_relaxed); + } +} void *MetadataAllocator::Allocate(size_t size, size_t alignment) { + assert(Tag != 0); assert(alignment <= alignof(void*)); assert(size % alignof(void*) == 0); + static OnceToken_t getenvToken; + SWIFT_ONCE_F(getenvToken, checkAllocatorDebugEnvironmentVariable, nullptr); + // If the size is larger than the maximum, just use malloc. if (size > PoolRange::MaxPoolAllocationSize) return malloc(size); // Allocate out of the pool. + auto sizeWithHeader = size; + if (SWIFT_UNLIKELY(_swift_debug_metadataAllocationIterationEnabled)) + sizeWithHeader += sizeof(AllocationHeader); PoolRange curState = AllocationPool.load(std::memory_order_relaxed); while (true) { char *allocation; @@ -5489,15 +5545,27 @@ void *MetadataAllocator::Allocate(size_t size, size_t alignment) { bool allocatedNewPage; // Try to allocate out of the current page. - if (size <= curState.Remaining) { + if (sizeWithHeader <= curState.Remaining) { allocatedNewPage = false; allocation = curState.Begin; - newState = PoolRange{curState.Begin + size, curState.Remaining - size}; + newState = PoolRange{curState.Begin + sizeWithHeader, + curState.Remaining - sizeWithHeader}; } else { + auto poolSize = PoolRange::PageSize; + if (SWIFT_UNLIKELY(_swift_debug_metadataAllocationIterationEnabled)) + poolSize -= sizeof(PoolTrailer); allocatedNewPage = true; allocation = new char[PoolRange::PageSize]; - newState = PoolRange{allocation + size, PoolRange::PageSize - size}; - __asan_poison_memory_region(allocation, PoolRange::PageSize); + + if (SWIFT_UNLIKELY(_swift_debug_metadataAllocationIterationEnabled)) { + PoolTrailer *newTrailer = (PoolTrailer *)(allocation + poolSize); + char *prevTrailer = curState.Begin + curState.Remaining; + newTrailer->PrevTrailer = prevTrailer; + newTrailer->PoolSize = poolSize; + } + newState = PoolRange{allocation + sizeWithHeader, + poolSize - sizeWithHeader}; + __asan_poison_memory_region(allocation, newState.Remaining); } // Swap in the new state. @@ -5506,9 +5574,18 @@ void *MetadataAllocator::Allocate(size_t size, size_t alignment) { std::memory_order_relaxed, std::memory_order_relaxed)) { // If that succeeded, we've successfully allocated. - __msan_allocated_memory(allocation, size); - __asan_unpoison_memory_region(allocation, size); - return allocation; + __msan_allocated_memory(allocation, sizeWithHeader); + __asan_unpoison_memory_region(allocation, sizeWithHeader); + + if (SWIFT_UNLIKELY(_swift_debug_metadataAllocationIterationEnabled)) { + AllocationHeader *header = (AllocationHeader *)allocation; + header->Size = size; + header->Tag = Tag; + + return allocation + sizeof(AllocationHeader); + } else { + return allocation; + } } // If it failed, go back to a neutral state and try again. @@ -5546,7 +5623,7 @@ void MetadataAllocator::Deallocate(const void *allocation, size_t size, } void *swift::allocateMetadata(size_t size, size_t alignment) { - return MetadataAllocator().Allocate(size, alignment); + return MetadataAllocator(MetadataTag).Allocate(size, alignment); } template<> diff --git a/stdlib/public/runtime/MetadataCache.h b/stdlib/public/runtime/MetadataCache.h index 270d77d43b2e7..047f97816197d 100644 --- a/stdlib/public/runtime/MetadataCache.h +++ b/stdlib/public/runtime/MetadataCache.h @@ -27,7 +27,13 @@ namespace swift { class MetadataAllocator : public llvm::AllocatorBase { +private: + uint16_t Tag; + public: + constexpr MetadataAllocator(uint16_t tag) : Tag(tag) {} + MetadataAllocator() = delete; + void Reset() {} LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t size, size_t alignment); @@ -37,12 +43,24 @@ class MetadataAllocator : public llvm::AllocatorBase { using AllocatorBase::Deallocate; void PrintStats() const {} + + MetadataAllocator withTag(uint16_t Tag) { + MetadataAllocator Allocator = *this; + Allocator.Tag = Tag; + return Allocator; + } +}; + +template +class TaggedMetadataAllocator: public MetadataAllocator { +public: + constexpr TaggedMetadataAllocator() : MetadataAllocator(StaticTag) {} }; /// A typedef for simple global caches. -template +template using SimpleGlobalCache = - ConcurrentMap; + ConcurrentMap>; template class StaticOwningPointer { @@ -87,9 +105,10 @@ struct ConcurrencyControl { ConcurrencyControl() = default; }; -template +template class LockingConcurrentMapStorage { - ConcurrentMap Map; + ConcurrentMap> Map; StaticOwningPointer Concurrency; public: @@ -1388,10 +1407,10 @@ class VariadicMetadataCacheEntryBase : } }; -template +template class MetadataCache : public LockingConcurrentMap> { + LockingConcurrentMapStorage> { }; } // namespace swift diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp index bef53aa1ea684..32f737d0a39b6 100644 --- a/stdlib/public/runtime/ProtocolConformance.cpp +++ b/stdlib/public/runtime/ProtocolConformance.cpp @@ -191,11 +191,10 @@ namespace { }; struct ConformanceCacheKey { - /// Either a Metadata* or a NominalTypeDescriptor*. - const void *Type; + const Metadata *Type; const ProtocolDescriptor *Proto; - ConformanceCacheKey(const void *type, const ProtocolDescriptor *proto) + ConformanceCacheKey(const Metadata *type, const ProtocolDescriptor *proto) : Type(type), Proto(proto) { assert(type); } @@ -203,7 +202,7 @@ namespace { struct ConformanceCacheEntry { private: - const void *Type; + const Metadata *Type; const ProtocolDescriptor *Proto; std::atomic Description; std::atomic FailureGeneration; @@ -267,7 +266,7 @@ struct ConformanceState { initializeProtocolConformanceLookup(); } - void cacheSuccess(const void *type, const ProtocolDescriptor *proto, + void cacheSuccess(const Metadata *type, const ProtocolDescriptor *proto, const ProtocolConformanceDescriptor *description) { auto result = Cache.getOrInsert(ConformanceCacheKey(type, proto), description, 0); @@ -278,7 +277,7 @@ struct ConformanceState { } } - void cacheFailure(const void *type, const ProtocolDescriptor *proto, + void cacheFailure(const Metadata *type, const ProtocolDescriptor *proto, size_t failureGeneration) { auto result = Cache.getOrInsert(ConformanceCacheKey(type, proto), @@ -291,7 +290,7 @@ struct ConformanceState { } } - ConformanceCacheEntry *findCached(const void *type, + ConformanceCacheEntry *findCached(const Metadata *type, const ProtocolDescriptor *proto) { return Cache.find(ConformanceCacheKey(type, proto)); } @@ -316,6 +315,9 @@ void ConformanceState::verify() const { static Lazy Conformances; +const void * const swift::_swift_debug_protocolConformanceStatePointer = + &Conformances; + static void _registerProtocolConformances(ConformanceState &C, const ProtocolConformanceRecord *begin, @@ -386,15 +388,6 @@ struct ConformanceCacheResult { } }; -/// Retrieve the type key from the given metadata, to be used when looking -/// into the conformance cache. -static const void *getConformanceCacheTypeKey(const Metadata *type) { - if (auto description = type->getTypeContextDescriptor()) - return description; - - return type; -} - /// Search for a conformance descriptor in the ConformanceCache. static ConformanceCacheResult @@ -443,22 +436,6 @@ searchInConformanceCache(const Metadata *type, } } - { - // For generic and resilient types, nondependent conformances - // are keyed by the nominal type descriptor rather than the - // metadata, so try that. - auto typeKey = getConformanceCacheTypeKey(type); - - // Hash and lookup the type-protocol pair in the cache. - if (auto *Value = C.findCached(typeKey, protocol)) { - if (Value->isSuccessful()) - return ConformanceCacheResult::cachedSuccess(Value->getDescription()); - - // We don't try to cache negative responses for generic - // patterns. - } - } - // If there is a superclass, look there. if (auto superclass = _swift_class_getSuperclass(type)) { type = superclass; diff --git a/test/DebugInfo/Inputs/curry_thunk_other.swift b/test/DebugInfo/Inputs/curry_thunk_other.swift new file mode 100644 index 0000000000000..914596bdfbc75 --- /dev/null +++ b/test/DebugInfo/Inputs/curry_thunk_other.swift @@ -0,0 +1,7 @@ +public struct HTTPMethod { + public let rawValue: String + + public init(rawValue: String) { + self.rawValue = rawValue + } +} diff --git a/test/DebugInfo/curry_thunk.swift b/test/DebugInfo/curry_thunk.swift new file mode 100644 index 0000000000000..3197a6a78ac17 --- /dev/null +++ b/test/DebugInfo/curry_thunk.swift @@ -0,0 +1,8 @@ +// RUN: %target-swift-frontend -primary-file %s %S/Inputs/curry_thunk_other.swift -emit-ir -g -o - | %FileCheck %s + +public func testCurryThunk() -> [HTTPMethod] { + return ["asdf"].map(HTTPMethod.init) +} + +// CHECK: [[FILE:![0-9]+]] = !DIFile(filename: "{{.*}}/curry_thunk.swift", directory: "{{.*}}") +// CHECK: {{![0-9]+}} = !DILocalVariable(name: "rawValue", arg: 1, scope: {{![0-9]+}}, file: {{![0-9]+}}, type: {{![0-9]+}}, flags: DIFlagArtificial) diff --git a/test/IDE/complete_stmt_controlling_expr.swift b/test/IDE/complete_stmt_controlling_expr.swift index c2fca5a6aa1fe..b76a9bfad2f14 100644 --- a/test/IDE/complete_stmt_controlling_expr.swift +++ b/test/IDE/complete_stmt_controlling_expr.swift @@ -120,6 +120,9 @@ // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_7 | %FileCheck %s -check-prefix=FOOSTRUCT_LOCALVAL // RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_LET_BIND_8 | %FileCheck %s -check-prefix=FOOSTRUCT_LOCALVAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_CASE_PATTERN_1| %FileCheck %s -check-prefix=OPTIONAL_FOOSTRUCT +// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GUARD_CASE_PATTERN_2| %FileCheck %s -check-prefix=OPTIONAL_FOOSTRUCT + struct FooStruct { var instanceVar : Int init(_: Int = 0) { } @@ -612,7 +615,12 @@ func testGuardLetBinding7(x: FooStruct?) { func testGuardLetBinding8(_ x: FooStruct?) { guard let boundVal = x, let other = testGuardLetBinding8(#^GUARD_LET_BIND_8^#) else {} } - +func testGuardCase(x:FooStruct?) { + guard case .#^GUARD_CASE_PATTERN_1^# = x {} +} +func testGuardCase(x:FooStruct?) { + guard case .#^GUARD_CASE_PATTERN_2^#some() = x {} +} // FOOSTRUCT_DOT: Begin completions // FOOSTRUCT_DOT-DAG: Decl[InstanceVar]/CurrNominal: instanceVar[#Int#]; @@ -635,3 +643,12 @@ func testGuardLetBinding8(_ x: FooStruct?) { // FOOSTRUCT_LOCALVAL: Begin completions // FOOSTRUCT_LOCALVAL-DAG: Decl[LocalVar]/Local{{(/TypeRelation\[Convertible\])?}}: boundVal[#FooStruct#]; // FOOSTRUCT_LOCALVAL: End completions + +// OPTIONAL_FOOSTRUCT: Begin completions, 5 items +// OPTIONAL_FOOSTRUCT-DAG: Keyword[nil]/None/Erase[1]: nil[#FooStruct?#]; name=nil +// OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: none[#Optional#]; name=none +// OPTIONAL_FOOSTRUCT-DAG: Decl[EnumElement]/CurrNominal/IsSystem: some({#FooStruct#})[#Optional#]; name=some(FooStruct) +// FIXME: 'FooStruct' members should not be shown. +// OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init()[#FooStruct#]; name=init() +// OPTIONAL_FOOSTRUCT-DAG: Decl[Constructor]/CurrNominal/TypeRelation[Convertible]: init({#Int#})[#FooStruct#]; name=init(Int) +// OPTIONAL_FOOSTRUCT: End completions diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift index dcd43a375dad8..1c35c2082e709 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_con_double.swift @@ -330,7 +330,7 @@ doit() // CHECK: } // CHECK: ; Function Attrs: noinline nounwind readnone -// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CySSGMb"([[INT]] {{%[0-9]+}}) #4 { +// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CySSGMb"([[INT]] {{%[0-9]+}}) #{{[0-9]+}} { // CHECK: entry: // CHECK-unknown: call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]CySiGMb"([[INT]] 0) // CHECK-unknown: ret diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift index 066d1ded0d795..fb1ca4b5a3a6a 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_con_int-2nd_anc_gen-1st-arg_subclass_arg.swift @@ -315,7 +315,7 @@ doit() // CHECK: } // CHECK: ; Function Attrs: noinline nounwind readnone -// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CySSGMb"([[INT]] {{%[0-9]+}}) #4 { +// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CySSGMb"([[INT]] {{%[0-9]+}}) #{{[0-9]+}} { // CHECK: entry: // CHECK-unknown: call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]CySiGMb"([[INT]] 0) // CHECK-unknown: ret diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift index 92fb12077cfb7..49b0c2df9cab1 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1arg-2ancs-1distinct_use-1st_anc_gen-1arg-1st_arg_subclass_arg-2nd_anc_gen-1st-arg_con_int.swift @@ -319,7 +319,7 @@ doit() // CHECK: } // CHECK: ; Function Attrs: noinline nounwind readnone -// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]LLCySSGMb"([[INT]] {{%[0-9]+}}) #4 { +// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]LLCySSGMb"([[INT]] {{%[0-9]+}}) #{{[0-9]+}} { // CHECK: entry: // CHECK-unknown: call swiftcc %swift.metadata_response @"$s4main9Ancestor1[[UNIQUE_ID_1]]LLCySSGMb"([[INT]] 0) // CHECK-unknown: ret diff --git a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift index bfc8f81574c2f..c440750f3aac3 100644 --- a/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift +++ b/test/IRGen/prespecialized-metadata/class-fileprivate-inmodule-1argument-1distinct_use-1st_argument_generic_class-1argument.swift @@ -285,7 +285,7 @@ doit() // CHECK: } // CHECK:; Function Attrs: noinline nounwind readnone -// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CyAA9Argument1ACLLCySiGGMb"([[INT]] [[REQUEST:%[0-9]+]]) #4 { +// CHECK: define linkonce_odr hidden swiftcc %swift.metadata_response @"$s4main5Value[[UNIQUE_ID_1]]CyAA9Argument1ACLLCySiGGMb"([[INT]] [[REQUEST:%[0-9]+]]) #{{[0-9]+}} { // CHECK: entry: // CHECK-unknown: ret // CHECK-apple: [[INITIALIZED_CLASS:%[0-9]+]] = call %objc_class* @objc_opt_self( diff --git a/test/IRGen/prespecialized-metadata/struct-inmodule-0argument.swift b/test/IRGen/prespecialized-metadata/struct-inmodule-0argument.swift index 3b2914c8738e9..037bfd746e419 100644 --- a/test/IRGen/prespecialized-metadata/struct-inmodule-0argument.swift +++ b/test/IRGen/prespecialized-metadata/struct-inmodule-0argument.swift @@ -15,7 +15,7 @@ func consume(_ t: T) { } } -// CHECK: define hidden swiftcc void @"$s4main4doityyF"() #0 { +// CHECK: define hidden swiftcc void @"$s4main4doityyF"() #{{[0-9]+}} { // CHECK: call swiftcc void @"$s4main7consumeyyxlF"(%swift.opaque* noalias nocapture %{{[0-9]+}}, %swift.type* bitcast ([[INT]]* getelementptr inbounds (<{ i8**, [[INT]], <{ i32, i32, i32, i32, i32, i32, i32 }>*, i32{{(, \[4 x i8\])?}}, i64 }>, <{ i8**, [[INT]], <{ i32, i32, i32, i32, i32, i32, i32 }>*, i32{{(, \[4 x i8\])?}}, i64 }>* @"$s4main5ValueVMf", i32 0, i32 1) to %swift.type*)) // CHECK: } func doit() { diff --git a/test/SPI/private_swiftinterface.swift b/test/SPI/private_swiftinterface.swift index 79168d2fd953c..8be3d34925410 100644 --- a/test/SPI/private_swiftinterface.swift +++ b/test/SPI/private_swiftinterface.swift @@ -21,7 +21,7 @@ // RUN: %FileCheck -check-prefix=CHECK-PUBLIC %s < %t/merged.swiftinterface // RUN: %FileCheck -check-prefix=CHECK-PRIVATE %s < %t/merged.private.swiftinterface -@_spi(HelperSPI) @_spi(OtherSPI) import SPIHelper +@_spi(HelperSPI) @_spi(OtherSPI) @_spi(OtherSPI) import SPIHelper // CHECK-PUBLIC: import SPIHelper // CHECK-PRIVATE: @_spi(OtherSPI) @_spi(HelperSPI) import SPIHelper diff --git a/tools/swift-inspect/Package.swift b/tools/swift-inspect/Package.swift new file mode 100644 index 0000000000000..da7fa1a88ff3c --- /dev/null +++ b/tools/swift-inspect/Package.swift @@ -0,0 +1,26 @@ +// swift-tools-version:5.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "swift-inspect", + dependencies: [ + .package(url: "https://github.com/apple/swift-argument-parser", from: "0.0.1"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages which this package depends on. + .target( + name: "swift-inspect", + dependencies: [ + "SymbolicationShims", + .product(name: "ArgumentParser", package: "swift-argument-parser"), + ]), + .testTarget( + name: "swiftInspectTests", + dependencies: ["swift-inspect"]), + .systemLibrary( + name: "SymbolicationShims") + ] +) diff --git a/tools/swift-inspect/README.md b/tools/swift-inspect/README.md new file mode 100644 index 0000000000000..21d3b967344c1 --- /dev/null +++ b/tools/swift-inspect/README.md @@ -0,0 +1,3 @@ +# swift-inspect + +A description of this package. diff --git a/tools/swift-inspect/Sources/SymbolicationShims/SymbolicationShims.h b/tools/swift-inspect/Sources/SymbolicationShims/SymbolicationShims.h new file mode 100644 index 0000000000000..363e56823499d --- /dev/null +++ b/tools/swift-inspect/Sources/SymbolicationShims/SymbolicationShims.h @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +#include + +struct CSTypeRef { + uintptr_t a, b; +}; + +struct Range { + uintptr_t location, length; +}; diff --git a/tools/swift-inspect/Sources/SymbolicationShims/module.modulemap b/tools/swift-inspect/Sources/SymbolicationShims/module.modulemap new file mode 100644 index 0000000000000..6cce7e47865dd --- /dev/null +++ b/tools/swift-inspect/Sources/SymbolicationShims/module.modulemap @@ -0,0 +1,4 @@ +module SymbolicationShims { + header "SymbolicationShims.h" + export * +} diff --git a/tools/swift-inspect/Sources/swift-inspect/Inspector.swift b/tools/swift-inspect/Sources/swift-inspect/Inspector.swift new file mode 100644 index 0000000000000..a77fa6bd8cd1f --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/Inspector.swift @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import Foundation +import SwiftRemoteMirror +import SymbolicationShims + +class Inspector { + let task: task_t + let symbolicator: CSTypeRef + let swiftCore: CSTypeRef + + init?(pid: pid_t) { + task = Self.findTask(pid, tryForkCorpse: false) + if task == 0 { return nil } + + symbolicator = CSSymbolicatorCreateWithTask(task) + swiftCore = CSSymbolicatorGetSymbolOwnerWithNameAtTime( + symbolicator, "libswiftCore.dylib", kCSNow) + _ = task_start_peeking(task) + } + + deinit { + task_stop_peeking(task) + mach_port_deallocate(mach_task_self_, task) + } + + static func findTask(_ pid: pid_t, tryForkCorpse: Bool) -> task_t { + var task = task_t() + var kr = task_for_pid(mach_task_self_, pid, &task) + if kr != KERN_SUCCESS { + print("Unable to get task for pid \(pid): \(machErrStr(kr))", to: &Std.err) + return 0 + } + + if !tryForkCorpse { + return task + } + + var corpse = task_t() + kr = task_generate_corpse(task, &corpse) + if kr == KERN_SUCCESS { + task_resume(task) + mach_port_deallocate(mach_task_self_, task) + return corpse + } else { + print("warning: unable to generate corpse for pid \(pid): \(machErrStr(kr))", to: &Std.err) + return task + } + } + + func passContext() -> UnsafeMutableRawPointer { + return Unmanaged.passRetained(self).toOpaque() + } + + func destroyContext() { + Unmanaged.passUnretained(self).release() + } + + func getAddr(symbolName: String) -> swift_addr_t { + let symbol = CSSymbolOwnerGetSymbolWithMangledName(swiftCore, symbolName) + let range = CSSymbolGetRange(symbol) + return swift_addr_t(range.location) + } + + enum Callbacks { + static let QueryDataLayout: @convention(c) + (UnsafeMutableRawPointer?, + DataLayoutQueryType, + UnsafeMutableRawPointer?, + UnsafeMutableRawPointer?) -> CInt + = QueryDataLayoutFn + + static let Free: (@convention(c) (UnsafeMutableRawPointer?, + UnsafeRawPointer?, + UnsafeMutableRawPointer?) -> Void)? = nil + + static let ReadBytes: @convention(c) + (UnsafeMutableRawPointer?, + swift_addr_t, + UInt64, + UnsafeMutablePointer?) -> + UnsafeRawPointer? + = ReadBytesFn + + static let GetStringLength: @convention(c) + (UnsafeMutableRawPointer?, + swift_addr_t) -> UInt64 + = GetStringLengthFn + + static let GetSymbolAddress: @convention(c) + (UnsafeMutableRawPointer?, + UnsafePointer?, + UInt64) -> swift_addr_t + = GetSymbolAddressFn + } +} + +private func instance(_ context: UnsafeMutableRawPointer?) -> Inspector { + Unmanaged.fromOpaque(context!).takeUnretainedValue() +} + +private func QueryDataLayoutFn(context: UnsafeMutableRawPointer?, + type: DataLayoutQueryType, + inBuffer: UnsafeMutableRawPointer?, + outBuffer: UnsafeMutableRawPointer?) -> CInt { + switch type { + case DLQ_GetPointerSize: + let size = UInt8(MemoryLayout.stride) + outBuffer!.storeBytes(of: size, toByteOffset: 0, as: UInt8.self) + return 1 + default: + return 0 + } +} + +private func ReadBytesFn( + context: UnsafeMutableRawPointer?, + address: swift_addr_t, + size: UInt64, + outContext: UnsafeMutablePointer? +) -> UnsafeRawPointer? { + task_peek(instance(context).task, address, size) +} + +private func GetStringLengthFn( + context: UnsafeMutableRawPointer?, + address: swift_addr_t +) -> UInt64 { + let maybeStr = task_peek_string(instance(context).task, address) + guard let str = maybeStr else { return 0 } + return UInt64(strlen(str)) +} + +private func GetSymbolAddressFn( + context: UnsafeMutableRawPointer?, + name: UnsafePointer?, + length: UInt64 +) -> swift_addr_t { + let nameStr: String = name!.withMemoryRebound(to: UInt8.self, + capacity: Int(length)) { + let buffer = UnsafeBufferPointer(start: $0, count: Int(length)) + return String(decoding: buffer, as: UTF8.self) + } + return instance(context).getAddr(symbolName: nameStr) +} diff --git a/tools/swift-inspect/Sources/swift-inspect/InterpolationExtensions.swift b/tools/swift-inspect/Sources/swift-inspect/InterpolationExtensions.swift new file mode 100644 index 0000000000000..26b59e41d9226 --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/InterpolationExtensions.swift @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import SwiftRemoteMirror + +extension DefaultStringInterpolation { + mutating func appendInterpolation(hex: swift_reflection_ptr_t) { + appendInterpolation("0x") + appendInterpolation(String(hex, radix: 16)) + } +} diff --git a/tools/swift-inspect/Sources/swift-inspect/Metadata.swift b/tools/swift-inspect/Sources/swift-inspect/Metadata.swift new file mode 100644 index 0000000000000..03f1db9dfab4a --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/Metadata.swift @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import SwiftRemoteMirror + +struct Allocation { + let allocation_t: swift_metadata_allocation_t + + var tag: swift_metadata_allocation_tag_t { allocation_t.Tag } + var ptr: swift_reflection_ptr_t { allocation_t.Ptr } + var size: Int { Int(allocation_t.Size) } +} + +extension Allocation: Comparable { + static func == (lhs: Self, rhs: Self) -> Bool { + lhs.ptr == rhs.ptr + } + + static func < (lhs: Self, rhs: Self) -> Bool { + lhs.ptr < rhs.ptr + } +} + +extension Allocation { + func metadata(in context: SwiftReflectionContextRef) -> Metadata? { + let ptr = context.metadataPointer(allocation: allocation_t) + if ptr != 0 { + let name = context.name(metadata: ptr) ?? "" + return .init(ptr: ptr, name: name) + } else { + return nil + } + } +} + +extension BidirectionalCollection where Element == Allocation { + func findGenericMetadata(in context: SwiftReflectionContextRef) -> [Metadata] { + var metadatas = self.compactMap { $0.metadata(in: context) } + for i in metadatas.indices { + let metadata = metadatas[i] + if let allocation = self.last(where: { metadata.ptr >= $0.ptr }) { + metadatas[i].allocation = allocation + } + } + return metadatas + } +} + +struct Metadata { + let ptr: swift_reflection_ptr_t + var allocation: Allocation? = nil + let name: String + + var offset: Int? { allocation.map { Int(self.ptr - $0.ptr) } } +} diff --git a/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift b/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift new file mode 100644 index 0000000000000..4467eb60ca138 --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/RemoteMirrorExtensions.swift @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import SwiftRemoteMirror + +extension SwiftReflectionContextRef { + struct Error: Swift.Error, CustomStringConvertible { + var description: String + + init(cString: UnsafePointer) { + description = String(cString: cString) + } + } + + func name(metadata: swift_reflection_ptr_t) -> String? { + let tr = swift_reflection_typeRefForMetadata(self, UInt(metadata)); + guard tr != 0 else { return nil } + + guard let cstr = swift_reflection_copyDemangledNameForTypeRef(self, tr) + else { return nil } + defer { free(cstr) } + return String(cString: cstr) + } + + func name(proto: swift_reflection_ptr_t) -> String? { + guard let cstr = swift_reflection_copyDemangledNameForProtocolDescriptor( + self, proto) else { return nil } + defer { free(cstr) } + return String(cString: cstr) + } + + func iterateConformanceCache( + _ body: (swift_reflection_ptr_t, swift_reflection_ptr_t) -> Void + ) throws { + var body = body + let errStr = swift_reflection_iterateConformanceCache(self, { + let callPtr = $2!.bindMemory(to: + ((swift_reflection_ptr_t, swift_reflection_ptr_t) -> Void).self, + capacity: 1) + callPtr.pointee($0, $1) + }, &body) + try throwError(str: errStr) + } + + func iterateMetadataAllocations( + _ body: (swift_metadata_allocation_t) -> Void + ) throws { + var body = body + let errStr = swift_reflection_iterateMetadataAllocations(self, { + let callPtr = $1!.bindMemory(to: + ((swift_metadata_allocation_t) -> Void).self, capacity: 1) + callPtr.pointee($0) + }, &body) + try throwError(str: errStr) + } + + func metadataPointer( + allocation: swift_metadata_allocation_t + ) -> swift_reflection_ptr_t { + swift_reflection_allocationMetadataPointer(self, allocation) + } + + private func throwError(str: UnsafePointer?) throws { + if let str = str { + throw Error(cString: str) + } + } + + var allocations: [Allocation] { + var allocations: [Allocation] = [] + try! iterateMetadataAllocations { allocation_t in + allocations.append(.init(allocation_t: allocation_t)) + } + return allocations + } +} diff --git a/tools/swift-inspect/Sources/swift-inspect/main.swift b/tools/swift-inspect/Sources/swift-inspect/main.swift new file mode 100644 index 0000000000000..53301f06cd21d --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/main.swift @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import ArgumentParser +import SwiftRemoteMirror + + +func argFail(_ message: String) -> Never { + print(message, to: &Std.err) + exit(EX_USAGE) +} + +func machErrStr(_ kr: kern_return_t) -> String { + let errStr = String(cString: mach_error_string(kr)) + let errHex = String(kr, radix: 16) + return "\(errStr) (0x\(errHex))" +} + +func dumpConformanceCache(context: SwiftReflectionContextRef) throws { + try context.iterateConformanceCache { type, proto in + let typeName = context.name(metadata: type) ?? "" + let protoName = context.name(proto: proto) ?? "" + print("Conformance: \(typeName): \(protoName)") + } +} + +func dumpRawMetadata(context: SwiftReflectionContextRef) throws { + for allocation in context.allocations { + print("Metadata allocation at: \(hex: allocation.ptr) " + + "size: \(allocation.size) tag: \(allocation.tag)") + } +} + +func dumpGenericMetadata(context: SwiftReflectionContextRef) throws { + let allocations = context.allocations.sorted() + let metadatas = allocations.findGenericMetadata(in: context) + + print("Address","Allocation","Size","Offset","Name", separator: "\t") + for metadata in metadatas { + print("\(hex: metadata.ptr)", terminator: "\t") + + if let allocation = metadata.allocation, let offset = metadata.offset { + print("\(hex: allocation.ptr)\t\(allocation.size)\t\(offset)", + terminator: "\t") + } else { + print("???\t???\t???", terminator: "\t") + + } + print(metadata.name) + } +} + +func makeReflectionContext( + nameOrPid: String +) -> (Inspector, SwiftReflectionContextRef) { + guard let pid = pidFromHint(nameOrPid) else { + argFail("Cannot find pid/process \(nameOrPid)") + } + + guard let inspector = Inspector(pid: pid) else { + argFail("Failed to inspect pid \(pid) (are you running as root?)") + } + + guard let reflectionContext = swift_reflection_createReflectionContextWithDataLayout( + inspector.passContext(), + Inspector.Callbacks.QueryDataLayout, + Inspector.Callbacks.Free, + Inspector.Callbacks.ReadBytes, + Inspector.Callbacks.GetStringLength, + Inspector.Callbacks.GetSymbolAddress + ) else { + argFail("Failed to create reflection context") + } + + return (inspector, reflectionContext) +} + +func withReflectionContext( + nameOrPid: String, + _ body: (SwiftReflectionContextRef) throws -> Void +) throws { + let (inspector, context) = makeReflectionContext(nameOrPid: nameOrPid) + defer { + swift_reflection_destroyReflectionContext(context) + inspector.destroyContext() + } + try body(context) +} + +struct SwiftInspect: ParsableCommand { + static let configuration = CommandConfiguration( + abstract: "Swift runtime debug tool", + subcommands: [ + DumpConformanceCache.self, + DumpRawMetadata.self, + DumpGenericMetadata.self, + ]) +} + +struct DumpConformanceCache: ParsableCommand { + static let configuration = CommandConfiguration( + abstract: "Print the contents of the target's protocol conformance cache.") + + @Argument(help: "The pid or partial name of the target process") + var nameOrPid: String + + func run() throws { + try withReflectionContext(nameOrPid: nameOrPid) { + try dumpConformanceCache(context: $0) + } + } +} + +struct DumpRawMetadata: ParsableCommand { + static let configuration = CommandConfiguration( + abstract: "Print the target's metadata allocations.") + @Argument(help: "The pid or partial name of the target process") + + var nameOrPid: String + + func run() throws { + try withReflectionContext(nameOrPid: nameOrPid) { + try dumpRawMetadata(context: $0) + } + } +} + +struct DumpGenericMetadata: ParsableCommand { + static let configuration = CommandConfiguration( + abstract: "Print the target's metadata allocations.") + @Argument(help: "The pid or partial name of the target process") + + var nameOrPid: String + + func run() throws { + try withReflectionContext(nameOrPid: nameOrPid) { + try dumpGenericMetadata(context: $0) + } + } +} + +SwiftInspect.main() diff --git a/tools/swift-inspect/Sources/swift-inspect/stdio.swift b/tools/swift-inspect/Sources/swift-inspect/stdio.swift new file mode 100644 index 0000000000000..169fb06145f0c --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/stdio.swift @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import Foundation + +enum Std { + struct File: TextOutputStream { + var underlying: UnsafeMutablePointer + + mutating func write(_ string: String) { + fputs(string, underlying) + } + } + + static var err = File(underlying: stderr) +} diff --git a/tools/swift-inspect/Sources/swift-inspect/symbolication.swift b/tools/swift-inspect/Sources/swift-inspect/symbolication.swift new file mode 100644 index 0000000000000..d1096307e59df --- /dev/null +++ b/tools/swift-inspect/Sources/swift-inspect/symbolication.swift @@ -0,0 +1,149 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import Foundation +import SymbolicationShims + +private let symbolicationPath = + "/System/Library/PrivateFrameworks/Symbolication.framework/Symbolication" +private let symbolicationHandle = dlopen(symbolicationPath, RTLD_LAZY)! + +private let coreSymbolicationPath = + "/System/Library/PrivateFrameworks/CoreSymbolication.framework/CoreSymbolication" +private let coreSymbolicationHandle = dlopen(coreSymbolicationPath, RTLD_LAZY)! + +private func symbol(_ handle: UnsafeMutableRawPointer, _ name: String) -> T { + guard let result = dlsym(handle, name) else { + fatalError("Unable to look up \(name) in Symbolication") + } + return unsafeBitCast(result, to: T.self) +} + +enum Sym { + static let pidFromHint: @convention(c) (AnyObject) -> pid_t = + symbol(symbolicationHandle, "pidFromHint") + static let CSSymbolicatorCreateWithTask: @convention(c) (task_t) -> CSTypeRef = + symbol(coreSymbolicationHandle, "CSSymbolicatorCreateWithTask") + static let CSSymbolicatorGetSymbolOwnerWithNameAtTime: + @convention(c) (CSTypeRef, UnsafePointer, CSMachineTime) -> CSTypeRef = + symbol(coreSymbolicationHandle, "CSSymbolicatorGetSymbolOwnerWithNameAtTime") + static let CSSymbolOwnerForeachSymbol: + @convention(c) (CSTypeRef, @convention(block) (CSTypeRef) -> Void) -> UInt = + symbol(coreSymbolicationHandle, "CSSymbolOwnerForeachSymbol") + static let CSSymbolOwnerGetSymbolWithMangledName: @convention(c) + (CSTypeRef, UnsafePointer) -> CSTypeRef = + symbol(coreSymbolicationHandle, "CSSymbolOwnerGetSymbolWithMangledName") + static let CSSymbolGetName: @convention(c) (CSTypeRef) -> UnsafePointer? = + symbol(coreSymbolicationHandle, "CSSymbolGetName") + static let CSSymbolGetMangledName: @convention(c) (CSTypeRef) -> UnsafePointer? = + symbol(coreSymbolicationHandle, "CSSymbolGetMangledName") + static let CSSymbolIsFunction: @convention(c) (CSTypeRef) -> CBool = + symbol(coreSymbolicationHandle, "CSSymbolIsFunction") + static let CSSymbolGetRange: @convention(c) (CSTypeRef) -> Range = + symbol(coreSymbolicationHandle, "CSSymbolGetRange") + static let task_start_peeking: @convention(c) (task_t) -> kern_return_t = + symbol(symbolicationHandle, "task_start_peeking") + static let task_peek: @convention(c) (task_t, mach_vm_address_t, mach_vm_size_t, + UnsafeMutablePointer) -> + kern_return_t = + symbol(symbolicationHandle, "task_peek") + static let task_peek_string: @convention(c) (task_t, mach_vm_address_t) -> + UnsafeMutablePointer? = + symbol(symbolicationHandle, "task_peek_string") + static let task_stop_peeking: @convention(c) (task_t) -> kern_return_t = + symbol(symbolicationHandle, "task_stop_peeking") +} + +typealias CSMachineTime = UInt64 +let kCSNow = CSMachineTime(Int64.max) + 1 + +func pidFromHint(_ hint: String) -> pid_t? { + let result = Sym.pidFromHint(hint as NSString) + return result == 0 ? nil : result +} + +func CSSymbolicatorCreateWithTask(_ task: task_t) -> CSTypeRef { + Sym.CSSymbolicatorCreateWithTask(task) +} + +func CSSymbolicatorGetSymbolOwnerWithNameAtTime( + _ symbolicator: CSTypeRef, + _ name: String, + _ time: CSMachineTime +) -> CSTypeRef { + Sym.CSSymbolicatorGetSymbolOwnerWithNameAtTime(symbolicator, name, time) +} + +@discardableResult +func CSSymbolOwnerForeachSymbol( + _ symbolOwner: CSTypeRef, + _ iterator: (CSTypeRef) -> Void +) -> UInt { + Sym.CSSymbolOwnerForeachSymbol(symbolOwner, iterator) +} + +func CSSymbolOwnerGetSymbolWithMangledName( + _ owner: CSTypeRef, + _ name: String +) -> CSTypeRef { + Sym.CSSymbolOwnerGetSymbolWithMangledName(owner, name) +} + +func CSSymbolGetName(_ sym: CSTypeRef) -> String? { + let name = Sym.CSSymbolGetName(sym) + return name.map({ String(cString: $0) }) +} + +func CSSymbolGetMangledName(_ sym: CSTypeRef) -> String? { + let name = Sym.CSSymbolGetMangledName(sym) + return name.map({ String(cString: $0) }) +} + +func CSSymbolIsFunction(_ sym: CSTypeRef) -> Bool { + Sym.CSSymbolIsFunction(sym) +} + +func CSSymbolGetRange(_ sym: CSTypeRef) -> Range { + Sym.CSSymbolGetRange(sym) +} + +func task_start_peeking(_ task: task_t) -> Bool { + let result = Sym.task_start_peeking(task) + if result == KERN_SUCCESS { + return true + } + + print("task_start_peeking failed: \(machErrStr(result))", to: &Std.err) + return false +} + +func task_peek( + _ task: task_t, _ start: mach_vm_address_t, _ size: mach_vm_size_t +) -> UnsafeRawPointer? { + var ptr: UnsafeRawPointer? = nil + let result = Sym.task_peek(task, start, size, &ptr) + if result != KERN_SUCCESS { + print("Unable to read (\(start), \(size)): \(machErrStr(result))", to: &Std.err) + return nil + } + return ptr +} + +func task_peek_string( + _ task: task_t, _ addr: mach_vm_address_t +) -> UnsafeMutablePointer? { + Sym.task_peek_string(task, addr) +} + +func task_stop_peeking(_ task: task_t) { + _ = Sym.task_stop_peeking(task) +} diff --git a/tools/swift-inspect/Tests/LinuxMain.swift b/tools/swift-inspect/Tests/LinuxMain.swift new file mode 100644 index 0000000000000..99cec42f4ee2c --- /dev/null +++ b/tools/swift-inspect/Tests/LinuxMain.swift @@ -0,0 +1,19 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import XCTest + +import swiftInspectTests + +var tests = [XCTestCaseEntry]() +tests += swiftInspectTests.allTests() +XCTMain(tests) diff --git a/tools/swift-inspect/Tests/swiftInspectTests/XCTestManifests.swift b/tools/swift-inspect/Tests/swiftInspectTests/XCTestManifests.swift new file mode 100644 index 0000000000000..5da9c77e988bf --- /dev/null +++ b/tools/swift-inspect/Tests/swiftInspectTests/XCTestManifests.swift @@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import XCTest + +#if !canImport(ObjectiveC) +public func allTests() -> [XCTestCaseEntry] { + return [ + testCase(swiftInspectTests.allTests), + ] +} +#endif diff --git a/tools/swift-inspect/Tests/swiftInspectTests/swiftInspectTests.swift b/tools/swift-inspect/Tests/swiftInspectTests/swiftInspectTests.swift new file mode 100644 index 0000000000000..f10ed4a8235b3 --- /dev/null +++ b/tools/swift-inspect/Tests/swiftInspectTests/swiftInspectTests.swift @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2020 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 +// +//===----------------------------------------------------------------------===// + +import XCTest +import class Foundation.Bundle + +final class swiftInspectTests: XCTestCase { + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct + // results. + + // Some of the APIs that we use below are available in macOS 10.13 and above. + guard #available(macOS 10.13, *) else { + return + } + + let fooBinary = productsDirectory.appendingPathComponent("swift-inspect") + + let process = Process() + process.executableURL = fooBinary + + let pipe = Pipe() + process.standardOutput = pipe + + try process.run() + process.waitUntilExit() + + let data = pipe.fileHandleForReading.readDataToEndOfFile() + let output = String(data: data, encoding: .utf8) + + XCTAssertEqual(output, "Hello, world!\n") + } + + /// Returns path to the built products directory. + var productsDirectory: URL { + #if os(macOS) + for bundle in Bundle.allBundles where bundle.bundlePath.hasSuffix(".xctest") { + return bundle.bundleURL.deletingLastPathComponent() + } + fatalError("couldn't find the products directory") + #else + return Bundle.main.bundleURL + #endif + } + + static var allTests = [ + ("testExample", testExample), + ] +} diff --git a/tools/swift-inspect/build_script_helper.py b/tools/swift-inspect/build_script_helper.py new file mode 100755 index 0000000000000..ae9b9c9747f2c --- /dev/null +++ b/tools/swift-inspect/build_script_helper.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python + +from __future__ import print_function + +import argparse +import os +import subprocess + + +def perform_build(args, swiftbuild_path): + swiftbuild_args = [ + swiftbuild_path, + "--package-path", + args.package_path, + "--build-path", + args.build_path, + "--configuration", + args.configuration, + "-Xswiftc", + "-I", + "-Xswiftc", + os.path.join(args.toolchain, 'usr', 'include', 'swift'), + "-Xswiftc", + "-L", + "-Xswiftc", + os.path.join(args.toolchain, 'usr', 'lib', 'swift', 'macosx'), + "-Xswiftc", + "-lswiftRemoteMirror" + ] + if args.verbose: + swiftbuild_args.append("--verbose") + print(' '.join(swiftbuild_args)) + subprocess.call(swiftbuild_args) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--verbose", "-v", action="store_true") + parser.add_argument("--package-path", type=str, required=True) + parser.add_argument("--build-path", type=str, required=True) + parser.add_argument("--toolchain", type=str, required=True) + parser.add_argument("--configuration", type=str, choices=['debug', 'release'], + default='release') + + args = parser.parse_args() + + # Create our bin directory so we can copy in the binaries. + bin_dir = os.path.join(args.build_path, "bin") + if not os.path.isdir(bin_dir): + os.makedirs(bin_dir) + + swiftbuild_path = os.path.join(args.toolchain, "usr", "bin", "swift-build") + perform_build(args, swiftbuild_path) + + +if __name__ == "__main__": + main() diff --git a/unittests/runtime/CMakeLists.txt b/unittests/runtime/CMakeLists.txt index b151e7eb38145..a827a54610c00 100644 --- a/unittests/runtime/CMakeLists.txt +++ b/unittests/runtime/CMakeLists.txt @@ -75,6 +75,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND # and the stdlib. $ $ + $ ) # The local stdlib implementation provides definitions of the swiftCore diff --git a/unittests/runtime/LongTests/CMakeLists.txt b/unittests/runtime/LongTests/CMakeLists.txt index 9a744261daa6d..e569e3f0554af 100644 --- a/unittests/runtime/LongTests/CMakeLists.txt +++ b/unittests/runtime/LongTests/CMakeLists.txt @@ -38,6 +38,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND # and the stdlib. $ $ + $ ) # The local stdlib implementation provides definitions of the swiftCore diff --git a/utils/build-script b/utils/build-script index aa79436709f7f..93ae848fa1fa9 100755 --- a/utils/build-script +++ b/utils/build-script @@ -222,6 +222,7 @@ def validate_arguments(toolchain, args): 'build_sourcekitlsp', 'build_tensorflow_swift_apis', 'build_toolchainbenchmarks', + 'build_swift_inspect', 'tsan_libdispatch_test', ] has_target_needing_toolchain = \ @@ -839,6 +840,8 @@ class BuildScriptInvocation(object): product_classes.append(products.SourceKitLSP) if self.args.build_toolchainbenchmarks: product_classes.append(products.Benchmarks) + if self.args.build_swift_inspect: + product_classes.append(products.SwiftInspect) if self.args.tsan_libdispatch_test: product_classes.append(products.TSanLibDispatch) return product_classes diff --git a/utils/build_swift/build_swift/driver_arguments.py b/utils/build_swift/build_swift/driver_arguments.py index 0fdd61854427a..fbf4f633c221e 100644 --- a/utils/build_swift/build_swift/driver_arguments.py +++ b/utils/build_swift/build_swift/driver_arguments.py @@ -593,6 +593,10 @@ def create_argument_parser(): toggle_true('build_toolchainbenchmarks'), help='build Swift Benchmarks using swiftpm against the just built ' 'toolchain') + option(['--swift-inspect'], + toggle_true('build_swift_inspect'), + help='build SwiftInspect using swiftpm against the just built ' + 'toolchain') option('--xctest', toggle_true('build_xctest'), help='build xctest') @@ -1012,6 +1016,9 @@ def create_argument_parser(): option('--skip-test-toolchain-benchmarks', toggle_false('test_toolchainbenchmarks'), help='skip testing toolchain benchmarks') + option('--skip-test-swift-inspect', + toggle_false('test_swift_inspect'), + help='skip testing swift_inspect') # ------------------------------------------------------------------------- in_group('Build settings specific for LLVM') diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py index 08daafda65cf0..7da789ba0984b 100644 --- a/utils/build_swift/tests/expected_options.py +++ b/utils/build_swift/tests/expected_options.py @@ -81,6 +81,7 @@ 'build_subdir': None, 'build_swift_dynamic_sdk_overlay': True, 'build_swift_dynamic_stdlib': True, + 'build_swift_inspect': False, 'build_swift_static_sdk_overlay': False, 'build_swift_static_stdlib': False, 'build_swift_stdlib_unittest_extra': False, @@ -215,6 +216,7 @@ 'test_osx': False, 'test_paths': [], 'test_pythonkit': False, + 'test_swift_inspect': True, 'test_tvos': False, 'test_tvos_host': False, 'test_tvos_simulator': False, @@ -518,6 +520,7 @@ class BuildScriptImplOption(_BaseOption): EnableOption('--install-skstresstester', dest='install_skstresstester'), EnableOption('--install-swiftevolve', dest='install_swiftevolve'), EnableOption('--toolchain-benchmarks', dest='build_toolchainbenchmarks'), + EnableOption('--swift-inspect', dest='build_swift_inspect'), EnableOption('--tsan-libdispatch-test'), EnableOption('--long-test'), EnableOption('--show-sdks'), @@ -581,6 +584,8 @@ class BuildScriptImplOption(_BaseOption): DisableOption('--skip-test-swiftevolve', dest='test_swiftevolve'), DisableOption('--skip-test-toolchain-benchmarks', dest='test_toolchainbenchmarks'), + DisableOption('--skip-test-swift-inspect', + dest='test_swift_inspect'), DisableOption('--skip-build-clang-tools-extra', dest='build_clang_tools_extra'), diff --git a/utils/gyb_sourcekit_support/__init__.py b/utils/gyb_sourcekit_support/__init__.py index 90b1a806cb02c..76630346f3793 100644 --- a/utils/gyb_sourcekit_support/__init__.py +++ b/utils/gyb_sourcekit_support/__init__.py @@ -14,9 +14,9 @@ # utils/gyb_sourcekit_support/ directory as a module. # # ---------------------------------------------------------------------------- -from UIDs import UID_KEYS -from UIDs import UID_KINDS -from UIDs import UID_REQUESTS +from .UIDs import UID_KEYS +from .UIDs import UID_KINDS +from .UIDs import UID_REQUESTS def check_uid_duplication(): diff --git a/utils/gyb_syntax_support/AttributeNodes.py b/utils/gyb_syntax_support/AttributeNodes.py index 0788c518531cf..f0d7d9cd8c9d3 100644 --- a/utils/gyb_syntax_support/AttributeNodes.py +++ b/utils/gyb_syntax_support/AttributeNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 ATTRIBUTE_NODES = [ # token-list -> token? token-list? diff --git a/utils/gyb_syntax_support/AvailabilityNodes.py b/utils/gyb_syntax_support/AvailabilityNodes.py index 9eaefa96ec997..0d9579344e6be 100644 --- a/utils/gyb_syntax_support/AvailabilityNodes.py +++ b/utils/gyb_syntax_support/AvailabilityNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 AVAILABILITY_NODES = [ # availability-spec-list -> availability-entry availability-spec-list? diff --git a/utils/gyb_syntax_support/Child.py b/utils/gyb_syntax_support/Child.py index 3cbc432be90c6..33621cc394c79 100644 --- a/utils/gyb_syntax_support/Child.py +++ b/utils/gyb_syntax_support/Child.py @@ -1,7 +1,7 @@ # flake8: noqa I201 -from Classification import classification_by_name -from Token import SYNTAX_TOKEN_MAP -from kinds import SYNTAX_BASE_KINDS, kind_to_type, lowercase_first_word +from .Classification import classification_by_name +from .Token import SYNTAX_TOKEN_MAP +from .kinds import SYNTAX_BASE_KINDS, kind_to_type, lowercase_first_word class Child(object): diff --git a/utils/gyb_syntax_support/Classification.py b/utils/gyb_syntax_support/Classification.py index f5d4df70c5349..fa11b05a35f2c 100644 --- a/utils/gyb_syntax_support/Classification.py +++ b/utils/gyb_syntax_support/Classification.py @@ -1,5 +1,5 @@ -from Node import error -from kinds import lowercase_first_word # noqa: I201 +from .Node import error +from .kinds import lowercase_first_word # noqa: I201 class SyntaxClassification(object): diff --git a/utils/gyb_syntax_support/CommonNodes.py b/utils/gyb_syntax_support/CommonNodes.py index 0827680553b7e..896ef7261b29f 100644 --- a/utils/gyb_syntax_support/CommonNodes.py +++ b/utils/gyb_syntax_support/CommonNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 COMMON_NODES = [ Node('Decl', kind='Syntax'), diff --git a/utils/gyb_syntax_support/DeclNodes.py b/utils/gyb_syntax_support/DeclNodes.py index f9b47d50b313d..8c76efc24d751 100644 --- a/utils/gyb_syntax_support/DeclNodes.py +++ b/utils/gyb_syntax_support/DeclNodes.py @@ -1,6 +1,6 @@ # flake8: noqa I201 -from Child import Child -from Node import Node +from .Child import Child +from .Node import Node DECL_NODES = [ diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py index c5ebc8a4b976b..2d2295fec724c 100644 --- a/utils/gyb_syntax_support/ExprNodes.py +++ b/utils/gyb_syntax_support/ExprNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 EXPR_NODES = [ # An inout expression. diff --git a/utils/gyb_syntax_support/GenericNodes.py b/utils/gyb_syntax_support/GenericNodes.py index 57ab1c5e67c4c..c8ffa13eae8c8 100644 --- a/utils/gyb_syntax_support/GenericNodes.py +++ b/utils/gyb_syntax_support/GenericNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 GENERIC_NODES = [ # generic-where-clause -> 'where' requirement-list diff --git a/utils/gyb_syntax_support/Node.py b/utils/gyb_syntax_support/Node.py index cae36316e14c3..eb3899a07e378 100644 --- a/utils/gyb_syntax_support/Node.py +++ b/utils/gyb_syntax_support/Node.py @@ -1,7 +1,7 @@ from __future__ import print_function import sys # noqa: I201 -from kinds import SYNTAX_BASE_KINDS, kind_to_type, lowercase_first_word +from .kinds import SYNTAX_BASE_KINDS, kind_to_type, lowercase_first_word def error(msg): diff --git a/utils/gyb_syntax_support/NodeSerializationCodes.py b/utils/gyb_syntax_support/NodeSerializationCodes.py index eeea90df395eb..7d1589e98cc89 100644 --- a/utils/gyb_syntax_support/NodeSerializationCodes.py +++ b/utils/gyb_syntax_support/NodeSerializationCodes.py @@ -1,4 +1,4 @@ -from Node import error +from .Node import error SYNTAX_NODE_SERIALIZATION_CODES = { diff --git a/utils/gyb_syntax_support/PatternNodes.py b/utils/gyb_syntax_support/PatternNodes.py index 20e5cc6662855..454c950ec6e8c 100644 --- a/utils/gyb_syntax_support/PatternNodes.py +++ b/utils/gyb_syntax_support/PatternNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 PATTERN_NODES = [ diff --git a/utils/gyb_syntax_support/StmtNodes.py b/utils/gyb_syntax_support/StmtNodes.py index 49edc89298a94..f662f3975a5bf 100644 --- a/utils/gyb_syntax_support/StmtNodes.py +++ b/utils/gyb_syntax_support/StmtNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 STMT_NODES = [ # continue-stmt -> 'continue' label? ';'? diff --git a/utils/gyb_syntax_support/Token.py b/utils/gyb_syntax_support/Token.py index aaacc4fcfeb33..0aa1e685f75aa 100644 --- a/utils/gyb_syntax_support/Token.py +++ b/utils/gyb_syntax_support/Token.py @@ -1,6 +1,6 @@ -from Classification import classification_by_name -from Node import error # noqa: I201 -from kinds import lowercase_first_word # noqa: I201 +from .Classification import classification_by_name +from .Node import error # noqa: I201 +from .kinds import lowercase_first_word # noqa: I201 class Token(object): diff --git a/utils/gyb_syntax_support/Trivia.py b/utils/gyb_syntax_support/Trivia.py index dc30c24d528f6..b9e606ad64d60 100644 --- a/utils/gyb_syntax_support/Trivia.py +++ b/utils/gyb_syntax_support/Trivia.py @@ -1,5 +1,5 @@ -from Node import error -from kinds import lowercase_first_word # noqa: I201 +from .Node import error +from .kinds import lowercase_first_word # noqa: I201 class Trivia(object): diff --git a/utils/gyb_syntax_support/TypeNodes.py b/utils/gyb_syntax_support/TypeNodes.py index a9d8dfeabbb14..11a3e2c7e6d47 100644 --- a/utils/gyb_syntax_support/TypeNodes.py +++ b/utils/gyb_syntax_support/TypeNodes.py @@ -1,5 +1,5 @@ -from Child import Child -from Node import Node # noqa: I201 +from .Child import Child +from .Node import Node # noqa: I201 TYPE_NODES = [ # simple-type-identifier -> identifier generic-argument-clause? diff --git a/utils/gyb_syntax_support/__init__.py b/utils/gyb_syntax_support/__init__.py index 63ddd8203bb29..e3960dc95c813 100644 --- a/utils/gyb_syntax_support/__init__.py +++ b/utils/gyb_syntax_support/__init__.py @@ -1,22 +1,23 @@ import textwrap -from AttributeNodes import ATTRIBUTE_NODES # noqa: I201 -from AvailabilityNodes import AVAILABILITY_NODES # noqa: I201 -import Classification # noqa: I201 -from CommonNodes import COMMON_NODES # noqa: I201 -from DeclNodes import DECL_NODES # noqa: I201 -from ExprNodes import EXPR_NODES # noqa: I201 -from GenericNodes import GENERIC_NODES # noqa: I201 - -from NodeSerializationCodes import SYNTAX_NODE_SERIALIZATION_CODES, \ +from .AttributeNodes import ATTRIBUTE_NODES # noqa: I201 +from .AvailabilityNodes import AVAILABILITY_NODES # noqa: I201 +from . import Classification # noqa: I201 +from .CommonNodes import COMMON_NODES # noqa: I201 +from .DeclNodes import DECL_NODES # noqa: I201 +from .ExprNodes import EXPR_NODES # noqa: I201 +from .GenericNodes import GENERIC_NODES # noqa: I201 + +from . import Token + +from .NodeSerializationCodes import SYNTAX_NODE_SERIALIZATION_CODES, \ get_serialization_code, \ verify_syntax_node_serialization_codes -from PatternNodes import PATTERN_NODES # noqa: I201 -from StmtNodes import STMT_NODES # noqa: I201 +from .PatternNodes import PATTERN_NODES # noqa: I201 +from .StmtNodes import STMT_NODES # noqa: I201 -import Token -from Trivia import TRIVIAS # noqa: I201 -from TypeNodes import TYPE_NODES # noqa: I201 +from .Trivia import TRIVIAS # noqa: I201 +from .TypeNodes import TYPE_NODES # noqa: I201 # Re-export global constants diff --git a/utils/line-directive b/utils/line-directive index b12260be5da39..c4db569a0e2fd 100755 --- a/utils/line-directive +++ b/utils/line-directive @@ -61,7 +61,10 @@ line_pattern = re.compile( def _make_line_map(target_filename, stream=None): """ - >>> from StringIO import StringIO + >>> try: + ... from StringIO import StringIO # py2 + ... except ModuleNotFoundError: + ... from io import StringIO # py3 >>> _make_line_map('box', ... StringIO('''// ###sourceLocation(file: "foo.bar", line: 3) ... line 2 @@ -101,7 +104,7 @@ def map_line_to_source_file(target_filename, target_line_num): >>> # manually handle closing and deleting this file to allow us to open >>> # the file by its name across all platforms. >>> t = NamedTemporaryFile(delete=False) - >>> t.write('''line 1 + >>> _ = t.write(b'''line 1 ... line 2 ... // ###sourceLocation(file: "foo.bar", line: 20) ... line 4 @@ -151,7 +154,7 @@ def map_line_from_source_file(source_filename, source_line_num, >>> # manually handle closing and deleting this file to allow us to open >>> # the file by its name across all platforms. >>> t = NamedTemporaryFile(delete=False) - >>> t.write('''line 1 + >>> _ = t.write(b'''line 1 ... line 2 ... // ###sourceLocation(file: "foo.bar", line: 20) ... line 4 @@ -237,7 +240,7 @@ def run(): >>> # manually handle closing and deleting this file to allow us to open >>> # the file by its name across all platforms. >>> target1 = NamedTemporaryFile(delete=False) - >>> target1.write('''line 1 + >>> _ = target1.write(b'''line 1 ... line 2 ... // ###sourceLocation(file: "foo.bar", line: 20) ... line 4 @@ -252,7 +255,7 @@ def run(): >>> # manually handle closing and deleting this file to allow us to open >>> # the file by its name across all platforms. >>> target2 = NamedTemporaryFile(delete=False) - >>> target2.write('''// ###sourceLocation(file: "foo.bar", line: 7) + >>> _ = target2.write(b'''// ###sourceLocation(file: "foo.bar", line: 7) ... line 2 ... line 3 ... // ###sourceLocation(file: "fox.box", line: 11) @@ -269,21 +272,21 @@ def run(): >>> # the file by its name across all platforms. >>> raw_output = NamedTemporaryFile(delete=False) >>> target1_name, target2_name = target1.name, target2.name - >>> raw_output.write('''A - ... %(target1_name)s:2:111: error one + >>> _ = raw_output.write('''A + ... {target1_name}:2:111: error one ... B - ... %(target1_name)s:4:222: error two + ... {target1_name}:4:222: error two ... C - ... %(target1_name)s:8:333: error three + ... {target1_name}:8:333: error three ... D - ... glitch in file %(target2_name)s:1 assert one + ... glitch in file {target2_name}:1 assert one ... E - ... glitch in file %(target2_name)s, line 2 assert two - ... glitch at %(target2_name)s, line 3 assert three - ... glitch at %(target2_name)s:4 assert four - ... glitch in [%(target2_name)s, line 5 assert five - ... glitch in [%(target2_name)s:22 assert six - ... ''' % locals()) + ... glitch in file {target2_name}, line 2 assert two + ... glitch at {target2_name}, line 3 assert three + ... glitch at {target2_name}:4 assert four + ... glitch in [{target2_name}, line 5 assert five + ... glitch in [{target2_name}:22 assert six + ... '''.format(**locals()).encode('utf-8')) >>> raw_output.flush() Run this tool on the two targets, using a portable version of Unix 'cat' to @@ -330,7 +333,7 @@ def run(): >>> # manually handle closing and deleting this file to allow us to open >>> # the file by its name across all platforms. >>> long_output = NamedTemporaryFile(delete=False) - >>> long_output.write(''' + >>> _ = long_output.write(b''' ... // ###sourceLocation(file: "/public/core/Map.swift.gyb", line: 1) ... // ###sourceLocation(file: "/public/core/Map.swift.gyb", line: 1) ... //===--- Map.swift.gyb - Lazily map over a Sequence -----------*- swif @@ -649,7 +652,8 @@ def run(): >>> long_output.flush() >>> long_output_result = subprocess.check_output([sys.executable, ... __file__, long_output.name, '--', - ... 'echo', long_output.name + ':112:27: error:']).rstrip() + ... 'echo', long_output.name + ':112:27: error:' + ... ]).rstrip().decode('ascii') >>> print(long_output_result) /public/core/Map.swift.gyb:117:27: error: >>> target1.close() @@ -700,7 +704,7 @@ def run(): ':(?P[0-9]+):(?P[0-9]+):(?P.*?)\n?$') assertion_pattern = re.compile( - '^(?P.*( file | at |#[0-9]+: |[\[]))' + + '^(?P.*( file | at |#[0-9]+: |[\\[]))' + sources + '(?P, line |:)(?P[0-9]+)(?P.*?)\n?$') diff --git a/utils/swift_build_support/swift_build_support/products/__init__.py b/utils/swift_build_support/swift_build_support/products/__init__.py index 9b3bc2588388c..18bbd2b3fe9bc 100644 --- a/utils/swift_build_support/swift_build_support/products/__init__.py +++ b/utils/swift_build_support/swift_build_support/products/__init__.py @@ -27,6 +27,7 @@ from .sourcekitlsp import SourceKitLSP from .swift import Swift from .swiftevolve import SwiftEvolve +from .swiftinspect import SwiftInspect from .swiftpm import SwiftPM from .swiftsyntax import SwiftSyntax from .tensorflow import TensorFlowSwiftAPIs @@ -47,6 +48,7 @@ 'PlaygroundSupport', 'PythonKit', 'Swift', + 'SwiftInspect', 'SwiftPM', 'TensorFlowSwiftAPIs', 'XCTest', diff --git a/utils/swift_build_support/swift_build_support/products/swiftinspect.py b/utils/swift_build_support/swift_build_support/products/swiftinspect.py new file mode 100644 index 0000000000000..758c4f97806ef --- /dev/null +++ b/utils/swift_build_support/swift_build_support/products/swiftinspect.py @@ -0,0 +1,79 @@ +# swift_build_support/products/swiftinspect.py --------------------*- python -*- +# +# This source file is part of the Swift.org open source project +# +# Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors +# Licensed under Apache License v2.0 with Runtime Library Exception +# +# See https://swift.org/LICENSE.txt for license information +# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +# +# ---------------------------------------------------------------------------- + +import os +import platform + +from . import product +from .. import shell +from .. import targets + + +# Build against the current installed toolchain. +class SwiftInspect(product.Product): + @classmethod + def product_source_name(cls): + return "swift-dt" + + @classmethod + def is_build_script_impl_product(cls): + return False + + def should_build(self, host_target): + return True + + def build(self, host_target): + run_build_script_helper(host_target, self, self.args) + + def should_test(self, host_target): + return self.args.test_swift_inspect + + def test(self, host_target): + """Just run a single instance of the command for both .debug and + .release. + """ + pass + + def should_install(self, host_target): + return False + + def install(self, host_target): + pass + + +def run_build_script_helper(host_target, product, args): + toolchain_path = args.install_destdir + if platform.system() == 'Darwin': + # The prefix is an absolute path, so concatenate without os.path. + toolchain_path += \ + targets.darwin_toolchain_prefix(args.install_prefix) + + # Our source_dir is expected to be './$SOURCE_ROOT/benchmarks'. That is due + # the assumption that each product is in its own build directory. This + # product is not like that and has its package/tools instead in + # ./$SOURCE_ROOT/swift/benchmark. + package_path = os.path.join(product.source_dir, + '..', 'swift', 'tools', 'swift-inspect') + package_path = os.path.abspath(package_path) + + # We use a separate python helper to enable quicker iteration when working + # on this by avoiding going through build-script to test small changes. + helper_path = os.path.join(package_path, 'build_script_helper.py') + + build_cmd = [ + helper_path, + '--verbose', + '--package-path', package_path, + '--build-path', product.build_dir, + '--toolchain', toolchain_path, + ] + shell.call(build_cmd)