Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -37,21 +37,6 @@ namespace lld { namespace elf { -template struct GAlloc { - static llvm::SpecificBumpPtrAllocator> IAlloc; - static llvm::SpecificBumpPtrAllocator> MAlloc; - static llvm::SpecificBumpPtrAllocator> EHAlloc; -}; - -template -llvm::SpecificBumpPtrAllocator> GAlloc::IAlloc; - -template -llvm::SpecificBumpPtrAllocator> GAlloc::MAlloc; - -template -llvm::SpecificBumpPtrAllocator> GAlloc::EHAlloc; - using llvm::object::Archive; class InputFile; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -387,7 +387,7 @@ // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. if (Config->Relocatable) - return new (GAlloc::IAlloc.Allocate()) + return new (alloc>()) InputSection(this, &Sec, Name); // Find the relocation target section and associate this @@ -430,14 +430,13 @@ // .eh_frame_hdr section for runtime. So we handle them with a special // class. For relocatable outputs, they are just passed through. if (Name == ".eh_frame" && !Config->Relocatable) - return new (GAlloc::EHAlloc.Allocate()) + return new (alloc>()) EhInputSection(this, &Sec, Name); if (shouldMerge(Sec)) - return new (GAlloc::MAlloc.Allocate()) + return new (alloc>()) MergeInputSection(this, &Sec, Name); - return new (GAlloc::IAlloc.Allocate()) - InputSection(this, &Sec, Name); + return new (alloc>()) InputSection(this, &Sec, Name); } template void elf::ObjectFile::initializeSymbols() { Index: ELF/Memory.h =================================================================== --- ELF/Memory.h +++ ELF/Memory.h @@ -24,12 +24,36 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/StringSaver.h" +#include namespace lld { namespace elf { + +// Use this arena if your object doesn't have a destructor. extern llvm::BumpPtrAllocator BAlloc; extern llvm::StringSaver Saver; +// These two classes are hack to keep track of all +// SpecificBumpPtrAllocator instances. +struct SpecificAllocBase { + SpecificAllocBase(); + virtual ~SpecificAllocBase() = default; + virtual void reset() = 0; + static std::vector Instances; +}; + +template struct SpecificAlloc : public SpecificAllocBase { + void reset() override { Alloc.DestroyAll(); } + llvm::SpecificBumpPtrAllocator Alloc; +}; + +// Use this arean if your object have a destructor. +// Your destructor will be invoked from freeArena(). +template static T *alloc() { + static SpecificAlloc Alloc; + return Alloc.Alloc.Allocate(); +} + void freeArena(); } } Index: ELF/Memory.cpp =================================================================== --- ELF/Memory.cpp +++ ELF/Memory.cpp @@ -9,7 +9,19 @@ #include "Memory.h" -llvm::BumpPtrAllocator lld::elf::BAlloc; -llvm::StringSaver lld::elf::Saver{BAlloc}; +using namespace llvm; +using namespace lld; +using namespace lld::elf; -void lld::elf::freeArena() { BAlloc.Reset(); } +BumpPtrAllocator elf::BAlloc; +StringSaver elf::Saver{BAlloc}; + +SpecificAllocBase::SpecificAllocBase() { Instances.push_back(this); } + +std::vector SpecificAllocBase::Instances; + +void elf::freeArena() { + for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances) + Alloc->reset(); + BAlloc.Reset(); +}