diff --git a/include/llvm/LLVMContext.h b/include/llvm/LLVMContext.h index 7cb6579aef6..76492b7102e 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/LLVMContext.h @@ -20,6 +20,7 @@ namespace llvm { class LLVMContextImpl; class StringRef; class Instruction; +class Module; template class SmallVectorImpl; /// This is an important class for using LLVM in a threaded context. It @@ -37,6 +38,13 @@ public: LLVMContext(); ~LLVMContext(); + /// addModule - Register a module as being instantiated in this context. If + /// the context is deleted, the module will be deleted as well. + void addModule(Module*); + + /// removeModule - Unregister a module from this context. + void removeModule(Module*); + // Pinned metadata names, which always have the same value. This is a // compile-time performance optimization, not a correctness optimization. enum { diff --git a/lib/VMCore/LLVMContext.cpp b/lib/VMCore/LLVMContext.cpp index 563c651315a..60fb830e9b5 100644 --- a/lib/VMCore/LLVMContext.cpp +++ b/lib/VMCore/LLVMContext.cpp @@ -34,6 +34,14 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { } LLVMContext::~LLVMContext() { delete pImpl; } +void LLVMContext::addModule(Module *M) { + pImpl->OwnedModules.insert(M); +} + +void LLVMContext::removeModule(Module *M) { + pImpl->OwnedModules.erase(M); +} + //===----------------------------------------------------------------------===// // Recoverable Backend Errors //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index 93a075f0fcc..610c5027c34 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "LLVMContextImpl.h" +#include "llvm/Module.h" #include using namespace llvm; @@ -51,6 +52,15 @@ struct DropReferences { } LLVMContextImpl::~LLVMContextImpl() { + // NOTE: We need to delete the contents of OwnedModules, but we have to + // duplicate it into a temporary vector, because the destructor of Module + // will try to remove itself from OwnedModules set. This would cause + // iterator invalidation if we iterated on the set directly. + std::vector Modules(OwnedModules.begin(), OwnedModules.end()); + for (std::vector::iterator I = Modules.begin(), E = Modules.end(); + I != E; ++I) + delete *I; + std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(), DropReferences()); std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(), diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index 51b2992898c..6df804ab084 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -115,6 +115,10 @@ public: class LLVMContextImpl { public: + /// OwnedModules - The set of modules instantiated in this context, and which + /// will be automatically deleted if this context is deleted. + SmallPtrSet OwnedModules; + void *InlineAsmDiagHandler, *InlineAsmDiagContext; typedef DenseMap(); + Context.addModule(this); } Module::~Module() { + Context.removeModule(this); dropAllReferences(); GlobalList.clear(); FunctionList.clear();