Skip to content

Commit 85fdc7a

Browse files
authored
Merge pull request swiftlang#31080 from CodaFi/why-I-R-ta
Give IRGenModule Ownership of its LLVMContext
2 parents dcf119b + 03b19f3 commit 85fdc7a

32 files changed

+348
-217
lines changed

include/swift/AST/IRGenRequests.h

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,87 @@ namespace llvm {
3838
class GlobalVariable;
3939
class LLVMContext;
4040
class Module;
41+
42+
namespace orc {
43+
class ThreadSafeModule;
44+
}; // namespace orc
45+
4146
}; // namespace llvm
4247

4348
namespace swift {
4449

50+
/// A pair consisting of an \c LLVMContext and an \c llvm::Module that enforces
51+
/// exclusive ownership of those resources, and ensures that they are
52+
/// deallocated or transferred together.
53+
///
54+
/// Note that the underlying module and context are either both valid pointers
55+
/// or both null. This class forbids the remaining cases by construction.
56+
class GeneratedModule final {
57+
private:
58+
std::unique_ptr<llvm::LLVMContext> Context;
59+
std::unique_ptr<llvm::Module> Module;
60+
61+
GeneratedModule() : Context(nullptr), Module(nullptr) {}
62+
63+
GeneratedModule(GeneratedModule const &) = delete;
64+
GeneratedModule &operator=(GeneratedModule const &) = delete;
65+
66+
public:
67+
/// Construct a \c GeneratedModule that owns a given module and context.
68+
///
69+
/// The given pointers must not be null. If a null \c GeneratedModule is
70+
/// needed, use \c GeneratedModule::null() instead.
71+
explicit GeneratedModule(std::unique_ptr<llvm::LLVMContext> &&Context,
72+
std::unique_ptr<llvm::Module> &&Module)
73+
: Context(std::move(Context)), Module(std::move(Module)) {
74+
assert(getModule() && "Use GeneratedModule::null() instead");
75+
assert(getContext() && "Use GeneratedModule::null() instead");
76+
}
77+
78+
GeneratedModule(GeneratedModule &&) = default;
79+
GeneratedModule& operator=(GeneratedModule &&) = default;
80+
81+
public:
82+
/// Construct a \c GeneratedModule that does not own any resources.
83+
static GeneratedModule null() {
84+
return GeneratedModule{};
85+
}
86+
87+
public:
88+
explicit operator bool() const {
89+
return Module != nullptr && Context != nullptr;
90+
}
91+
92+
public:
93+
const llvm::Module *getModule() const { return Module.get(); }
94+
llvm::Module *getModule() { return Module.get(); }
95+
96+
const llvm::LLVMContext *getContext() const { return Context.get(); }
97+
llvm::LLVMContext *getContext() { return Context.get(); }
98+
99+
public:
100+
/// Release ownership of the context and module to the caller, consuming
101+
/// this value in the process.
102+
///
103+
/// The REPL is the only caller that needs this. New uses of this function
104+
/// should be avoided at all costs.
105+
std::pair<llvm::LLVMContext *, llvm::Module *> release() && {
106+
return { Context.release(), Module.release() };
107+
}
108+
109+
public:
110+
/// Transfers ownership of the underlying module and context to an
111+
/// ORC-compatible context.
112+
llvm::orc::ThreadSafeModule intoThreadSafeContext() &&;
113+
};
114+
45115
struct IRGenDescriptor {
46116
const IRGenOptions &Opts;
47117
llvm::PointerUnion<ModuleDecl *, SourceFile *> Ctx;
48118
SILModule *SILMod;
49119
StringRef ModuleName;
50120
const PrimarySpecificPaths &PSPs;
51121
StringRef PrivateDiscriminator;
52-
llvm::LLVMContext &LLVMContext;
53122
ArrayRef<std::string> parallelOutputFilenames;
54123
llvm::GlobalVariable **outModuleHash;
55124
llvm::StringSet<> *LinkerDirectives;
@@ -73,15 +142,14 @@ struct IRGenDescriptor {
73142
forFile(const IRGenOptions &Opts, SourceFile &SF,
74143
std::unique_ptr<SILModule> &&SILMod, StringRef ModuleName,
75144
const PrimarySpecificPaths &PSPs, StringRef PrivateDiscriminator,
76-
llvm::LLVMContext &LLVMContext, llvm::GlobalVariable **outModuleHash,
145+
llvm::GlobalVariable **outModuleHash,
77146
llvm::StringSet<> *LinkerDirectives) {
78147
return IRGenDescriptor{Opts,
79148
&SF,
80149
SILMod.release(),
81150
ModuleName,
82151
PSPs,
83152
PrivateDiscriminator,
84-
LLVMContext,
85153
{},
86154
outModuleHash,
87155
LinkerDirectives};
@@ -91,7 +159,6 @@ struct IRGenDescriptor {
91159
forWholeModule(const IRGenOptions &Opts, swift::ModuleDecl *M,
92160
std::unique_ptr<SILModule> &&SILMod, StringRef ModuleName,
93161
const PrimarySpecificPaths &PSPs,
94-
llvm::LLVMContext &LLVMContext,
95162
ArrayRef<std::string> parallelOutputFilenames,
96163
llvm::GlobalVariable **outModuleHash,
97164
llvm::StringSet<> *LinkerDirectives) {
@@ -101,7 +168,6 @@ struct IRGenDescriptor {
101168
ModuleName,
102169
PSPs,
103170
"",
104-
LLVMContext,
105171
parallelOutputFilenames,
106172
outModuleHash,
107173
LinkerDirectives};
@@ -116,7 +182,7 @@ void reportEvaluatedRequest(UnifiedStatsReporter &stats,
116182

117183
class IRGenSourceFileRequest
118184
: public SimpleRequest<IRGenSourceFileRequest,
119-
std::unique_ptr<llvm::Module>(IRGenDescriptor),
185+
GeneratedModule(IRGenDescriptor),
120186
RequestFlags::Uncached|RequestFlags::DependencySource> {
121187
public:
122188
using SimpleRequest::SimpleRequest;
@@ -125,7 +191,7 @@ class IRGenSourceFileRequest
125191
friend SimpleRequest;
126192

127193
// Evaluation.
128-
std::unique_ptr<llvm::Module>
194+
GeneratedModule
129195
evaluate(Evaluator &evaluator, IRGenDescriptor desc) const;
130196

131197
public:
@@ -138,7 +204,7 @@ class IRGenSourceFileRequest
138204

139205
class IRGenWholeModuleRequest
140206
: public SimpleRequest<IRGenWholeModuleRequest,
141-
std::unique_ptr<llvm::Module>(IRGenDescriptor),
207+
GeneratedModule(IRGenDescriptor),
142208
RequestFlags::Uncached> {
143209
public:
144210
using SimpleRequest::SimpleRequest;
@@ -147,7 +213,7 @@ class IRGenWholeModuleRequest
147213
friend SimpleRequest;
148214

149215
// Evaluation.
150-
std::unique_ptr<llvm::Module>
216+
GeneratedModule
151217
evaluate(Evaluator &evaluator, IRGenDescriptor desc) const;
152218

153219
public:

include/swift/AST/IRGenTypeIDZone.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
SWIFT_REQUEST(IRGen, IRGenSourceFileRequest,
18-
std::unique_ptr<llvm::Module>(IRGenDescriptor),
18+
GeneratedModule(IRGenDescriptor),
1919
Uncached, NoLocationInfo)
2020
SWIFT_REQUEST(IRGen, IRGenWholeModuleRequest,
21-
std::unique_ptr<llvm::Module>(IRGenDescriptor),
21+
GeneratedModule(IRGenDescriptor),
2222
Uncached, NoLocationInfo)
2323

include/swift/IRGen/IRGenPublic.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ class IRGenModule;
3131
std::pair<IRGenerator *, IRGenModule *>
3232
createIRGenModule(SILModule *SILMod, StringRef OutputFilename,
3333
StringRef MainInputFilenameForDebugInfo,
34-
StringRef PrivateDiscriminator,
35-
llvm::LLVMContext &LLVMContext);
34+
StringRef PrivateDiscriminator);
3635

3736
/// Delete the IRGenModule and IRGenerator obtained by the above call.
3837
void deleteIRGenModule(std::pair<IRGenerator *, IRGenModule *> &Module);

include/swift/Subsystems.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace swift {
4848
class DiagnosticEngine;
4949
class Evaluator;
5050
class FileUnit;
51+
class GeneratedModule;
5152
class GenericEnvironment;
5253
class GenericParamList;
5354
class IRGenOptions;
@@ -230,24 +231,22 @@ namespace swift {
230231
/// Turn the given Swift module into either LLVM IR or native code
231232
/// and return the generated LLVM IR module.
232233
/// If you set an outModuleHash, then you need to call performLLVM.
233-
std::unique_ptr<llvm::Module>
234+
GeneratedModule
234235
performIRGeneration(const IRGenOptions &Opts, ModuleDecl *M,
235236
std::unique_ptr<SILModule> SILMod,
236237
StringRef ModuleName, const PrimarySpecificPaths &PSPs,
237-
llvm::LLVMContext &LLVMContext,
238238
ArrayRef<std::string> parallelOutputFilenames,
239239
llvm::GlobalVariable **outModuleHash = nullptr,
240240
llvm::StringSet<> *LinkerDirectives = nullptr);
241241

242242
/// Turn the given Swift module into either LLVM IR or native code
243243
/// and return the generated LLVM IR module.
244244
/// If you set an outModuleHash, then you need to call performLLVM.
245-
std::unique_ptr<llvm::Module>
245+
GeneratedModule
246246
performIRGeneration(const IRGenOptions &Opts, SourceFile &SF,
247247
std::unique_ptr<SILModule> SILMod,
248248
StringRef ModuleName, const PrimarySpecificPaths &PSPs,
249249
StringRef PrivateDiscriminator,
250-
llvm::LLVMContext &LLVMContext,
251250
llvm::GlobalVariable **outModuleHash = nullptr,
252251
llvm::StringSet<> *LinkerDirectives = nullptr);
253252

@@ -289,9 +288,7 @@ namespace swift {
289288
UnifiedStatsReporter *Stats);
290289

291290
/// Dump YAML describing all fixed-size types imported from the given module.
292-
bool performDumpTypeInfo(const IRGenOptions &Opts,
293-
SILModule &SILMod,
294-
llvm::LLVMContext &LLVMContext);
291+
bool performDumpTypeInfo(const IRGenOptions &Opts, SILModule &SILMod);
295292

296293
/// Creates a TargetMachine from the IRGen opts and AST Context.
297294
std::unique_ptr<llvm::TargetMachine>

lib/FrontendTool/FrontendTool.cpp

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/AST/FineGrainedDependencies.h"
3333
#include "swift/AST/GenericSignatureBuilder.h"
3434
#include "swift/AST/IRGenOptions.h"
35+
#include "swift/AST/IRGenRequests.h"
3536
#include "swift/AST/NameLookup.h"
3637
#include "swift/AST/ASTMangler.h"
3738
#include "swift/AST/ReferencedNameTracker.h"
@@ -1376,27 +1377,26 @@ static bool serializeSIB(SILModule *SM, const PrimarySpecificPaths &PSPs,
13761377
return Context.hadError();
13771378
}
13781379

1379-
static void generateIR(const IRGenOptions &IRGenOpts,
1380-
std::unique_ptr<SILModule> SM,
1381-
const PrimarySpecificPaths &PSPs,
1382-
StringRef OutputFilename, ModuleOrSourceFile MSF,
1383-
std::unique_ptr<llvm::Module> &IRModule,
1384-
llvm::GlobalVariable *&HashGlobal,
1385-
ArrayRef<std::string> parallelOutputFilenames,
1386-
llvm::StringSet<> &LinkerDirectives) {
1387-
// FIXME: We shouldn't need to use the global context here, but
1388-
// something is persisting across calls to performIRGeneration.
1389-
auto &LLVMContext = getGlobalLLVMContext();
1390-
IRModule = MSF.is<SourceFile *>()
1391-
? performIRGeneration(IRGenOpts, *MSF.get<SourceFile *>(),
1392-
std::move(SM), OutputFilename, PSPs,
1393-
MSF.get<SourceFile *>()->getPrivateDiscriminator().str(),
1394-
LLVMContext, &HashGlobal,
1395-
&LinkerDirectives)
1396-
: performIRGeneration(IRGenOpts, MSF.get<ModuleDecl *>(),
1397-
std::move(SM), OutputFilename, PSPs,
1398-
LLVMContext, parallelOutputFilenames,
1399-
&HashGlobal, &LinkerDirectives);
1380+
static GeneratedModule
1381+
generateIR(const IRGenOptions &IRGenOpts,
1382+
std::unique_ptr<SILModule> SM,
1383+
const PrimarySpecificPaths &PSPs,
1384+
StringRef OutputFilename, ModuleOrSourceFile MSF,
1385+
llvm::GlobalVariable *&HashGlobal,
1386+
ArrayRef<std::string> parallelOutputFilenames,
1387+
llvm::StringSet<> &LinkerDirectives) {
1388+
if (auto *SF = MSF.dyn_cast<SourceFile *>()) {
1389+
return performIRGeneration(IRGenOpts, *SF,
1390+
std::move(SM), OutputFilename, PSPs,
1391+
SF->getPrivateDiscriminator().str(),
1392+
&HashGlobal,
1393+
&LinkerDirectives);
1394+
} else {
1395+
return performIRGeneration(IRGenOpts, MSF.get<ModuleDecl *>(),
1396+
std::move(SM), OutputFilename, PSPs,
1397+
parallelOutputFilenames,
1398+
&HashGlobal, &LinkerDirectives);
1399+
}
14001400
}
14011401

14021402
static bool processCommandLineAndRunImmediately(const CompilerInvocation &Invocation,
@@ -1425,7 +1425,7 @@ static bool processCommandLineAndRunImmediately(const CompilerInvocation &Invoca
14251425
static bool validateTBDIfNeeded(const CompilerInvocation &Invocation,
14261426
ModuleOrSourceFile MSF,
14271427
bool astGuaranteedToCorrespondToSIL,
1428-
llvm::Module &IRModule) {
1428+
const llvm::Module &IRModule) {
14291429
if (!astGuaranteedToCorrespondToSIL ||
14301430
!inputFileKindCanHaveTBDValidated(Invocation.getInputKind()))
14311431
return false;
@@ -1663,7 +1663,7 @@ static bool performCompileStepsPostSILGen(
16631663
Stats->flushTracesAndProfiles();
16641664

16651665
if (Action == FrontendOptions::ActionType::DumpTypeInfo)
1666-
return performDumpTypeInfo(IRGenOpts, *SM, getGlobalLLVMContext());
1666+
return performDumpTypeInfo(IRGenOpts, *SM);
16671667

16681668
if (Action == FrontendOptions::ActionType::Immediate)
16691669
return processCommandLineAndRunImmediately(
@@ -1677,10 +1677,9 @@ static bool performCompileStepsPostSILGen(
16771677
StringRef OutputFilename = PSPs.OutputFilename;
16781678
std::vector<std::string> ParallelOutputFilenames =
16791679
Invocation.getFrontendOptions().InputsAndOutputs.copyOutputFilenames();
1680-
std::unique_ptr<llvm::Module> IRModule;
16811680
llvm::GlobalVariable *HashGlobal;
1682-
generateIR(
1683-
IRGenOpts, std::move(SM), PSPs, OutputFilename, MSF, IRModule, HashGlobal,
1681+
auto IRModule = generateIR(
1682+
IRGenOpts, std::move(SM), PSPs, OutputFilename, MSF, HashGlobal,
16841683
ParallelOutputFilenames, LinkerDirectives);
16851684

16861685
// Walk the AST for indexing after IR generation. Walking it before seems
@@ -1698,10 +1697,11 @@ static bool performCompileStepsPostSILGen(
16981697
return HadError;
16991698

17001699
if (validateTBDIfNeeded(Invocation, MSF, astGuaranteedToCorrespondToSIL,
1701-
*IRModule))
1700+
*IRModule.getModule()))
17021701
return true;
17031702

1704-
return generateCode(Invocation, Instance, OutputFilename, IRModule.get(),
1703+
return generateCode(Invocation, Instance, OutputFilename,
1704+
IRModule.getModule(),
17051705
HashGlobal) ||
17061706
HadError;
17071707
}

lib/FrontendTool/TBD.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ bool swift::inputFileKindCanHaveTBDValidated(InputFileKind kind) {
7575
}
7676

7777
static bool validateSymbolSet(DiagnosticEngine &diags,
78-
llvm::StringSet<> symbols, llvm::Module &IRModule,
78+
llvm::StringSet<> symbols,
79+
const llvm::Module &IRModule,
7980
bool diagnoseExtraSymbolsInTBD) {
8081
auto error = false;
8182

@@ -135,7 +136,8 @@ static bool validateSymbolSet(DiagnosticEngine &diags,
135136
return error;
136137
}
137138

138-
bool swift::validateTBD(ModuleDecl *M, llvm::Module &IRModule,
139+
bool swift::validateTBD(ModuleDecl *M,
140+
const llvm::Module &IRModule,
139141
const TBDGenOptions &opts,
140142
bool diagnoseExtraSymbolsInTBD) {
141143
llvm::StringSet<> symbols;
@@ -145,7 +147,8 @@ bool swift::validateTBD(ModuleDecl *M, llvm::Module &IRModule,
145147
diagnoseExtraSymbolsInTBD);
146148
}
147149

148-
bool swift::validateTBD(FileUnit *file, llvm::Module &IRModule,
150+
bool swift::validateTBD(FileUnit *file,
151+
const llvm::Module &IRModule,
149152
const TBDGenOptions &opts,
150153
bool diagnoseExtraSymbolsInTBD) {
151154
llvm::StringSet<> symbols;

lib/FrontendTool/TBD.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@ struct TBDGenOptions;
2828
bool writeTBD(ModuleDecl *M, StringRef OutputFilename,
2929
const TBDGenOptions &Opts);
3030
bool inputFileKindCanHaveTBDValidated(InputFileKind kind);
31-
bool validateTBD(ModuleDecl *M, llvm::Module &IRModule,
31+
bool validateTBD(ModuleDecl *M,
32+
const llvm::Module &IRModule,
3233
const TBDGenOptions &opts,
3334
bool diagnoseExtraSymbolsInTBD);
34-
bool validateTBD(FileUnit *M, llvm::Module &IRModule,
35+
bool validateTBD(FileUnit *M,
36+
const llvm::Module &IRModule,
3537
const TBDGenOptions &opts,
3638
bool diagnoseExtraSymbolsInTBD);
3739
}

lib/IRGen/GenArchetype.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ withOpaqueTypeGenericArgs(IRGenFunction &IGF,
435435
}
436436
types.push_back(args.back()->getType());
437437
});
438-
auto bufTy = llvm::StructType::get(IGF.IGM.LLVMContext, types);
438+
auto bufTy = llvm::StructType::get(IGF.IGM.getLLVMContext(), types);
439439
alloca = IGF.createAlloca(bufTy, IGF.IGM.getPointerAlignment());
440440
allocaSize = IGF.IGM.getPointerSize() * args.size();
441441
IGF.Builder.CreateLifetimeStart(alloca, allocaSize);

lib/IRGen/GenBuiltin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ if (Builtin.ID == BuiltinValueKind::id) { \
657657
// If the type is floating-point, then we need to bitcast to integer.
658658
auto valueTy = origValueTy;
659659
if (valueTy->isFloatingPointTy()) {
660-
valueTy = llvm::IntegerType::get(IGF.IGM.LLVMContext,
660+
valueTy = llvm::IntegerType::get(IGF.IGM.getLLVMContext(),
661661
valueTy->getPrimitiveSizeInBits());
662662
}
663663

0 commit comments

Comments
 (0)