llvmc: Add a new option type (switch_list).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108673 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2010-07-19 03:16:25 +00:00
parent 9ece46d172
commit fc97aeb4e6
3 changed files with 52 additions and 9 deletions

View File

@ -32,6 +32,7 @@ def actions;
def alias_option; def alias_option;
def switch_option; def switch_option;
def switch_list_option;
def parameter_option; def parameter_option;
def parameter_list_option; def parameter_list_option;
def prefix_option; def prefix_option;

View File

@ -299,7 +299,7 @@ separate option groups syntactically.
* Possible option types: * Possible option types:
- ``switch_option`` - a simple boolean switch without arguments, for example - ``switch_option`` - a simple boolean switch without arguments, for example
``-O2`` or ``-time``. At most one occurrence is allowed. ``-O2`` or ``-time``. At most one occurrence is allowed by default.
- ``parameter_option`` - option that takes one argument, for example - ``parameter_option`` - option that takes one argument, for example
``-std=c99``. It is also allowed to use spaces instead of the equality ``-std=c99``. It is also allowed to use spaces instead of the equality
@ -321,6 +321,13 @@ separate option groups syntactically.
option types, aliases are not allowed to have any properties besides the option types, aliases are not allowed to have any properties besides the
aliased option name. Usage example: ``(alias_option "preprocess", "E")`` aliased option name. Usage example: ``(alias_option "preprocess", "E")``
- ``switch_list_option`` - like ``switch_option`` with the ``zero_or_more``
property, but remembers how many times the switch was turned on. Useful
mostly for forwarding. Example: when ``-foo`` is a switch option (with the
``zero_or_more`` property), the command ``driver -foo -foo`` is forwarded
as ``some-tool -foo``, but when ``-foo`` is a switch list, the same command
is forwarded as ``some-tool -foo -foo``.
* Possible option properties: * Possible option properties:

View File

