[PATCH] unique_ptrify llvm::getLazyBitcodeModule's MemoryBuffer parameter
David Blaikie
dblaikie at gmail.com
Tue Aug 12 15:50:19 PDT 2014
On Tue, Aug 12, 2014 at 3:41 PM, Duncan P. N. Exon Smith
<dexonsmith at apple.com> wrote:
>
>> 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.
Yeah, you might be right - all I'm doing here is making that "lie" a
bit more obvious (well, pushing it up to the point where the lying
starts). If there's a nice way not to lie, I'm all for that.
> I think using shallow MemoryBuffer is a reasonable approach.
Yep - this leans on MemoryBuffer's "not always owning" mechanics which
is something Lang & I have talked about killing off at some point (I
think trending in favor of "not owning" but I forget - or at least
trying to make as many uses as possible explicitly non-owning,
perhaps) so that might not be a viable long term solution. But maybe
it is - I'm not sure how hazy the future of MemoryBuffer is. In any
case, multiple layers of optional ownership don't exactly make me
happy.
Even one layer of optional ownership makes me a bit sad, though maybe
it's the right tool.
> 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...)
Maybe that's what it'll come to - I really dislike optional ownership,
but if used judiciously it might be a tool we need in our toolkit.
This certainly isn't the only place where this API conundrum has come
up.
- David
More information about the llvm-commits
mailing list