This is an archive of the discontinued LLVM Phabricator instance.

[lldb] Add an EnumFlags class for representing flags based on enums
Needs ReviewPublic

Authored by teemperor on Jan 6 2021, 6:07 AM.

Details

Reviewers
JDevlieghere
Summary

There are many instances of Flags variables in LLDB that are not really a set of bit flags,
but actually more a list of enumerators from one of LLDB's 'flags enums' (see the FLAGS_ENUM macro
for finding most of those).

The problem with using Flags for these enums is that it's impossible to know what the actual
enum is that is being used for giving the bits in Flags any meaning. Given that the variables
are essentially never documented and often just called something like m_flags, the only way to
find the right enum is to follow the code execution until you find a line where someone accesses
one of the bits via one of the enumerators.

These variables are also very often exposed directly via the SB API, so we can't just remove all of them
and replace them with struct+bitfields or something similar.

To make dealing with those variables less fragile, I would propose adding a EnumFlags template to
LLDB. The class mirrors the normal Flags API for the most part so that we don't have to rewrite
all the code that moves to the new class, but all methods are now typed with the specific enum that
is being used to give the bits meaning. This way it's clear from just looking at the variable type what
the right enum is. Also, we can now just type all the member functions so that they now reject enumerators
from other enums, so it's now impossible to even use the wrong enum without getting a compiler error.

I migrated the Flags variables that didn't require any larger refactorings to the new class as part of the patch.
The plan is to migrate the other variables (especially the largest offender: TypeFlags) in separate follow-up
patches.

Some Questions & Answers I expect to come up in the review:

Q: Are the llvm::ArrayRef<T> arguments getting optimized to the same code as the old bitflags?
A: Yes, it's the same with -O2.

Q: Do we still need Flags?
A: Actually, there are a few uses left for this class. The class could be useful to have in LLVM
as it's nicer than just operating on plain uintX_t types, so maybe we should rewrite it and move it into
ADT or Support.

Q: Should EnumFlags be in LLVM?
A: IMHO no. I think the whole enums-as-bitfields thing can be done much simpler with bitfields. LLDB has
to keep doing it as it's exposed the SB API, but I don't think we should encourage this pattern.

Diff Detail

Event Timeline

teemperor created this revision.Jan 6 2021, 6:07 AM
teemperor requested review of this revision.Jan 6 2021, 6:07 AM

This looks like a great improvement. Would it be possible to implement Flags in terms of EnumFlags<uint32_t> (possibly using partial specialization) and get rid of the existing class that way?

lldb/include/lldb/Utility/EnumFlags.h
114

Nit: would = {} be more "generic"?