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
This commit is contained in:
Mikhail Glushenkov 2009-12-17 07:49:16 +00:00
parent 24723288a2
commit 994dbe0073
5 changed files with 111 additions and 42 deletions

View File

@ -84,6 +84,7 @@ def stop_compilation;
def unpack_values; def unpack_values;
def warning; def warning;
def error; def error;
def set_option;
def unset_option; def unset_option;
// Increase/decrease the edge weight. // Increase/decrease the edge weight.

View File

@ -11,20 +11,30 @@ def OptList : OptionList<[
(switch_option "baz", (help "dummy")), (switch_option "baz", (help "dummy")),
(parameter_option "foo_p", (help "dummy")), (parameter_option "foo_p", (help "dummy")),
(parameter_option "bar_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< def Preprocess : OptionPreprocessor<
(case (case
// CHECK: W1 // CHECK: W1
// CHECK: foo = false;
// CHECK: foo_p = "";
// CHECK: foo_l.clear();
(and (switch_on "foo"), (any_switch_on ["bar", "baz"])), (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: W2
// CHECK: foo = true;
// CHECK: foo_p = "asdf";
(and (switch_on ["foo", "bar"]), (any_empty ["foo_p", "bar_p"])), (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: W3
// CHECK: foo = true;
// CHECK: bar = true;
// CHECK: baz = true;
(and (empty ["foo_p", "bar_p"]), (any_not_empty ["baz_p"])), (and (empty ["foo_p", "bar_p"]), (any_not_empty ["baz_p"])),
(warning "W3")) [(warning "W3"), (set_option ["foo", "bar", "baz"])])
>; >;
// Shut up warnings... // Shut up warnings...
@ -38,7 +48,8 @@ def dummy : Tool<
(switch_on "baz"), (error), (switch_on "baz"), (error),
(not_empty "foo_p"), (error), (not_empty "foo_p"), (error),
(not_empty "bar_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">]>; def Graph : CompilationGraph<[Edge<"root", "dummy">]>;

View File

@ -656,10 +656,10 @@ For example, without those definitions the following command wouldn't work::
$ llvmc hello.cpp $ llvmc hello.cpp
llvmc: Unknown suffix: cpp llvmc: Unknown suffix: cpp
The language map entries should be added only for tools that are The language map entries are needed only for the tools that are linked from the
linked with the root node. Since tools are not allowed to have root node. Since a tool can't have multiple output languages, for inner nodes of
multiple output languages, for nodes "inside" the graph the input and the graph the input and output languages should match. This is enforced at
output languages should match. This is enforced at compile-time. compile-time.
Option preprocessor Option preprocessor
=================== ===================
@ -672,24 +672,31 @@ the driver with both of these options enabled.
The ``OptionPreprocessor`` feature is reserved specially for these The ``OptionPreprocessor`` feature is reserved specially for these
occasions. Example (adapted from the built-in Base plugin):: 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 def Preprocess : OptionPreprocessor<
(so that they are not forwarded to the compiler). (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 ``OptionPreprocessor`` is basically a single big ``case`` expression, which is
evaluated only once right after the plugin is loaded. The only allowed actions evaluated only once right after the plugin is loaded. The only allowed actions
in ``OptionPreprocessor`` are ``error``, ``warning`` and a special action in ``OptionPreprocessor`` are ``error``, ``warning`` and two special actions:
``unset_option``, which, as the name suggests, unsets a given option. For ``unset_option`` and ``set_option``. As their names suggest, they can be used to
convenience, ``unset_option`` also works on lists. 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 More advanced topics

View File

@ -91,7 +91,9 @@ def OptList : OptionList<[
// Option preprocessor. // Option preprocessor.
def Preprocess : OptionPreprocessor< 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"]), (unset_option ["O0", "O1", "O2"]),
(and (switch_on "O2"), (any_switch_on ["O0", "O1"])), (and (switch_on "O2"), (any_switch_on ["O0", "O1"])),
(unset_option ["O0", "O1"]), (unset_option ["O0", "O1"]),

View File

@ -2303,11 +2303,32 @@ class EmitPreprocessOptionsCallback :
public HandlerTable<EmitPreprocessOptionsCallbackHandler> public HandlerTable<EmitPreprocessOptionsCallbackHandler>
{ {
typedef EmitPreprocessOptionsCallbackHandler Handler; typedef EmitPreprocessOptionsCallbackHandler Handler;
typedef void
(EmitPreprocessOptionsCallback::* HandlerImpl)
(const Init*, unsigned, raw_ostream&) const;
const OptionDescriptions& OptDescs_; const OptionDescriptions& OptDescs_;
void onUnsetOptionStr(const Init* I, void onListOrDag(HandlerImpl h,
unsigned IndentLevel, raw_ostream& O) const 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<const ListInit*>(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 std::string& OptName = InitPtrToString(I);
const OptionDescription& OptDesc = OptDescs_.FindOption(OptName); 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, void onUnsetOption(const DagInit& d,
unsigned IndentLevel, raw_ostream& O) const unsigned IndentLevel, raw_ostream& O) const
{ {
checkNumberOfArguments(d, 1); this->onListOrDag(&EmitPreprocessOptionsCallback::onUnsetOptionImpl,
Init* I = d.getArg(0); d, IndentLevel, O);
}
if (typeid(*I) == typeid(ListInit)) { void onSetParameter(const DagInit& d,
const ListInit& L = *static_cast<const ListInit*>(I); unsigned IndentLevel, raw_ostream& O) const {
this->onUnsetOptionList(L, IndentLevel, O); checkNumberOfArguments(d, 2);
} const std::string& OptName = InitPtrToString(d.getArg(0));
else { const std::string& Value = InitPtrToString(d.getArg(1));
this->onUnsetOptionStr(I, IndentLevel, O); 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: public:
@ -2357,6 +2404,7 @@ public:
AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag); AddHandler("error", &EmitPreprocessOptionsCallback::onErrorDag);
AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag); AddHandler("warning", &EmitPreprocessOptionsCallback::onWarningDag);
AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption); AddHandler("unset_option", &EmitPreprocessOptionsCallback::onUnsetOption);
AddHandler("set_option", &EmitPreprocessOptionsCallback::onSetOption);
staticMembersInitialized_ = true; staticMembersInitialized_ = true;
} }