Skip to content

Commit f27f1cd

Browse files
authored
Merge pull request swiftlang#30863 from dan-zheng/synthesized-file-unit
[AutoDiff] Add generated implicit declarations to SynthesizedFileUnit.
2 parents ecf1e4e + de4deb5 commit f27f1cd

File tree

17 files changed

+216
-30
lines changed

17 files changed

+216
-30
lines changed

include/swift/AST/Module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ enum class FileUnitKind {
9595
Builtin,
9696
/// A serialized Swift AST.
9797
SerializedAST,
98+
/// A synthesized file.
99+
Synthesized,
98100
/// An imported Clang module.
99101
ClangModule,
100102
/// A Clang module imported from DWARF.

include/swift/AST/SourceFile.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,6 @@ class SourceFile final : public FileUnit {
394394
void cacheVisibleDecls(SmallVectorImpl<ValueDecl *> &&globals) const;
395395
const SmallVectorImpl<ValueDecl *> &getCachedVisibleDecls() const;
396396

397-
void addVisibleDecl(ValueDecl *decl);
398-
399397
virtual void lookupValue(DeclName name, NLKind lookupKind,
400398
SmallVectorImpl<ValueDecl*> &result) const override;
401399

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===--- SynthesizedFileUnit.h - A synthesized file unit --------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_AST_SYNTHESIZEDFILEUNIT_H
14+
#define SWIFT_AST_SYNTHESIZEDFILEUNIT_H
15+
16+
#include "swift/AST/FileUnit.h"
17+
#include "swift/Basic/Debug.h"
18+
19+
namespace swift {
20+
21+
/// A container for synthesized module-level declarations.
22+
class SynthesizedFileUnit final : public FileUnit {
23+
/// Synthesized top level declarations.
24+
TinyPtrVector<ValueDecl *> TopLevelDecls;
25+
26+
/// A unique identifier representing this file; used to mark private decls
27+
/// within the file to keep them from conflicting with other files in the
28+
/// same module.
29+
mutable Identifier PrivateDiscriminator;
30+
31+
public:
32+
SynthesizedFileUnit(ModuleDecl &M);
33+
~SynthesizedFileUnit() = default;
34+
35+
/// Add a synthesized top-level declaration.
36+
void addTopLevelDecl(ValueDecl *D) { TopLevelDecls.push_back(D); }
37+
38+
virtual void lookupValue(DeclName name, NLKind lookupKind,
39+
SmallVectorImpl<ValueDecl *> &result) const override;
40+
41+
void lookupObjCMethods(
42+
ObjCSelector selector,
43+
SmallVectorImpl<AbstractFunctionDecl *> &results) const override;
44+
45+
Identifier getDiscriminatorForPrivateValue(const ValueDecl *D) const override;
46+
47+
void getTopLevelDecls(SmallVectorImpl<Decl*> &results) const override;
48+
49+
ArrayRef<ValueDecl *> getTopLevelDecls() const {
50+
return TopLevelDecls;
51+
};
52+
53+
static bool classof(const FileUnit *file) {
54+
return file->getKind() == FileUnitKind::Synthesized;
55+
}
56+
static bool classof(const DeclContext *DC) {
57+
return isa<FileUnit>(DC) && classof(cast<FileUnit>(DC));
58+
}
59+
};
60+
61+
} // namespace swift
62+
63+
#endif // SWIFT_AST_SYNTHESIZEDFILEUNIT_H

include/swift/SILOptimizer/Utils/Differentiation/ADContext.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "swift/AST/DiagnosticsSIL.h"
2121
#include "swift/AST/Expr.h"
22+
#include "swift/AST/SynthesizedFileUnit.h"
2223
#include "swift/SIL/SILBuilder.h"
2324
#include "swift/SILOptimizer/Utils/Differentiation/Common.h"
2425
#include "swift/SILOptimizer/Utils/Differentiation/DifferentiationInvoker.h"
@@ -66,6 +67,9 @@ class ADContext {
6667
/// Shared pass manager.
6768
SILPassManager &passManager;
6869

70+
/// A synthesized file unit.
71+
SynthesizedFileUnit *synthesizedFile = nullptr;
72+
6973
/// The worklist (stack) of `differentiable_function` instructions to be
7074
/// processed.
7175
llvm::SmallVector<DifferentiableFunctionInst *, 32>
@@ -122,6 +126,10 @@ class ADContext {
122126
SILPassManager &getPassManager() const { return passManager; }
123127
Lowering::TypeConverter &getTypeConverter() { return module.Types; }
124128

129+
/// Get or create a synthesized file for adding generated linear map structs
130+
/// and branching trace enums. Used by `LinearMapInfo`.
131+
SynthesizedFileUnit &getOrCreateSynthesizedFile();
132+
125133
/// Returns true if the `differentiable_function` instruction worklist is
126134
/// empty.
127135
bool isDifferentiableFunctionInstsWorklistEmpty() const {

include/swift/SILOptimizer/Utils/Differentiation/LinearMapInfo.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_SILOPTIMIZER_UTILS_DIFFERENTIATION_LINEARMAPINFO_H
1919

2020
#include "swift/AST/AutoDiff.h"
21+
#include "swift/AST/SynthesizedFileUnit.h"
2122
#include "swift/SIL/ApplySite.h"
2223
#include "swift/SILOptimizer/Analysis/DifferentiableActivityAnalysis.h"
2324
#include "llvm/ADT/DenseMap.h"
@@ -85,6 +86,9 @@ class LinearMapInfo {
8586
/// Mapping from linear map structs to their branching trace enum fields.
8687
llvm::DenseMap<StructDecl *, VarDecl *> linearMapStructEnumFields;
8788

89+
/// A synthesized file unit.
90+
SynthesizedFileUnit &synthesizedFile;
91+
8892
/// A type converter, used to compute struct/enum SIL types.
8993
Lowering::TypeConverter &typeConverter;
9094

@@ -97,13 +101,8 @@ class LinearMapInfo {
97101
VarDecl *addVarDecl(NominalTypeDecl *nominal, StringRef name, Type type);
98102

99103
/// Retrieves the file unit that contains implicit declarations in the
100-
/// current Swift module. If it does not exist, create one.
101-
///
102-
// FIXME: Currently it defaults to the file containing `original`, if it can
103-
// be determined. Otherwise, it defaults to any file unit in the module. To
104-
// handle this more properly, we could revive the DerivedFileUnit class to
105-
// contain all synthesized implicit type declarations.
106-
SourceFile &getDeclarationFileUnit();
104+
/// current Swift module.
105+
SynthesizedFileUnit &getSynthesizedFile() { return synthesizedFile; }
107106

108107
/// Computes and sets the access level for the given nominal type, given the
109108
/// original function linkage.

lib/AST/Decl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,7 @@ static_assert(sizeof(checkSourceLocType(&ID##Decl::getLoc)) == 2, \
639639
return getSerializedLocs()->Loc;
640640
}
641641
case FileUnitKind::Builtin:
642+
case FileUnitKind::Synthesized:
642643
case FileUnitKind::ClangModule:
643644
case FileUnitKind::DWARFModule:
644645
return SourceLoc();

lib/AST/DeclContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,9 @@ unsigned DeclContext::printContext(raw_ostream &OS, const unsigned indent,
623623
case FileUnitKind::Source:
624624
OS << " file=\"" << cast<SourceFile>(this)->getFilename() << "\"";
625625
break;
626+
case FileUnitKind::Synthesized:
627+
OS << " synthesized file";
628+
break;
626629
case FileUnitKind::SerializedAST:
627630
case FileUnitKind::ClangModule:
628631
case FileUnitKind::DWARFModule:

lib/AST/Module.cpp

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "swift/AST/ProtocolConformance.h"
3939
#include "swift/AST/ReferencedNameTracker.h"
4040
#include "swift/AST/SourceFile.h"
41+
#include "swift/AST/SynthesizedFileUnit.h"
4142
#include "swift/AST/TypeCheckRequests.h"
4243
#include "swift/Basic/Compiler.h"
4344
#include "swift/Basic/SourceManager.h"
@@ -218,6 +219,7 @@ class swift::SourceLookupCache {
218219

219220
SmallVector<ValueDecl *, 0> AllVisibleValues;
220221
};
222+
221223
SourceLookupCache &SourceFile::getCache() const {
222224
if (!Cache) {
223225
const_cast<SourceFile *>(this)->Cache =
@@ -317,6 +319,10 @@ SourceLookupCache::SourceLookupCache(const ModuleDecl &M) {
317319
FrontendStatsTracer tracer(M.getASTContext().Stats,
318320
"module-populate-cache");
319321
for (const FileUnit *file : M.getFiles()) {
322+
if (auto *SFU = dyn_cast<SynthesizedFileUnit>(file)) {
323+
addToUnqualifiedLookupCache(SFU->getTopLevelDecls(), false);
324+
continue;
325+
}
320326
auto &SF = *cast<SourceFile>(file);
321327
addToUnqualifiedLookupCache(SF.getTopLevelDecls(), false);
322328
}
@@ -1173,6 +1179,9 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
11731179
case FileUnitKind::Builtin:
11741180
// The Builtin module declares no operators.
11751181
return nullptr;
1182+
case FileUnitKind::Synthesized:
1183+
// Synthesized files currently declare no operators.
1184+
return nullptr;
11761185
case FileUnitKind::Source:
11771186
break;
11781187
case FileUnitKind::SerializedAST:
@@ -1520,6 +1529,9 @@ StringRef ModuleDecl::getModuleFilename() const {
15201529
Result = LF->getFilename();
15211530
continue;
15221531
}
1532+
// Skip synthesized files.
1533+
if (auto *SFU = dyn_cast<SynthesizedFileUnit>(F))
1534+
continue;
15231535
return StringRef();
15241536
}
15251537
return Result;
@@ -2232,11 +2244,6 @@ SourceFile::getCachedVisibleDecls() const {
22322244
return getCache().AllVisibleValues;
22332245
}
22342246

2235-
void SourceFile::addVisibleDecl(ValueDecl *decl) {
2236-
Decls->push_back(decl);
2237-
getCache().AllVisibleValues.push_back(decl);
2238-
}
2239-
22402247
static void performAutoImport(
22412248
SourceFile &SF,
22422249
SourceFile::ImplicitModuleImportKind implicitModuleImportKind) {
@@ -2662,6 +2669,70 @@ SourceFile::lookupOpaqueResultType(StringRef MangledName) {
26622669
return nullptr;
26632670
}
26642671

2672+
//===----------------------------------------------------------------------===//
2673+
// SynthesizedFileUnit Implementation
2674+
//===----------------------------------------------------------------------===//
2675+
2676+
SynthesizedFileUnit::SynthesizedFileUnit(ModuleDecl &M)
2677+
: FileUnit(FileUnitKind::Synthesized, M) {
2678+
M.getASTContext().addDestructorCleanup(*this);
2679+
}
2680+
2681+
Identifier
2682+
SynthesizedFileUnit::getDiscriminatorForPrivateValue(const ValueDecl *D) const {
2683+
assert(D->getDeclContext()->getModuleScopeContext() == this);
2684+
2685+
// Use cached primitive discriminator if it exists.
2686+
if (!PrivateDiscriminator.empty())
2687+
return PrivateDiscriminator;
2688+
2689+
assert(1 == count_if(getParentModule()->getFiles(),
2690+
[](const FileUnit *FU) -> bool {
2691+
return isa<SynthesizedFileUnit>(FU);
2692+
}) &&
2693+
"Cannot promise uniqueness if multiple synthesized file units exist");
2694+
2695+
// Use a discriminator invariant across Swift version: a hash of the module
2696+
// name and a special string.
2697+
llvm::MD5 hash;
2698+
hash.update(getParentModule()->getName().str());
2699+
// TODO: Use a more robust discriminator for synthesized files. Pick something
2700+
// that cannot conflict with `SourceFile` discriminators.
2701+
hash.update("SYNTHESIZED FILE");
2702+
llvm::MD5::MD5Result result;
2703+
hash.final(result);
2704+
2705+
// Use the hash as a hex string, prefixed with an underscore to make sure
2706+
// it is a valid identifier.
2707+
// FIXME: There are more compact ways to encode a 16-byte value.
2708+
SmallString<33> buffer{"_"};
2709+
SmallString<32> hashString;
2710+
llvm::MD5::stringifyResult(result, hashString);
2711+
buffer += hashString;
2712+
PrivateDiscriminator = getASTContext().getIdentifier(buffer.str().upper());
2713+
return PrivateDiscriminator;
2714+
}
2715+
2716+
void SynthesizedFileUnit::lookupValue(
2717+
DeclName name, NLKind lookupKind,
2718+
SmallVectorImpl<ValueDecl *> &result) const {
2719+
for (auto *decl : TopLevelDecls) {
2720+
if (decl->getFullName().matchesRef(name))
2721+
result.push_back(decl);
2722+
}
2723+
}
2724+
2725+
void SynthesizedFileUnit::lookupObjCMethods(
2726+
ObjCSelector selector,
2727+
SmallVectorImpl<AbstractFunctionDecl *> &results) const {
2728+
// Synthesized files only contain top-level declarations, no `@objc` methods.
2729+
}
2730+
2731+
void SynthesizedFileUnit::getTopLevelDecls(
2732+
SmallVectorImpl<swift::Decl *> &results) const {
2733+
results.append(TopLevelDecls.begin(), TopLevelDecls.end());
2734+
}
2735+
26652736
//===----------------------------------------------------------------------===//
26662737
// Miscellaneous
26672738
//===----------------------------------------------------------------------===//
@@ -2700,6 +2771,9 @@ void swift::simple_display(llvm::raw_ostream &out, const FileUnit *file) {
27002771
case FileUnitKind::Builtin:
27012772
out << "(Builtin)";
27022773
return;
2774+
case FileUnitKind::Synthesized:
2775+
out << "(synthesized)";
2776+
return;
27032777
case FileUnitKind::DWARFModule:
27042778
case FileUnitKind::ClangModule:
27052779
case FileUnitKind::SerializedAST:

lib/IRGen/GenDecl.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ class ObjCProtocolInitializerVisitor
415415
} // end anonymous namespace
416416

417417
namespace {
418+
418419
class PrettySourceFileEmission : public llvm::PrettyStackTraceEntry {
419420
const SourceFile &SF;
420421
public:
@@ -424,6 +425,19 @@ class PrettySourceFileEmission : public llvm::PrettyStackTraceEntry {
424425
os << "While emitting IR for source file " << SF.getFilename() << '\n';
425426
}
426427
};
428+
429+
class PrettySynthesizedFileUnitEmission : public llvm::PrettyStackTraceEntry {
430+
const SynthesizedFileUnit &SFU;
431+
432+
public:
433+
explicit PrettySynthesizedFileUnitEmission(const SynthesizedFileUnit &SFU)
434+
: SFU(SFU) {}
435+
436+
void print(raw_ostream &os) const override {
437+
os << "While emitting IR for synthesized file" << &SFU << "\n";
438+
}
439+
};
440+
427441
} // end anonymous namespace
428442

429443
/// Emit all the top-level code in the source file.
@@ -475,6 +489,13 @@ void IRGenModule::emitSourceFile(SourceFile &SF) {
475489
}
476490
}
477491

492+
/// Emit all the top-level code in the synthesized file unit.
493+
void IRGenModule::emitSynthesizedFileUnit(SynthesizedFileUnit &SFU) {
494+
PrettySynthesizedFileUnitEmission StackEntry(SFU);
495+
for (auto *decl : SFU.getTopLevelDecls())
496+
emitGlobalDecl(decl);
497+
}
498+
478499
/// Collect elements of an already-existing global list with the given
479500
/// \c name into \c list.
480501
///

lib/IRGen/IRGen.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,11 @@ performIRGeneration(const IRGenOptions &Opts, ModuleDecl *M,
990990
}
991991
}
992992

993+
// Emit synthesized file units.
994+
for (auto *File : M->getFiles())
995+
if (auto *nextSFU = dyn_cast<SynthesizedFileUnit>(File))
996+
IGM.emitSynthesizedFileUnit(*nextSFU);
997+
993998
// Okay, emit any definitions that we suddenly need.
994999
irgen.emitLazyDefinitions();
9951000

@@ -1235,6 +1240,9 @@ static void performParallelIRGeneration(
12351240
if (auto *SF = dyn_cast<SourceFile>(File)) {
12361241
CurrentIGMPtr IGM = irgen.getGenModule(SF);
12371242
IGM->emitSourceFile(*SF);
1243+
} else if (auto *nextSFU = dyn_cast<SynthesizedFileUnit>(File)) {
1244+
CurrentIGMPtr IGM = irgen.getGenModule(nextSFU);
1245+
IGM->emitSynthesizedFileUnit(*nextSFU);
12381246
} else {
12391247
File->collectLinkLibraries([&](LinkLibrary LinkLib) {
12401248
irgen.getPrimaryIGM()->addLinkLibrary(LinkLib);

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/Module.h"
2626
#include "swift/AST/ReferenceCounting.h"
2727
#include "swift/AST/SourceFile.h"
28+
#include "swift/AST/SynthesizedFileUnit.h"
2829
#include "swift/Basic/ClusteredBitVector.h"
2930
#include "swift/Basic/LLVM.h"
3031
#include "swift/Basic/OptimizationMode.h"
@@ -1289,6 +1290,7 @@ private: \
12891290
llvm::LLVMContext &getLLVMContext() const { return LLVMContext; }
12901291

12911292
void emitSourceFile(SourceFile &SF);
1293+
void emitSynthesizedFileUnit(SynthesizedFileUnit &SFU);
12921294
void addLinkLibrary(const LinkLibrary &linkLib);
12931295

12941296
/// Attempt to finalize the module.

0 commit comments

Comments
 (0)