Skip to content

Commit ab2300b

Browse files
EliaGerettojoker-eph
authored andcommitted
[PassManagerBuilder] Remove global extension when a plugin is unloaded
This commit fixes PR39321. GlobalExtensions is not guaranteed to be destroyed when optimizer plugins are unloaded. If it is indeed destroyed after a plugin is dlclose-d, the destructor of the corresponding ExtensionFn is not mapped anymore, causing a call to unmapped memory during destruction. This commit guarantees that extensions coming from external plugins are removed from GlobalExtensions when the plugin is unloaded if GlobalExtensions has not been destroyed yet. Differential Revision: https://reviews.llvm.org/D71959
1 parent 87d98c1 commit ab2300b

File tree

2 files changed

+58
-11
lines changed

2 files changed

+58
-11
lines changed

llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ class PassManagerBuilder {
6262
typedef std::function<void(const PassManagerBuilder &Builder,
6363
legacy::PassManagerBase &PM)>
6464
ExtensionFn;
65+
typedef int GlobalExtensionID;
66+
6567
enum ExtensionPointTy {
6668
/// EP_EarlyAsPossible - This extension point allows adding passes before
6769
/// any other transformations, allowing them to see the code as it is coming
@@ -193,7 +195,17 @@ class PassManagerBuilder {
193195
/// Adds an extension that will be used by all PassManagerBuilder instances.
194196
/// This is intended to be used by plugins, to register a set of
195197
/// optimisations to run automatically.
196-
static void addGlobalExtension(ExtensionPointTy Ty, ExtensionFn Fn);
198+
///
199+
/// \returns A global extension identifier that can be used to remove the
200+
/// extension.
201+
static GlobalExtensionID addGlobalExtension(ExtensionPointTy Ty,
202+
ExtensionFn Fn);
203+
/// Removes an extension that was previously added using addGlobalExtension.
204+
/// This is also intended to be used by plugins, to remove any extension that
205+
/// was previously registered before being unloaded.
206+
///
207+
/// \param ExtensionID Identifier of the extension to be removed.
208+
static void removeGlobalExtension(GlobalExtensionID ExtensionID);
197209
void addExtension(ExtensionPointTy Ty, ExtensionFn Fn);
198210

199211
private:
@@ -222,10 +234,20 @@ class PassManagerBuilder {
222234
/// used by optimizer plugins to allow all front ends to transparently use
223235
/// them. Create a static instance of this class in your plugin, providing a
224236
/// private function that the PassManagerBuilder can use to add your passes.
225-
struct RegisterStandardPasses {
237+
class RegisterStandardPasses {
238+
PassManagerBuilder::GlobalExtensionID ExtensionID;
239+
240+
public:
226241
RegisterStandardPasses(PassManagerBuilder::ExtensionPointTy Ty,
227242
PassManagerBuilder::ExtensionFn Fn) {
228-
PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn));
243+
ExtensionID = PassManagerBuilder::addGlobalExtension(Ty, std::move(Fn));
244+
}
245+
246+
~RegisterStandardPasses() {
247+
// If the collection holding the global extensions is destroyed after the
248+
// plugin is unloaded, the extension has to be removed here. Indeed, the
249+
// destructor of the ExtensionFn may reference code in the plugin.
250+
PassManagerBuilder::removeGlobalExtension(ExtensionID);
229251
}
230252
};
231253

llvm/lib/Transforms/IPO/PassManagerBuilder.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
1515
#include "llvm-c/Transforms/PassManagerBuilder.h"
16+
#include "llvm/ADT/STLExtras.h"
1617
#include "llvm/ADT/SmallVector.h"
1718
#include "llvm/Analysis/BasicAliasAnalysis.h"
1819
#include "llvm/Analysis/CFLAndersAliasAnalysis.h"
@@ -187,8 +188,13 @@ PassManagerBuilder::~PassManagerBuilder() {
187188
}
188189

189190
/// Set of global extensions, automatically added as part of the standard set.
190-
static ManagedStatic<SmallVector<std::pair<PassManagerBuilder::ExtensionPointTy,
191-
PassManagerBuilder::ExtensionFn>, 8> > GlobalExtensions;
191+
static ManagedStatic<
192+
SmallVector<std::tuple<PassManagerBuilder::ExtensionPointTy,
193+
PassManagerBuilder::ExtensionFn,
194+
PassManagerBuilder::GlobalExtensionID>,
195+
8>>
196+
GlobalExtensions;
197+
static PassManagerBuilder::GlobalExtensionID GlobalExtensionsCounter;
192198

193199
/// Check if GlobalExtensions is constructed and not empty.
194200
/// Since GlobalExtensions is a managed static, calling 'empty()' will trigger
@@ -197,10 +203,29 @@ static bool GlobalExtensionsNotEmpty() {
197203
return GlobalExtensions.isConstructed() && !GlobalExtensions->empty();
198204
}
199205

200-
void PassManagerBuilder::addGlobalExtension(
201-
PassManagerBuilder::ExtensionPointTy Ty,
202-
PassManagerBuilder::ExtensionFn Fn) {
203-
GlobalExtensions->push_back(std::make_pair(Ty, std::move(Fn)));
206+
PassManagerBuilder::GlobalExtensionID
207+
PassManagerBuilder::addGlobalExtension(PassManagerBuilder::ExtensionPointTy Ty,
208+
PassManagerBuilder::ExtensionFn Fn) {
209+
auto ExtensionID = GlobalExtensionsCounter++;
210+
GlobalExtensions->push_back(std::make_tuple(Ty, std::move(Fn), ExtensionID));
211+
return ExtensionID;
212+
}
213+
214+
void PassManagerBuilder::removeGlobalExtension(
215+
PassManagerBuilder::GlobalExtensionID ExtensionID) {
216+
// RegisterStandardPasses may try to call this function after GlobalExtensions
217+
// has already been destroyed; doing so should not generate an error.
218+
if (!GlobalExtensions.isConstructed())
219+
return;
220+
221+
auto GlobalExtension =
222+
llvm::find_if(*GlobalExtensions, [ExtensionID](const auto &elem) {
223+
return std::get<2>(elem) == ExtensionID;
224+
});
225+
assert(GlobalExtension != GlobalExtensions->end() &&
226+
"The extension ID to be removed should always be valid.");
227+
228+
GlobalExtensions->erase(GlobalExtension);
204229
}
205230

206231
void PassManagerBuilder::addExtension(ExtensionPointTy Ty, ExtensionFn Fn) {
@@ -211,8 +236,8 @@ void PassManagerBuilder::addExtensionsToPM(ExtensionPointTy ETy,
211236
legacy::PassManagerBase &PM) const {
212237
if (GlobalExtensionsNotEmpty()) {
213238
for (auto &Ext : *GlobalExtensions) {
214-
if (Ext.first == ETy)
215-
Ext.second(*this, PM);
239+
if (std::get<0>(Ext) == ETy)
240+
std::get<1>(Ext)(*this, PM);
216241
}
217242
}
218243
for (unsigned i = 0, e = Extensions.size(); i != e; ++i)

0 commit comments

Comments
 (0)