Skip to content

Commit 5321a7c

Browse files
committed
SIL: Only enable instruction leaks checking in the frontend's and SILOpt's modules.
Leaks checking is not thread safe and e.g. lldb creates multiple SILModules in multiple threads, which would result in false alarms. Ideally we would make it thread safe, e.g. by putting the instruction counters in the SILModule, but this would be a big effort and it's not worth doing it. Leaks checking in the frontend's and SILOpt's SILModule (not including SILModules created for module interface building) is a good enough test. rdar://84688015
1 parent 2ad0eb7 commit 5321a7c

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)