Skip to content

Commit 360afd6

Browse files
authored
Merge pull request swiftlang#34073 from CodaFi/crossfire
Serialization for Incremental Swift Dependency Information
2 parents ef972eb + 3c2b376 commit 360afd6

20 files changed

+209
-91
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ class alignas(1 << DeclAlignInBits) Decl {
578578
HasAnyUnavailableValues : 1
579579
);
580580

581-
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1,
581+
SWIFT_INLINE_BITFIELD(ModuleDecl, TypeDecl, 1+1+1+1+1+1+1+1+1+1,
582582
/// If the module was or is being compiled with `-enable-testing`.
583583
TestingEnabled : 1,
584584

@@ -607,7 +607,10 @@ class alignas(1 << DeclAlignInBits) Decl {
607607
IsNonSwiftModule : 1,
608608

609609
/// Whether this module is the main module.
610-
IsMainModule : 1
610+
IsMainModule : 1,
611+
612+
/// Whether this module has incremental dependency information available.
613+
HasIncrementalInfo : 1
611614
);
612615

613616
SWIFT_INLINE_BITFIELD(PrecedenceGroupDecl, Decl, 1+2,

include/swift/AST/FineGrainedDependencies.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,14 @@ namespace swift {
5959
class DependencyTracker;
6060
class DiagnosticEngine;
6161
class FrontendOptions;
62+
class ModuleDecl;
6263
class SourceFile;
6364

6465
/// Use a new namespace to help keep the experimental code from clashing.
6566
namespace fine_grained_dependencies {
6667

68+
class SourceFileDepGraph;
69+
6770
using StringVec = std::vector<std::string>;
6871

6972
template <typename Element> using ConstPtrVec = std::vector<const Element *>;
@@ -343,11 +346,11 @@ class BiIndexedTwoStageMap {
343346
// MARK: Start of fine-grained-dependency-specific code
344347
//==============================================================================
345348

346-
/// The entry point into this system from the frontend:
347-
/// Write out the .swiftdeps file for a frontend compilation of a primary file.
348-
bool emitReferenceDependencies(DiagnosticEngine &diags, SourceFile *SF,
349-
const DependencyTracker &depTracker,
350-
StringRef outputPath, bool alsoEmitDotFile);
349+
bool withReferenceDependencies(
350+
llvm::PointerUnion<ModuleDecl *, SourceFile *> MSF,
351+
const DependencyTracker &depTracker, StringRef outputPath,
352+
bool alsoEmitDotFile, llvm::function_ref<bool(SourceFileDepGraph &&)>);
353+
351354
//==============================================================================
352355
// MARK: Enums
353356
//==============================================================================

include/swift/AST/FineGrainedDependencyFormat.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,11 @@ bool readFineGrainedDependencyGraph(llvm::StringRef path,
124124

125125
/// Tries to write the dependency graph to the given path name.
126126
/// Returns true if there was an error.
127-
bool writeFineGrainedDependencyGraph(DiagnosticEngine &diags, llvm::StringRef path,
127+
bool writeFineGrainedDependencyGraphToPath(DiagnosticEngine &diags,
128+
llvm::StringRef path,
129+
const SourceFileDepGraph &g);
130+
131+
void writeFineGrainedDependencyGraph(llvm::BitstreamWriter &Out,
128132
const SourceFileDepGraph &g);
129133

130134
} // namespace fine_grained_dependencies

include/swift/AST/Module.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,12 @@ class ModuleDecl : public DeclContext, public TypeDecl {
517517
Bits.ModuleDecl.RawResilienceStrategy = unsigned(strategy);
518518
}
519519

520+
/// Returns true if this module was or is being compiled for testing.
521+
bool hasIncrementalInfo() const { return Bits.ModuleDecl.HasIncrementalInfo; }
522+
void setHasIncrementalInfo(bool enabled = true) {
523+
Bits.ModuleDecl.HasIncrementalInfo = enabled;
524+
}
525+
520526
/// \returns true if this module is a system module; note that the StdLib is
521527
/// considered a system module.
522528
bool isSystemModule() const {

include/swift/Subsystems.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ namespace swift {
7575
class TypeConverter;
7676
}
7777

78+
namespace fine_grained_dependencies {
79+
class SourceFileDepGraph;
80+
}
81+
7882
/// @{
7983

8084
/// \returns true if the declaration should be verified. This can return
@@ -174,8 +178,10 @@ namespace swift {
174178
using ModuleOrSourceFile = PointerUnion<ModuleDecl *, SourceFile *>;
175179

176180
/// Serializes a module or single source file to the given output file.
177-
void serialize(ModuleOrSourceFile DC, const SerializationOptions &options,
178-
const SILModule *M = nullptr);
181+
void
182+
serialize(ModuleOrSourceFile DC, const SerializationOptions &options,
183+
const SILModule *M = nullptr,
184+
const fine_grained_dependencies::SourceFileDepGraph *DG = nullptr);
179185

180186
/// Serializes a module or single source file to the given output file and
181187
/// returns back the file's contents as a memory buffer.

lib/AST/FineGrainedDependencyFormat.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -289,16 +289,13 @@ class Serializer {
289289
unsigned LastIdentifierID = 0;
290290
std::vector<StringRef> IdentifiersToWrite;
291291

292-
SmallVector<char, 0> Buffer;
293-
llvm::BitstreamWriter Out{Buffer};
292+
llvm::BitstreamWriter &Out;
294293

295294
/// A reusable buffer for emitting records.
296295
SmallVector<uint64_t, 64> ScratchRecord;
297296

298297
std::array<unsigned, 256> AbbrCodes;
299298

300-
void writeFineGrainedDependencyGraph(const SourceFileDepGraph &g);
301-
302299
void addIdentifier(StringRef str);
303300
unsigned getIdentifier(StringRef str);
304301

@@ -321,8 +318,10 @@ class Serializer {
321318
void writeMetadata();
322319

323320
public:
324-
void writeFineGrainedDependencyGraph(llvm::raw_ostream &os,
325-
const SourceFileDepGraph &g);
321+
Serializer(llvm::BitstreamWriter &ExistingOut) : Out(ExistingOut) {}
322+
323+
public:
324+
void writeFineGrainedDependencyGraph(const SourceFileDepGraph &g);
326325
};
327326

328327
} // end namespace
@@ -467,20 +466,22 @@ unsigned Serializer::getIdentifier(StringRef str) {
467466
return iter->second;
468467
}
469468

470-
void Serializer::writeFineGrainedDependencyGraph(llvm::raw_ostream &os,
471-
const SourceFileDepGraph &g) {
472-
writeFineGrainedDependencyGraph(g);
473-
os.write(Buffer.data(), Buffer.size());
474-
os.flush();
469+
void swift::fine_grained_dependencies::writeFineGrainedDependencyGraph(
470+
llvm::BitstreamWriter &Out, const SourceFileDepGraph &g) {
471+
Serializer serializer{Out};
472+
serializer.writeFineGrainedDependencyGraph(g);
475473
}
476474

477-
bool swift::fine_grained_dependencies::writeFineGrainedDependencyGraph(
475+
bool swift::fine_grained_dependencies::writeFineGrainedDependencyGraphToPath(
478476
DiagnosticEngine &diags, StringRef path,
479477
const SourceFileDepGraph &g) {
480478
PrettyStackTraceStringAction stackTrace("saving fine-grained dependency graph", path);
481479
return withOutputFile(diags, path, [&](llvm::raw_ostream &out) {
482-
Serializer serializer;
483-
serializer.writeFineGrainedDependencyGraph(out, g);
480+
SmallVector<char, 0> Buffer;
481+
llvm::BitstreamWriter Writer{Buffer};
482+
writeFineGrainedDependencyGraph(Writer, g);
483+
out.write(Buffer.data(), Buffer.size());
484+
out.flush();
484485
return false;
485486
});
486-
}
487+
}

lib/AST/FrontendSourceFileDepGraphFactory.cpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -236,30 +236,20 @@ std::string DependencyKey::computeNameForProvidedEntity<
236236
// MARK: Entry point into frontend graph construction
237237
//==============================================================================
238238

239-
bool fine_grained_dependencies::emitReferenceDependencies(
240-
DiagnosticEngine &diags, SourceFile *const SF,
241-
const DependencyTracker &depTracker,
242-
StringRef outputPath,
243-
const bool alsoEmitDotFile) {
244-
245-
// Before writing to the dependencies file path, preserve any previous file
246-
// that may have been there. No error handling -- this is just a nicety, it
247-
// doesn't matter if it fails.
248-
llvm::sys::fs::rename(outputPath, outputPath + "~");
249-
250-
SourceFileDepGraph g = FrontendSourceFileDepGraphFactory(
251-
SF, outputPath, depTracker, alsoEmitDotFile)
252-
.construct();
253-
254-
bool hadError = writeFineGrainedDependencyGraph(diags, outputPath, g);
255-
256-
// If path is stdout, cannot read it back, so check for "-"
257-
assert(outputPath == "-" || g.verifyReadsWhatIsWritten(outputPath));
258-
259-
if (alsoEmitDotFile)
260-
g.emitDotFile(outputPath, diags);
261-
262-
return hadError;
239+
bool fine_grained_dependencies::withReferenceDependencies(
240+
llvm::PointerUnion<ModuleDecl *, SourceFile *> MSF,
241+
const DependencyTracker &depTracker, StringRef outputPath,
242+
bool alsoEmitDotFile,
243+
llvm::function_ref<bool(SourceFileDepGraph &&)> cont) {
244+
if (MSF.dyn_cast<ModuleDecl *>()) {
245+
llvm_unreachable("Cannot construct dependency graph for modules!");
246+
} else {
247+
auto *SF = MSF.get<SourceFile *>();
248+
SourceFileDepGraph g = FrontendSourceFileDepGraphFactory(
249+
SF, outputPath, depTracker, alsoEmitDotFile)
250+
.construct();
251+
return cont(std::move(g));
252+
}
263253
}
264254

265255
//==============================================================================

lib/AST/Module.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ ModuleDecl::ModuleDecl(Identifier name, ASTContext &ctx,
484484
Bits.ModuleDecl.IsSystemModule = 0;
485485
Bits.ModuleDecl.IsNonSwiftModule = 0;
486486
Bits.ModuleDecl.IsMainModule = 0;
487+
Bits.ModuleDecl.HasIncrementalInfo = 0;
487488
}
488489

489490
ArrayRef<ImplicitImport> ModuleDecl::getImplicitImports() const {

lib/AST/NameLookupRequests.cpp

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,15 @@ void DirectLookupRequest::writeDependencySink(
300300

301301
void LookupInModuleRequest::writeDependencySink(
302302
evaluator::DependencyCollector &reqTracker, QualifiedLookupResult l) const {
303-
auto *module = std::get<0>(getStorage());
303+
auto *DC = std::get<0>(getStorage());
304304
auto member = std::get<1>(getStorage());
305-
auto *DC = std::get<4>(getStorage());
306305

307-
// Decline to record lookups outside our module.
308-
if (!DC->getParentSourceFile() ||
309-
module->getParentModule() != DC->getParentModule()) {
310-
return;
306+
// Decline to record lookups if the module in question has no incremental
307+
// dependency information available.
308+
auto *module = DC->getParentModule();
309+
if (module->isMainModule() || module->hasIncrementalInfo()) {
310+
reqTracker.addTopLevelName(member.getBaseName());
311311
}
312-
reqTracker.addTopLevelName(member.getBaseName());
313312
}
314313

315314
//----------------------------------------------------------------------------//
@@ -343,16 +342,14 @@ swift::extractNearestSourceLoc(const LookupConformanceDescriptor &desc) {
343342

344343
void ModuleQualifiedLookupRequest::writeDependencySink(
345344
evaluator::DependencyCollector &reqTracker, QualifiedLookupResult l) const {
346-
auto *DC = std::get<0>(getStorage());
347345
auto *module = std::get<1>(getStorage());
348346
auto member = std::get<2>(getStorage());
349347

350-
// Decline to record lookups outside our module.
351-
if (!DC->getParentSourceFile() ||
352-
module != DC->getModuleScopeContext()->getParentModule()) {
353-
return;
348+
// Decline to record lookups if the module in question has no incremental
349+
// dependency information available.
350+
if (module->isMainModule() || module->hasIncrementalInfo()) {
351+
reqTracker.addTopLevelName(member.getBaseName());
354352
}
355-
reqTracker.addTopLevelName(member.getBaseName());
356353
}
357354

358355
//----------------------------------------------------------------------------//
@@ -370,16 +367,13 @@ void LookupConformanceInModuleRequest::writeDependencySink(
370367
if (!Adoptee)
371368
return;
372369

373-
auto source = reqTracker.getRecorder().getActiveDependencySourceOrNull();
374-
if (source.isNull())
375-
return;
376-
377-
// Decline to record conformances defined outside of the active module.
370+
// Decline to record lookups if the module in question has no incremental
371+
// dependency information available.
378372
auto *conformance = lookupResult.getConcrete();
379-
if (source.get()->getParentModule() !=
380-
conformance->getDeclContext()->getParentModule())
381-
return;
382-
reqTracker.addPotentialMember(Adoptee);
373+
auto *module = conformance->getDeclContext()->getParentModule();
374+
if (module->isMainModule() || module->hasIncrementalInfo()) {
375+
reqTracker.addPotentialMember(Adoptee);
376+
}
383377
}
384378

385379
//----------------------------------------------------------------------------//

lib/FrontendTool/FrontendTool.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/DiagnosticsSema.h"
3131
#include "swift/AST/FileSystem.h"
3232
#include "swift/AST/FineGrainedDependencies.h"
33+
#include "swift/AST/FineGrainedDependencyFormat.h"
3334
#include "swift/AST/GenericSignatureBuilder.h"
3435
#include "swift/AST/IRGenOptions.h"
3536
#include "swift/AST/IRGenRequests.h"
@@ -1370,6 +1371,35 @@ static bool dumpAST(CompilerInstance &Instance) {
13701371
return Instance.getASTContext().hadError();
13711372
}
13721373

1374+
static bool emitReferenceDependencies(CompilerInstance &Instance,
1375+
SourceFile *const SF,
1376+
StringRef outputPath) {
1377+
const auto alsoEmitDotFile = Instance.getInvocation()
1378+
.getLangOptions()
1379+
.EmitFineGrainedDependencySourcefileDotFiles;
1380+
1381+
// Before writing to the dependencies file path, preserve any previous file
1382+
// that may have been there. No error handling -- this is just a nicety, it
1383+
// doesn't matter if it fails.
1384+
llvm::sys::fs::rename(outputPath, outputPath + "~");
1385+
1386+
using SourceFileDepGraph = fine_grained_dependencies::SourceFileDepGraph;
1387+
return fine_grained_dependencies::withReferenceDependencies(
1388+
SF, *Instance.getDependencyTracker(), outputPath, alsoEmitDotFile,
1389+
[&](SourceFileDepGraph &&g) -> bool {
1390+
const bool hadError =
1391+
fine_grained_dependencies::writeFineGrainedDependencyGraphToPath(
1392+
Instance.getDiags(), outputPath, g);
1393+
1394+
// If path is stdout, cannot read it back, so check for "-"
1395+
assert(outputPath == "-" || g.verifyReadsWhatIsWritten(outputPath));
1396+
1397+
if (alsoEmitDotFile)
1398+
g.emitDotFile(outputPath, Instance.getDiags());
1399+
return hadError;
1400+
});
1401+
}
1402+
13731403
static void emitReferenceDependenciesForAllPrimaryInputsIfNeeded(
13741404
CompilerInstance &Instance) {
13751405
const auto &Invocation = Instance.getInvocation();
@@ -1384,13 +1414,11 @@ static void emitReferenceDependenciesForAllPrimaryInputsIfNeeded(
13841414
const std::string &referenceDependenciesFilePath =
13851415
Invocation.getReferenceDependenciesFilePathForPrimary(
13861416
SF->getFilename());
1387-
if (!referenceDependenciesFilePath.empty()) {
1388-
const auto LangOpts = Invocation.getLangOptions();
1389-
(void)fine_grained_dependencies::emitReferenceDependencies(
1390-
Instance.getDiags(), SF, *Instance.getDependencyTracker(),
1391-
referenceDependenciesFilePath,
1392-
LangOpts.EmitFineGrainedDependencySourcefileDotFiles);
1417+
if (referenceDependenciesFilePath.empty()) {
1418+
continue;
13931419
}
1420+
1421+
emitReferenceDependencies(Instance, SF, referenceDependenciesFilePath);
13941422
}
13951423
}
13961424
static void

lib/Serialization/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ add_swift_host_library(swiftSerialization STATIC
88
SerializedModuleLoader.cpp
99
SerializedSILLoader.cpp
1010
SerializeDoc.cpp
11+
SerializeIncremental.cpp
1112
SerializeSIL.cpp
1213

1314
LLVM_LINK_COMPONENTS

lib/Serialization/ModuleFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,9 @@ class ModuleFile
465465
return Core->Bits.IsImplicitDynamicEnabled;
466466
}
467467

468+
/// \c true if this module has incremental dependency information.
469+
bool hasIncrementalInfo() const { return Core->hasIncrementalInfo(); }
470+
468471
/// Associates this module file with the AST node representing it.
469472
///
470473
/// Checks that the file is compatible with the AST module it's being loaded

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,17 @@ ModuleFileSharedCore::ModuleFileSharedCore(
14271427
break;
14281428
}
14291429

1430+
case INCREMENTAL_INFORMATION_BLOCK_ID: {
1431+
HasIncrementalInfo = true;
1432+
// Skip incremental info if present. The Frontend currently doesn't do
1433+
// anything with this.
1434+
if (cursor.SkipBlock()) {
1435+
info.status = error(Status::Malformed);
1436+
return;
1437+
}
1438+
break;
1439+
}
1440+
14301441
default:
14311442
// Unknown top-level block, possibly for use by a future version of the
14321443
// module format.

0 commit comments

Comments
 (0)