This is an archive of the discontinued LLVM Phabricator instance.

[BinaryStream] Simplify the process of using BinaryStreams
AcceptedPublic

Authored by zturner on May 16 2017, 12:14 AM.

Details

Reviewers
rnk
amccarth
Summary

The goal here is cutting down on boilerplate required to use these classes.

Often you have an array and you just want to use it. With the current design, you have to first construct a BinaryByteStream, and then create a BinaryStreamRef from it. Worse, the BinaryStreamRef holds a pointer to the BinaryByteStream, so you can't just create a temporary one to appease the compiler, you have to actually hold onto both the ArrayRef as well as the BinaryByteStream *AND* the BinaryStreamReader on top of that. This makes for very cumbersome code, often requiring one to store a BinaryByteStream in a class just to circumvent this.

At the cost of some added complexity (not exposed to users, but internal to the library), we can do better than this. This patch allows us to construct BinaryStreamReaders and BinaryStreamWriters directly from source data (e.g. StringRef, MutableArrayRef<uint8_t>, etc). Not only does this reduce the amount of code you have to type and make it more obvious how to use it, but it solves real lifetime issues when it's inconvenient to hold onto a BinaryByteStream for a long time.

The additional complexity is in the form of an added layer of indirection. Whereas before we simply stored a BinaryStream* in the ref, we now store both a BinaryStream* and a std::shared_ptr<BinaryStream>. When the user wants to construct a BinaryStreamRef directly from an ArrayRef etc, we allocate an internal object that holds ownership over a BinaryByteStream and forwards all calls, and store this in the shared_ptr<>. This also maintains the ref semantics, as you can copy it by value and references refer to the same underlying stream -- the one being held in the object stored in the shared_ptr.

Diff Detail

Event Timeline

zturner created this revision.May 16 2017, 12:14 AM

+amccarth since he's used some of this stuff before too.

Also, in case it's not obvious, I included the changes to COFFDumper as an example of how it can simplify code (see especially the part where i no longer have to hold a copy of a BinaryStreamRef inside of a class.

The only real downside to this patch is that all instances of BinaryStreamRef become larger by sizeof(std::shared_ptr<T>), and we frequently pass them by value. But that seems somewhat minor.

rnk edited edge metadata.May 16 2017, 1:15 PM

This makes things shorter, but it does it by using templates to forward constructor arguments. Do we really want to do that? Is there some way we can simplify this code by removing some of the overlapping stream concepts instead?

llvm/lib/Support/BinaryStreamRef.cpp
19

Do we really need two refs? ArrayRef is already a pretty crappy name for a non-owning array. In general, can we have four word class names, max?

In D33229#756559, @rnk wrote:

This makes things shorter, but it does it by using templates to forward constructor arguments. Do we really want to do that? Is there some way we can simplify this code by removing some of the overlapping stream concepts instead?

I could get rid of the forwarding constructor by just providing a couple of explicit overloads.

zturner updated this revision to Diff 99225.May 16 2017, 4:49 PM

Deleted the forwarding constructors and made the private owning implementation names shorter.

rnk accepted this revision.May 17 2017, 12:39 PM

lgtm

This revision is now accepted and ready to land.May 17 2017, 12:39 PM