[PATCH] unique_ptrify llvm::getLazyBitcodeModule's MemoryBuffer parameter

Duncan P. N. Exon Smith dexonsmith at apple.com
Tue Aug 12 15:41:32 PDT 2014


> On 2014-Aug-12, at 14:51, David Blaikie <dblaikie at gmail.com> wrote:
> 
> Hi lhames, rafael,
> 
> This turned out to be a bit tricky as there are some callers doing
> strange things with ownership of the this MemoryBuffer.
> 
> A couple of callers (llvm::getBitcodeTargetTriple,
> llvm::parseBitcodeFile) don't take ownership of the MemoryBuffer, but
> still want to construct a Module (but they either ensure it's fully
> materialized, or otherwise destroy it before the function is over, being
> sure to take the MemoryBuffer back from the Module so it is not
> destroyed). Some of these callers were adjusted to use ScopeGuards to
> ensure the release of a fake local unique_ptr, others were able to be
> adjusted to pass ownership transiently, then take it back again later.
> 
> Other ideas are welcome - one possible option would be to create new
> shallow MemoryBuffers in these cases. Another would be to make these
> data structures consistently non-owning, though that sounds difficult
> for other users. I'd like to throw a few ideas around here because I
> think this pattern shows up a few times in LLVM - where an API has
> multiple users, some of whom want to give ownership, some of whom don't.
> I'd like to figure out a good/consistent/simple answer for when we come
> across this again.
> 
> http://reviews.llvm.org/D4876
> 
> Files:
>  include/llvm/ADT/ScopeGuard.h
>  include/llvm/Bitcode/ReaderWriter.h
>  include/llvm/IR/GVMaterializer.h
>  include/llvm/IR/Module.h
>  lib/Bitcode/Reader/BitReader.cpp
>  lib/Bitcode/Reader/BitcodeReader.cpp
>  lib/Bitcode/Reader/BitcodeReader.h
>  lib/IR/Module.cpp
>  lib/IRReader/IRReader.cpp
>  lib/LTO/LTOModule.cpp
>  lib/Object/IRObjectFile.cpp
>  unittests/Bitcode/BitReaderTest.cpp
>  unittests/ExecutionEngine/JIT/JITTest.cpp
> <D4876.12420.patch>_______________________________________________

I'm not sure this is the right direction -- in particular, I think using
`std::unique_ptr<>` in BitcodeReader is really confusing when it doesn't
actually own the buffer, and *that* problem should be solved first.

I think using shallow MemoryBuffer is a reasonable approach.

Another way to make `BitcodeReader::Buffer` easier to reason about is to
use a type something like this (name is terrible):

    enum class sometimes_unique_policy { Unowned, Owned };
    template <class T> class sometimes_unique_ptr {
      PointerIntPair<T *, 1> Ptr;
    public:
      sometimes_unique_ptr(T *Ptr, sometimes_unique_policy Policy)
          : Ptr(Ptr, Policy == sometimes_unique_policy::Owned) {}
      sometimes_unique_ptr(std::unique_ptr<T> Unique)
          : Ptr(Unique.release(), true) {}
      explicit sometimes_unique_ptr(T &Ref) : Ptr(&Ref, false) {}
      ~sometimes_unique_ptr() {
        if (isOwned())
          delete get();
      }
      bool isOwned() const { return Ptr.getInt(); }
      T *get() const { return Ptr.getPointer(); }
      // etc.
    };

`getLazyBitcodeModule()` can look like this:

    ErrorOr<Module *>
    getLazyBitcodeModule(sometimes_unique_ptr<MemoryBuffer> Buffer,
                         LLVMContext &Context);

If you pass it a reference, it releases it; if you pass it a unique_ptr<>,
it deletes it.

(I'm not familiar enough with ADT to know if we have a type like this
already...)





More information about the llvm-commits mailing list