Skip to content

Commit a61ed80

Browse files
committed
[Macros] Track macro dependency separately in module trace
Macro plugins are not normal Swift modules, track them differently. Add "swiftmacros" field to the JSON file. rdar://118013482
1 parent 728d680 commit a61ed80

14 files changed

+191
-59
lines changed

include/swift/AST/ModuleLoader.h

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,25 @@ class DependencyTracker {
106106
: path(std::move(Path)), fingerprint(std::move(FP)) {}
107107
};
108108

109-
inline static std::string getPath(const IncrementalDependency &id) {
110-
return id.path;
109+
struct MacroPluginDependency {
110+
Identifier moduleName;
111+
std::string path;
112+
113+
MacroPluginDependency(const Identifier &moduleName, const std::string &path)
114+
: moduleName(moduleName), path(path) {}
115+
};
116+
117+
template <typename Dep>
118+
inline static const std::string getPath(const Dep &dep) {
119+
return dep.path;
111120
}
112-
typedef ArrayRefView<IncrementalDependency, std::string, getPath>
113-
DependencyPathArrayRef;
121+
template <typename Dep>
122+
using PathArrayRefView = ArrayRefView<Dep, const std::string, getPath>;
114123

115124
std::shared_ptr<clang::DependencyCollector> clangCollector;
116125
SmallVector<IncrementalDependency, 8> incrementalDeps;
117126
llvm::StringSet<> incrementalDepsUniquer;
127+
llvm::SetVector<MacroPluginDependency> macroPluginDeps;
118128

119129
public:
120130
explicit DependencyTracker(
@@ -134,6 +144,12 @@ class DependencyTracker {
134144
/// \p File is performed.
135145
void addIncrementalDependency(StringRef File, Fingerprint FP);
136146

147+
/// Adds a macro plugin dependency.
148+
///
149+
/// No additional canonicalization or adulteration of the file path in
150+
/// \p File is performed.
151+
void addMacroPluginDependency(StringRef File, Identifier ModuleName);
152+
137153
/// Fetches the list of dependencies.
138154
ArrayRef<std::string> getDependencies() const;
139155

@@ -143,8 +159,19 @@ class DependencyTracker {
143159

144160
/// A view of the paths of the dependencies known to have incremental swift
145161
/// dependency information embedded inside of them.
146-
DependencyPathArrayRef getIncrementalDependencyPaths() const {
147-
return DependencyPathArrayRef(getIncrementalDependencies());
162+
PathArrayRefView<IncrementalDependency>
163+
getIncrementalDependencyPaths() const {
164+
return PathArrayRefView<IncrementalDependency>(
165+
getIncrementalDependencies());
166+
}
167+
168+
/// The list of macro plugin dependencies.
169+
ArrayRef<MacroPluginDependency> getMacroPluginDependencies() const;
170+
171+
PathArrayRefView<MacroPluginDependency>
172+
getMacroPluginDependencyPaths() const {
173+
return PathArrayRefView<MacroPluginDependency>(
174+
getMacroPluginDependencies());
148175
}
149176

150177
/// Return the underlying clang::DependencyCollector that this
@@ -353,4 +380,28 @@ class ModuleLoader {
353380

354381
} // namespace swift
355382

383+
namespace llvm {
384+
template <>
385+
struct DenseMapInfo<swift::DependencyTracker::MacroPluginDependency> {
386+
using MacroPluginDependency = swift::DependencyTracker::MacroPluginDependency;
387+
388+
static MacroPluginDependency getEmptyKey() {
389+
return {DenseMapInfo<swift::Identifier>::getEmptyKey(), ""};
390+
}
391+
392+
static MacroPluginDependency getTombstoneKey() {
393+
return {DenseMapInfo<swift::Identifier>::getTombstoneKey(), ""};
394+
}
395+
396+
static unsigned getHashValue(MacroPluginDependency Val) {
397+
return hash_combine(Val.moduleName, Val.path);
398+
}
399+
400+
static bool isEqual(const MacroPluginDependency &LHS,
401+
const MacroPluginDependency &RHS) {
402+
return LHS.moduleName == RHS.moduleName && LHS.path == RHS.path;
403+
}
404+
};
405+
} // namespace llvm
406+
356407
#endif

include/swift/AST/PluginLoader.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ class PluginLoader {
8888
llvm::Expected<LoadedExecutablePlugin *>
8989
loadExecutablePlugin(llvm::StringRef path);
9090

91-
/// Add the specified path to the dependency tracker if needed.
92-
void recordDependency(StringRef path);
91+
/// Add the specified plugin associated with the module name to the dependency
92+
/// tracker if needed.
93+
void recordDependency(const PluginEntry &plugin, Identifier moduleName);
9394
};
9495

9596
} // namespace swift

include/swift/Basic/Statistics.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ FRONTEND_STATISTIC(AST, NumASTBytesAllocated)
115115
/// AST context's dependency collector.
116116
FRONTEND_STATISTIC(AST, NumDependencies)
117117
FRONTEND_STATISTIC(AST, NumIncrementalDependencies)
118+
FRONTEND_STATISTIC(AST, NumMacroPluginDependencies)
118119

119120
/// Number of top-level, dynamic, and member names referenced in this frontend
120121
/// job's source file, as tracked by the AST context's referenced-name tracker.

lib/AST/FrontendSourceFileDepGraphFactory.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,9 @@ class ExternalDependencyEnumerator {
550550
for (StringRef s : depTracker.getDependencies()) {
551551
enumerateUse<NodeKind::externalDepend>(enumerator, s, llvm::None);
552552
}
553+
for (const auto &dep : depTracker.getMacroPluginDependencies()) {
554+
enumerateUse<NodeKind::externalDepend>(enumerator, dep.path, llvm::None);
555+
}
553556
}
554557

555558
private:

lib/AST/ModuleLoader.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ void DependencyTracker::addIncrementalDependency(StringRef File,
5959
}
6060
}
6161

62+
void DependencyTracker::addMacroPluginDependency(StringRef File,
63+
Identifier ModuleName) {
64+
macroPluginDeps.insert({ModuleName, std::string(File)});
65+
}
66+
6267
ArrayRef<std::string>
6368
DependencyTracker::getDependencies() const {
6469
return clangCollector->getDependencies();
@@ -69,6 +74,11 @@ DependencyTracker::getIncrementalDependencies() const {
6974
return incrementalDeps;
7075
}
7176

77+
ArrayRef<DependencyTracker::MacroPluginDependency>
78+
DependencyTracker::getMacroPluginDependencies() const {
79+
return macroPluginDeps.getArrayRef();
80+
}
81+
7282
std::shared_ptr<clang::DependencyCollector>
7383
DependencyTracker::getClangCollector() {
7484
return clangCollector;

lib/AST/PluginLoader.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,14 @@ const PluginLoader::PluginEntry &
150150
PluginLoader::lookupPluginByModuleName(Identifier moduleName) {
151151
auto &map = getPluginMap();
152152
auto found = map.find(moduleName);
153-
if (found != map.end()) {
154-
return found->second;
155-
} else {
153+
if (found == map.end()) {
156154
static PluginEntry notFound{"", ""};
157155
return notFound;
158156
}
157+
158+
// Track the dependency.
159+
recordDependency(found->second, moduleName);
160+
return found->second;
159161
}
160162

161163
llvm::Expected<LoadedLibraryPlugin *>
@@ -166,9 +168,6 @@ PluginLoader::loadLibraryPlugin(StringRef path) {
166168
return llvm::createStringError(err, err.message());
167169
}
168170

169-
// Track the dependency.
170-
recordDependency(path);
171-
172171
// Load the plugin.
173172
auto plugin = getRegistry()->loadLibraryPlugin(resolvedPath);
174173
if (!plugin) {
@@ -193,9 +192,6 @@ PluginLoader::loadExecutablePlugin(StringRef path) {
193192
return llvm::createStringError(err, err.message());
194193
}
195194

196-
// Track the dependency.
197-
recordDependency(path);
198-
199195
// Load the plugin.
200196
auto plugin =
201197
getRegistry()->loadExecutablePlugin(resolvedPath, disableSandbox);
@@ -213,7 +209,26 @@ PluginLoader::loadExecutablePlugin(StringRef path) {
213209
return plugin;
214210
}
215211

216-
void PluginLoader::recordDependency(StringRef path) {
217-
if (DepTracker)
218-
DepTracker->addDependency(path, /*IsSystem=*/false);
212+
void PluginLoader::recordDependency(const PluginEntry &plugin,
213+
Identifier moduleName) {
214+
if (!DepTracker)
215+
return;
216+
217+
// libraryPath: non-nil, executablePath: nil: in-process library plugin.
218+
// libraryPath: non-nil, executablePath: non-nil: external library plugin.
219+
// libraryPath: nil, executablePath: non-nil: executable plugin.
220+
StringRef path =
221+
!plugin.libraryPath.empty() ? plugin.libraryPath : plugin.executablePath;
222+
223+
// NOTE: We don't track plugin-server path as a dependency because it doesn't
224+
// provide much value.
225+
226+
assert(!path.empty());
227+
SmallString<128> resolvedPath;
228+
auto fs = Ctx.SourceMgr.getFileSystem();
229+
if (auto err = fs->getRealPath(path, resolvedPath)) {
230+
return;
231+
}
232+
233+
DepTracker->addMacroPluginDependency(resolvedPath, moduleName);
219234
}

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ bool ExplicitModuleInterfaceBuilder::collectDepsForSerialization(
110110
auto IncDeps =
111111
Instance.getDependencyTracker()->getIncrementalDependencyPaths();
112112
InitialDepNames.append(IncDeps.begin(), IncDeps.end());
113+
auto MacroDeps =
114+
Instance.getDependencyTracker()->getMacroPluginDependencyPaths();
115+
InitialDepNames.append(MacroDeps.begin(), MacroDeps.end());
113116
InitialDepNames.push_back(interfacePath.str());
114117
for (const auto &extra : extraDependencies) {
115118
InitialDepNames.push_back(extra.str());

lib/FrontendTool/FrontendTool.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ static void countASTStats(UnifiedStatsReporter &Stats,
311311
if (auto *D = Instance.getDependencyTracker()) {
312312
C.NumDependencies = D->getDependencies().size();
313313
C.NumIncrementalDependencies = D->getIncrementalDependencies().size();
314+
C.NumMacroPluginDependencies = D->getMacroPluginDependencies().size();
314315
}
315316

316317
for (auto SF : Instance.getPrimarySourceFiles()) {

lib/FrontendTool/LoadedModuleTrace.cpp

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,18 @@ struct SwiftModuleTraceInfo {
4646
bool SupportsLibraryEvolution;
4747
};
4848

49+
struct SwiftMacroTraceInfo {
50+
Identifier Name;
51+
std::string Path;
52+
};
53+
4954
struct LoadedModuleTraceFormat {
5055
static const unsigned CurrentVersion = 2;
5156
unsigned Version;
5257
Identifier Name;
5358
std::string Arch;
5459
std::vector<SwiftModuleTraceInfo> SwiftModules;
60+
std::vector<SwiftMacroTraceInfo> SwiftMacros;
5561
};
5662
} // namespace
5763

@@ -68,6 +74,15 @@ template <> struct ObjectTraits<SwiftModuleTraceInfo> {
6874
}
6975
};
7076

77+
template <>
78+
struct ObjectTraits<SwiftMacroTraceInfo> {
79+
static void mapping(Output &out, SwiftMacroTraceInfo &contents) {
80+
StringRef name = contents.Name.str();
81+
out.mapRequired("name", name);
82+
out.mapRequired("path", contents.Path);
83+
}
84+
};
85+
7186
// Version notes:
7287
// 1. Keys: name, arch, swiftmodules
7388
// 2. New keys: version, swiftmodulesDetailedInfo
@@ -87,6 +102,8 @@ template <> struct ObjectTraits<LoadedModuleTraceFormat> {
87102
out.mapRequired("swiftmodules", moduleNames);
88103

89104
out.mapRequired("swiftmodulesDetailedInfo", contents.SwiftModules);
105+
106+
out.mapRequired("swiftmacros", contents.SwiftMacros);
90107
}
91108
};
92109
} // namespace json
@@ -549,8 +566,7 @@ void ABIDependencyEvaluator::printABIExportMap(llvm::raw_ostream &os) const {
549566
// FIXME: Use the VFS instead of handling paths directly. We are particularly
550567
// sloppy about handling relative paths in the dependency tracker.
551568
static void computeSwiftModuleTraceInfo(
552-
ASTContext &ctx,
553-
const SmallPtrSetImpl<ModuleDecl *> &abiDependencies,
569+
ASTContext &ctx, const SmallPtrSetImpl<ModuleDecl *> &abiDependencies,
554570
const llvm::DenseMap<StringRef, ModuleDecl *> &pathToModuleDecl,
555571
const DependencyTracker &depTracker, StringRef prebuiltCachePath,
556572
std::vector<SwiftModuleTraceInfo> &traceInfo) {
@@ -567,8 +583,8 @@ static void computeSwiftModuleTraceInfo(
567583
SmallVector<std::string, 16> dependencies{deps.begin(), deps.end()};
568584
auto incrDeps = depTracker.getIncrementalDependencyPaths();
569585
dependencies.append(incrDeps.begin(), incrDeps.end());
570-
auto sharedLibraryExtRegex =
571-
llvm::Regex("dylib|so|dll", llvm::Regex::IgnoreCase);
586+
// NOTE: macro dependencies are handled differently.
587+
// See 'computeSwiftMacroTraceInfo()'.
572588
for (const auto &depPath : dependencies) {
573589

574590
// Decide if this is a swiftmodule based on the extension of the raw
@@ -580,10 +596,8 @@ static void computeSwiftModuleTraceInfo(
580596
auto isSwiftmodule = moduleFileType == file_types::TY_SwiftModuleFile;
581597
auto isSwiftinterface =
582598
moduleFileType == file_types::TY_SwiftModuleInterfaceFile;
583-
auto isSharedLibrary =
584-
sharedLibraryExtRegex.match(llvm::sys::path::extension(depPath));
585599

586-
if (!(isSwiftmodule || isSwiftinterface || isSharedLibrary))
600+
if (!(isSwiftmodule || isSwiftinterface))
587601
continue;
588602

589603
auto dep = pathToModuleDecl.find(depPath);
@@ -639,34 +653,6 @@ static void computeSwiftModuleTraceInfo(
639653
continue;
640654
}
641655

642-
// If we found a shared library, it must be a compiler plugin dependency.
643-
if (isSharedLibrary) {
644-
// Infer the module name by dropping the library prefix and extension.
645-
// e.g "/path/to/lib/libPlugin.dylib" -> "Plugin"
646-
auto moduleName = llvm::sys::path::stem(depPath);
647-
#if !defined(_WIN32)
648-
moduleName.consume_front("lib");
649-
#endif
650-
651-
StringRef realDepPath =
652-
fs::real_path(depPath, buffer, /*expand_tile*/ true)
653-
? StringRef(depPath)
654-
: buffer.str();
655-
656-
traceInfo.push_back(
657-
{/*Name=*/
658-
ctx.getIdentifier(moduleName),
659-
/*Path=*/
660-
realDepPath.str(),
661-
/*IsImportedDirectly=*/
662-
false,
663-
/*SupportsLibraryEvolution=*/
664-
false});
665-
buffer.clear();
666-
667-
continue;
668-
}
669-
670656
// Skip cached modules in the prebuilt cache. We will add the corresponding
671657
// swiftinterface from the SDK directly, but this isn't checked. :-/
672658
//
@@ -706,6 +692,22 @@ static void computeSwiftModuleTraceInfo(
706692
});
707693
}
708694

695+
static void
696+
computeSwiftMacroTraceInfo(ASTContext &ctx, const DependencyTracker &depTracker,
697+
std::vector<SwiftMacroTraceInfo> &traceInfo) {
698+
for (const auto &macroDep : depTracker.getMacroPluginDependencies()) {
699+
traceInfo.push_back({macroDep.moduleName, macroDep.path});
700+
}
701+
702+
// Again, almost a re-implementation of reversePathSortedFilenames :(.
703+
std::sort(
704+
traceInfo.begin(), traceInfo.end(),
705+
[](const SwiftMacroTraceInfo &m1, const SwiftMacroTraceInfo &m2) -> bool {
706+
return std::lexicographical_compare(m1.Path.rbegin(), m1.Path.rend(),
707+
m2.Path.rbegin(), m2.Path.rend());
708+
});
709+
}
710+
709711
// [NOTE: Bailing-vs-crashing-in-trace-emission] There are certain edge cases
710712
// in trace emission where an invariant that you think should hold does not hold
711713
// in practice. For example, sometimes we have seen modules without any
@@ -765,10 +767,14 @@ bool swift::emitLoadedModuleTraceIfNeeded(ModuleDecl *mainModule,
765767
*depTracker, opts.PrebuiltModuleCachePath,
766768
swiftModules);
767769

770+
std::vector<SwiftMacroTraceInfo> swiftMacros;
771+
computeSwiftMacroTraceInfo(ctxt, *depTracker, swiftMacros);
772+
768773
LoadedModuleTraceFormat trace = {
769774
/*version=*/LoadedModuleTraceFormat::CurrentVersion,
770775
/*name=*/mainModule->getName(),
771-
/*arch=*/ctxt.LangOpts.Target.getArchName().str(), swiftModules};
776+
/*arch=*/ctxt.LangOpts.Target.getArchName().str(), swiftModules,
777+
swiftMacros};
772778

773779
// raw_fd_ostream is unbuffered, and we may have multiple processes writing,
774780
// so first write to memory and then dump the buffer to the trace file.

lib/FrontendTool/MakeStyleDependencies.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ bool swift::emitMakeDependenciesIfNeeded(DiagnosticEngine &diags,
132132
dependencyString.push_back(' ');
133133
dependencyString.append(frontend::utils::escapeForMake(path, buffer).str());
134134
}
135+
auto macroPluginDependencyPath =
136+
reversePathSortedFilenames(depTracker->getMacroPluginDependencyPaths());
137+
for (auto const &path : macroPluginDependencyPath) {
138+
dependencyString.push_back(' ');
139+
dependencyString.append(frontend::utils::escapeForMake(path, buffer).str());
140+
}
135141

136142
// FIXME: Xcode can't currently handle multiple targets in a single
137143
// dependency line.

0 commit comments

Comments
 (0)