Skip to content

Commit c834696

Browse files
committed
Add SynthesizedFileUnit.
`SynthesizedFileUnit` is a container for synthesized declarations. Currently, it only supports module-level declarations. It is used by the SIL differentiation transform, which generates implicit struct and enum declarations.
1 parent f9ef75f commit c834696

File tree

11 files changed

+181
-0
lines changed

11 files changed

+181
-0
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.
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 *FD) { TopLevelDecls.push_back(FD); }
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

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: 74 additions & 0 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,7 @@ lookupOperatorDeclForName(const FileUnit &File, SourceLoc Loc,
11731179
case FileUnitKind::Builtin:
11741180
// The Builtin module declares no operators.
11751181
return nullptr;
1182+
case FileUnitKind::Synthesized:
11761183
case FileUnitKind::Source:
11771184
break;
11781185
case FileUnitKind::SerializedAST:
@@ -2657,6 +2664,70 @@ SourceFile::lookupOpaqueResultType(StringRef MangledName) {
26572664
return nullptr;
26582665
}
26592666

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

lib/Index/Index.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ bool IndexSwiftASTWalker::visitImports(
737737
switch (File->getKind()) {
738738
case FileUnitKind::Source:
739739
case FileUnitKind::Builtin:
740+
case FileUnitKind::Synthesized:
740741
break;
741742
case FileUnitKind::SerializedAST:
742743
assert(!IsClangModuleOpt.hasValue() &&
@@ -1515,6 +1516,9 @@ void IndexSwiftASTWalker::getRecursiveModuleImports(
15151516
case FileUnitKind::Builtin:
15161517
Info += "builtin";
15171518
break;
1519+
case FileUnitKind::Synthesized:
1520+
Info += "synthesized";
1521+
break;
15181522
case FileUnitKind::Source:
15191523
Info += "source, file=\"";
15201524
Info += cast<SourceFile>(FU)->getFilename();

lib/Index/IndexRecord.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ static void addModuleDependencies(ArrayRef<ModuleDecl::ImportedModule> imports,
406406
switch (FU->getKind()) {
407407
case FileUnitKind::Source:
408408
case FileUnitKind::Builtin:
409+
case FileUnitKind::Synthesized:
409410
break;
410411
case FileUnitKind::SerializedAST:
411412
case FileUnitKind::DWARFModule:

0 commit comments

Comments
 (0)