[LLVMdev] Modifying the support CommandLine Library to support option categories and iteration over registered options
Daniel Liew
daniel.liew at imperial.ac.uk
Wed Feb 6 10:16:50 PST 2013
Hi,
I'm a contributor to the KLEE project (based on LLVM) and I'm
currently looking at trying to add the following functionality to
KLEE...
(1). Be able to iterate through registered command line options and
programmatically hide them. We're interested in this because we wish
to hide (unless -help-hidden is called) several LLVM options.
(2). Be able to place an option into a category on initialisation.
Then when --help (or something similar) is called options are shown by
category and then alphabetically within a category.
I've taken a look at the current HEAD of LLVM source code and as far
as I can tell (1) currently isn't possible because of the following
line in lib/support/CommandLine.cpp
static Option *RegisteredOptionList = 0;
so the pointer to the underlying storage model for options is hidden
from clients such as KLEE.
I also don't see any code to support (2). I noticed that "clang
--help-hidden" shows options categorised but I couldn't figure out how
this was working. The options in other categories such as "Driver
options" were mentioned in
./projects/clang/include/clang/Driver/Options.td which is a language I
don't really recognise and besides I'm reasonably confident that KLEE
doesn't use it. Please tell me if there is a way to use the current
version of the LLVM command line library in its current form but as
far I can tell it's not possible.
So I have ideas for implementing ideas (1) and (2) but I don't want to
spend time implementing it if the idea won't be accepted and merged
into LLVM so I wanted to discuss the idea first a little first before
diving in.
To implement idea (2) we could have something like this in LLVM
command Line library
class llvm::cl::OptionCategory
{
protected OptionCategory() { //code to register category with a
global store, all heavy lifting work is done here! }
virtual const char* getName()=0; //shown as option category header
name in --help
virtual const char* getHelpDescription()=0; //shown below the option
category header name in --help
}
class llvm::cl::DefaultCategory
{
virtual const char* getName() { return "General";}
virtual const char* getHelpDescription() { return "";}
}
then clients in their own code could simply implement their own
categories by sub-classing e.g.
class klee::SMTLIBOptionsCategory : public llvm::cl::OptionCategory
{
virtual const char* getName() { return "SMTLIB";}
virtual const char* getHelpDescription() { return "These options
control the behaviour of the SMTLIB printer";}
}
and now when a client declares an option we could have an additional
applicator llvm::cl::category<TYPE> . For example
cl::opt<bool> printHumanReadable("smtlib-human-readable",
cl::desc("foobar"), cl::init(false),
cl::category<SMTLIBOptionsCategory>);
If a client does not place their option in a category then by default
the LLVM command line library could put the option in the
DefaultCategory.
I personally think the above approach suggested is reasonable because
it doesn't break the existing client syntax for creating command line
options. Although it does sort of break the philosophy of not having
to sub class but a client needs to do SOMETHING to introduce a new
category right? If the boiler plate code of constructing a class for
an Option category is annoying we could introduce a macro like ...
CL_DECLARE_CATEGORY( klee::SMTLIBOptionsCategory, "SMTLIB", "These
options control the behaviour of the SMTLIB printer")
As an alternative we could use a string (e.g.
cl::category("SMTLIBOptionsCategory") ) thus avoiding the need to
create sub classes of llvm::cl::OptionCategory but we loose the
benefit of type-checking.
Ideally I'd also not like to break the existing behaviour of --help so
maybe we could something like this ....
--help : Shows alphabetically order list of command line options which
is the current behaviour
--help=all : Shows all (non-hidden) options but in categories and
alphabetically order within each category.
--help=<category> : Shows options in category <category> only
--help-list-categories : List the option categories
Now to implement idea (1). We could introduce an Iterator that gives
access to the llvm::cl::Option object and expose a few setter/getter
methods to clients. We could also be fancy and have a template
parameter to the function that gives access to the iterator so we can
pick what category of options we iterate over...
llvm::cl::iterator i =
llvm::cl::getOptionsIterator<DefaultCategory>(); //Grab the Options
iterator
I'm not sure what setters and getters are appropriate but to implement
what KLEE needs we need to be able get the option name and to be able
set/get the hidden attribute of an option. I suppose reading the
current value of the option (either as a printable string or as its
actual type) would also be useful as well.
So what do people think? If there are no major objections I'll try and
implement the ideas I described above and submit a patch.
Thanks,
Dan Liew.
More information about the llvm-dev
mailing list