Skip to content

Commit 90d05c1

Browse files
committed
Lazily Associated a SILRemarkStreamer with an LLVMContext at IRGen time
Corrects a mistake introduced in #31106 I was under the impression that the LLVMContext for an instance of llvm::remarks::RemarkStreamer was somehow just scratch-space. It turns out the ASMPrinters don't gather remarks data from modules, they gather it from the remark streamer associated with the module's context. Thus, we cannot have the module's context be distinct from whatever context the streamer is eventually associated with. In order to bring these two systems back into harmony, introduce a simple ownership contract to SILRemarkStreamer. That is, it starts owned by a SILModule, in which case the SILRemarkStreamer holds onto the underlying LLVM object as the optimizer emits remarks. When it comes time to IRGen the module, then and only then do we install the streamer on the module's context. This tranfers ownership of the underlying LLVM streamer to LLVM itself, so it acts as a consuming operation. When we are about to perform IR Generation, the SILModule will be expiring anyways, so the streamer was already about to be destroyed. We're just putting it to better use doing its job.
1 parent 477af9f commit 90d05c1

File tree

5 files changed

+41
-16
lines changed

5 files changed

+41
-16
lines changed

include/swift/SIL/SILModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,9 @@ class SILModule {
523523
swift::SILRemarkStreamer *getSILRemarkStreamer() {
524524
return silRemarkStreamer.get();
525525
}
526+
std::unique_ptr<swift::SILRemarkStreamer> takeSILRemarkStreamer() {
527+
return std::move(silRemarkStreamer);
528+
}
526529
void installSILRemarkStreamer();
527530

528531
// This is currently limited to VarDecl because the visibility of global

include/swift/SIL/SILRemarkStreamer.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ namespace swift {
2626

2727
class SILRemarkStreamer {
2828
private:
29-
/// The \c LLVMContext the underlying streamer uses for scratch space.
30-
std::unique_ptr<llvm::LLVMContext> streamerContext;
29+
/// The underlying LLVM streamer.
30+
///
31+
/// If owned by a SILModule, this will be non-null.
32+
std::unique_ptr<llvm::remarks::RemarkStreamer> streamer;
33+
3134
/// The remark output stream used to record SIL remarks to a file.
3235
std::unique_ptr<llvm::raw_fd_ostream> remarkStream;
3336

@@ -53,6 +56,12 @@ class SILRemarkStreamer {
5356

5457
const ASTContext &getASTContext() const { return ctx; }
5558

59+
public:
60+
/// Perform a one-time ownership transfer to associate the underlying
61+
/// \c llvm::remarks::RemarkStreamer with the given \c LLVMContext.
62+
void intoLLVMContext(llvm::LLVMContext &Ctx) &;
63+
64+
public:
5665
/// Emit a remark through the streamer.
5766
template <typename RemarkT>
5867
void emit(const OptRemark::Remark<RemarkT> &remark);

lib/IRGen/IRGen.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "swift/LLVMPasses/Passes.h"
3535
#include "swift/LLVMPasses/PassesFwd.h"
3636
#include "swift/SIL/SILModule.h"
37+
#include "swift/SIL/SILRemarkStreamer.h"
3738
#include "swift/SILOptimizer/PassManager/PassManager.h"
3839
#include "swift/SILOptimizer/PassManager/PassPipeline.h"
3940
#include "swift/SILOptimizer/PassManager/Passes.h"
@@ -884,7 +885,7 @@ static void embedBitcode(llvm::Module *M, const IRGenOptions &Opts)
884885
NewUsed->setSection("llvm.metadata");
885886
}
886887

887-
static void initLLVMModule(const IRGenModule &IGM, ModuleDecl &M) {
888+
static void initLLVMModule(const IRGenModule &IGM, SILModule &SIL) {
888889
auto *Module = IGM.getModule();
889890
assert(Module && "Expected llvm:Module for IR generation!");
890891

@@ -902,12 +903,17 @@ static void initLLVMModule(const IRGenModule &IGM, ModuleDecl &M) {
902903

903904
auto *MDNode = IGM.getModule()->getOrInsertNamedMetadata("swift.module.flags");
904905
auto &Context = IGM.getModule()->getContext();
905-
auto *Value = M.isStdlibModule() ? llvm::ConstantInt::getTrue(Context)
906-
: llvm::ConstantInt::getFalse(Context);
906+
auto *Value = SIL.getSwiftModule()->isStdlibModule()
907+
? llvm::ConstantInt::getTrue(Context)
908+
: llvm::ConstantInt::getFalse(Context);
907909
MDNode->addOperand(llvm::MDTuple::get(Context,
908910
{llvm::MDString::get(Context,
909911
"standard-library"),
910912
llvm::ConstantAsMetadata::get(Value)}));
913+
914+
if (auto streamer = SIL.takeSILRemarkStreamer()) {
915+
std::move(streamer)->intoLLVMContext(Module->getContext());
916+
}
911917
}
912918

913919
std::pair<IRGenerator *, IRGenModule *>
@@ -926,7 +932,7 @@ swift::irgen::createIRGenModule(SILModule *SILMod, StringRef OutputFilename,
926932
*irgen, std::move(targetMachine), nullptr, "", OutputFilename,
927933
MainInputFilenameForDebugInfo, PrivateDiscriminator);
928934

929-
initLLVMModule(*IGM, *SILMod->getSwiftModule());
935+
initLLVMModule(*IGM, *SILMod);
930936

931937
return std::pair<IRGenerator *, IRGenModule *>(irgen, IGM);
932938
}
@@ -969,7 +975,7 @@ performIRGeneration(const IRGenOptions &Opts, ModuleDecl *M,
969975
PSPs.OutputFilename, PSPs.MainInputFilenameForDebugInfo,
970976
PrivateDiscriminator);
971977

972-
initLLVMModule(IGM, *SILMod->getSwiftModule());
978+
initLLVMModule(IGM, *SILMod);
973979

974980
// Run SIL level IRGen preparation passes.
975981
runIRGenPreparePasses(*SILMod, IGM);
@@ -1217,7 +1223,7 @@ static void performParallelIRGeneration(
12171223
nextSF->getPrivateDiscriminator().str());
12181224
IGMcreated = true;
12191225

1220-
initLLVMModule(*IGM, *SILMod->getSwiftModule());
1226+
initLLVMModule(*IGM, *SILMod);
12211227
if (!DidRunSILCodeGenPreparePasses) {
12221228
// Run SIL level IRGen preparation passes on the module the first time
12231229
// around.
@@ -1431,7 +1437,7 @@ swift::createSwiftModuleObjectFile(SILModule &SILMod, StringRef Buffer,
14311437

14321438
IRGenModule IGM(irgen, std::move(targetMachine), nullptr,
14331439
OutputPath, OutputPath, "", "");
1434-
initLLVMModule(IGM, *SILMod.getSwiftModule());
1440+
initLLVMModule(IGM, SILMod);
14351441
auto *Ty = llvm::ArrayType::get(IGM.Int8Ty, Buffer.size());
14361442
auto *Data =
14371443
llvm::ConstantDataArray::getString(IGM.getLLVMContext(),

lib/SIL/Utils/SILRemarkStreamer.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,20 @@ using namespace swift;
1919
SILRemarkStreamer::SILRemarkStreamer(
2020
std::unique_ptr<llvm::remarks::RemarkStreamer> &&streamer,
2121
std::unique_ptr<llvm::raw_fd_ostream> &&stream, const ASTContext &Ctx)
22-
: streamerContext(std::make_unique<llvm::LLVMContext>()),
23-
remarkStream(std::move(stream)), ctx(Ctx) {
24-
streamerContext->setMainRemarkStreamer(std::move(streamer));
25-
}
22+
: streamer(std::move(streamer)),
23+
remarkStream(std::move(stream)), ctx(Ctx) { }
2624

2725
llvm::remarks::RemarkStreamer &SILRemarkStreamer::getLLVMStreamer() {
28-
return *streamerContext->getMainRemarkStreamer();
26+
return *streamer.get();
2927
}
3028

3129
const llvm::remarks::RemarkStreamer &
3230
SILRemarkStreamer::getLLVMStreamer() const {
33-
return *streamerContext->getMainRemarkStreamer();
31+
return *streamer.get();
32+
}
33+
34+
void SILRemarkStreamer::intoLLVMContext(llvm::LLVMContext &Ctx) & {
35+
Ctx.setMainRemarkStreamer(std::move(streamer));
3436
}
3537

3638
std::unique_ptr<SILRemarkStreamer>

test/Driver/opt-record-bitstream.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swiftc_driver -O -wmo -save-optimization-record=bitstream %s -module-name optrecordmod -o %t/opt-record 2>&1 | %FileCheck -allow-empty %s
2+
// RUN: %target-swift-frontend -c -O -wmo -save-optimization-record=bitstream -save-optimization-record-path %t/optrecordmod.opt.bitstream %s -module-name optrecordmod -o %t/opt-record.o 2>&1 | %FileCheck -allow-empty %s
33
// RUN: llvm-bcanalyzer -dump %t/optrecordmod.opt.bitstream | %FileCheck -check-prefix=BITSTREAM %s
4+
// RUN: otool -l %t/opt-record.o | %FileCheck -check-prefix=OBJ %s
45

56
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos
67

8+
// Ensure we emitted the appropriate section
9+
10+
// OBJ: sectname __remarks
11+
712
// CHECK-NOT: remark
813

914
var a: Int = 1

0 commit comments

Comments
 (0)