Skip to content

Commit a0c529a

Browse files
authored
Merge pull request #33954 from hamishknight/sym-city-two
2 parents a97e47a + 088a86e commit a0c529a

File tree

11 files changed

+198
-48
lines changed

11 files changed

+198
-48
lines changed

include/swift/AST/IRGenRequests.h

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class IRGenOptions;
3030
class SILModule;
3131
class SILOptions;
3232
struct TBDGenOptions;
33+
class TBDGenDescriptor;
3334

3435
namespace irgen {
3536
class IRGenModule;
@@ -126,6 +127,9 @@ class GeneratedModule final {
126127
struct IRGenDescriptor {
127128
llvm::PointerUnion<FileUnit *, ModuleDecl *> Ctx;
128129

130+
using SymsToEmit = Optional<llvm::SmallVector<std::string, 1>>;
131+
SymsToEmit SymbolsToEmit;
132+
129133
const IRGenOptions &Opts;
130134
const TBDGenOptions &TBDOpts;
131135
const SILOptions &SILOpts;
@@ -143,12 +147,13 @@ struct IRGenDescriptor {
143147
llvm::GlobalVariable **outModuleHash;
144148

145149
friend llvm::hash_code hash_value(const IRGenDescriptor &owner) {
146-
return llvm::hash_combine(owner.Ctx);
150+
return llvm::hash_combine(owner.Ctx, owner.SymbolsToEmit, owner.SILMod);
147151
}
148152

149153
friend bool operator==(const IRGenDescriptor &lhs,
150154
const IRGenDescriptor &rhs) {
151-
return lhs.Ctx == rhs.Ctx;
155+
return lhs.Ctx == rhs.Ctx && lhs.SymbolsToEmit == rhs.SymbolsToEmit &&
156+
lhs.SILMod == rhs.SILMod;
152157
}
153158

154159
friend bool operator!=(const IRGenDescriptor &lhs,
@@ -162,9 +167,10 @@ struct IRGenDescriptor {
162167
const TBDGenOptions &TBDOpts, const SILOptions &SILOpts,
163168
Lowering::TypeConverter &Conv, std::unique_ptr<SILModule> &&SILMod,
164169
StringRef ModuleName, const PrimarySpecificPaths &PSPs,
165-
StringRef PrivateDiscriminator,
170+
StringRef PrivateDiscriminator, SymsToEmit symsToEmit = None,
166171
llvm::GlobalVariable **outModuleHash = nullptr) {
167172
return IRGenDescriptor{file,
173+
symsToEmit,
168174
Opts,
169175
TBDOpts,
170176
SILOpts,
@@ -182,10 +188,11 @@ struct IRGenDescriptor {
182188
const TBDGenOptions &TBDOpts, const SILOptions &SILOpts,
183189
Lowering::TypeConverter &Conv,
184190
std::unique_ptr<SILModule> &&SILMod, StringRef ModuleName,
185-
const PrimarySpecificPaths &PSPs,
191+
const PrimarySpecificPaths &PSPs, SymsToEmit symsToEmit = None,
186192
ArrayRef<std::string> parallelOutputFilenames = {},
187193
llvm::GlobalVariable **outModuleHash = nullptr) {
188194
return IRGenDescriptor{M,
195+
symsToEmit,
189196
Opts,
190197
TBDOpts,
191198
SILOpts,
@@ -198,13 +205,17 @@ struct IRGenDescriptor {
198205
outModuleHash};
199206
}
200207

201-
/// Retrieves the files to perform IR generation for.
202-
TinyPtrVector<FileUnit *> getFiles() const;
208+
/// Retrieves the files to perform IR generation for. If the descriptor is
209+
/// configured only to emit a specific set of symbols, this will be empty.
210+
TinyPtrVector<FileUnit *> getFilesToEmit() const;
203211

204212
/// For a single file, returns its parent module, otherwise returns the module
205213
/// itself.
206214
ModuleDecl *getParentModule() const;
207215

216+
/// Retrieve a descriptor suitable for generating TBD for the file or module.
217+
TBDGenDescriptor getTBDGenDescriptor() const;
218+
208219
/// Compute the linker directives to emit.
209220
std::vector<std::string> getLinkerDirectives() const;
210221
};
@@ -254,6 +265,26 @@ class OptimizedIRRequest
254265
GeneratedModule evaluate(Evaluator &evaluator, IRGenDescriptor desc) const;
255266
};
256267

268+
using SymbolsToEmit = SmallVector<std::string, 1>;
269+
270+
/// Return the object code for a specific set of symbols in a file or module.
271+
class SymbolObjectCodeRequest : public SimpleRequest<SymbolObjectCodeRequest,
272+
StringRef(IRGenDescriptor),
273+
RequestFlags::Cached> {
274+
public:
275+
using SimpleRequest::SimpleRequest;
276+
277+
private:
278+
friend SimpleRequest;
279+
280+
// Evaluation.
281+
StringRef evaluate(Evaluator &evaluator, IRGenDescriptor desc) const;
282+
283+
public:
284+
// Caching.
285+
bool isCached() const { return true; }
286+
};
287+
257288
/// The zone number for IRGen.
258289
#define SWIFT_TYPEID_ZONE IRGen
259290
#define SWIFT_TYPEID_HEADER "swift/AST/IRGenTypeIDZone.def"

include/swift/AST/IRGenTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ SWIFT_REQUEST(IRGen, IRGenRequest,
2020
SWIFT_REQUEST(IRGen, OptimizedIRRequest,
2121
GeneratedModule(IRGenDescriptor),
2222
Uncached, NoLocationInfo)
23+
SWIFT_REQUEST(IRGen, SymbolObjectCodeRequest,
24+
StringRef(SymbolsToEmit, IRGenDescriptor),
25+
Cached, NoLocationInfo)

include/swift/AST/SILGenRequests.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTTypeIDs.h"
2121
#include "swift/AST/EvaluatorDependencies.h"
2222
#include "swift/AST/SimpleRequest.h"
23+
#include "swift/SIL/SILDeclRef.h"
2324

2425
namespace swift {
2526

@@ -40,22 +41,30 @@ template<typename Request>
4041
void reportEvaluatedRequest(UnifiedStatsReporter &stats,
4142
const Request &request);
4243

44+
using SILRefsToEmit = llvm::SmallVector<SILDeclRef, 1>;
45+
4346
/// Describes a file or module to be lowered to SIL.
4447
struct ASTLoweringDescriptor {
4548
llvm::PointerUnion<FileUnit *, ModuleDecl *> context;
4649
Lowering::TypeConverter &conv;
4750
const SILOptions &opts;
4851

52+
/// A specific set of SILDeclRefs to emit. If set, only these refs will be
53+
/// emitted. Otherwise the entire \c context will be emitted.
54+
Optional<SILRefsToEmit> refsToEmit;
55+
4956
friend llvm::hash_code hash_value(const ASTLoweringDescriptor &owner) {
5057
return llvm::hash_combine(owner.context, (void *)&owner.conv,
51-
(void *)&owner.opts);
58+
(void *)&owner.opts,
59+
owner.refsToEmit);
5260
}
5361

5462
friend bool operator==(const ASTLoweringDescriptor &lhs,
5563
const ASTLoweringDescriptor &rhs) {
5664
return lhs.context == rhs.context &&
5765
&lhs.conv == &rhs.conv &&
58-
&lhs.opts == &rhs.opts;
66+
&lhs.opts == &rhs.opts &&
67+
lhs.refsToEmit == rhs.refsToEmit;
5968
}
6069

6170
friend bool operator!=(const ASTLoweringDescriptor &lhs,
@@ -65,19 +74,21 @@ struct ASTLoweringDescriptor {
6574

6675
public:
6776
static ASTLoweringDescriptor
68-
forFile(FileUnit &sf, Lowering::TypeConverter &conv, const SILOptions &opts) {
69-
return ASTLoweringDescriptor{&sf, conv, opts};
77+
forFile(FileUnit &sf, Lowering::TypeConverter &conv, const SILOptions &opts,
78+
Optional<SILRefsToEmit> refsToEmit = None) {
79+
return ASTLoweringDescriptor{&sf, conv, opts, refsToEmit};
7080
}
7181

72-
static ASTLoweringDescriptor forWholeModule(ModuleDecl *mod,
73-
Lowering::TypeConverter &conv,
74-
const SILOptions &opts) {
75-
return ASTLoweringDescriptor{mod, conv, opts};
82+
static ASTLoweringDescriptor
83+
forWholeModule(ModuleDecl *mod, Lowering::TypeConverter &conv,
84+
const SILOptions &opts,
85+
Optional<SILRefsToEmit> refsToEmit = None) {
86+
return ASTLoweringDescriptor{mod, conv, opts, refsToEmit};
7687
}
7788

78-
/// For a single file input, returns a single element array containing that
79-
/// file. Otherwise returns an array of each file in the module.
80-
ArrayRef<FileUnit *> getFiles() const;
89+
/// Retrieves the files to generate SIL for. If the descriptor is configured
90+
/// only to emit a specific set of SILDeclRefs, this will be empty.
91+
ArrayRef<FileUnit *> getFilesToEmit() const;
8192

8293
/// If the module or file contains SIL that needs parsing, returns the file
8394
/// to be parsed, or \c nullptr if parsing isn't required.

include/swift/Basic/AnyValue.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ namespace llvm {
2929
hash_code hash_value(const llvm::PointerUnion<PT1, PT2> &ptr) {
3030
return hash_value(ptr.getOpaqueValue());
3131
}
32+
33+
// FIXME: Belongs in LLVM itself
34+
template<typename T>
35+
hash_code hash_value(const llvm::Optional<T> &opt) {
36+
if (!opt)
37+
return 1;
38+
return hash_value(*opt);
39+
}
3240
}
3341

3442
namespace swift {

include/swift/SIL/SILDeclRef.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,10 @@ struct SILDeclRef {
277277
SILLinkage getLinkage(ForDefinition_t forDefinition) const;
278278

279279
/// Return the hash code for the SIL declaration.
280-
llvm::hash_code getHashCode() const {
281-
return llvm::hash_combine(loc.getOpaqueValue(),
282-
static_cast<int>(kind),
283-
isForeign, defaultArgIndex);
280+
friend llvm::hash_code hash_value(const SILDeclRef &ref) {
281+
return llvm::hash_combine(ref.loc.getOpaqueValue(),
282+
static_cast<int>(ref.kind),
283+
ref.isForeign, ref.defaultArgIndex);
284284
}
285285

286286
bool operator==(SILDeclRef rhs) const {

lib/IRGen/GenDecl.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "swift/SIL/FormalLinkage.h"
3535
#include "swift/SIL/SILDebugScope.h"
3636
#include "swift/SIL/SILModule.h"
37+
#include "swift/Subsystems.h"
3738
#include "clang/AST/ASTContext.h"
3839
#include "clang/AST/DeclCXX.h"
3940
#include "clang/AST/GlobalDecl.h"
@@ -443,7 +444,10 @@ class PrettySynthesizedFileUnitEmission : public llvm::PrettyStackTraceEntry {
443444

444445
/// Emit all the top-level code in the source file.
445446
void IRGenModule::emitSourceFile(SourceFile &SF) {
446-
assert(SF.ASTStage == SourceFile::TypeChecked);
447+
// Type-check the file if we haven't already (this may be necessary for .sil
448+
// files, which don't get fully type-checked by parsing).
449+
performTypeChecking(SF);
450+
447451
PrettySourceFileEmission StackEntry(SF);
448452

449453
// Emit types and other global decls.

lib/IRGen/IRGen.cpp

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/ProtocolConformance.h"
2424
#include "swift/AST/SILGenRequests.h"
2525
#include "swift/AST/SILOptimizerRequests.h"
26+
#include "swift/AST/TBDGenRequests.h"
2627
#include "swift/Basic/Defer.h"
2728
#include "swift/Basic/Dwarf.h"
2829
#include "swift/Basic/Platform.h"
@@ -40,6 +41,7 @@
4041
#include "swift/SILOptimizer/PassManager/PassPipeline.h"
4142
#include "swift/SILOptimizer/PassManager/Passes.h"
4243
#include "swift/Subsystems.h"
44+
#include "swift/TBDGen/TBDGen.h"
4345
#include "../Serialization/ModuleFormat.h"
4446
#include "clang/Basic/TargetInfo.h"
4547
#include "clang/Frontend/CompilerInstance.h"
@@ -907,6 +909,52 @@ static void runIRGenPreparePasses(SILModule &Module,
907909
executePassPipelinePlan(&Module, plan, /*isMandatory*/ true, &IRModule);
908910
}
909911

912+
namespace {
913+
using IREntitiesToEmit = SmallVector<LinkEntity, 1>;
914+
915+
struct SymbolSourcesToEmit {
916+
SILRefsToEmit silRefsToEmit;
917+
IREntitiesToEmit irEntitiesToEmit;
918+
};
919+
920+
static Optional<SymbolSourcesToEmit>
921+
getSymbolSourcesToEmit(const IRGenDescriptor &desc) {
922+
if (!desc.SymbolsToEmit)
923+
return None;
924+
925+
assert(!desc.SILMod && "Already emitted SIL?");
926+
927+
// First retrieve the symbol source map to figure out what we need to build,
928+
// making sure to include non-public symbols.
929+
auto &ctx = desc.getParentModule()->getASTContext();
930+
auto tbdDesc = desc.getTBDGenDescriptor();
931+
tbdDesc.getOptions().PublicSymbolsOnly = false;
932+
auto symbolMap =
933+
llvm::cantFail(ctx.evaluator(SymbolSourceMapRequest{std::move(tbdDesc)}));
934+
935+
// Then split up the symbols so they can be emitted by the appropriate part
936+
// of the pipeline.
937+
SILRefsToEmit silRefsToEmit;
938+
IREntitiesToEmit irEntitiesToEmit;
939+
for (const auto &symbol : *desc.SymbolsToEmit) {
940+
auto source = symbolMap.find(symbol);
941+
assert(source && "Couldn't find symbol");
942+
switch (source->kind) {
943+
case SymbolSource::Kind::SIL:
944+
silRefsToEmit.push_back(source->getSILDeclRef());
945+
break;
946+
case SymbolSource::Kind::IR:
947+
irEntitiesToEmit.push_back(source->getIRLinkEntity());
948+
break;
949+
case SymbolSource::Kind::LinkerDirective:
950+
case SymbolSource::Kind::Unknown:
951+
llvm_unreachable("Not supported");
952+
}
953+
}
954+
return SymbolSourcesToEmit{silRefsToEmit, irEntitiesToEmit};
955+
}
956+
} // end of anonymous namespace
957+
910958
/// Generates LLVM IR, runs the LLVM passes and produces the output file.
911959
/// All this is done in a single thread.
912960
GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
@@ -917,20 +965,25 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
917965
auto &Ctx = M->getASTContext();
918966
assert(!Ctx.hadError());
919967

968+
auto symsToEmit = getSymbolSourcesToEmit(desc);
969+
assert(!symsToEmit || symsToEmit->irEntitiesToEmit.empty() &&
970+
"IR symbol emission not implemented yet");
971+
920972
// If we've been provided a SILModule, use it. Otherwise request the lowered
921973
// SIL for the file or module.
922974
auto SILMod = std::unique_ptr<SILModule>(desc.SILMod);
923975
if (!SILMod) {
924-
auto loweringDesc =
925-
ASTLoweringDescriptor{desc.Ctx, desc.Conv, desc.SILOpts};
976+
auto loweringDesc = ASTLoweringDescriptor{
977+
desc.Ctx, desc.Conv, desc.SILOpts,
978+
symsToEmit.map([](const auto &x) { return x.silRefsToEmit; })};
926979
SILMod = llvm::cantFail(Ctx.evaluator(LoweredSILRequest{loweringDesc}));
927980

928981
// If there was an error, bail.
929982
if (Ctx.hadError())
930983
return GeneratedModule::null();
931984
}
932985

933-
auto filesToEmit = desc.getFiles();
986+
auto filesToEmit = desc.getFilesToEmit();
934987
auto *primaryFile =
935988
dyn_cast_or_null<SourceFile>(desc.Ctx.dyn_cast<FileUnit *>());
936989

@@ -1334,7 +1387,8 @@ GeneratedModule swift::performIRGeneration(
13341387
const auto &SILOpts = SILModPtr->getOptions();
13351388
auto desc = IRGenDescriptor::forWholeModule(
13361389
M, Opts, TBDOpts, SILOpts, SILModPtr->Types, std::move(SILMod),
1337-
ModuleName, PSPs, parallelOutputFilenames, outModuleHash);
1390+
ModuleName, PSPs, /*symsToEmit*/ None, parallelOutputFilenames,
1391+
outModuleHash);
13381392

13391393
if (Opts.shouldPerformIRGenerationInParallel() &&
13401394
!parallelOutputFilenames.empty()) {
@@ -1358,7 +1412,8 @@ performIRGeneration(FileUnit *file, const IRGenOptions &Opts,
13581412
const auto &SILOpts = SILModPtr->getOptions();
13591413
auto desc = IRGenDescriptor::forFile(
13601414
file, Opts, TBDOpts, SILOpts, SILModPtr->Types, std::move(SILMod),
1361-
ModuleName, PSPs, PrivateDiscriminator, outModuleHash);
1415+
ModuleName, PSPs, PrivateDiscriminator, /*symsToEmit*/ None,
1416+
outModuleHash);
13621417
return llvm::cantFail(file->getASTContext().evaluator(IRGenRequest{desc}));
13631418
}
13641419

@@ -1447,12 +1502,6 @@ GeneratedModule OptimizedIRRequest::evaluate(Evaluator &evaluator,
14471502

14481503
bindExtensions(*parentMod);
14491504

1450-
// Type-check the files that need emitting.
1451-
for (auto *file : desc.getFiles()) {
1452-
if (auto *SF = dyn_cast<SourceFile>(file))
1453-
performTypeChecking(*SF);
1454-
}
1455-
14561505
if (ctx.hadError())
14571506
return GeneratedModule::null();
14581507

@@ -1464,3 +1513,23 @@ GeneratedModule OptimizedIRRequest::evaluate(Evaluator &evaluator,
14641513
irMod.getTargetMachine());
14651514
return irMod;
14661515
}
1516+
1517+
StringRef SymbolObjectCodeRequest::evaluate(Evaluator &evaluator,
1518+
IRGenDescriptor desc) const {
1519+
auto &ctx = desc.getParentModule()->getASTContext();
1520+
auto mod = cantFail(evaluator(OptimizedIRRequest{desc}));
1521+
auto *targetMachine = mod.getTargetMachine();
1522+
1523+
// Add the passes to emit the LLVM module as object code.
1524+
// TODO: Use compileAndWriteLLVM.
1525+
legacy::PassManager emitPasses;
1526+
emitPasses.add(createTargetTransformInfoWrapperPass(
1527+
targetMachine->getTargetIRAnalysis()));
1528+
1529+
SmallString<0> output;
1530+
raw_svector_ostream os(output);
1531+
targetMachine->addPassesToEmitFile(emitPasses, os, nullptr, CGFT_ObjectFile);
1532+
emitPasses.run(*mod.getModule());
1533+
os << '\0';
1534+
return ctx.AllocateCopy(output.str());
1535+
}

0 commit comments

Comments
 (0)