summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Glushenkov <foldr@codedgers.com>2009-01-28 03:47:20 +0000
committerMikhail Glushenkov <foldr@codedgers.com>2009-01-28 03:47:20 +0000
commit19d3e82905db7c5882f22ad945724e90e9f4914b (patch)
treeb1d727d4df7dc3eb09c227eda0a390f06368e5c4
parent6c55b1ca7b72c90ce93ca25bc35aefef7d7deda4 (diff)
downloadllvm-19d3e82905db7c5882f22ad945724e90e9f4914b.tar.gz
llvm-19d3e82905db7c5882f22ad945724e90e9f4914b.tar.bz2
llvm-19d3e82905db7c5882f22ad945724e90e9f4914b.tar.xz
Add three new option properties.
Adds new option properties 'multi_val', 'one_or_more' and 'zero_or_one'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63172 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CompilerDriver/Common.td5
-rw-r--r--test/LLVMC/ExternOptions.td3
-rw-r--r--test/LLVMC/MultiValuedOption.td21
-rw-r--r--test/LLVMC/OneOrMore.td22
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst57
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp148
6 files changed, 201 insertions, 55 deletions
diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td
index 097dd4f38e..1f6bacc787 100644
--- a/include/llvm/CompilerDriver/Common.td
+++ b/include/llvm/CompilerDriver/Common.td
@@ -36,11 +36,14 @@ def prefix_list_option;
// Possible option properties.
+def extern;
def help;
def hidden;
+def multi_val;
+def one_or_more;
def really_hidden;
def required;
-def extern;
+def zero_or_one;
// Empty DAG marker.
def empty;
diff --git a/test/LLVMC/ExternOptions.td b/test/LLVMC/ExternOptions.td
index 11383cb15b..a04a88b002 100644
--- a/test/LLVMC/ExternOptions.td
+++ b/test/LLVMC/ExternOptions.td
@@ -1,6 +1,7 @@
// Check that extern options work.
// The dummy tool and graph are required to silence warnings.
-// RUN: tblgen -I $srcroot/include --gen-llvmc %s | grep {extern .* AutoGeneratedSwitch_Wall}
+// RUN: tblgen -I $srcroot/include --gen-llvmc %s -o %t
+// RUN: grep {extern .* AutoGeneratedSwitch_Wall} %t
include "llvm/CompilerDriver/Common.td"
diff --git a/test/LLVMC/MultiValuedOption.td b/test/LLVMC/MultiValuedOption.td
new file mode 100644
index 0000000000..d68a115af1
--- /dev/null
+++ b/test/LLVMC/MultiValuedOption.td
@@ -0,0 +1,21 @@
+// Check that multivalued options work.
+// The dummy tool and graph are required to silence warnings.
+// RUN: tblgen -I $srcroot/include --gen-llvmc %s -o %t
+// RUN: grep cl::multi_val(2) %t | count 1
+
+include "llvm/CompilerDriver/Common.td"
+
+def OptList : OptionList<[
+ (prefix_list_option "foo", (multi_val 2)),
+ (parameter_list_option "baz", (multi_val 2), (extern))]>;
+
+def dummy_tool : Tool<[
+(cmd_line "dummy_cmd"),
+(in_language "dummy"),
+(out_language "dummy"),
+(actions (case
+ (not_empty "foo"), (forward_as "foo", "bar"),
+ (not_empty "baz"), (forward "baz")))
+]>;
+
+def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>;
diff --git a/test/LLVMC/OneOrMore.td b/test/LLVMC/OneOrMore.td
new file mode 100644
index 0000000000..f27ae9707d
--- /dev/null
+++ b/test/LLVMC/OneOrMore.td
@@ -0,0 +1,22 @@
+// Check that (one_or_more) and (zero_or_one) properties work.
+// The dummy tool and graph are required to silence warnings.
+// RUN: tblgen -I $srcroot/include --gen-llvmc %s -o %t
+// RUN: grep cl::ZeroOrOne %t | count 1
+// RUN: grep cl::OneOrMore %t | count 1
+
+include "llvm/CompilerDriver/Common.td"
+
+def OptList : OptionList<[
+ (prefix_list_option "foo", (one_or_more)),
+ (parameter_list_option "baz", (zero_or_one))]>;
+
+def dummy_tool : Tool<[
+(cmd_line "dummy_cmd"),
+(in_language "dummy"),
+(out_language "dummy"),
+(actions (case
+ (not_empty "foo"), (forward_as "foo", "bar"),
+ (not_empty "baz"), (forward "baz")))
+]>;
+
+def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>;
diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst
index 53049d7b3c..9aca609ca1 100644
--- a/tools/llvmc/doc/LLVMC-Reference.rst
+++ b/tools/llvmc/doc/LLVMC-Reference.rst
@@ -262,37 +262,47 @@ separate option groups syntactically.
* Possible option types:
- - ``switch_option`` - a simple boolean switch without arguments,
- for example ``-O2`` or ``-time``.
+ - ``switch_option`` - a simple boolean switch without arguments, for example
+ ``-O2`` or ``-time``. At most one occurrence is allowed.
- - ``parameter_option`` - option that takes one argument, for
- example ``-std=c99``. It is also allowed to use spaces instead of
- the equality sign: ``-std c99``.
+ - ``parameter_option`` - option that takes one argument, for example
+ ``-std=c99``. It is also allowed to use spaces instead of the equality
+ sign: ``-std c99``. At most one occurrence is allowed.
- - ``parameter_list_option`` - same as the above, but more than one
- option occurence is allowed.
+ - ``parameter_list_option`` - same as the above, but more than one option
+ occurence is allowed.
- - ``prefix_option`` - same as the parameter_option, but the option
- name and argument do not have to be separated. Example:
- ``-ofile``. This can be also specified as ``-o file``; however,
- ``-o=file`` will be parsed incorrectly (``=file`` will be
- interpreted as option value).
+ - ``prefix_option`` - same as the parameter_option, but the option name and
+ argument do not have to be separated. Example: ``-ofile``. This can be also
+ specified as ``-o file``; however, ``-o=file`` will be parsed incorrectly
+ (``=file`` will be interpreted as option value). At most one occurrence is
+ allowed.
- - ``prefix_list_option`` - same as the above, but more than one
- occurence of the option is allowed; example: ``-lm -lpthread``.
+ - ``prefix_list_option`` - same as the above, but more than one occurence of
+ the option is allowed; example: ``-lm -lpthread``.
- - ``alias_option`` - a special option type for creating
- aliases. Unlike other option types, aliases are not allowed to
- have any properties besides the aliased option name. Usage
- example: ``(alias_option "preprocess", "E")``
+ - ``alias_option`` - a special option type for creating aliases. Unlike other
+ option types, aliases are not allowed to have any properties besides the
+ aliased option name. Usage example: ``(alias_option "preprocess", "E")``
* Possible option properties:
- - ``help`` - help string associated with this option. Used for
- ``--help`` output.
+ - ``help`` - help string associated with this option. Used for ``--help``
+ output.
+
+ - ``required`` - this option must be specified exactly once (or, in case of
+ the list options without the ``multi_val`` property, at least
+ once). Incompatible with ``zero_or_one`` and ``one_or_more``.
- - ``required`` - this option is obligatory.
+ - ``one_or_more`` - the option must be specified at least one time. Useful
+ only for list options in conjunction with ``multi_val``; for ordinary lists
+ it is synonymous with ``required``. Incompatible with ``required`` and
+ ``zero_or_one``.
+
+ - ``zero_or_one`` - the option can be specified zero or one times. Useful
+ only for list options in conjunction with ``multi_val``. Incompatible with
+ ``required`` and ``one_or_more``.
- ``hidden`` - the description of this option will not appear in
the ``--help`` output (but will appear in the ``--help-hidden``
@@ -301,6 +311,11 @@ separate option groups syntactically.
- ``really_hidden`` - the option will not be mentioned in any help
output.
+ - ``multi_val n`` - this option takes *n* arguments (can be useful in some
+ special cases). Usage example: ``(parameter_list_option "foo", (multi_val
+ 3))``. Only list options can have this attribute; you can, however, use
+ the ``one_or_more`` and ``zero_or_one`` properties.
+
- ``extern`` - this option is defined in some other plugin, see below.
External options
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index ec023ba728..bd9073d559 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -127,13 +127,19 @@ bool oneOf(const char* lst, char c) {
return false;
}
+template <class I, class S>
+void checkedIncrement(I& P, I E, S ErrorString) {
+ ++P;
+ if (P == E)
+ throw ErrorString;
+}
+
//===----------------------------------------------------------------------===//
/// Back-end specific code
/// OptionType - One of six different option types. See the
/// documentation for detailed description of differences.
-/// Extern* options are those that are defined in some other plugin.
namespace OptionType {
enum OptionType { Alias, Switch, Parameter, ParameterList,
Prefix, PrefixList};
@@ -171,7 +177,8 @@ OptionType::OptionType stringToOptionType(const std::string& T) {
namespace OptionDescriptionFlags {
enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
- ReallyHidden = 0x4, Extern = 0x8 };
+ ReallyHidden = 0x4, Extern = 0x8,
+ OneOrMore = 0x10, ZeroOrOne = 0x20 };
}
/// OptionDescription - Represents data contained in a single
@@ -181,11 +188,12 @@ struct OptionDescription {
std::string Name;
unsigned Flags;
std::string Help;
+ unsigned MultiVal;
OptionDescription(OptionType::OptionType t = OptionType::Switch,
const std::string& n = "",
const std::string& h = DefaultHelpString)
- : Type(t), Name(n), Flags(0x0), Help(h)
+ : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1)
{}
/// GenTypeDeclaration - Returns the C++ variable type of this
@@ -203,17 +211,26 @@ struct OptionDescription {
bool isAlias() const;
+ bool isMultiVal() const;
+
bool isExtern() const;
void setExtern();
bool isRequired() const;
void setRequired();
+ bool isOneOrMore() const;
+ void setOneOrMore();
+
+ bool isZeroOrOne() const;
+ void setZeroOrOne();
+
bool isHidden() const;
void setHidden();
bool isReallyHidden() const;
void setReallyHidden();
+
};
void OptionDescription::Merge (const OptionDescription& other)
@@ -235,6 +252,10 @@ bool OptionDescription::isAlias() const {
return Type == OptionType::Alias;
}
+bool OptionDescription::isMultiVal() const {
+ return MultiVal == 1;
+}
+
bool OptionDescription::isExtern() const {
return Flags & OptionDescriptionFlags::Extern;
}
@@ -249,6 +270,20 @@ void OptionDescription::setRequired() {
Flags |= OptionDescriptionFlags::Required;
}
+bool OptionDescription::isOneOrMore() const {
+ return Flags & OptionDescriptionFlags::OneOrMore;
+}
+void OptionDescription::setOneOrMore() {
+ Flags |= OptionDescriptionFlags::OneOrMore;
+}
+
+bool OptionDescription::isZeroOrOne() const {
+ return Flags & OptionDescriptionFlags::ZeroOrOne;
+}
+void OptionDescription::setZeroOrOne() {
+ Flags |= OptionDescriptionFlags::ZeroOrOne;
+}
+
bool OptionDescription::isHidden() const {
return Flags & OptionDescriptionFlags::Hidden;
}
@@ -405,8 +440,11 @@ public:
AddHandler("extern", &CollectOptionProperties::onExtern);
AddHandler("help", &CollectOptionProperties::onHelp);
AddHandler("hidden", &CollectOptionProperties::onHidden);
+ AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
+ AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
AddHandler("required", &CollectOptionProperties::onRequired);
+ AddHandler("zero_or_one", &CollectOptionProperties::onZeroOrOne);
staticMembersInitialized_ = true;
}
@@ -439,9 +477,46 @@ private:
void onRequired (const DagInit* d) {
checkNumberOfArguments(d, 0);
+ if (optDesc_.isOneOrMore())
+ throw std::string("An option can't have both (required) "
+ "and (one_or_more) properties!");
optDesc_.setRequired();
}
+ void onOneOrMore (const DagInit* d) {
+ checkNumberOfArguments(d, 0);
+ if (optDesc_.isRequired() || optDesc_.isZeroOrOne())
+ throw std::string("Only one of (required), (zero_or_one) or "
+ "(one_or_more) properties is allowed!");
+ if (!OptionType::IsList(optDesc_.Type))
+ llvm::cerr << "Warning: specifying the 'one_or_more' property "
+ "on a non-list option will have no effect.\n";
+ optDesc_.setOneOrMore();
+ }
+
+ void onZeroOrOne (const DagInit* d) {
+ checkNumberOfArguments(d, 0);
+ if (optDesc_.isRequired() || optDesc_.isOneOrMore())
+ throw std::string("Only one of (required), (zero_or_one) or "
+ "(one_or_more) properties is allowed!");
+ if (!OptionType::IsList(optDesc_.Type))
+ llvm::cerr << "Warning: specifying the 'zero_or_one' property"
+ "on a non-list option will have no effect.\n";
+ optDesc_.setZeroOrOne();
+ }
+
+ void onMultiVal (const DagInit* d) {
+ checkNumberOfArguments(d, 1);
+ int val = InitPtrToInt(d->getArg(0));
+ if (val < 2)
+ throw std::string("Error in the 'multi_val' property: "
+ "the value must be greater than 1!");
+ if (!OptionType::IsList(optDesc_.Type))
+ throw std::string("The multi_val property is valid only "
+ "on list options!");
+ optDesc_.MultiVal = val;
+ }
+
};
/// AddOption - A function object that is applied to every option
@@ -639,7 +714,6 @@ private:
};
-
/// CollectToolDescriptions - Gather information about tool properties
/// from the parsed TableGen data (basically a wrapper for the
/// CollectToolProperties function object).
@@ -1131,13 +1205,6 @@ void TokenizeCmdline(const std::string& CmdLine, StrVector& Out) {
}
}
-template <class I, class S>
-void checkedIncrement(I& P, I E, S ErrorString) {
- ++P;
- if (P == E)
- throw ErrorString;
-}
-
/// SubstituteSpecialCommands - Perform string substitution for $CALL
/// and $ENV. Helper function used by EmitCmdLineVecFill().
StrVector::const_iterator SubstituteSpecialCommands
@@ -1308,18 +1375,31 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
case OptionType::PrefixList:
O << Indent << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
- << Indent << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
+ << Indent << "E = " << D.GenVariableName() << ".end(); B != E;) {\n"
<< Indent << Indent1 << "vec.push_back(\"" << Name << "\" + "
- << "*B);\n";
+ << "*B);\n"
+ << Indent << Indent1 << "++B;\n";
+
+ for (int i = 1, j = D.MultiVal; i < j; ++i) {
+ O << Indent << Indent1 << "vec.push_back(*B);\n"
+ << Indent << Indent1 << "++B;\n";
+ }
+
+ O << Indent << "}\n";
break;
case OptionType::ParameterList:
O << Indent << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
<< Indent << "E = " << D.GenVariableName()
- << ".end() ; B != E; ++B) {\n"
- << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n"
- << Indent << Indent1 << "vec.push_back(*B);\n"
- << Indent << "}\n";
+ << ".end() ; B != E;) {\n"
+ << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n";
+
+ for (int i = 0, j = D.MultiVal; i < j; ++i) {
+ O << Indent << Indent1 << "vec.push_back(*B);\n"
+ << Indent << Indent1 << "++B;\n";
+ }
+
+ O << Indent << "}\n";
break;
case OptionType::Alias:
default:
@@ -1376,6 +1456,9 @@ class EmitActionHandler {
const std::string& Name = InitPtrToString(Dag.getArg(0));
const OptionDescription& D = OptDescs.FindOption(Name);
+ if (D.isMultiVal())
+ throw std::string("Can't use unpack_values with multi-valued options!");
+
if (OptionType::IsList(D.Type)) {
O << IndentLevel << "for (" << D.GenTypeDeclaration()
<< "::iterator B = " << D.GenVariableName() << ".begin(),\n"
@@ -1599,27 +1682,28 @@ void EmitOptionDefintions (const OptionDescriptions& descs,
O << ", cl::Prefix";
if (val.isRequired()) {
- switch (val.Type) {
- case OptionType::PrefixList:
- case OptionType::ParameterList:
+ if (OptionType::IsList(val.Type) && !val.isMultiVal())
O << ", cl::OneOrMore";
- break;
- default:
+ else
O << ", cl::Required";
- }
+ }
+ else if (val.isOneOrMore() && OptionType::IsList(val.Type)) {
+ O << ", cl::OneOrMore";
+ }
+ else if (val.isZeroOrOne() && OptionType::IsList(val.Type)) {
+ O << ", cl::ZeroOrOne";
}
- if (val.isReallyHidden() || val.isHidden()) {
- if (val.isRequired())
- O << " |";
- else
- O << ",";
- if (val.isReallyHidden())
- O << " cl::ReallyHidden";
- else
- O << " cl::Hidden";
+ if (val.isReallyHidden()) {
+ O << ", cl::ReallyHidden";
+ }
+ else if (val.isHidden()) {
+ O << ", cl::Hidden";
}
+ if (val.MultiVal > 1)
+ O << ", cl::multi_val(" << val.MultiVal << ")";
+
if (!val.Help.empty())
O << ", cl::desc(\"" << val.Help << "\")";