diff options
author | Mikhail Glushenkov <foldr@codedgers.com> | 2009-01-28 03:47:20 +0000 |
---|---|---|
committer | Mikhail Glushenkov <foldr@codedgers.com> | 2009-01-28 03:47:20 +0000 |
commit | 8139ba3e8ca3f6c8dcf56cc0ccda4bd8304784ef (patch) | |
tree | b1d727d4df7dc3eb09c227eda0a390f06368e5c4 | |
parent | c591ed14a05f0b1865f99de3c8e2d0b875ba5ca8 (diff) | |
download | external_llvm-8139ba3e8ca3f6c8dcf56cc0ccda4bd8304784ef.zip external_llvm-8139ba3e8ca3f6c8dcf56cc0ccda4bd8304784ef.tar.gz external_llvm-8139ba3e8ca3f6c8dcf56cc0ccda4bd8304784ef.tar.bz2 |
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.td | 5 | ||||
-rw-r--r-- | test/LLVMC/ExternOptions.td | 3 | ||||
-rw-r--r-- | test/LLVMC/MultiValuedOption.td | 21 | ||||
-rw-r--r-- | test/LLVMC/OneOrMore.td | 22 | ||||
-rw-r--r-- | tools/llvmc/doc/LLVMC-Reference.rst | 57 | ||||
-rw-r--r-- | utils/TableGen/LLVMCConfigurationEmitter.cpp | 148 |
6 files changed, 201 insertions, 55 deletions
diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td index 097dd4f..1f6bacc 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 11383cb..a04a88b 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 0000000..d68a115 --- /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 0000000..f27ae97 --- /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 53049d7..9aca609 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 ec023ba..bd9073d 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 << "\")"; |