Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f00953c
[Diags-Experimental-Formatting] Fixes for printing diagnostics when #…
owenv Apr 18, 2020
96696c8
[Diag-Experimental-Formatting] Add a formatting test for Swift diags …
owenv Apr 20, 2020
40759df
[SourceKit] Include operation kind in compile notifications
DavidGoldman May 15, 2020
67a2fe4
Fix up compile operation kind
DavidGoldman May 18, 2020
d3c685d
IRGen: Correctly compute the offset for a non-fixed field after an em…
aschwaighofer May 18, 2020
b01889c
Acutally use the variable I introduced
aschwaighofer May 19, 2020
081fb11
Fix test on linux
aschwaighofer May 19, 2020
af27e8f
[CodeCompletion] Avoid suggesting duplicated module names
rintaro May 19, 2020
5cbf3f3
stdlib: remove `llvm-config.h` from swiftLLVMSupport
compnerd May 19, 2020
3ae3a7b
Restore documentation for the pattern-matching operator as applied to…
gwynne May 20, 2020
131e1d3
Removed support for iOS 8.2 and earlier from lit.cfg
gribozavr May 20, 2020
b6a79b5
[SourceKit] Don't handle OperationKind::all
DavidGoldman May 20, 2020
28a61ea
[Test] Have llvm-support-odr-violation.sh use platform-dylib-dir.
mikeash May 20, 2020
5b10c5f
Merge pull request #31900 from compnerd/config
compnerd May 20, 2020
0637e17
runtime: improve error handling path for the runtime
compnerd May 19, 2020
6116f7d
[CodeCompletion] Disable fast-completion dependecy checking test cases
rintaro May 6, 2020
522a9fe
Merge pull request #31892 from rintaro/ide-completion-duplicatedmodul…
rintaro May 20, 2020
6d3a3db
Merge pull request #31830 from DavidGoldman/compileopkind
benlangmuir May 20, 2020
961764a
Merge pull request #31909 from gribozavr/simplify-lit-cfg
gribozavr May 20, 2020
9ee5911
Merge pull request #31907 from gwynne/sr-12842-range-pattern-match-op…
CodaFi May 20, 2020
115bd28
Naive Dependency Replay
CodaFi May 16, 2020
c5280c8
Merge pull request #31916 from rintaro/sourcekit-disabletest-rdar6292…
rintaro May 20, 2020
5f0f163
Merge pull request #31914 from mikeash/odr-violation-test-dylib-dir
mikeash May 20, 2020
1553c6d
Merge pull request #31863 from aschwaighofer/irgen_fix_heaplayout_emp…
aschwaighofer May 20, 2020
0ab9fd7
Merge pull request #31124 from owenv/pretty-printed-diags-source-loca…
swift-ci May 20, 2020
ffca352
[AutoDiff] Remove flaky SR-12650 negative test. (#31919)
dan-zheng May 20, 2020
49d76c3
Merge pull request #31902 from compnerd/error-recording
compnerd May 20, 2020
0a7929e
Refine Naive Dependency Collection Algorithm
CodaFi May 18, 2020
d93f44a
Merge pull request #31837 from CodaFi/record-scratch
CodaFi May 21, 2020
870ca6d
Add instructions on how to create a 32-bit iOS simulator device
gribozavr May 20, 2020
446dc9f
Merge pull request #31928 from gribozavr/iphonesimulator-i386-instruc…
gribozavr May 21, 2020
e67e8ab
Prespecialize common metadata (#31925)
airspeedswift May 21, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
31 changes: 30 additions & 1 deletion include/swift/AST/AnyRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ struct AnyRequestVTable {
static SourceLoc getNearestLoc(const void *ptr) {
return static_cast<const Request *>(ptr)->getNearestLoc();
}
static bool isCached(const void *ptr) {
return static_cast<const Request *>(ptr)->isCached();
}
};

const uint64_t typeID;
Expand All @@ -78,8 +81,29 @@ struct AnyRequestVTable {
const std::function<void(const void *, DiagnosticEngine &)> diagnoseCycle;
const std::function<void(const void *, DiagnosticEngine &)> noteCycleStep;
const std::function<SourceLoc(const void *)> getNearestLoc;
const std::function<bool(const void *)> isCached;

template <typename Request>
template <typename Request,
typename std::enable_if<Request::isEverCached>::type * = nullptr>
static const AnyRequestVTable *get() {
static const AnyRequestVTable vtable = {
TypeID<Request>::value,
sizeof(Request),
&Impl<Request>::copy,
&Impl<Request>::getHash,
&Impl<Request>::deleter,
&Impl<Request>::isEqual,
&Impl<Request>::simpleDisplay,
&Impl<Request>::diagnoseCycle,
&Impl<Request>::noteCycleStep,
&Impl<Request>::getNearestLoc,
&Impl<Request>::isCached,
};
return &vtable;
}

template <typename Request,
typename std::enable_if<!Request::isEverCached>::type * = nullptr>
static const AnyRequestVTable *get() {
static const AnyRequestVTable vtable = {
TypeID<Request>::value,
Expand All @@ -92,6 +116,7 @@ struct AnyRequestVTable {
&Impl<Request>::diagnoseCycle,
&Impl<Request>::noteCycleStep,
&Impl<Request>::getNearestLoc,
[](auto){ return false; },
};
return &vtable;
}
Expand Down Expand Up @@ -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<Derived> &lhs,
const AnyRequestBase<Derived> &rhs) {
Expand Down
25 changes: 14 additions & 11 deletions include/swift/AST/Evaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class Evaluator {
/// so all clients must cope with cycles.
llvm::DenseMap<AnyRequest, std::vector<AnyRequest>> dependencies;

evaluator::DependencyCollector collector;
evaluator::DependencyRecorder recorder;

/// Retrieve the request function for the given zone and request IDs.
AbstractRequestFunction *getAbstractRequestFunction(uint8_t zoneID,
Expand Down Expand Up @@ -268,8 +268,8 @@ class Evaluator {
typename std::enable_if<Request::isEverCached>::type * = nullptr>
llvm::Expected<typename Request::OutputType>
operator()(const Request &request) {
evaluator::DependencyCollector::StackRAII<Request> incDeps{collector,
request};
evaluator::DependencyRecorder::StackRAII<Request> 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.
Expand All @@ -285,8 +285,8 @@ class Evaluator {
typename std::enable_if<!Request::isEverCached>::type * = nullptr>
llvm::Expected<typename Request::OutputType>
operator()(const Request &request) {
evaluator::DependencyCollector::StackRAII<Request> incDeps{collector,
request};
evaluator::DependencyRecorder::StackRAII<Request> incDeps{recorder,
request};
return getResultUncached(request);
}

Expand Down Expand Up @@ -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 <typename Request,
typename std::enable_if<!Request::isDependencySink>::type * = nullptr>
// Report the result of evaluating a request that is not a dependency sink.
template <typename Request, typename std::enable_if<
!Request::isDependencySink>::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 <typename Request,
typename std::enable_if<Request::isDependencySink>::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:
Expand Down
139 changes: 116 additions & 23 deletions include/swift/AST/EvaluatorDependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -106,30 +107,78 @@ inline DependencyScope getScopeForAccessLevel(AccessLevel l) {
// of individual contexts.
using DependencySource = llvm::PointerIntPair<SourceFile *, 1, DependencyScope>;

/// 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<evaluator::DependencySource, 8> 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<NominalTypeDecl *>::getEmptyKey(),
llvm::DenseMapInfo<DeclBaseName>::getEmptyKey()};
}

static Reference tombstone() {
return {Kind::Empty,
llvm::DenseMapInfo<NominalTypeDecl *>::getTombstoneKey(),
llvm::DenseMapInfo<DeclBaseName>::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<Reference, Reference::Info> scratch;

public:
explicit DependencyCollector(DependencyRecorder &parent) : parent(parent) {}

public:
/// Registers a named reference from the current dependency scope to a member
Expand Down Expand Up @@ -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<evaluator::DependencySource, 8> 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<AnyRequest, llvm::DenseSet<DependencyCollector::Reference,
DependencyCollector::Reference::Info>>
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<swift::ActiveRequest> &stack,
llvm::function_ref<void(DependencyCollector &)> rec);

public:
/// Returns the scope of the current active scope.
///
Expand Down Expand Up @@ -197,14 +290,14 @@ struct DependencyCollector {
/// dependency source stack. It is specialized to be zero-cost for
/// requests that are not dependency sources.
template <typename Request, typename = detail::void_t<>> struct StackRAII {
StackRAII(DependencyCollector &DC, const Request &Req) {}
StackRAII(DependencyRecorder &DR, const Request &Req) {}
};

template <typename Request>
struct StackRAII<Request,
typename std::enable_if<Request::isDependencySource>::type> {
NullablePtr<DependencyCollector> Coll;
StackRAII(DependencyCollector &coll, const Request &Req) {
NullablePtr<DependencyRecorder> 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.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/IRGenRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class IRGenSourceFileRequest
public:
// Incremental dependencies.
evaluator::DependencySource
readDependencySource(const evaluator::DependencyCollector &) const;
readDependencySource(const evaluator::DependencyRecorder &) const;
};

class IRGenWholeModuleRequest
Expand Down
10 changes: 5 additions & 5 deletions include/swift/AST/NameLookupRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<ProtocolDecl *> result) const;
};
Expand Down Expand Up @@ -330,7 +330,7 @@ class GetDestructorRequest
public:
// Incremental dependencies.
evaluator::DependencySource
readDependencySource(const evaluator::DependencyCollector &) const;
readDependencySource(const evaluator::DependencyRecorder &) const;
};

class GenericParamListRequest :
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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;
};
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/ParseRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/SILGenRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/SimpleRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ SourceLoc extractNearestSourceLoc(const std::tuple<First, Rest...> &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
Expand Down
Loading