diff --git a/docs/Testing.md b/docs/Testing.md index 09306082790ed..b8f02d25b725b 100644 --- a/docs/Testing.md +++ b/docs/Testing.md @@ -38,7 +38,7 @@ uses an iOS 10.3 simulator configuration named "iPhone 5" for 32-bit testing. window, or with the command line: ```sh - xcrun simctl create 'iPhone 5' 'com.apple.CoreSimulator.SimDeviceType.iPhone-5' + xcrun simctl create 'iPhone 5' com.apple.CoreSimulator.SimDeviceType.iPhone-5 com.apple.CoreSimulator.SimRuntime.iOS-10-3 ``` 3. Append `--ios` to the `utils/build-script` command line (see below). diff --git a/include/swift/AST/AnyRequest.h b/include/swift/AST/AnyRequest.h index 63332fd68e7a6..669174e3bf978 100644 --- a/include/swift/AST/AnyRequest.h +++ b/include/swift/AST/AnyRequest.h @@ -66,6 +66,9 @@ struct AnyRequestVTable { static SourceLoc getNearestLoc(const void *ptr) { return static_cast(ptr)->getNearestLoc(); } + static bool isCached(const void *ptr) { + return static_cast(ptr)->isCached(); + } }; const uint64_t typeID; @@ -78,8 +81,29 @@ struct AnyRequestVTable { const std::function diagnoseCycle; const std::function noteCycleStep; const std::function getNearestLoc; + const std::function isCached; - template + template ::type * = nullptr> + static const AnyRequestVTable *get() { + static const AnyRequestVTable vtable = { + TypeID::value, + sizeof(Request), + &Impl::copy, + &Impl::getHash, + &Impl::deleter, + &Impl::isEqual, + &Impl::simpleDisplay, + &Impl::diagnoseCycle, + &Impl::noteCycleStep, + &Impl::getNearestLoc, + &Impl::isCached, + }; + return &vtable; + } + + template ::type * = nullptr> static const AnyRequestVTable *get() { static const AnyRequestVTable vtable = { TypeID::value, @@ -92,6 +116,7 @@ struct AnyRequestVTable { &Impl::diagnoseCycle, &Impl::noteCycleStep, &Impl::getNearestLoc, + [](auto){ return false; }, }; return &vtable; } @@ -194,6 +219,10 @@ class AnyRequestBase { return getVTable()->getNearestLoc(getRawStorage()); } + bool isCached() const { + return getVTable()->isCached(getRawStorage()); + } + /// Compare two instances for equality. friend bool operator==(const AnyRequestBase &lhs, const AnyRequestBase &rhs) { diff --git a/include/swift/AST/Evaluator.h b/include/swift/AST/Evaluator.h index 59de0280e6869..64eb1c1379421 100644 --- a/include/swift/AST/Evaluator.h +++ b/include/swift/AST/Evaluator.h @@ -225,7 +225,7 @@ class Evaluator { /// so all clients must cope with cycles. llvm::DenseMap> dependencies; - evaluator::DependencyCollector collector; + evaluator::DependencyRecorder recorder; /// Retrieve the request function for the given zone and request IDs. AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID, @@ -268,8 +268,8 @@ class Evaluator { typename std::enable_if::type * = nullptr> llvm::Expected operator()(const Request &request) { - evaluator::DependencyCollector::StackRAII incDeps{collector, - request}; + evaluator::DependencyRecorder::StackRAII incDeps{recorder, + request}; // The request can be cached, but check a predicate to determine // whether this particular instance is cached. This allows more // fine-grained control over which instances get cache. @@ -285,8 +285,8 @@ class Evaluator { typename std::enable_if::type * = nullptr> llvm::Expected operator()(const Request &request) { - evaluator::DependencyCollector::StackRAII incDeps{collector, - request}; + evaluator::DependencyRecorder::StackRAII incDeps{recorder, + request}; return getResultUncached(request); } @@ -431,19 +431,22 @@ class Evaluator { } private: - // Report the result of evaluating a request that is not a dependency sink - - // which is to say do nothing. - template ::type * = nullptr> + // Report the result of evaluating a request that is not a dependency sink. + template ::type * = nullptr> void reportEvaluatedResult(const Request &r, - const typename Request::OutputType &o) {} + const typename Request::OutputType &o) { + recorder.replay(ActiveRequest(r)); + } // Report the result of evaluating a request that is a dependency sink. template ::type * = nullptr> void reportEvaluatedResult(const Request &r, const typename Request::OutputType &o) { - r.writeDependencySink(collector, o); + return recorder.record(activeRequests, [&r, &o](auto &c) { + return r.writeDependencySink(c, o); + }); } public: diff --git a/include/swift/AST/EvaluatorDependencies.h b/include/swift/AST/EvaluatorDependencies.h index ceb16440c67bf..3abfa066761c6 100644 --- a/include/swift/AST/EvaluatorDependencies.h +++ b/include/swift/AST/EvaluatorDependencies.h @@ -18,6 +18,7 @@ #ifndef SWIFT_AST_EVALUATOR_DEPENDENCIES_H #define SWIFT_AST_EVALUATOR_DEPENDENCIES_H +#include "swift/AST/AnyRequest.h" #include "swift/AST/AttrKind.h" #include "swift/AST/SourceFile.h" #include "llvm/ADT/PointerIntPair.h" @@ -106,30 +107,78 @@ inline DependencyScope getScopeForAccessLevel(AccessLevel l) { // of individual contexts. using DependencySource = llvm::PointerIntPair; -/// A \c DependencyCollector is an aggregator of named references discovered in a -/// particular \c DependencyScope during the course of request evaluation. +struct DependencyRecorder; + struct DependencyCollector { -private: - /// A stack of dependency sources in the order they were evaluated. - llvm::SmallVector dependencySources; + struct Reference { + public: + enum class Kind { + Empty, + Tombstone, + UsedMember, + PotentialMember, + TopLevel, + Dynamic, + } kind; -public: - enum class Mode { - // Enables the current "status quo" behavior of the dependency collector. - // - // By default, the dependency collector moves to register dependencies in - // the referenced name trackers at the top of the active dependency stack. - StatusQuo, - // Enables an experimental mode to only register private dependencies. - // - // This mode restricts the dependency collector to ignore changes of - // scope. This has practical effect of charging all unqualified lookups to - // the primary file being acted upon instead of to the destination file. - ExperimentalPrivateDependencies, + NominalTypeDecl *subject; + DeclBaseName name; + + private: + Reference(Kind kind, NominalTypeDecl *subject, DeclBaseName name) + : kind(kind), subject(subject), name(name) {} + + public: + static Reference empty() { + return {Kind::Empty, llvm::DenseMapInfo::getEmptyKey(), + llvm::DenseMapInfo::getEmptyKey()}; + } + + static Reference tombstone() { + return {Kind::Empty, + llvm::DenseMapInfo::getTombstoneKey(), + llvm::DenseMapInfo::getTombstoneKey()}; + } + + public: + static Reference usedMember(NominalTypeDecl *subject, DeclBaseName name) { + return {Kind::UsedMember, subject, name}; + } + + static Reference potentialMember(NominalTypeDecl *subject) { + return {Kind::PotentialMember, subject, DeclBaseName()}; + } + + static Reference topLevel(DeclBaseName name) { + return {Kind::TopLevel, nullptr, name}; + } + + static Reference dynamic(DeclBaseName name) { + return {Kind::Dynamic, nullptr, name}; + } + + public: + struct Info { + static inline Reference getEmptyKey() { return Reference::empty(); } + static inline Reference getTombstoneKey() { + return Reference::tombstone(); + } + static inline unsigned getHashValue(const Reference &Val) { + return llvm::hash_combine(Val.kind, Val.subject, + Val.name.getAsOpaquePointer()); + } + static bool isEqual(const Reference &LHS, const Reference &RHS) { + return LHS.kind == RHS.kind && LHS.subject == RHS.subject && + LHS.name == RHS.name; + } + }; }; - Mode mode; - explicit DependencyCollector(Mode mode) : mode{mode} {}; + DependencyRecorder &parent; + llvm::DenseSet scratch; + +public: + explicit DependencyCollector(DependencyRecorder &parent) : parent(parent) {} public: /// Registers a named reference from the current dependency scope to a member @@ -168,6 +217,50 @@ struct DependencyCollector { /// a name that is found by \c AnyObject lookup. void addDynamicLookupName(DeclBaseName name); +public: + const DependencyRecorder &getRecorder() const { return parent; } + bool empty() const { return scratch.empty(); } +}; + +/// A \c DependencyCollector is an aggregator of named references discovered in a +/// particular \c DependencyScope during the course of request evaluation. +struct DependencyRecorder { + friend DependencyCollector; +private: + /// A stack of dependency sources in the order they were evaluated. + llvm::SmallVector dependencySources; + +public: + enum class Mode { + // Enables the current "status quo" behavior of the dependency collector. + // + // By default, the dependency collector moves to register dependencies in + // the referenced name trackers at the top of the active dependency stack. + StatusQuo, + // Enables an experimental mode to only register private dependencies. + // + // This mode restricts the dependency collector to ignore changes of + // scope. This has practical effect of charging all unqualified lookups to + // the primary file being acted upon instead of to the destination file. + ExperimentalPrivateDependencies, + }; + Mode mode; + llvm::DenseMap> + requestReferences; + bool isRecording; + + explicit DependencyRecorder(Mode mode) + : mode{mode}, requestReferences{}, isRecording{false} {}; + +private: + void realize(const DependencyCollector::Reference &ref); + +public: + void replay(const swift::ActiveRequest &req); + void record(const llvm::SetVector &stack, + llvm::function_ref rec); + public: /// Returns the scope of the current active scope. /// @@ -197,14 +290,14 @@ struct DependencyCollector { /// dependency source stack. It is specialized to be zero-cost for /// requests that are not dependency sources. template > struct StackRAII { - StackRAII(DependencyCollector &DC, const Request &Req) {} + StackRAII(DependencyRecorder &DR, const Request &Req) {} }; template struct StackRAII::type> { - NullablePtr Coll; - StackRAII(DependencyCollector &coll, const Request &Req) { + NullablePtr Coll; + StackRAII(DependencyRecorder &coll, const Request &Req) { auto Source = Req.readDependencySource(coll); // If there is no source to introduce, bail. This can occur if // a request originates in the context of a module. diff --git a/include/swift/AST/IRGenRequests.h b/include/swift/AST/IRGenRequests.h index dd19afa4bedb6..3cd8212176aee 100644 --- a/include/swift/AST/IRGenRequests.h +++ b/include/swift/AST/IRGenRequests.h @@ -200,7 +200,7 @@ class IRGenSourceFileRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; class IRGenWholeModuleRequest diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h index df8c0dea04179..e15c8b787dce1 100644 --- a/include/swift/AST/NameLookupRequests.h +++ b/include/swift/AST/NameLookupRequests.h @@ -189,7 +189,7 @@ class InheritedProtocolsRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &e) const; + readDependencySource(const evaluator::DependencyRecorder &e) const; void writeDependencySink(evaluator::DependencyCollector &tracker, ArrayRef result) const; }; @@ -330,7 +330,7 @@ class GetDestructorRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; class GenericParamListRequest : @@ -434,7 +434,7 @@ class UnqualifiedLookupRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; void writeDependencySink(evaluator::DependencyCollector &tracker, LookupResult res) const; }; @@ -506,7 +506,7 @@ class ModuleQualifiedLookupRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; void writeDependencySink(evaluator::DependencyCollector &tracker, QualifiedLookupResult lookupResult) const; }; @@ -533,7 +533,7 @@ class QualifiedLookupRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// The input type for a direct lookup request. diff --git a/include/swift/AST/ParseRequests.h b/include/swift/AST/ParseRequests.h index b37e00695676e..bd641893490d4 100644 --- a/include/swift/AST/ParseRequests.h +++ b/include/swift/AST/ParseRequests.h @@ -103,7 +103,7 @@ class ParseSourceFileRequest public: evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; void simple_display(llvm::raw_ostream &out, @@ -125,7 +125,7 @@ class CodeCompletionSecondPassRequest public: evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// The zone number for the parser. diff --git a/include/swift/AST/SILGenRequests.h b/include/swift/AST/SILGenRequests.h index 3f93c5608ed7b..c47b07a8b3c2b 100644 --- a/include/swift/AST/SILGenRequests.h +++ b/include/swift/AST/SILGenRequests.h @@ -104,7 +104,7 @@ class SILGenerationRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// Parses a .sil file into a SILModule. diff --git a/include/swift/AST/SimpleRequest.h b/include/swift/AST/SimpleRequest.h index 2ab9003b6d2f0..42751e142682c 100644 --- a/include/swift/AST/SimpleRequest.h +++ b/include/swift/AST/SimpleRequest.h @@ -232,7 +232,7 @@ SourceLoc extractNearestSourceLoc(const std::tuple &value) { /// the 3 caching kinds defined above. /// \code /// evaluator::DependencySource -/// readDependencySource(const evaluator::DependencyCollector &) const; +/// readDependencySource(const evaluator::DependencyRecorder &) const; /// \endcode /// /// Requests that define dependency sinks should instead override diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 3d96d17924add..200663d00cb80 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -123,7 +123,7 @@ class SuperclassTypeRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &e) const; + readDependencySource(const evaluator::DependencyRecorder &e) const; void writeDependencySink(evaluator::DependencyCollector &tracker, Type t) const; }; @@ -893,7 +893,7 @@ class TypeCheckFunctionBodyUntilRequest : public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// Request to obtain a list of stored properties in a nominal type. @@ -2034,7 +2034,7 @@ class TypeCheckSourceFileRequest public: // Incremental dependencies. evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &) const; + readDependencySource(const evaluator::DependencyRecorder &) const; }; /// Computes whether the specified type or a super-class/super-protocol has the @@ -2277,7 +2277,7 @@ class LookupAllConformancesInContextRequest public: // Incremental dependencies evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &eval) const; + readDependencySource(const evaluator::DependencyRecorder &eval) const; void writeDependencySink(evaluator::DependencyCollector &tracker, ProtocolConformanceLookupResult r) const; }; @@ -2305,7 +2305,7 @@ class CheckRedeclarationRequest public: evaluator::DependencySource - readDependencySource(const evaluator::DependencyCollector &eval) const; + readDependencySource(const evaluator::DependencyRecorder &eval) const; void writeDependencySink(evaluator::DependencyCollector &tracker, evaluator::SideEffect) const; }; diff --git a/include/swift/Basic/SourceManager.h b/include/swift/Basic/SourceManager.h index d05e8c9e66f81..d503772799b38 100644 --- a/include/swift/Basic/SourceManager.h +++ b/include/swift/Basic/SourceManager.h @@ -268,6 +268,11 @@ class SourceManager { else return 0; } + +public: + bool isLocInVirtualFile(SourceLoc Loc) const { + return getVirtualFile(Loc) != nullptr; + } }; } // end namespace swift diff --git a/lib/AST/Evaluator.cpp b/lib/AST/Evaluator.cpp index b4a8ea3a369cb..d1e5b7aa16e1f 100644 --- a/lib/AST/Evaluator.cpp +++ b/lib/AST/Evaluator.cpp @@ -21,6 +21,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/SaveAndRestore.h" using namespace swift; @@ -60,12 +61,13 @@ void Evaluator::registerRequestFunctions( requestFunctionsByZone.push_back({zoneID, functions}); } -static evaluator::DependencyCollector::Mode +static evaluator::DependencyRecorder::Mode computeDependencyModeFromFlags(bool enableExperimentalPrivateDeps) { - using Mode = evaluator::DependencyCollector::Mode; + using Mode = evaluator::DependencyRecorder::Mode; if (enableExperimentalPrivateDeps) { return Mode::ExperimentalPrivateDependencies; } + return Mode::StatusQuo; } @@ -74,8 +76,7 @@ Evaluator::Evaluator(DiagnosticEngine &diags, bool debugDumpCycles, bool enableExperimentalPrivateDeps) : diags(diags), debugDumpCycles(debugDumpCycles), buildDependencyGraph(buildDependencyGraph), - collector{computeDependencyModeFromFlags(enableExperimentalPrivateDeps)} { -} + recorder{computeDependencyModeFromFlags(enableExperimentalPrivateDeps)} {} void Evaluator::emitRequestEvaluatorGraphViz(llvm::StringRef graphVizPath) { std::error_code error; @@ -378,24 +379,115 @@ void Evaluator::dumpDependenciesGraphviz() const { printDependenciesGraphviz(llvm::dbgs()); } +void evaluator::DependencyRecorder::realize( + const DependencyCollector::Reference &ref) { + auto *tracker = getActiveDependencyTracker(); + assert(tracker && "cannot realize dependency without name tracker!"); + + using Kind = evaluator::DependencyCollector::Reference::Kind; + switch (ref.kind) { + case Kind::Empty: + case Kind::Tombstone: + llvm_unreachable("cannot record empty dependency"); + case Kind::UsedMember: + tracker->addUsedMember({ref.subject, ref.name}, isActiveSourceCascading()); + break; + case Kind::PotentialMember: + tracker->addUsedMember({ref.subject, Identifier()}, + isActiveSourceCascading()); + break; + case Kind::TopLevel: + tracker->addTopLevelName(ref.name, isActiveSourceCascading()); + break; + case Kind::Dynamic: + tracker->addDynamicLookupName(ref.name, isActiveSourceCascading()); + break; + } +} + void evaluator::DependencyCollector::addUsedMember(NominalTypeDecl *subject, DeclBaseName name) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addUsedMember({subject, name}, isActiveSourceCascading()); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::usedMember(subject, name)); + } + return parent.realize(Reference::usedMember(subject, name)); } void evaluator::DependencyCollector::addPotentialMember( NominalTypeDecl *subject) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addUsedMember({subject, Identifier()}, isActiveSourceCascading()); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::potentialMember(subject)); + } + return parent.realize(Reference::potentialMember(subject)); } void evaluator::DependencyCollector::addTopLevelName(DeclBaseName name) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addTopLevelName(name, isActiveSourceCascading()); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::topLevel(name)); + } + return parent.realize(Reference::topLevel(name)); } void evaluator::DependencyCollector::addDynamicLookupName(DeclBaseName name) { - if (auto *tracker = getActiveDependencyTracker()) - tracker->addDynamicLookupName(name, isActiveSourceCascading()); + if (parent.mode == + DependencyRecorder::Mode::ExperimentalPrivateDependencies) { + scratch.insert(Reference::dynamic(name)); + } + return parent.realize(Reference::dynamic(name)); +} + +void evaluator::DependencyRecorder::record( + const llvm::SetVector &stack, + llvm::function_ref rec) { + assert(!isRecording && "Probably not a good idea to allow nested recording"); + if (!getActiveDependencyTracker()) { + return; + } + + llvm::SaveAndRestore restore(isRecording, true); + + DependencyCollector collector{*this}; + rec(collector); + if (collector.empty()) { + return; + } + + assert(mode != Mode::StatusQuo); + for (const auto &request : stack) { + if (!request.isCached()) { + continue; + } + + auto entry = requestReferences.find_as(request); + if (entry == requestReferences.end()) { + requestReferences.insert({AnyRequest(request), collector.scratch}); + continue; + } + + entry->second.insert(collector.scratch.begin(), collector.scratch.end()); + } +} + +void evaluator::DependencyRecorder::replay(const swift::ActiveRequest &req) { + assert(!isRecording && "Probably not a good idea to allow nested recording"); + + if (mode == Mode::StatusQuo || !getActiveDependencyTracker()) { + return; + } + + if (!req.isCached()) { + return; + } + + auto entry = requestReferences.find_as(req); + if (entry == requestReferences.end()) { + return; + } + + for (const auto &ref : entry->second) { + realize(ref); + } } diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp index b526d8108bd9a..5b44f7fa0dce2 100644 --- a/lib/AST/NameLookupRequests.cpp +++ b/lib/AST/NameLookupRequests.cpp @@ -89,7 +89,7 @@ void InheritedProtocolsRequest::cacheResult(ArrayRef PDs) const } evaluator::DependencySource InheritedProtocolsRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { auto *PD = std::get<0>(getStorage()); // Ignore context changes for protocols outside our module. This // prevents transitive cascading edges when e.g. our private @@ -184,7 +184,7 @@ void ExtendedNominalRequest::writeDependencySink( auto *SF = std::get<0>(getStorage())->getParentSourceFile(); if (!SF) return; - if (SF != tracker.getActiveDependencySourceOrNull()) + if (SF != tracker.getRecorder().getActiveDependencySourceOrNull()) return; tracker.addPotentialMember(value); } @@ -208,7 +208,7 @@ void GetDestructorRequest::cacheResult(DestructorDecl *value) const { } evaluator::DependencySource GetDestructorRequest::readDependencySource( - const evaluator::DependencyCollector &eval) const { + const evaluator::DependencyRecorder &eval) const { // Looking up the deinitializer currently always occurs in a private // scope because it is impossible to reference 'deinit' in user code, and a // valid 'deinit' declaration cannot occur outside of the @@ -338,7 +338,7 @@ swift::extractNearestSourceLoc(const LookupConformanceDescriptor &desc) { //----------------------------------------------------------------------------// evaluator::DependencySource ModuleQualifiedLookupRequest::readDependencySource( - const evaluator::DependencyCollector &eval) const { + const evaluator::DependencyRecorder &eval) const { auto *DC = std::get<0>(getStorage()); auto options = std::get<3>(getStorage()); @@ -385,7 +385,7 @@ void LookupConformanceInModuleRequest::writeDependencySink( if (!Adoptee) return; - auto *source = reqTracker.getActiveDependencySourceOrNull(); + auto *source = reqTracker.getRecorder().getActiveDependencySourceOrNull(); if (!source) return; @@ -402,7 +402,7 @@ void LookupConformanceInModuleRequest::writeDependencySink( //----------------------------------------------------------------------------// evaluator::DependencySource UnqualifiedLookupRequest::readDependencySource( - const evaluator::DependencyCollector &) const { + const evaluator::DependencyRecorder &) const { auto &desc = std::get<0>(getStorage()); // FIXME(Evaluator Incremental Dependencies): This maintains compatibility // with the existing scheme, but the existing scheme is totally ad-hoc. We @@ -426,7 +426,7 @@ void UnqualifiedLookupRequest::writeDependencySink( //----------------------------------------------------------------------------// evaluator::DependencySource QualifiedLookupRequest::readDependencySource( - const evaluator::DependencyCollector &) const { + const evaluator::DependencyRecorder &) const { auto *dc = std::get<0>(getStorage()); auto opts = std::get<3>(getStorage()); // FIXME(Evaluator Incremental Dependencies): This is an artifact of the diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp index be94bfb98449e..91d3a48763dae 100644 --- a/lib/AST/TypeCheckRequests.cpp +++ b/lib/AST/TypeCheckRequests.cpp @@ -158,7 +158,7 @@ void SuperclassTypeRequest::cacheResult(Type value) const { } evaluator::DependencySource SuperclassTypeRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { const auto access = std::get<0>(getStorage())->getFormalAccess(); return { e.getActiveDependencySourceOrNull(), @@ -1349,7 +1349,7 @@ void CheckRedeclarationRequest::cacheResult(evaluator::SideEffect) const { } evaluator::DependencySource CheckRedeclarationRequest::readDependencySource( - const evaluator::DependencyCollector &eval) const { + const evaluator::DependencyRecorder &eval) const { auto *current = std::get<0>(getStorage()); auto *currentDC = current->getDeclContext(); return { @@ -1384,7 +1384,7 @@ void CheckRedeclarationRequest::writeDependencySink( evaluator::DependencySource LookupAllConformancesInContextRequest::readDependencySource( - const evaluator::DependencyCollector &collector) const { + const evaluator::DependencyRecorder &collector) const { const auto *nominal = std::get<0>(getStorage()) ->getAsGenericContext() ->getSelfNominalTypeDecl(); @@ -1427,7 +1427,7 @@ void ResolveTypeEraserTypeRequest::cacheResult(Type value) const { //----------------------------------------------------------------------------// evaluator::DependencySource TypeCheckSourceFileRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { return {std::get<0>(getStorage()), evaluator::DependencyScope::Cascading}; } @@ -1460,7 +1460,7 @@ void TypeCheckSourceFileRequest::cacheResult(evaluator::SideEffect) const { evaluator::DependencySource TypeCheckFunctionBodyUntilRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { // We're going under a function body scope, unconditionally flip the scope // to private. return { diff --git a/lib/Frontend/PrintingDiagnosticConsumer.cpp b/lib/Frontend/PrintingDiagnosticConsumer.cpp index b7f2a9ea60d8f..ab4937d448b8b 100644 --- a/lib/Frontend/PrintingDiagnosticConsumer.cpp +++ b/lib/Frontend/PrintingDiagnosticConsumer.cpp @@ -381,6 +381,9 @@ namespace { }; unsigned LineNumber; + // The line number displayed to the user. This may differ from the actual + // line number if #sourceLocation is used. + unsigned DisplayLineNumber; std::string LineText; SmallVector Messages; SmallVector Highlights; @@ -448,8 +451,10 @@ namespace { } public: - AnnotatedLine(unsigned LineNumber, StringRef LineText) - : LineNumber(LineNumber), LineText(LineText) {} + AnnotatedLine(unsigned LineNumber, unsigned DisplayLineNumber, + StringRef LineText) + : LineNumber(LineNumber), DisplayLineNumber(DisplayLineNumber), + LineText(LineText) {} unsigned getLineNumber() { return LineNumber; } @@ -469,7 +474,7 @@ namespace { } void render(unsigned LineNumberIndent, raw_ostream &Out) { - printNumberedGutter(LineNumber, LineNumberIndent, Out); + printNumberedGutter(DisplayLineNumber, LineNumberIndent, Out); // Determine if the line is all-ASCII. This will determine a number of // later formatting decisions. @@ -628,14 +633,17 @@ namespace { /// diagnostic message. This is printed alongside the file path so it can be /// parsed by editors and other tooling. SourceLoc PrimaryLoc; + /// Whether the excerpt is from a virtual file (e.g. one introduced using + /// #sourceLocation). + bool FromVirtualFile; std::vector AnnotatedLines; /// Return the AnnotatedLine for a given SourceLoc, creating it if it /// doesn't already exist. AnnotatedLine &lineForLoc(SourceLoc Loc) { - // FIXME: This call to `getLineAndColumn` is expensive. - unsigned lineNo = SM.getLineAndColumn(Loc).first; - AnnotatedLine newLine(lineNo, ""); + // FIXME: This call to `getLineNumber` is expensive. + unsigned lineNo = SM.getLineNumber(Loc); + AnnotatedLine newLine(lineNo, 0, ""); auto iter = std::lower_bound(AnnotatedLines.begin(), AnnotatedLines.end(), newLine, [](AnnotatedLine l1, AnnotatedLine l2) { @@ -643,6 +651,7 @@ namespace { }); if (iter == AnnotatedLines.end() || iter->getLineNumber() != lineNo) { newLine.LineText = SM.getLineString(BufferID, lineNo); + newLine.DisplayLineNumber = SM.getLineAndColumn(Loc).first; return *AnnotatedLines.insert(iter, newLine); } else { return *iter; @@ -658,10 +667,8 @@ namespace { void lineRangesForRange(CharSourceRange Range, SmallVectorImpl &LineRanges) { - // FIXME: The calls to `getLineAndColumn` and `getLocForLineCol` are - // expensive. - unsigned startLineNo = SM.getLineAndColumn(Range.getStart()).first; - unsigned endLineNo = SM.getLineAndColumn(Range.getEnd()).first; + unsigned startLineNo = SM.getLineNumber(Range.getStart()); + unsigned endLineNo = SM.getLineNumber(Range.getEnd()); if (startLineNo == endLineNo) { LineRanges.push_back(Range); @@ -687,10 +694,19 @@ namespace { LineRanges.push_back(CharSourceRange(SM, lastLineStart, Range.getEnd())); } + void printLineEllipsis(raw_ostream &Out) { + Out.changeColor(ColoredStream::Colors::CYAN, true); + Out << llvm::formatv("{0}...\n", + llvm::fmt_repeat(" ", getPreferredLineNumberIndent())); + Out.resetColor(); + } + public: AnnotatedFileExcerpt(SourceManager &SM, unsigned BufferID, SourceLoc PrimaryLoc) - : SM(SM), BufferID(BufferID), PrimaryLoc(PrimaryLoc) {} + : SM(SM), BufferID(BufferID), PrimaryLoc(PrimaryLoc) { + FromVirtualFile = SM.isLocInVirtualFile(PrimaryLoc); + } unsigned getPreferredLineNumberIndent() { // The lines are already in sorted ascending order, and we render one line @@ -734,13 +750,14 @@ namespace { auto primaryLineAndColumn = SM.getLineAndColumn(PrimaryLoc); Out.changeColor(ColoredStream::Colors::CYAN); Out << std::string(lineNumberIndent + 1, '=') << " " - << SM.getIdentifierForBuffer(BufferID) << ":" + << SM.getDisplayNameForLoc(PrimaryLoc) << ":" << primaryLineAndColumn.first << ":" << primaryLineAndColumn.second << " " << std::string(lineNumberIndent + 1, '=') << "\n"; Out.resetColor(); - // Print one extra line at the top for context. - if (AnnotatedLines.front().getLineNumber() > 1) + // Print one extra line at the top for context, so long as this isn't an + // excerpt from a virtual file. + if (AnnotatedLines.front().getLineNumber() > 1 && !FromVirtualFile) printNumberedLine(SM, BufferID, AnnotatedLines.front().getLineNumber() - 1, lineNumberIndent, Out); @@ -754,14 +771,18 @@ namespace { for (auto line = AnnotatedLines.begin() + 1; line != AnnotatedLines.end(); ++line) { unsigned lineNumber = line->getLineNumber(); - if (lineNumber - lastLineNumber > maxIntermediateLines) { + if (FromVirtualFile) { + // Don't print intermediate lines in virtual files, as they may not + // make sense in context. Instead, just print an ellipsis between them + // if they're not consecutive in the actual source file. + if (lineNumber - lastLineNumber > 1) { + printLineEllipsis(Out); + } + } else if (lineNumber - lastLineNumber > maxIntermediateLines) { // Use an ellipsis to denote an ommitted part of the file. printNumberedLine(SM, BufferID, lastLineNumber + 1, lineNumberIndent, Out); - Out.changeColor(ColoredStream::Colors::CYAN); - Out << llvm::formatv("{0}...\n", - llvm::fmt_repeat(" ", lineNumberIndent)); - Out.resetColor(); + printLineEllipsis(Out); printNumberedLine(SM, BufferID, lineNumber - 1, lineNumberIndent, Out); } else { @@ -774,11 +795,14 @@ namespace { line->render(lineNumberIndent, Out); lastLineNumber = lineNumber; } - // Print one extra line at the bottom for context. - printNumberedLine( - SM, BufferID, - AnnotatedLines[AnnotatedLines.size() - 1].getLineNumber() + 1, - lineNumberIndent, Out); + // Print one extra line at the bottom for context, so long as the excerpt + // isn't from a virtual file. + if (!FromVirtualFile) { + printNumberedLine( + SM, BufferID, + AnnotatedLines[AnnotatedLines.size() - 1].getLineNumber() + 1, + lineNumberIndent, Out); + } } }; } // end anonymous namespace @@ -788,14 +812,17 @@ namespace swift { /// complete diagnostic message. class AnnotatedSourceSnippet { SourceManager &SM; - std::map FileExcerpts; + std::map FileExcerpts; SmallVector, 1> UnknownLocationMessages; AnnotatedFileExcerpt &excerptForLoc(SourceLoc Loc) { + StringRef bufName = SM.getDisplayNameForLoc(Loc); unsigned bufID = SM.findBufferContainingLoc(Loc); - FileExcerpts.emplace(bufID, AnnotatedFileExcerpt(SM, bufID, Loc)); - return FileExcerpts.find(bufID)->second; + // Use the buffer display name as the key in the excerpt map instead of the + // buffer identifier to respect #sourceLocation directives. + FileExcerpts.emplace(bufName, AnnotatedFileExcerpt(SM, bufID, Loc)); + return FileExcerpts.find(bufName)->second; } public: diff --git a/lib/IDE/CodeCompletion.cpp b/lib/IDE/CodeCompletion.cpp index 6d7e0434eb437..63d59acd325a5 100644 --- a/lib/IDE/CodeCompletion.cpp +++ b/lib/IDE/CodeCompletion.cpp @@ -6196,6 +6196,8 @@ void CodeCompletionCallbacksImpl::doneParsing() { break; } + llvm::SmallPtrSet seenModuleNames; + for (auto &Request: Lookup.RequestedCachedResults) { // Use the current SourceFile as the DeclContext so that we can use it to // perform qualified lookup, and to get the correct visibility for @@ -6248,7 +6250,9 @@ void CodeCompletionCallbacksImpl::doneParsing() { return; // already handled. RequestedModules.push_back({std::move(K), TheModule, Request.OnlyTypes, Request.OnlyPrecedenceGroups}); - if (Request.IncludeModuleQualifier) + + if (Request.IncludeModuleQualifier && + seenModuleNames.insert(TheModule->getName()).second) Lookup.addModuleName(TheModule); } }; @@ -6263,8 +6267,10 @@ void CodeCompletionCallbacksImpl::doneParsing() { Lookup.getToplevelCompletions(Request.OnlyTypes); // Add the qualifying module name - if (Request.IncludeModuleQualifier) - Lookup.addModuleName(CurDeclContext->getParentModule()); + auto curModule = CurDeclContext->getParentModule(); + if (Request.IncludeModuleQualifier && + seenModuleNames.insert(curModule->getName()).second) + Lookup.addModuleName(curModule); // Add results for all imported modules. ModuleDecl::ImportFilter ImportFilter; diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp index 09b938a92921a..ec3d205149d3a 100644 --- a/lib/IRGen/GenHeap.cpp +++ b/lib/IRGen/GenHeap.cpp @@ -292,7 +292,7 @@ static llvm::Value *calcInitOffset(swift::irgen::IRGenFunction &IGF, auto &prevElt = layout.getElement(i - 1); auto prevType = layout.getElementTypes()[i - 1]; // Start calculating offsets from the last fixed-offset field. - Size lastFixedOffset = layout.getElement(i - 1).getByteOffset(); + Size lastFixedOffset = layout.getElement(i - 1).getByteOffsetDuringLayout(); if (auto *fixedType = dyn_cast(&prevElt.getType())) { // If the last fixed-offset field is also fixed-size, we can // statically compute the end of the fixed-offset fields. diff --git a/lib/IRGen/IRGenRequests.cpp b/lib/IRGen/IRGenRequests.cpp index ed62a24084d8f..5116c83c1abde 100644 --- a/lib/IRGen/IRGenRequests.cpp +++ b/lib/IRGen/IRGenRequests.cpp @@ -53,7 +53,7 @@ SourceLoc swift::extractNearestSourceLoc(const IRGenDescriptor &desc) { } evaluator::DependencySource IRGenSourceFileRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { auto &desc = std::get<0>(getStorage()); return { desc.Ctx.dyn_cast(), diff --git a/lib/IRGen/StructLayout.cpp b/lib/IRGen/StructLayout.cpp index 4b2d8598065ee..66f11250ab5a5 100644 --- a/lib/IRGen/StructLayout.cpp +++ b/lib/IRGen/StructLayout.cpp @@ -312,7 +312,8 @@ void StructLayoutBuilder::addNonFixedSizeElement(ElementLayout &elt) { /// Add an empty element to the aggregate. void StructLayoutBuilder::addEmptyElement(ElementLayout &elt) { - elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal)); + auto byteOffset = isFixedLayout() ? CurSize : Size(0); + elt.completeEmpty(elt.getType().isPOD(ResilienceExpansion::Maximal), byteOffset); } /// Add an element at the fixed offset of the current end of the diff --git a/lib/IRGen/StructLayout.h b/lib/IRGen/StructLayout.h index bc20701d74a1f..541c2cd268988 100644 --- a/lib/IRGen/StructLayout.h +++ b/lib/IRGen/StructLayout.h @@ -114,6 +114,14 @@ class ElementLayout { /// The offset in bytes from the start of the struct. unsigned ByteOffset; + /// The offset in bytes from the start of the struct, except EmptyFields are + /// placed at the current byte offset instead of 0. For the purpose of the + /// final layout empty fields are placed at offset 0, that however creates a + /// whole slew of special cases to deal with. Instead of dealing with these + /// special cases during layout, we pretend that empty fields are placed + /// just like any other field at the current offset. + unsigned ByteOffsetForLayout; + /// The index of this element, either in the LLVM struct (if fixed) /// or in the non-fixed elements array (if non-fixed). unsigned Index : 28; @@ -142,13 +150,15 @@ class ElementLayout { TheKind = other.TheKind; IsPOD = other.IsPOD; ByteOffset = other.ByteOffset; + ByteOffsetForLayout = other.ByteOffsetForLayout; Index = other.Index; } - void completeEmpty(IsPOD_t isPOD) { + void completeEmpty(IsPOD_t isPOD, Size byteOffset) { TheKind = unsigned(Kind::Empty); IsPOD = unsigned(isPOD); ByteOffset = 0; + ByteOffsetForLayout = byteOffset.getValue(); Index = 0; // make a complete write of the bitfield } @@ -156,6 +166,7 @@ class ElementLayout { TheKind = unsigned(Kind::InitialNonFixedSize); IsPOD = unsigned(isPOD); ByteOffset = 0; + ByteOffsetForLayout = ByteOffset; Index = 0; // make a complete write of the bitfield } @@ -163,6 +174,7 @@ class ElementLayout { TheKind = unsigned(Kind::Fixed); IsPOD = unsigned(isPOD); ByteOffset = byteOffset.getValue(); + ByteOffsetForLayout = ByteOffset; Index = structIndex; assert(getByteOffset() == byteOffset); @@ -172,6 +184,7 @@ class ElementLayout { TheKind = unsigned(Kind::EmptyTailAllocatedCType); IsPOD = unsigned(isPOD); ByteOffset = byteOffset.getValue(); + ByteOffsetForLayout = ByteOffset; Index = 0; assert(getByteOffset() == byteOffset); @@ -228,6 +241,17 @@ class ElementLayout { return Size(ByteOffset); } + /// The offset in bytes from the start of the struct, except EmptyFields are + /// placed at the current byte offset instead of 0. For the purpose of the + /// final layout empty fields are placed at offset 0, that however creates a + /// whole slew of special cases to deal with. Instead of dealing with these + /// special cases during layout, we pretend that empty fields are placed + /// just like any other field at the current offset. + Size getByteOffsetDuringLayout() const { + assert(isCompleted() && hasByteOffset()); + return Size(ByteOffsetForLayout); + } + /// Given that this element has a fixed offset, return the index in /// the LLVM struct. unsigned getStructIndex() const { diff --git a/lib/Parse/ParseRequests.cpp b/lib/Parse/ParseRequests.cpp index c424b959e9dde..8f1f9d23cd3b5 100644 --- a/lib/Parse/ParseRequests.cpp +++ b/lib/Parse/ParseRequests.cpp @@ -168,7 +168,7 @@ ArrayRef ParseSourceFileRequest::evaluate(Evaluator &evaluator, } evaluator::DependencySource ParseSourceFileRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { return {std::get<0>(getStorage()), evaluator::DependencyScope::Cascading}; } @@ -196,7 +196,7 @@ void swift::simple_display(llvm::raw_ostream &out, evaluator::DependencySource CodeCompletionSecondPassRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { return {std::get<0>(getStorage()), e.getActiveSourceScope()}; } diff --git a/lib/SILGen/SILGenRequests.cpp b/lib/SILGen/SILGenRequests.cpp index a854ebe37a5ee..6d441591d31e4 100644 --- a/lib/SILGen/SILGenRequests.cpp +++ b/lib/SILGen/SILGenRequests.cpp @@ -47,7 +47,7 @@ SourceLoc swift::extractNearestSourceLoc(const SILGenDescriptor &desc) { } evaluator::DependencySource SILGenerationRequest::readDependencySource( - const evaluator::DependencyCollector &e) const { + const evaluator::DependencyRecorder &e) const { auto &desc = std::get<0>(getStorage()); // We don't track dependencies in whole-module mode. diff --git a/stdlib/include/llvm/Config/llvm-config.h.cmake b/stdlib/include/llvm/Config/llvm-config.h.cmake deleted file mode 100644 index 475c93efd653d..0000000000000 --- a/stdlib/include/llvm/Config/llvm-config.h.cmake +++ /dev/null @@ -1,82 +0,0 @@ -/*===------- llvm/Config/llvm-config.h - llvm configuration -------*- C -*-===*/ -/* */ -/* Part of the LLVM Project, under the Apache License v2.0 with LLVM */ -/* Exceptions. */ -/* See https://llvm.org/LICENSE.txt for license information. */ -/* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ -/* */ -/*===----------------------------------------------------------------------===*/ - -/* This file enumerates variables from the LLVM configuration so that they - can be in exported headers and won't override package specific directives. - This is a C header that can be included in the llvm-c headers. */ - -#ifndef LLVM_CONFIG_H -#define LLVM_CONFIG_H - -/* Define if LLVM_ENABLE_DUMP is enabled */ -#cmakedefine LLVM_ENABLE_DUMP - -/* Target triple LLVM will generate code for by default */ -#cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" - -/* Define if threads enabled */ -#cmakedefine01 LLVM_ENABLE_THREADS - -/* Has gcc/MSVC atomic intrinsics */ -#cmakedefine01 LLVM_HAS_ATOMICS - -/* Host triple LLVM will be executed on */ -#cmakedefine LLVM_HOST_TRIPLE "${LLVM_HOST_TRIPLE}" - -/* LLVM architecture name for the native architecture, if available */ -#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} - -/* LLVM name for the native AsmParser init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser - -/* LLVM name for the native AsmPrinter init function, if available */ -#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter - -/* LLVM name for the native Disassembler init function, if available */ -#cmakedefine LLVM_NATIVE_DISASSEMBLER LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler - -/* LLVM name for the native Target init function, if available */ -#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target - -/* LLVM name for the native TargetInfo init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo - -/* LLVM name for the native target MC init function, if available */ -#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC - -/* Define if this is Unixish platform */ -#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} - -/* Define if we have the Intel JIT API runtime support library */ -#cmakedefine01 LLVM_USE_INTEL_JITEVENTS - -/* Define if we have the oprofile JIT-support library */ -#cmakedefine01 LLVM_USE_OPROFILE - -/* Define if we have the perf JIT-support library */ -#cmakedefine01 LLVM_USE_PERF - -/* Major version of the LLVM API */ -#define LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} - -/* Minor version of the LLVM API */ -#define LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} - -/* Patch version of the LLVM API */ -#define LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} - -/* LLVM version string */ -#define LLVM_VERSION_STRING "${PACKAGE_VERSION}" - -/* Whether LLVM records statistics for use with GetStatistics(), - * PrintStatistics() or PrintStatisticsJSON() - */ -#cmakedefine01 LLVM_FORCE_ENABLE_STATS - -#endif diff --git a/stdlib/include/llvm/Support/Compiler.h b/stdlib/include/llvm/Support/Compiler.h index 79af6f5d3c686..c6b8c8f4f6605 100644 --- a/stdlib/include/llvm/Support/Compiler.h +++ b/stdlib/include/llvm/Support/Compiler.h @@ -15,8 +15,6 @@ #ifndef LLVM_SUPPORT_COMPILER_H #define LLVM_SUPPORT_COMPILER_H -#include "llvm/Config/llvm-config.h" - #ifdef __cplusplus #include #endif diff --git a/stdlib/public/LLVMSupport/CMakeLists.txt b/stdlib/public/LLVMSupport/CMakeLists.txt index 1e688137c17d3..0df322e5172b1 100644 --- a/stdlib/public/LLVMSupport/CMakeLists.txt +++ b/stdlib/public/LLVMSupport/CMakeLists.txt @@ -1,23 +1,3 @@ - -set(LLVM_DEFAULT_TARGET_TRIPLE) -set(LLVM_ENABLE_DUMP) -set(LLVM_ENABLE_THREADS YES) -set(LLVM_FORCE_ENABLE_STATS NO) -set(LLVM_HAS_ATOMICS YES) -set(LLVM_HOST_TRIPLE) -set(LLVM_NATIVE_ARCH) -if(SWIFT_PRIMARY_VARIANT_SDK STREQUAL Windows) - set(LLVM_ON_UNIX NO) -else() - set(LLVM_ON_UNIX YES) -endif() -set(LLVM_USE_INTEL_JITEVENTS NO) -set(LLVM_USE_OPROFILE NO) -set(LLVM_USE_PERF NO) - -configure_file(${PROJECT_SOURCE_DIR}/include/llvm/Config/llvm-config.h.cmake - ${CMAKE_CURRENT_BINARY_DIR}/llvm/Config/llvm-config.h) - add_swift_target_library(swiftLLVMSupport OBJECT_LIBRARY ErrorHandling.cpp Hashing.cpp diff --git a/stdlib/public/LLVMSupport/ErrorHandling.cpp b/stdlib/public/LLVMSupport/ErrorHandling.cpp index ad8e8ae5b73ff..f40c614d46a6f 100644 --- a/stdlib/public/LLVMSupport/ErrorHandling.cpp +++ b/stdlib/public/LLVMSupport/ErrorHandling.cpp @@ -21,22 +21,50 @@ # include #else # include +# include #endif +#include + +#if defined(__APPLE__) +#include +#elif defined(__ANDROID__) +#include +#endif + +namespace { +void error(const char *fmt, ...) { + char buffer[1024]; + va_list argp; + + va_start(argp, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, argp); + va_end(argp); + +#if defined(__APPLE__) + asl_log(nullptr, nullptr, ASL_LEVEL_ERR, "%s", buffer); +#elif defined(__ANDROID__) + __android_log_printf(ANDROID_LOG_FATAL, "SwiftRuntime", "%s", buffer); +#elif defined(_WIN32) +#define STDERR_FILENO 2 + _write(STDERR_FILENO, buffer, strlen(buffer)); +#else + write(STDERR_FILENO, buffer, strlen(buffer)); +#endif +} +} + using namespace llvm; void __swift::__runtime::llvm::report_fatal_error(const char *Reason, bool GenCrashDiag) { - report_fatal_error(std::string(Reason), GenCrashDiag); + error("LLVM ERROR: %s\n", Reason); + abort(); } void __swift::__runtime::llvm::report_fatal_error(const std::string &Reason, bool GenCrashDiag) { - // Blast the result out to stderr. We don't try hard to make sure this - // succeeds (e.g. handling EINTR) and we can't use errs() here because - // raw ostreams can call report_fatal_error. - fprintf(stderr, "LLVM ERROR: %s\n", Reason.c_str()); - abort(); + report_fatal_error(Reason.c_str(), GenCrashDiag); } void __swift::__runtime::llvm::report_fatal_error(StringRef Reason, @@ -48,7 +76,7 @@ void __swift::__runtime::llvm::report_bad_alloc_error(const char *Reason, bool GenCrashDiag) { // Don't call the normal error handler. It may allocate memory. Directly write // an OOM to stderr and abort. - fprintf(stderr, "LLVM ERROR: out of memory\n"); + error("LLVM ERROR: out of memory\n"); abort(); } @@ -58,11 +86,11 @@ void __swift::__runtime::llvm::llvm_unreachable_internal( // llvm_unreachable is intended to be used to indicate "impossible" // situations, and not legitimate runtime errors. if (msg) - fprintf(stderr, "%s\n", msg); - fprintf(stderr, "UNREACHABLE executed"); + error("%s\n", msg); + error("UNREACHABLE executed"); if (file) - fprintf(stderr, " at %s:%u", file, line); - fprintf(stderr, "!\n"); + error(" at %s:%u", file, line); + error("!\n"); abort(); #ifdef LLVM_BUILTIN_UNREACHABLE // Windows systems and possibly others don't declare abort() to be noreturn, diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt index 3f9c7362c5803..add40e7fc4567 100644 --- a/stdlib/public/core/CMakeLists.txt +++ b/stdlib/public/core/CMakeLists.txt @@ -107,6 +107,7 @@ set(SWIFTLIB_ESSENTIAL Pointer.swift Policy.swift PrefixWhile.swift + Prespecialize.swift Print.swift PtrAuth.swift Random.swift diff --git a/stdlib/public/core/GroupInfo.json b/stdlib/public/core/GroupInfo.json index 1b9a209004e67..64e403948a1ef 100644 --- a/stdlib/public/core/GroupInfo.json +++ b/stdlib/public/core/GroupInfo.json @@ -209,6 +209,7 @@ "OptionSet.swift", "OutputStream.swift", "Policy.swift", + "Prespecialize.swift", "Print.swift", "REPL.swift", "Random.swift", diff --git a/stdlib/public/core/Prespecialize.swift b/stdlib/public/core/Prespecialize.swift new file mode 100644 index 0000000000000..1f3dff447070d --- /dev/null +++ b/stdlib/public/core/Prespecialize.swift @@ -0,0 +1,96 @@ +@inline(never) +private func consume(_ t: T) { + withExtendedLifetime(t) { t in } +} +@usableFromInline +internal func _prespecialize() { + consume(Array<()>.self) + consume(Array<(Optional, Any)>.self) + consume(Array.self) + consume(Array.self) + consume(Array>.self) + consume(Array>.self) + consume(Array.self) + consume(Array.self) + consume(Array>.self) + consume(Array>.self) + consume(ClosedRange.self) + consume(ContiguousArray<(AnyHashable, Any)>.self) + consume(ContiguousArray<(Optional, Any)>.self) + consume(ContiguousArray.self) + consume(ContiguousArray.self) + consume(ContiguousArray>.self) + consume(ContiguousArray.self) + consume(ContiguousArray.self) + consume(Dictionary.Index.self) + consume(Dictionary.Iterator.self) + consume(Dictionary.self) + consume(Dictionary.Iterator.self) + consume(Dictionary.self) + consume(Dictionary.Iterator.self) + consume(Dictionary.self) + consume(Dictionary.self) + consume(Dictionary.Iterator.self) + consume(Dictionary.self) + consume(Dictionary.self) + consume(Dictionary>.self) + consume(Dictionary>.self) + consume(Dictionary.self) + consume(Dictionary.self) + consume(IndexingIterator>>.self) + consume(IndexingIterator>.self) + consume(IndexingIterator>.self) + consume(IndexingIterator>.self) + consume(IndexingIterator>.self) + consume(IndexingIterator.self) + consume(Optional<()>.self) + consume(Optional<(Any, Any)>.self) + consume(Optional<(AnyHashable, Any)>.self) + consume(Optional<(AnyHashable, AnyHashable)>.self) + consume(Optional<(CodingUserInfoKey, Any)>.self) + consume(Optional<(Int64, Bool)>.self) + consume(Optional<(Optional, Any)>.self) + consume(Optional<(String, Any)>.self) + consume(Optional<(String, AnyObject)>.self) + consume(Optional<(String, Array)>.self) + consume(Optional<(String, Int64)>.self) + consume(Optional<(String, String)>.self) + consume(Optional<(String, UInt8)>.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional>.self) + consume(Optional>.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional>.self) + consume(Optional>.self) + consume(Optional>.self) + consume(Optional>>.self) + consume(Optional>.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional>.self) + consume(Optional>.self) + consume(Optional>.self) + consume(Optional.self) + consume(Optional.self) + consume(Optional>.self) + consume(PartialRangeFrom.self) + consume(Range.self) + consume(ReversedCollection>.self) + consume(ReversedCollection>.Iterator.self) + consume(Set.self) + consume(Set.self) + consume(Set.Iterator.self) + consume(Set.self) + consume(Unmanaged.self) + consume(UnsafeBufferPointer.self) + consume(UnsafeBufferPointer.self) + consume(UnsafePointer.self) +} diff --git a/stdlib/public/core/Range.swift b/stdlib/public/core/Range.swift index 71357d1476dce..85e7db7b7c9c2 100644 --- a/stdlib/public/core/Range.swift +++ b/stdlib/public/core/Range.swift @@ -74,6 +74,25 @@ public protocol RangeExpression { } extension RangeExpression { + + /// Returns a Boolean value indicating whether a value is included in a + /// range. + /// + /// You can use the pattern-matching operator (`~=`) to test whether a value + /// is included in a range. The pattern-matching operator is used + /// internally in `case` statements for pattern matching. The following + /// example uses the `~=` operator to test whether an integer is included in + /// a range of single-digit numbers: + /// + /// let chosenNumber = 3 + /// if 0..<10 ~= chosenNumber { + /// print("\(chosenNumber) is a single digit.") + /// } + /// // Prints "3 is a single digit." + /// + /// - Parameters: + /// - pattern: A range. + /// - bound: A value to match against `pattern`. @inlinable public static func ~= (pattern: Self, value: Bound) -> Bool { return pattern.contains(value) diff --git a/test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift b/test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift deleted file mode 100644 index 2d3083da33ab6..0000000000000 --- a/test/AutoDiff/compiler_crashers_fixed/sr12650-noderivative-parameter-type-mangling.swift +++ /dev/null @@ -1,37 +0,0 @@ -// RUN: %target-build-swift -g %s - -// SR-12650: IRGenDebugInfo type reconstruction crash because `@noDerivative` -// parameters are not mangled. - -import _Differentiation -func id(_ x: Float, _ y: Float) -> Float { x } -let transformed: @differentiable (Float, @noDerivative Float) -> Float = id - -// Incorrect reconstructed type for $sS3fIedgyyd_D -// Original type: -// (sil_function_type type=@differentiable @callee_guaranteed (Float, @noDerivative Float) -> Float -// (input=struct_type decl=Swift.(file).Float) -// (input=struct_type decl=Swift.(file).Float) -// (result=struct_type decl=Swift.(file).Float) -// (substitution_map generic_signature=) -// (substitution_map generic_signature=)) -// Reconstructed type: -// (sil_function_type type=@differentiable @callee_guaranteed (Float, Float) -> Float -// (input=struct_type decl=Swift.(file).Float) -// (input=struct_type decl=Swift.(file).Float) -// (result=struct_type decl=Swift.(file).Float) -// (substitution_map generic_signature=) -// (substitution_map generic_signature=)) -// Stack dump: -// ... -// 1. Swift version 5.3-dev (LLVM 803d1b184d, Swift 477af9f90d) -// 2. While evaluating request IRGenSourceFileRequest(IR Generation for file "noderiv.swift") -// 0 swift 0x00000001104c7ae8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 -// 1 swift 0x00000001104c6a68 llvm::sys::RunSignalHandlers() + 248 -// 2 swift 0x00000001104c80dd SignalHandler(int) + 285 -// 3 libsystem_platform.dylib 0x00007fff718335fd _sigtramp + 29 -// 4 libsystem_platform.dylib 000000000000000000 _sigtramp + 18446603338611739168 -// 5 libsystem_c.dylib 0x00007fff71709808 abort + 120 -// 6 swift 0x0000000110604152 (anonymous namespace)::IRGenDebugInfoImpl::getOrCreateType(swift::irgen::DebugTypeInfo) (.cold.20) + 146 -// 7 swift 0x000000010c24ab1e (anonymous namespace)::IRGenDebugInfoImpl::getOrCreateType(swift::irgen::DebugTypeInfo) + 3614 -// 8 swift 0x000000010c245437 swift::irgen::IRGenDebugInfo::emitGlobalVariableDeclaration(llvm::GlobalVariable*, llvm::StringRef, llvm::StringRef, swift::irgen::DebugTypeInfo, bool, bool, llvm::Optional) + 167 diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h new file mode 100644 index 0000000000000..b91209ef648da --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/OverlayTest.h @@ -0,0 +1,2 @@ +#include + diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h new file mode 100644 index 0000000000000..48336b32085b6 --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Headers/Overlayed.h @@ -0,0 +1,13 @@ + +#ifndef OVERLAYED_H +#define OVERLAYED_H + +struct __attribute__((swift_name("Overlayed"))) OVOverlayed { + double x, y, z; +}; + +double OVOverlayedInOriginalFunc(struct OVOverlayed s) __attribute__((swift_name("Overlayed.inOriginalFunc(self:)"))); + +struct OVOverlayed createOverlayed(); + +#endif diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap new file mode 100644 index 0000000000000..52db6e58085c2 --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.framework/Modules/module.modulemap @@ -0,0 +1,7 @@ +framework module OverlayTest { + umbrella header "OverlayTest.h" + + export * + module * { export * } +} + diff --git a/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface b/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface new file mode 100644 index 0000000000000..ad75d7f67b6ea --- /dev/null +++ b/test/IDE/Inputs/mock-sdk/OverlayTest.swiftinterface @@ -0,0 +1,10 @@ +// swift-interface-format-version: 1.0 +// swift-module-flags: -module-name OverlayTest + +@_exported import OverlayTest + +public extension Overlayed { + public func inOverlayFunc() {} +} + +public func createOverlayedInOverlay() -> Overlayed diff --git a/test/IDE/complete_overlaymodule.swift b/test/IDE/complete_overlaymodule.swift new file mode 100644 index 0000000000000..b4cd14d62c226 --- /dev/null +++ b/test/IDE/complete_overlaymodule.swift @@ -0,0 +1,37 @@ +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=TYPE_GLOBAL | %FileCheck %s --check-prefix=TYPE_GLOBAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=EXPR_GLOBAL | %FileCheck %s --check-prefix=EXPR_GLOBAL +// RUN: %target-swift-ide-test -code-completion -source-filename %s -I %S/Inputs/mock-sdk -F %S/Inputs/mock-sdk -code-completion-token=EXPR_MEMBER | %FileCheck %s --check-prefix=EXPR_MEMBER + +import OverlayTest + +func testGlobalType() { + let _: #^TYPE_GLOBAL^# +// TYPE_GLOBAL: Begin completions +// TYPE_GLOBAL-NOT: OverlayTest[#Module#] +// TYPE_GLOBAL-DAG: Decl[Module]/None: OverlayTest[#Module#]; +// TYPE_GLOBAL-NOT: OverlayTest[#Module#] +// TYPE_GLOBAL-DAG: Decl[Struct]/OtherModule[OverlayTest.Overlayed]: Overlayed[#Overlayed#]; +// TYPE_GLOBAL: End completions +} +func testGlobalExpr() { + let _ = #^EXPR_GLOBAL^# +// EPXR_GLOBAL: Begin completions +// EXPR_GLOBAL-NOT: OverlayTest[#Module#] +// EXPR_GLOBAL-DAG: Decl[Module]/None: OverlayTest[#Module#]; +// EXPR_GLOBAL-NOT: OverlayTest[#Module#] +// EXPR_GLOBAL-DAG: Decl[Struct]/OtherModule[OverlayTest.Overlayed]: Overlayed[#Overlayed#]; +// EXPR_GLOBAL-DAG: Decl[FreeFunction]/OtherModule[OverlayTest]: createOverlayedInOverlay()[#Overlayed#]; +// EXPR_GLOBAL-DAG: Decl[FreeFunction]/OtherModule[OverlayTest.Overlayed]: createOverlayed()[#Overlayed#]; +// EPXR_GLOBAL: End completions +} +func testGlobalExpr(value: Overlayed) { + value.#^EXPR_MEMBER^# +// EXPR_MEMBER: Begin completions, 6 items +// EXPR_MEMBER-DAG: Keyword[self]/CurrNominal: self[#Overlayed#]; name=self +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: x[#Double#]; name=x +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: y[#Double#]; name=y +// EXPR_MEMBER-DAG: Decl[InstanceVar]/CurrNominal: z[#Double#]; name=z +// EXPR_MEMBER-DAG: Decl[InstanceMethod]/CurrNominal: inOverlayFunc()[#Void#]; name=inOverlayFunc() +// EXPR_MEMBER-DAG: Decl[InstanceMethod]/CurrNominal: inOriginalFunc()[#Double#]; name=inOriginalFunc() +// EXPR_MEMBER: End completions +} diff --git a/test/IRGen/partial_apply.sil b/test/IRGen/partial_apply.sil index 14da9028dfb95..b7607cb996163 100644 --- a/test/IRGen/partial_apply.sil +++ b/test/IRGen/partial_apply.sil @@ -767,3 +767,82 @@ bb0(%x : $*ResilientInt, %y : $SwiftClass): %t = tuple() return %t : $() } + +protocol Proto1 {} +protocol Proto2 {} +struct EmptyType : Proto1 { } + +struct SomeType : Proto2 { + var d : ResilientInt // some resilient type + var x : Int +} + +sil @foo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () + +// CHECK-64-LABEL: define{{.*}} swiftcc void @empty_followed_by_non_fixed(%T13partial_apply8SomeTypeV* noalias nocapture %0) +// CHECK-64: [[FLAGS:%.*]] = load i32, i32* +// CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 +// CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 +// CHECK-64: [[NOTALIGNMASK:%.*]] = xor i64 [[ALIGNMASK]], -1 +// Make sure we take the header offset (16) into account. +// CHECK-64: [[TMP:%.*]] = add i64 16, [[ALIGNMASK]] +// CHECK-64: [[OFFSET:%.*]] = and i64 [[TMP]], [[NOTALIGNMASK]] +// CHECK-64: [[CONTEXT:%.*]] = call noalias %swift.refcounted* @swift_allocObject +// CHECK-64: [[CAST:%.*]] = bitcast %swift.refcounted* [[CONTEXT]] to <{ %swift.refcounted }>* +// CHECK-64: [[CAST2:%.*]] = bitcast <{ %swift.refcounted }>* [[CAST]] to i8* +// CHECK-64: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[CAST2]], i64 [[OFFSET]] +// CHECK-64: [[CAST3:%.*]] = bitcast i8* [[GEP]] to %T13partial_apply8SomeTypeV* +// CHECK-64: call %T13partial_apply8SomeTypeV* @"$s13partial_apply8SomeTypeVWOb"(%T13partial_apply8SomeTypeV* {{.*}}, %T13partial_apply8SomeTypeV* [[CAST3]]) + +sil @empty_followed_by_non_fixed : $@convention(thin) (EmptyType, @in_guaranteed SomeType) -> () { +entry(%0 : $EmptyType, %1: $*SomeType): + %5 = alloc_stack $EmptyType + store %0 to %5 : $*EmptyType + %31 = function_ref @foo : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () + %32 = alloc_stack $EmptyType + copy_addr %5 to [initialization] %32 : $*EmptyType + %34 = alloc_stack $SomeType + copy_addr %1 to [initialization] %34 : $*SomeType // id: %35 + %36 = partial_apply [callee_guaranteed] %31(%32, %34) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Proto1, τ_0_1 : Proto2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> () + release_value %36: $@callee_guaranteed () ->() + dealloc_stack %34 : $*SomeType + dealloc_stack %32 : $*EmptyType + dealloc_stack %5 : $*EmptyType + %40 = tuple() + return %40 : $() +} + +struct FixedType { + var f: Int32 +} +// CHECK-64-LABEL: define{{.*}} swiftcc void @fixed_followed_by_empty_followed_by_non_fixed +// CHECK-64-NOT: ret +// CHECK-64: [[FLAGS:%.*]] = load i32, i32* +// CHECK-64: [[FLAGS2:%.*]] = zext i32 [[FLAGS]] to i64 +// CHECK-64: [[ALIGNMASK:%.*]] = and i64 [[FLAGS2]], 255 +// CHECK-64: [[NOTALIGNMASK:%.*]] = xor i64 [[ALIGNMASK]], -1 +// Make sure we compute the correct offset of the non-fixed field. +// CHECK-64: [[TMP:%.*]] = add i64 20, [[ALIGNMASK]] +// CHECK-64: ret + +sil @foo2 : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1, @in_guaranteed τ_0_2) -> () +sil @fixed_followed_by_empty_followed_by_non_fixed : $@convention(thin) (EmptyType, @in_guaranteed SomeType, FixedType) -> () { +entry(%0 : $EmptyType, %1: $*SomeType, %3: $FixedType): + %5 = alloc_stack $EmptyType + store %0 to %5 : $*EmptyType + %7 = alloc_stack $FixedType + store %3 to %7 : $*FixedType + %31 = function_ref @foo2 : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1, @in_guaranteed τ_0_2) -> () + %32 = alloc_stack $EmptyType + copy_addr %5 to [initialization] %32 : $*EmptyType + %34 = alloc_stack $SomeType + copy_addr %1 to [initialization] %34 : $*SomeType // id: %35 + %36 = partial_apply [callee_guaranteed] %31(%7, %32, %34) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1, @in_guaranteed τ_0_2) -> () + release_value %36: $@callee_guaranteed () ->() + dealloc_stack %34 : $*SomeType + dealloc_stack %32 : $*EmptyType + dealloc_stack %7 : $*FixedType + dealloc_stack %5 : $*EmptyType + %40 = tuple() + return %40 : $() +} diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift b/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift index 2675887fc0dbf..4710a68489d1d 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_bridged.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift b/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift index 68965b5e9a97d..bf1e727ae15a3 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_clangmodule.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift b/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift index d9d6f90daf3d6..da85e9ce70768 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_otherfile.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift b/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift index 30cbd7b97a37f..31404c00a919c 100644 --- a/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift +++ b/test/SourceKit/CodeComplete/complete_checkdeps_swiftmodule.swift @@ -5,6 +5,7 @@ func foo() { /*HERE*/ } +// REQUIRES: rdar62923248 // REQUIRES: shell // RUN: %empty-directory(%t/Frameworks) diff --git a/test/SourceKit/CompileNotifications/arg-parsing.swift b/test/SourceKit/CompileNotifications/arg-parsing.swift index 67bfc0cd20928..7dc654d7d5ac5 100644 --- a/test/SourceKit/CompileNotifications/arg-parsing.swift +++ b/test/SourceKit/CompileNotifications/arg-parsing.swift @@ -4,6 +4,7 @@ // ARG_PARSE_0: key.notification: source.notification.compile-will-start // ARG_PARSE_0: key.compileid: [[CID1:".*"]] // ARG_PARSE_0: key.compilerargs-string: "{{.*}}.swift -no-such-arg" +// ARG_PARSE_0: key.compile_operation: source.compile.operation.code-completion // ARG_PARSE_0: } // ARG_PARSE_0: { // ARG_PARSE_0: key.notification: source.notification.compile-did-finish @@ -15,6 +16,7 @@ // ARG_PARSE_0: } // ARG_PARSE_0: ] // ARG_PARSE_0: key.compileid: [[CID1]] +// ARG_PARSE_0: key.compile_operation: source.compile.operation.code-completion // ARG_PARSE_0: } // ARG_PARSE_0-NOT: compile-will-start // ARG_PARSE_0-NOT: compile-did-finish diff --git a/test/SourceKit/CompileNotifications/code-completion.swift b/test/SourceKit/CompileNotifications/code-completion.swift index 53dbb2084d6b9..8ec32210e6e0e 100644 --- a/test/SourceKit/CompileNotifications/code-completion.swift +++ b/test/SourceKit/CompileNotifications/code-completion.swift @@ -3,10 +3,12 @@ // COMPILE_1: key.notification: source.notification.compile-will-start, // COMPILE_1: key.filepath: "{{.*}}SOURCE_DIR{{.*}}code-completion.swift", // COMPILE_1: key.compileid: [[CID1:".*"]] +// COMPILE_1: key.compile_operation: source.compile.operation.code-completion // COMPILE_1: } // COMPILE_1: { // COMPILE_1: key.notification: source.notification.compile-did-finish, // COMPILE_1: key.compileid: [[CID1]] +// COMPILE_1: key.compile_operation: source.compile.operation.code-completion // COMPILE_1: } // COMPILE_1-NOT: compile-will-start // COMPILE_1-NOT: compile-did-finish \ No newline at end of file diff --git a/test/diagnostics/Inputs/RenamedObjc.h b/test/diagnostics/Inputs/RenamedObjc.h new file mode 100644 index 0000000000000..a4ed605ce18e4 --- /dev/null +++ b/test/diagnostics/Inputs/RenamedObjc.h @@ -0,0 +1,9 @@ +@import Foundation; + +#define SWIFT_NAME(X) __attribute__((swift_name(#X))) + +#pragma clang assume_nonnull begin +@interface SwiftNameTest : NSObject ++ (instancetype)g:(id)x outParam:(int *)foo SWIFT_NAME(init(g:)); +@end +#pragma clang assume_nonnull end diff --git a/test/diagnostics/Inputs/module.map b/test/diagnostics/Inputs/module.map new file mode 100644 index 0000000000000..02eaefab7c2e1 --- /dev/null +++ b/test/diagnostics/Inputs/module.map @@ -0,0 +1,4 @@ +module RenamedObjc { + header "RenamedObjc.h" + export * +} diff --git a/test/diagnostics/pretty-printed-diags-in-clang-buffer.swift b/test/diagnostics/pretty-printed-diags-in-clang-buffer.swift new file mode 100644 index 0000000000000..049ca95278278 --- /dev/null +++ b/test/diagnostics/pretty-printed-diags-in-clang-buffer.swift @@ -0,0 +1,20 @@ +// RUN: %empty-directory(%t.mcp) +// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -enable-experimental-diagnostic-formatting -I %S/Inputs/ -typecheck %s -module-cache-path %t.mcp 2>&1 | %FileCheck %s + +// REQUIRES: objc_interop + +import RenamedObjc + +let foo = SwiftNameTest(g: "") + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}Inputs{{[/\]+}}RenamedObjc.h:7:1 +// CHECK: 7 | + (instancetype)g:(id)x outParam:(int *)foo SWIFT_NAME(init(g:)); +// CHECK: | ^ warning: too few parameters in swift_name attribute (expected 2; got 1) +// CHECK: | ^ note: please report this issue to the owners of 'RenamedObjc' + + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diags-in-clang-buffer.swift:8:28 +// CHECK: 7 | +// CHECK: 8 | let foo = SwiftNameTest(g: "") +// CHECK: | ~~ +// CHECK: | ^ error: argument passed to call that takes no arguments diff --git a/test/diagnostics/pretty-printed-source-loc-directive-diags.swift b/test/diagnostics/pretty-printed-source-loc-directive-diags.swift new file mode 100644 index 0000000000000..cebc5a22884bb --- /dev/null +++ b/test/diagnostics/pretty-printed-source-loc-directive-diags.swift @@ -0,0 +1,77 @@ +// RUN: not %target-swift-frontend -enable-experimental-diagnostic-formatting -typecheck %s 2>&1 | %FileCheck %s + +// Error split between the real file and a virtual one. +#sourceLocation(file: "abc.swift", line: 9) +let x = 1 +#sourceLocation() +let x = 2 + +// Error split between two virtual files. +#sourceLocation(file: "abc.swift", line: 4) +let y = 1 +#sourceLocation(file: "xyz.swift", line: 18) +let y = 2 +#sourceLocation() + +// Error within a virtual file on non-consecutive lines. +#sourceLocation(file: "abc.swift", line: 1) +let z = 1 +// space +let z = 2 +#sourceLocation() + +// Error with note location placed in the same virtual file via a separate #sourceLocation block. +#sourceLocation(file: "abc.swift", line: 1) +let a = 1 +#sourceLocation() + + +#sourceLocation(file: "abc.swift", line: 10) +let a = 2 +#sourceLocation() + +// Error at the beginning of a virtual file. +#sourceLocation(file: "abc.swift", line: 1) +let any: Any = "" +let zz: Int = any +#sourceLocation() + +// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-source-loc-directive-diags.swift:[[#LINE:]]:5 +// CHECK: [[#LINE-1]] | #sourceLocation() +// CHECK: [[#LINE]] | let x = 2 +// CHECK: | ^ error: invalid redeclaration of 'x' +// CHECK: [[#LINE+1]] | +// CHECK: abc.swift:9:5 +// CHECK: 9 | let x = 1 +// CHECK: | ^ note: 'x' previously declared here + + +// CHECK: abc.swift:4:5 +// CHECK: 4 | let y = 1 +// CHECK: | ^ note: 'y' previously declared here +// CHECK: xyz.swift:18:5 +// CHECK: 18 | let y = 2 +// CHECK: | ^ error: invalid redeclaration of 'y' + + +// CHECK: abc.swift:3:5 +// CHECK: 1 | let z = 1 +// CHECK: | ^ note: 'z' previously declared here +// CHECK: ... +// CHECK: 3 | let z = 2 +// CHECK: | ^ error: invalid redeclaration of 'z' + + +// CHECK: abc.swift:10:5 +// CHECK: 1 | let a = 1 +// CHECK: | ^ note: 'a' previously declared here +// CHECK: ... +// CHECK: 10 | let a = 2 +// CHECK: | ^ error: invalid redeclaration of 'a' + + +// CHECK: abc.swift:2:15 +// CHECK: 2 | let zz: Int = any as! Int +// CHECK: | ~~~++++++++ +// CHECK: | ^ error: cannot convert value of type 'Any' to specified type 'Int' [insert ' as! Int'] + diff --git a/test/lit.cfg b/test/lit.cfg index 7bd3a75e9fb70..1ec595ca6ad04 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -60,24 +60,6 @@ def darwin_get_sdk_version(sdk_path): "ProductBuildVersion"]).rstrip() return (name, vers, build) - -def darwin_sdk_build_version_split(version): - m = re.search("([0-9]+)([A-Z])([0-9]+)", version) - return (int(m.group(1)), m.group(2), int(m.group(3))) - - -def darwin_sdk_build_version_cmp(lhs, rhs): - # The `_cmp` function is provided to port the Python 2 global `cmp` - # function forward to Python 3. The function implementation is taken - # directly from the recommendation that announced its removal. - # See: https://docs.python.org/3.0/whatsnew/3.0.html#ordering-comparisons - def _cmp(a, b): - return (a > b) - (a < b) - return _cmp( - darwin_sdk_build_version_split(lhs), - darwin_sdk_build_version_split(rhs)) - - # Run sw_vers on the target to be tested and return the results. def darwin_get_sw_vers(commandPrefix=[]): name = lit.util.executeCommand( @@ -98,22 +80,12 @@ def darwin_get_ios_sim_vers(): def get_simulator_command(run_os, run_cpu, sdk_path): (name, vers, build) = darwin_get_sdk_version(sdk_path) if run_os == 'ios': - # There are two binaries for the iOS simulator: 'sim' and 'simctl'. - # 'sim' is only supported for iOS <= 8.1 and early versions of 8.2. - # 'simctl' is supported for iOS >= 8.2. - # 'simctl' used to have a bug where it failed to propagate the exit - # code of the child process. This was fixed only in the middle of 8.2 - # development cycle. - if ((darwin_sdk_build_version_cmp(build, "12E999") <= 0) or - (darwin_sdk_build_version_cmp("12F1", build) <= 0 and - darwin_sdk_build_version_cmp(build, "12F12") <= 0) or - (darwin_sdk_build_version_cmp("12H1", build) <= 0 and - darwin_sdk_build_version_cmp(build, "12H11") <= 0)): - return "sim" - elif run_cpu == "i386": + if run_cpu == "i386": if min(darwin_get_ios_sim_vers()) > 10.3: - print("ERROR: Install iOS 10.3 or older simulator for 32bit testing") - print("INFO: Xcode -> Preferences -> Components -> Simulators") + print("ERROR: Your system does not have a 32-bit iOS simulator installed.") + print("INFO: 1. Install iOS 10.3 or older simulator (Xcode -> Preferences -> Components -> Simulators).") + print("INFO: 2. Create a 32-bit iPhone 5 device. Run:") + print("INFO: $ xcrun simctl create 'iPhone 5' com.apple.CoreSimulator.SimDeviceType.iPhone-5 com.apple.CoreSimulator.SimRuntime.iOS-10-3") sys.exit(1) else: return "simctl spawn --standalone 'iPhone 5'" @@ -130,15 +102,6 @@ def get_lldb_python_path(lldb_build_root): lldb_path = os.path.join(lldb_build_root, 'bin', 'lldb') return subprocess.check_output([lldb_path, "-P"]).rstrip() -assert darwin_sdk_build_version_cmp("11A1", "12A1") < 0 -assert darwin_sdk_build_version_cmp("12A1", "11A1") > 0 - -assert darwin_sdk_build_version_cmp("11A1", "11B1") < 0 -assert darwin_sdk_build_version_cmp("11B1", "11A1") > 0 - -assert darwin_sdk_build_version_cmp("11A22", "11A100") < 0 -assert darwin_sdk_build_version_cmp("11A100", "11A22") > 0 - ### # Check that the object root is known. diff --git a/test/stdlib/llvm-support-odr-violation.test-sh b/test/stdlib/llvm-support-odr-violation.test-sh index 09b6aea648656..3621136b105d4 100644 --- a/test/stdlib/llvm-support-odr-violation.test-sh +++ b/test/stdlib/llvm-support-odr-violation.test-sh @@ -1,2 +1,2 @@ -// RUN: %llvm-nm --defined-only -C %platform-module-dir/%target-library-name(swiftCore) | %FileCheck --allow-empty %s +// RUN: %llvm-nm --defined-only -C %platform-dylib-dir/%target-library-name(swiftCore) | %FileCheck --allow-empty %s // CHECK-NOT: [^:]llvm:: diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp index cdc17f6009e97..46e4ab3d83012 100644 --- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp +++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp @@ -3181,6 +3181,21 @@ class CompileTrackingConsumer final : public trace::TraceConsumer { }; } // end anonymous namespace +static Optional getUIDForOperationKind(trace::OperationKind OpKind) { + static UIdent CompileOperationIndexSource("source.compile.operation.index-source"); + static UIdent CompileOperationCodeCompletion("source.compile.operation.code-completion"); + switch (OpKind) { + case trace::OperationKind::PerformSema: + return None; + case trace::OperationKind::IndexSource: + return CompileOperationIndexSource; + case trace::OperationKind::CodeCompletion: + return CompileOperationCodeCompletion; + default: + llvm_unreachable("Unknown operation kind"); + } +} + void CompileTrackingConsumer::operationStarted( uint64_t OpId, trace::OperationKind OpKind, const trace::SwiftInvocation &Inv, const trace::StringPairs &OpArgs) { @@ -3193,7 +3208,9 @@ void CompileTrackingConsumer::operationStarted( Dict.set(KeyNotification, CompileWillStartUID); Dict.set(KeyCompileID, std::to_string(OpId)); Dict.set(KeyFilePath, Inv.Args.PrimaryFile); - // FIXME: OperationKind + if (auto OperationUID = getUIDForOperationKind(OpKind)) { + Dict.set(KeyCompileOperation, OperationUID.getValue()); + } Dict.set(KeyCompilerArgsString, Inv.Args.Arguments); sourcekitd::postNotification(RespBuilder.createResponse()); } @@ -3209,6 +3226,9 @@ void CompileTrackingConsumer::operationFinished( auto Dict = RespBuilder.getDictionary(); Dict.set(KeyNotification, CompileDidFinishUID); Dict.set(KeyCompileID, std::to_string(OpId)); + if (auto OperationUID = getUIDForOperationKind(OpKind)) { + Dict.set(KeyCompileOperation, OperationUID.getValue()); + } auto DiagArray = Dict.setArray(KeyDiagnostics); for (const auto &DiagInfo : Diagnostics) { fillDictionaryForDiagnosticInfo(DiagArray.appendDictionary(), DiagInfo); diff --git a/utils/gyb_sourcekit_support/UIDs.py b/utils/gyb_sourcekit_support/UIDs.py index 33b80673032c5..974544dbbb111 100644 --- a/utils/gyb_sourcekit_support/UIDs.py +++ b/utils/gyb_sourcekit_support/UIDs.py @@ -182,6 +182,7 @@ def __init__(self, internal_name, external_name): KEY('CompletionCheckDependencyInterval', 'key.completion_check_dependency_interval'), KEY('AnnotatedTypename', 'key.annotated.typename'), + KEY('CompileOperation', 'key.compile_operation'), ]