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"
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.
912960GeneratedModule 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