From 994dbe007394da2ecdc815a8784bbfa6067dceb2 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Thu, 17 Dec 2009 07:49:16 +0000 Subject: [PATCH] Add a 'set_option' action for use in OptionPreprocessor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91594 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CompilerDriver/Common.td | 1 + test/LLVMC/OptionPreprocessor.td | 21 +++-- tools/llvmc/doc/LLVMC-Reference.rst | 43 +++++----- tools/llvmc/plugins/Base/Base.td.in | 4 +- utils/TableGen/LLVMCConfigurationEmitter.cpp | 84 +++++++++++++++----- 5 files changed, 111 insertions(+), 42 deletions(-) diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td index 8d2f63b3306..9c3e861c220 100644 --- a/include/llvm/CompilerDriver/Common.td +++ b/include/llvm/CompilerDriver/Common.td @@ -84,6 +84,7 @@ def stop_compilation; def unpack_values; def warning; def error; +def set_option; def unset_option; // Increase/decrease the edge weight. diff --git a/test/LLVMC/OptionPreprocessor.td b/test/LLVMC/OptionPreprocessor.td index 5661db865d7..44ebfa49bbd 100644 --- a/test/LLVMC/OptionPreprocessor.td +++ b/test/LLVMC/OptionPreprocessor.td @@ -11,20 +11,30 @@ def OptList : OptionList<[ (switch_option "baz", (help "dummy")), (parameter_option "foo_p", (help "dummy")), (parameter_option "bar_p", (help "dummy")), -(parameter_option "baz_p", (help "dummy")) +(parameter_option "baz_p", (help "dummy")), +(parameter_list_option "foo_l", (help "dummy")) ]>; def Preprocess : OptionPreprocessor< (case // CHECK: W1 + // CHECK: foo = false; + // CHECK: foo_p = ""; + // CHECK: foo_l.clear(); (and (switch_on "foo"), (any_switch_on ["bar", "baz"])), - (warning "W1"), + [(warning "W1"), (unset_option "foo"), + (unset_option "foo_p"), (unset_option "foo_l")], // CHECK: W2 + // CHECK: foo = true; + // CHECK: foo_p = "asdf"; (and (switch_on ["foo", "bar"]), (any_empty ["foo_p", "bar_p"])), - (warning "W2"), + [(warning "W2"), (set_option "foo"), (set_option "foo_p", "asdf")], // CHECK: W3 + // CHECK: foo = true; + // CHECK: bar = true; + // CHECK: baz = true; (and (empty ["foo_p", "bar_p"]), (any_not_empty ["baz_p"])), - (warning "W3")) + [(warning "W3"), (set_option ["foo", "bar", "baz"])]) >; // Shut up warnings... @@ -38,7 +48,8 @@ def dummy : Tool< (switch_on "baz"), (error), (not_empty "foo_p"), (error), (not_empty "bar_p"), (error), - (not_empty "baz_p"), (error))) + (not_empty "baz_p"), (error), + (not_empty "foo_l"), (error))) ]>; def Graph : CompilationGraph<[Edge<"root", "dummy">]>; diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst index 4d80a2a6e16..7336195dfed 100644 --- a/tools/llvmc/doc/LLVMC-Reference.rst +++ b/tools/llvmc/doc/LLVMC-Reference.rst @@ -656,10 +656,10 @@ For example, without those definitions the following command wouldn't work:: $ llvmc hello.cpp llvmc: Unknown suffix: cpp -The language map entries should be added only for tools that are -linked with the root node. Since tools are not allowed to have -multiple output languages, for nodes "inside" the graph the input and -output languages should match. This is enforced at compile-time. +The language map entries are needed only for the tools that are linked from the +root node. Since a tool can't have multiple output languages, for inner nodes of +the graph the input and output languages should match. This is enforced at +compile-time. Option preprocessor =================== @@ -672,24 +672,31 @@ the driver with both of these options enabled. The ``OptionPreprocessor`` feature is reserved specially for these occasions. Example (adapted from the built-in Base plugin):: - def Preprocess : OptionPreprocessor< - (case (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])), - [(unset_option ["O0", "O1", "O2"]), - (warning "Multiple -O options specified, defaulted to -O3.")], - (and (switch_on "O2"), (any_switch_on ["O0", "O1"])), - (unset_option ["O0", "O1"]), - (and (switch_on "O1"), (switch_on "O0")), - (unset_option "O0")) - >; -Here, ``OptionPreprocessor`` is used to unset all spurious optimization options -(so that they are not forwarded to the compiler). + def Preprocess : OptionPreprocessor< + (case (not (any_switch_on ["O0", "O1", "O2", "O3"])), + (set_option "O2"), + (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])), + (unset_option ["O0", "O1", "O2"]), + (and (switch_on "O2"), (any_switch_on ["O0", "O1"])), + (unset_option ["O0", "O1"]), + (and (switch_on "O1"), (switch_on "O0")), + (unset_option "O0")) + >; + +Here, ``OptionPreprocessor`` is used to unset all spurious ``-O`` options so +that they are not forwarded to the compiler. If no optimization options are +specified, ``-O2`` is enabled. ``OptionPreprocessor`` is basically a single big ``case`` expression, which is evaluated only once right after the plugin is loaded. The only allowed actions -in ``OptionPreprocessor`` are ``error``, ``warning`` and a special action -``unset_option``, which, as the name suggests, unsets a given option. For -convenience, ``unset_option`` also works on lists. +in ``OptionPreprocessor`` are ``error``, ``warning`` and two special actions: +``unset_option`` and ``set_option``. As their names suggest, they can be used to +set or unset a given option. To set a parameter option with ``set_option``, use +the two-argument form: ``(set_option "parameter", "value")``. For convenience, +``set_option`` and ``unset_option`` also work on lists (that is, instead of +``[(unset_option "A"), (unset_option "B")]`` you can use ``(unset_option ["A", +"B"])``). More advanced topics diff --git a/tools/llvmc/plugins/Base/Base.td.in b/tools/llvmc/plugins/Base/Base.td.in index 8f928cc40cb..1413593bdfe 100644 --- a/tools/llvmc/plugins/Base/Base.td.in +++ b/tools/llvmc/plugins/Base/Base.td.in @@ -91,7 +91,9 @@ def OptList : OptionList<[ // Option preprocessor. def Preprocess : OptionPreprocessor< -(case (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])), +(case (not (any_switch_on ["O0", "O1", "O2", "O3"])), + (set_option "O2"), + (and (switch_on "O3"), (any_switch_on ["O0", "O1", "O2"])), (unset_option ["O0", "O1", "O2"]), (and (switch_on "O2"), (any_switch_on ["O0", "O1"])), (unset_option ["O0", "O1"]), diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index be3382c29d5..3ff7bc4d2ef 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -2303,11 +2303,32 @@ class EmitPreprocessOptionsCallback : public HandlerTable { typedef EmitPreprocessOptionsCallbackHandler Handler; + typedef void + (EmitPreprocessOptionsCallback::* HandlerImpl) + (const Init*, unsigned, raw_ostream&) const; const OptionDescriptions& OptDescs_; - void onUnsetOptionStr(const Init* I, - unsigned IndentLevel, raw_ostream& O) const + void onListOrDag(HandlerImpl h, + const DagInit& d, unsigned IndentLevel, raw_ostream& O) const + { + checkNumberOfArguments(d, 1); + const Init* I = d.getArg(0); + + // If I is a list, apply h to each element. + if (typeid(*I) == typeid(ListInit)) { + const ListInit& L = *static_cast(I); + for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) + ((this)->*(h))(*B, IndentLevel, O); + } + // Otherwise, apply h to I. + else { + ((this)->*(h))(I, IndentLevel, O); + } + } + + void onUnsetOptionImpl(const Init* I, + unsigned IndentLevel, raw_ostream& O) const { const std::string& OptName = InitPtrToString(I); const OptionDescription& OptDesc = OptDescs_.FindOption(OptName); @@ -2326,26 +2347,52 @@ class EmitPreprocessOptionsCallback : } } - void onUnsetOptionList(const ListInit& L, - unsigned IndentLevel, raw_ostream& O) const - { - for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) - this->onUnsetOptionStr(*B, IndentLevel, O); - } - void onUnsetOption(const DagInit& d, unsigned IndentLevel, raw_ostream& O) const { - checkNumberOfArguments(d, 1); - Init* I = d.getArg(0); + this->onListOrDag(&EmitPreprocessOptionsCallback::onUnsetOptionImpl, + d, IndentLevel, O); + } - if (typeid(*I) == typeid(ListInit)) { - const ListInit& L = *static_cast(I); - this->onUnsetOptionList(L, IndentLevel, O); - } - else { - this->onUnsetOptionStr(I, IndentLevel, O); - } + void onSetParameter(const DagInit& d, + unsigned IndentLevel, raw_ostream& O) const { + checkNumberOfArguments(d, 2); + const std::string& OptName = InitPtrToString(d.getArg(0)); + const std::string& Value = InitPtrToString(d.getArg(1)); + const OptionDescription& OptDesc = OptDescs_.FindOption(OptName); + + if (OptDesc.isParameter()) + O.indent(IndentLevel) << OptDesc.GenVariableName() + << " = \"" << Value << "\";\n"; + else + throw "Two-argument 'set_option' " + "can be only applied to parameter options!"; + } + + void onSetSwitch(const Init* I, + unsigned IndentLevel, raw_ostream& O) const { + const std::string& OptName = InitPtrToString(I); + const OptionDescription& OptDesc = OptDescs_.FindOption(OptName); + + if (OptDesc.isSwitch()) + O.indent(IndentLevel) << OptDesc.GenVariableName() << " = true;\n"; + else + throw "One-argument 'set_option' can be only applied to switch options!"; + } + + void onSetOption(const DagInit& d, + unsigned IndentLevel, raw_ostream& O) const + { + checkNumberOfArguments(d, 1); + + // Two arguments: (set_option "parameter", "value") + if (d.getNumArgs() > 1) + this->onSetParameter(d, IndentLevel, O); + // One argument: (set_option "switch") + // or (set_option ["switch1", "switch2", ...]) + else + this->onListOrDag(&EmitPreprocessOptionsCallback::onSetSwitch, + d, IndentLevel, O); } public: @@ -2357,6 +2404,7 @@ public: AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag); AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag); AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption); + AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption); staticMembersInitialized_ = true; }