@ -188,21 +188,25 @@ void apply(F Fun, T0& Arg0, T1& Arg1) {
/// documentation for detailed description of differences. /// documentation for detailed description of differences.
namespace OptionType { namespace OptionType {
enum OptionType { Alias, Switch, Parameter, ParameterList, enum OptionType { Alias, Switch, SwitchList,
Prefix, PrefixList}; Parameter, ParameterList, Prefix, PrefixList };
bool IsAlias(OptionType t) { bool IsAlias(OptionType t) {
return (t == Alias); return (t == Alias);
} }
bool IsList (OptionType t) { bool IsList (OptionType t) {
return (t == ParameterList || t == PrefixList); return (t == SwitchList || t == ParameterList || t == PrefixList);
} }
bool IsSwitch (OptionType t) { bool IsSwitch (OptionType t) {
return (t == Switch); return (t == Switch);
} }
bool IsSwitchList (OptionType t) {
return (t == SwitchList);
}
bool IsParameter (OptionType t) { bool IsParameter (OptionType t) {
return (t == Parameter || t == Prefix); return (t == Parameter || t == Prefix);
} }
@ -214,6 +218,8 @@ OptionType::OptionType stringToOptionType(const std::string& T) {
return OptionType::Alias; return OptionType::Alias;
else if (T == "switch_option") else if (T == "switch_option")
return OptionType::Switch; return OptionType::Switch;
else if (T == "switch_list_option")
return OptionType::SwitchList;
else if (T == "parameter_option") else if (T == "parameter_option")
return OptionType::Parameter; return OptionType::Parameter;
else if (T == "parameter_list_option") else if (T == "parameter_list_option")
@ -300,6 +306,9 @@ struct OptionDescription {
bool isSwitch() const bool isSwitch() const
{ return OptionType::IsSwitch(this->Type); } { return OptionType::IsSwitch(this->Type); }
bool isSwitchList() const
{ return OptionType::IsSwitchList(this->Type); }
bool isParameter() const bool isParameter() const
{ return OptionType::IsParameter(this->Type); } { return OptionType::IsParameter(this->Type); }
@ -417,6 +426,8 @@ const char* OptionDescription::GenTypeDeclaration() const {
return "cl::list<std::string>"; return "cl::list<std::string>";
case OptionType::Switch: case OptionType::Switch:
return "cl::opt<bool>"; return "cl::opt<bool>";
case OptionType::SwitchList:
return "cl::list<bool>";
case OptionType::Parameter: case OptionType::Parameter:
case OptionType::Prefix: case OptionType::Prefix:
default: default:
@ -434,6 +445,8 @@ std::string OptionDescription::GenVariableName() const {
return "AutoGeneratedList_" + EscapedName; return "AutoGeneratedList_" + EscapedName;
case OptionType::Switch: case OptionType::Switch:
return "AutoGeneratedSwitch_" + EscapedName; return "AutoGeneratedSwitch_" + EscapedName;
case OptionType::SwitchList:
return "AutoGeneratedSwitchList_" + EscapedName;
case OptionType::Prefix: case OptionType::Prefix:
case OptionType::Parameter: case OptionType::Parameter:
default: default:
@ -709,7 +722,7 @@ private:
void onZeroOrMore (const DagInit& d) { void onZeroOrMore (const DagInit& d) {
CheckNumberOfArguments(d, 0); CheckNumberOfArguments(d, 0);
if (OptionType::IsList(optDesc_.Type)) if (optDesc_.isList())
llvm::errs() << "Warning: specifying the 'zero_or_more' property " llvm::errs() << "Warning: specifying the 'zero_or_more' property "
"on a list option has no effect.\n"; "on a list option has no effect.\n";
@ -720,7 +733,7 @@ private:
void onOptional (const DagInit& d) { void onOptional (const DagInit& d) {
CheckNumberOfArguments(d, 0); CheckNumberOfArguments(d, 0);
if (!OptionType::IsList(optDesc_.Type)) if (!optDesc_.isList())
llvm::errs() << "Warning: specifying the 'optional' property" llvm::errs() << "Warning: specifying the 'optional' property"
"on a non-list option has no effect.\n"; "on a non-list option has no effect.\n";
@ -734,7 +747,7 @@ private:
if (val < 2) if (val < 2)
throw "Error in the 'multi_val' property: " throw "Error in the 'multi_val' property: "
"the value must be greater than 1!"; "the value must be greater than 1!";
if (!OptionType::IsList(optDesc_.Type)) if (!optDesc_.isList())
throw "The multi_val property is valid only on list options!"; throw "The multi_val property is valid only on list options!";
optDesc_.MultiVal = val; optDesc_.MultiVal = val;
} }
@ -1855,6 +1868,8 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
<< D.GenVariableName() << "));\n"; << D.GenVariableName() << "));\n";
break; break;
case OptionType::PrefixList: case OptionType::PrefixList:
// TODO: remove duplication across PrefixList / ParameterList / SwitchList
// branches
O.indent(IndentLevel) O.indent(IndentLevel)
<< "for (" << D.GenTypeDeclaration() << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"; << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
@ -1891,6 +1906,20 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
O.indent(IndentLevel1) << "++B;\n"; O.indent(IndentLevel1) << "++B;\n";
} }
O.indent(IndentLevel) << "}\n";
break;
case OptionType::SwitchList:
O.indent(IndentLevel)
<< "for (" << D.GenTypeDeclaration() << "::iterator B = "
<< D.GenVariableName() << ".begin(),\n";
O.indent(IndentLevel) << "E = " << D.GenVariableName()
<< ".end() ; B != E;) {\n";
O.indent(IndentLevel1) << "unsigned pos = " << D.GenVariableName()
<< ".getPosition(B - " << D.GenVariableName()
<< ".begin());\n";
O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
<< Name << "\"));\n";
O.indent(IndentLevel1) << "++B;\n";
O.indent(IndentLevel) << "}\n"; O.indent(IndentLevel) << "}\n";
break; break;
case OptionType::Alias: case OptionType::Alias:
@ -1999,14 +2028,20 @@ class EmitActionHandlersCallback :
const std::string& Name = InitPtrToString(Dag.getArg(0)); const std::string& Name = InitPtrToString(Dag.getArg(0));
const OptionDescription& D = OptDescs.FindListOrParameter(Name); const OptionDescription& D = OptDescs.FindListOrParameter(Name);
if (D.isSwitchList()) {
throw std::runtime_error
("forward_value is not allowed with switch_list");
}
if (D.isParameter()) { if (D.isParameter()) {
O.indent(IndentLevel) << "vec.push_back(std::make_pair(" O.indent(IndentLevel) << "vec.push_back(std::make_pair("
<< D.GenVariableName() << ".getPosition(), " << D.GenVariableName() << ".getPosition(), "
<< D.GenVariableName() << "));\n"; << D.GenVariableName() << "));\n";
} }
else { else {
O.indent(IndentLevel) << "for (cl::list<std::string>::iterator B = " O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
<< D.GenVariableName() << ".begin(), \n"; << "::iterator B = " << D.GenVariableName()
<< ".begin(), \n";
O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName() O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
<< ".end(); B != E; ++B)\n"; << ".end(); B != E; ++B)\n";
O.indent(IndentLevel) << "{\n"; O.indent(IndentLevel) << "{\n";