Skip to content

Commit 088a86e

Browse files
committed
Introduce SymbolObjectCodeRequest
Add SymbolObjectCodeRequest, which emits object code for a specific set of symbols by querying TBDGen for the source of the symbols, and asking SILGen (and eventually IRGen) to emit them.
1 parent cb09945 commit 088a86e

File tree

4 files changed

+132
-14
lines changed

4 files changed

+132
-14
lines changed

include/swift/AST/IRGenRequests.h

Lines changed: 36 additions & 5 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.
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.
202210
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)

lib/IRGen/IRGen.cpp

Lines changed: 79 additions & 4 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,12 +965,17 @@ 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.
@@ -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

@@ -1458,3 +1513,23 @@ GeneratedModule OptimizedIRRequest::evaluate(Evaluator &evaluator,
14581513
irMod.getTargetMachine());
14591514
return irMod;
14601515
}
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+
}

lib/IRGen/IRGenRequests.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ SourceLoc swift::extractNearestSourceLoc(const IRGenDescriptor &desc) {
5353
}
5454

5555
TinyPtrVector<FileUnit *> IRGenDescriptor::getFilesToEmit() const {
56+
// If we've been asked to emit a specific set of symbols, we don't emit any
57+
// whole files.
58+
if (SymbolsToEmit)
59+
return {};
60+
5661
// For a whole module, we emit IR for all files.
5762
if (auto *mod = Ctx.dyn_cast<ModuleDecl *>())
5863
return TinyPtrVector<FileUnit *>(mod->getFiles());
@@ -76,17 +81,21 @@ ModuleDecl *IRGenDescriptor::getParentModule() const {
7681
return Ctx.get<ModuleDecl *>();
7782
}
7883

79-
std::vector<std::string> IRGenDescriptor::getLinkerDirectives() const {
80-
auto opts = TBDOpts;
81-
opts.LinkerDirectivesOnly = true;
84+
TBDGenDescriptor IRGenDescriptor::getTBDGenDescriptor() const {
8285
if (auto *file = Ctx.dyn_cast<FileUnit *>()) {
83-
return getPublicSymbols(TBDGenDescriptor::forFile(file, opts));
86+
return TBDGenDescriptor::forFile(file, TBDOpts);
8487
} else {
8588
auto *M = Ctx.get<ModuleDecl *>();
86-
return getPublicSymbols(TBDGenDescriptor::forModule(M, opts));
89+
return TBDGenDescriptor::forModule(M, TBDOpts);
8790
}
8891
}
8992

93+
std::vector<std::string> IRGenDescriptor::getLinkerDirectives() const {
94+
auto desc = getTBDGenDescriptor();
95+
desc.getOptions().LinkerDirectivesOnly = true;
96+
return getPublicSymbols(std::move(desc));
97+
}
98+
9099
evaluator::DependencySource IRGenRequest::readDependencySource(
91100
const evaluator::DependencyRecorder &e) const {
92101
auto &desc = std::get<0>(getStorage());

0 commit comments

Comments
 (0)