This is an archive of the discontinued LLVM Phabricator instance.

Enhance CodeView record deserialization with some template metaprogramming
ClosedPublic

Authored by zturner on May 11 2016, 3:13 PM.

Details

Summary

The general idea is to introduce a variadic template function which can deserialize arbitrary sequences of items from a byte stream. For example, if you write:

const Layout *L;
StringRef S;
uint64_t N;
consume(Data, L, S, N);

it will deserialize each of these in sequence, returning an error at any point if there is a problem.

There are a few cases where things get more complicated.

  1. Sometimes fields might only be present if a particular condition is true. For example, if a function is an introducing pure virtual function, then a VFTableOffset will be present, otherwise it won't. To handle this we introduce the notion of conditional fields, specified with the CONDITIONAL_FIELD macro.
  2. There might be a field which represents a number N of elements, and then an N element array might follow. To handle this we introduce the ARRAY_FIELD_N macro.
  3. There are occasions where what follows is an array whose length is not encoded, but which runs until the end of the buffer. To handle this we introduce the ARRAY_FIELD_TAIL macro.

These macros work by constructing a lambda function with the given conditional, so that it is evaluated lazily, meaning that if you write

const uint64_t Count;
ArrayRef<uint32_t> Items;
consume(Data, Count, ARRAY_FIELD_N(Items, Count));

it will work, because Count in the macro is not evaluated until it processes that item, at which point it has already been deserialized.

There are 2 remaining instances where I was not able to come up with a good solution that allows us to use this variadic template. One involves a nested "sub field" which must be deserialized, and another involves a complex nibble decoding algorithm.

In any case, this should handle 90% of cases, and greatly reduces the amount of boilerplate needed to deserialize records.

Diff Detail

Event Timeline

zturner updated this revision to Diff 56969.May 11 2016, 3:13 PM
zturner retitled this revision from to Enhance CodeView record deserialization with some template metaprogramming.
zturner updated this object.
zturner added reviewers: rnk, amccarth.
zturner added a subscriber: llvm-commits.
zturner updated this revision to Diff 56972.May 11 2016, 3:28 PM
rnk added inline comments.May 11 2016, 5:32 PM
include/llvm/DebugInfo/CodeView/RecordSerialization.h
55–59

Seems kind of awkward that uint64_t is a leaf numeric, but uint32_t is fixed length.

142

These macros have fairly generic names. We can prefix them with LLVM_, or we could hide them in TypeRecord.cpp along with all the deserialize method implementations.

zturner added inline comments.May 11 2016, 5:37 PM
include/llvm/DebugInfo/CodeView/RecordSerialization.h
55–59

Yea, I thought of this too, but I'm not sure what a good solution is. Could make another macro like LEAF_64_FIELD and use a similar pattern to the other ones to select a different overload.

142

Rather prefix with CV_ than LLVM_, since at least that indicates what they're used for.

zturner updated this revision to Diff 57064.May 12 2016, 10:00 AM

Fix review suggestions. Made it clear that uint64's use a different decoding algorithm, and added a CV_ prefix to the macros.

rnk accepted this revision.May 12 2016, 10:33 AM
rnk edited edge metadata.

lgtm

This revision is now accepted and ready to land.May 12 2016, 10:33 AM
Eugene.Zelenko added a subscriber: Eugene.Zelenko.

Committed in r269315.

lib/DebugInfo/CodeView/RecordSerialization.cpp