Skip to content

Commit af2b72e

Browse files
authored
Merge pull request #39980 from eeckstein/fix-silmodule-leak-detection
SIL: Only enable instruction leaks checking in the frontend's and SILOpt's modules.
2 parents 0a04cce + 5321a7c commit af2b72e

File tree

8 files changed

+38
-3
lines changed

8 files changed

+38
-3
lines changed

include/swift/AST/SILOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ class SILOptions {
198198
/// Are we parsing the stdlib, i.e. -parse-stdlib?
199199
bool ParseStdlib = false;
200200

201+
/// If true, check for leaking instructions when the SILModule is destructed.
202+
///
203+
/// Warning: this is not thread safe. It can only be enabled in case there
204+
/// is a single SILModule in a single thread.
205+
bool checkSILModuleLeaks = false;
206+
201207
/// The name of the file to which the backend should save optimization
202208
/// records.
203209
std::string OptRecordFile;

include/swift/SIL/SILInstruction.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,9 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
349349
void setDebugScope(const SILDebugScope *DS);
350350

351351
/// Total number of created and deleted SILInstructions.
352-
/// It is used only for collecting the compiler statistics.
352+
///
353+
/// Ideally, those counters would be inside SILModules to allow mutiple
354+
/// SILModules (e.g. in different threads).
353355
static int NumCreatedInstructions;
354356
static int NumDeletedInstructions;
355357

@@ -759,6 +761,11 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
759761
static int getNumDeletedInstructions() {
760762
return NumDeletedInstructions;
761763
}
764+
765+
static void resetInstructionCounts() {
766+
NumCreatedInstructions = 0;
767+
NumDeletedInstructions = 0;
768+
}
762769

763770
/// Pretty-print the value.
764771
void dump() const;

lib/FrontendTool/FrontendTool.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,6 +2065,10 @@ int swift::performFrontend(ArrayRef<const char *> Args,
20652065
FrontendOptions::ActionType::Immediate) {
20662066
llvm::setBugReportMsg(nullptr);
20672067
}
2068+
2069+
/// Enable leaks checking because this SILModule is the only one in the process
2070+
/// (leaks checking is not thread safe).
2071+
Invocation.getSILOptions().checkSILModuleLeaks = true;
20682072

20692073
PrettyStackTraceFrontend frontendTrace(Invocation.getLangOptions());
20702074

lib/IRGen/IRGen.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,8 +1145,10 @@ GeneratedModule IRGenRequest::evaluate(Evaluator &evaluator,
11451145
// Free the memory occupied by the SILModule.
11461146
// Execute this task in parallel to the embedding of bitcode.
11471147
auto SILModuleRelease = [&SILMod]() {
1148+
bool checkForLeaks = SILMod->getOptions().checkSILModuleLeaks;
11481149
SILMod.reset(nullptr);
1149-
SILModule::checkForLeaksAfterDestruction();
1150+
if (checkForLeaks)
1151+
SILModule::checkForLeaksAfterDestruction();
11501152
};
11511153
auto Thread = std::thread(SILModuleRelease);
11521154
// Wait for the thread to terminate.
@@ -1447,8 +1449,10 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
14471449
// Free the memory occupied by the SILModule.
14481450
// Execute this task in parallel to the LLVM compilation.
14491451
auto SILModuleRelease = [&SILMod]() {
1452+
bool checkForLeaks = SILMod->getOptions().checkSILModuleLeaks;
14501453
SILMod.reset(nullptr);
1451-
SILModule::checkForLeaksAfterDestruction();
1454+
if (checkForLeaks)
1455+
SILModule::checkForLeaksAfterDestruction();
14521456
};
14531457
auto releaseModuleThread = std::thread(SILModuleRelease);
14541458

lib/SIL/IR/SILModule.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ SILModule::~SILModule() {
151151
}
152152

153153
void SILModule::checkForLeaks() const {
154+
155+
/// Leak checking is not thread safe, because the instruction counters are
156+
/// global non-atomic variables. Leak checking can only be done in case there
157+
/// is a single SILModule in a single thread.
158+
if (!getOptions().checkSILModuleLeaks)
159+
return;
160+
154161
int instsInModule = std::distance(scheduledForDeletion.begin(),
155162
scheduledForDeletion.end());
156163
for (const SILFunction &F : *this) {

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ ParseSILModuleRequest::evaluate(Evaluator &evaluator,
7474
auto bufferID = SF->getBufferID();
7575
assert(bufferID);
7676

77+
// For leak detection.
78+
SILInstruction::resetInstructionCounts();
79+
7780
auto silMod = SILModule::createEmptyModule(desc.context, desc.conv,
7881
desc.opts);
7982
SILParserState parserState(*silMod.get());

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,6 +2149,9 @@ ASTLoweringRequest::evaluate(Evaluator &evaluator,
21492149
return llvm::cantFail(evaluator(ParseSILModuleRequest{desc}));
21502150
}
21512151

2152+
// For leak detection.
2153+
SILInstruction::resetInstructionCounts();
2154+
21522155
auto silMod = SILModule::createEmptyModule(desc.context, desc.conv,
21532156
desc.opts);
21542157

tools/sil-opt/SILOpt.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ int main(int argc, char **argv) {
483483
SILOpts.VerifySILOwnership = !DisableSILOwnershipVerifier;
484484
SILOpts.OptRecordFile = RemarksFilename;
485485
SILOpts.OptRecordPasses = RemarksPasses;
486+
SILOpts.checkSILModuleLeaks = true;
486487

487488
SILOpts.VerifyExclusivity = VerifyExclusivity;
488489
if (EnforceExclusivity.getNumOccurrences() != 0) {

0 commit comments

Comments
 (0)