Reputation: 13830
I want to pass a variable number of arguments to my LLVM opt pass.
To do this, I do something like:
static cl::list<std::string> Files(cl::Positional, cl::OneOrMore);
static cl::list<std::string> Libraries("l", cl::ZeroOrMore);
However, if I now invoke opt like:
foo@foo-Ubuntu:~/llvm-ir-obfuscation$ opt -load cmake-build-debug/water/libMapInstWMPass.so -mapiWM programs/ll/sum100.ll -S 2 3 4 -o foo.ll
opt: Too many positional arguments specified!
Can specify at most 2 positional arguments: See: opt -help
, then I get errors that opt will accept at most 2 positional arguments.
What am I doing wrong?
Upvotes: 3
Views: 2647
Reputation: 2329
I think the problem is that opt
is already parsing its own arguments, and has already the bitcode file to process as a positional argument, so having more than one positional arguments creates ambiguity.
The documentation explains the API as if it is used in a standalone application. So, for example, if you do something like this:
int main(int argc, char *argv[]) {
cl::list<std::string> Files(cl::Positional, cl::OneOrMore);
cl::list<std::string> Files2(cl::Positional, cl::OneOrMore);
cl::list<std::string> Libraries("l", cl::ZeroOrMore);
cl::ParseCommandLineOptions(argc, argv);
for(auto &e : Libraries) outs() << e << "\n";
outs() << "....\n";
for(auto &e : Files) outs() << e << "\n";
outs() << "....\n";
for(auto &e : Files2) outs() << e << "\n";
outs() << "....\n";
}
you get something like this:
$ foo -l one two three four five six
one
....
two
three
four
five
....
six
....
Now, if you swap around the two positional argument definitions, or even change the cl::OneOrMore
of Files2
option to cl::ZeroOrMore
, you will get an error
$ option: error - option can never match, because another positional argument will match an unbounded number of values, and this option does not require a value!
Personally, when I use opt
I forego the positiontal argument option and do something like this:
cl::list<std::string> Lists("lists", cl::desc("Specify names"), cl::OneOrMore);
which allows me to do this:
opt -load ./fooPass.so -foo -o out.bc -lists one ./in.bc -lists two
and iterating over the std::string
list the same way I get:
one
two
Upvotes: 3
Reputation: 4195
As @compor suggests, this probably has something to do with intertwining arguments for opt
and your own pass. The CommandLine library is primarily written for standalone applications within the LLVM framework.
However, you can do something like:
static cl::list<std::string> Args1("args1", cl::Positional, cl::CommaSeparated);
static cl::list<std::string> Args2("args2", cl::ZeroOrMore);
This has the advantage that you can input multiple arguments on the command-line using either commas, e.g., arg1,arg2,...
or by using the identifier -args1 arg1 arg2 ...
; and these get inserted into the Args1
list. If you just supply a single positional argument arg
on the command line, then Args1
will contain this argument only.
Also, you can specify -args2 arg
on the command-line wherever you with (named non-positional option). These will go into the Args2
list.
Upvotes: 2