mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-12 13:48:45 +00:00
Remove all references to plugins from the LLVMC docs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@130090 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
685501836b
commit
834b93b51d
@ -18,17 +18,16 @@ Introduction
|
|||||||
============
|
============
|
||||||
|
|
||||||
LLVMC is a generic compiler driver, designed to be customizable and
|
LLVMC is a generic compiler driver, designed to be customizable and
|
||||||
extensible. It plays the same role for LLVM as the ``gcc`` program
|
extensible. It plays the same role for LLVM as the ``gcc`` program does for
|
||||||
does for GCC - LLVMC's job is essentially to transform a set of input
|
GCC - LLVMC's job is essentially to transform a set of input files into a set of
|
||||||
files into a set of targets depending on configuration rules and user
|
targets depending on configuration rules and user options. What makes LLVMC
|
||||||
options. What makes LLVMC different is that these transformation rules
|
different is that these transformation rules are completely customizable - in
|
||||||
are completely customizable - in fact, LLVMC knows nothing about the
|
fact, LLVMC knows nothing about the specifics of transformation (even the
|
||||||
specifics of transformation (even the command-line options are mostly
|
command-line options are mostly not hard-coded) and regards the transformation
|
||||||
not hard-coded) and regards the transformation structure as an
|
structure as an abstract graph. The structure of this graph is described in
|
||||||
abstract graph. The structure of this graph is completely determined
|
high-level TableGen code, from which an efficient C++ representation is
|
||||||
by plugins, which can be either statically or dynamically linked. This
|
automatically derived. This makes it possible to adapt LLVMC for other
|
||||||
makes it possible to easily adapt LLVMC for other purposes - for
|
purposes - for example, as a build tool for game resources.
|
||||||
example, as a build tool for game resources.
|
|
||||||
|
|
||||||
Because LLVMC employs TableGen_ as its configuration language, you
|
Because LLVMC employs TableGen_ as its configuration language, you
|
||||||
need to be familiar with it to customize LLVMC.
|
need to be familiar with it to customize LLVMC.
|
||||||
@ -36,8 +35,8 @@ need to be familiar with it to customize LLVMC.
|
|||||||
.. _TableGen: http://llvm.org/docs/TableGenFundamentals.html
|
.. _TableGen: http://llvm.org/docs/TableGenFundamentals.html
|
||||||
|
|
||||||
|
|
||||||
Compiling with LLVMC
|
Compiling with ``llvmc``
|
||||||
====================
|
========================
|
||||||
|
|
||||||
LLVMC tries hard to be as compatible with ``gcc`` as possible,
|
LLVMC tries hard to be as compatible with ``gcc`` as possible,
|
||||||
although there are some small differences. Most of the time, however,
|
although there are some small differences. Most of the time, however,
|
||||||
@ -78,17 +77,13 @@ possible to choose the ``clang`` compiler with the ``-clang`` option.
|
|||||||
Predefined options
|
Predefined options
|
||||||
==================
|
==================
|
||||||
|
|
||||||
LLVMC has some built-in options that can't be overridden in the
|
LLVMC has some built-in options that can't be overridden in the TableGen code:
|
||||||
configuration libraries:
|
|
||||||
|
|
||||||
* ``-o FILE`` - Output file name.
|
* ``-o FILE`` - Output file name.
|
||||||
|
|
||||||
* ``-x LANGUAGE`` - Specify the language of the following input files
|
* ``-x LANGUAGE`` - Specify the language of the following input files
|
||||||
until the next -x option.
|
until the next -x option.
|
||||||
|
|
||||||
* ``-load PLUGIN_NAME`` - Load the specified plugin DLL. Example:
|
|
||||||
``-load $LLVM_DIR/Release/lib/LLVMCSimple.so``.
|
|
||||||
|
|
||||||
* ``-v`` - Enable verbose mode, i.e. print out all executed commands.
|
* ``-v`` - Enable verbose mode, i.e. print out all executed commands.
|
||||||
|
|
||||||
* ``--save-temps`` - Write temporary files to the current directory and do not
|
* ``--save-temps`` - Write temporary files to the current directory and do not
|
||||||
@ -103,124 +98,90 @@ configuration libraries:
|
|||||||
precedence.
|
precedence.
|
||||||
|
|
||||||
* ``--check-graph`` - Check the compilation for common errors like mismatched
|
* ``--check-graph`` - Check the compilation for common errors like mismatched
|
||||||
output/input language names, multiple default edges and cycles. Because of
|
output/input language names, multiple default edges and cycles. Exit with code
|
||||||
plugins, these checks can't be performed at compile-time. Exit with code zero
|
zero if no errors were found, and return the number of found errors
|
||||||
if no errors were found, and return the number of found errors
|
otherwise. Hidden option, useful for debugging.
|
||||||
otherwise. Hidden option, useful for debugging LLVMC plugins.
|
|
||||||
|
|
||||||
* ``--view-graph`` - Show a graphical representation of the compilation graph
|
* ``--view-graph`` - Show a graphical representation of the compilation graph
|
||||||
and exit. Requires that you have ``dot`` and ``gv`` programs installed. Hidden
|
and exit. Requires that you have ``dot`` and ``gv`` programs installed. Hidden
|
||||||
option, useful for debugging LLVMC plugins.
|
option, useful for debugging.
|
||||||
|
|
||||||
* ``--write-graph`` - Write a ``compilation-graph.dot`` file in the current
|
* ``--write-graph`` - Write a ``compilation-graph.dot`` file in the current
|
||||||
directory with the compilation graph description in Graphviz format (identical
|
directory with the compilation graph description in Graphviz format (identical
|
||||||
to the file used by the ``--view-graph`` option). The ``-o`` option can be
|
to the file used by the ``--view-graph`` option). The ``-o`` option can be
|
||||||
used to set the output file name. Hidden option, useful for debugging LLVMC
|
used to set the output file name. Hidden option, useful for debugging.
|
||||||
plugins.
|
|
||||||
|
|
||||||
* ``--help``, ``--help-hidden``, ``--version`` - These options have
|
* ``--help``, ``--help-hidden``, ``--version`` - These options have
|
||||||
their standard meaning.
|
their standard meaning.
|
||||||
|
|
||||||
Compiling LLVMC plugins
|
Compiling LLVMC-based drivers
|
||||||
=======================
|
=============================
|
||||||
|
|
||||||
It's easiest to start working on your own LLVMC plugin by copying the
|
It's easiest to start working on your own LLVMC driver by copying the skeleton
|
||||||
skeleton project which lives under ``$LLVMC_DIR/plugins/Simple``::
|
project which lives under ``$LLVMC_DIR/examples/Skeleton``::
|
||||||
|
|
||||||
$ cd $LLVMC_DIR/plugins
|
$ cd $LLVMC_DIR/examples
|
||||||
$ cp -r Simple MyPlugin
|
$ cp -r Skeleton MyDriver
|
||||||
$ cd MyPlugin
|
$ cd MyDriver
|
||||||
$ ls
|
$ ls
|
||||||
Makefile PluginMain.cpp Simple.td
|
AutoGenerated.td Hooks.cpp Main.cpp Makefile
|
||||||
|
|
||||||
As you can see, our basic plugin consists of only two files (not
|
As you can see, our basic driver consists of only three files (not counting the
|
||||||
counting the build script). ``Simple.td`` contains TableGen
|
build script). ``AutoGenerated.td`` contains TableGen description of the
|
||||||
description of the compilation graph; its format is documented in the
|
compilation graph; its format is documented in the following
|
||||||
following sections. ``PluginMain.cpp`` is just a helper file used to
|
sections. ``Hooks.cpp`` is an empty file that should be used for hook
|
||||||
compile the auto-generated C++ code produced from TableGen source. It
|
definitions (see `below`__). ``Main.cpp`` is just a helper used to compile the
|
||||||
can also contain hook definitions (see `below`__).
|
auto-generated C++ code produced from TableGen source.
|
||||||
|
|
||||||
__ hooks_
|
__ hooks_
|
||||||
|
|
||||||
The first thing that you should do is to change the ``LLVMC_PLUGIN``
|
The first thing that you should do is to change the ``LLVMC_BASED_DRIVER``
|
||||||
variable in the ``Makefile`` to avoid conflicts (since this variable
|
variable in the ``Makefile``::
|
||||||
is used to name the resulting library)::
|
|
||||||
|
|
||||||
LLVMC_PLUGIN=MyPlugin
|
LLVMC_BASED_DRIVER=MyDriver
|
||||||
|
|
||||||
It is also a good idea to rename ``Simple.td`` to something less
|
It can also be a good idea to put your TableGen code into a file with a less
|
||||||
generic::
|
generic name::
|
||||||
|
|
||||||
$ mv Simple.td MyPlugin.td
|
$ touch MyDriver.td
|
||||||
|
$ vim AutoGenerated.td
|
||||||
To build your plugin as a dynamic library, just ``cd`` to its source
|
|
||||||
directory and run ``make``. The resulting file will be called
|
|
||||||
``plugin_llvmc_$(LLVMC_PLUGIN).$(DLL_EXTENSION)`` (in our case,
|
|
||||||
``plugin_llvmc_MyPlugin.so``). This library can be then loaded in with the
|
|
||||||
``-load`` option. Example::
|
|
||||||
|
|
||||||
$ cd $LLVMC_DIR/plugins/Simple
|
|
||||||
$ make
|
|
||||||
$ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
|
|
||||||
|
|
||||||
Compiling standalone LLVMC-based drivers
|
|
||||||
========================================
|
|
||||||
|
|
||||||
By default, the ``llvmc`` executable consists of a driver core plus several
|
|
||||||
statically linked plugins (``Base`` and ``Clang`` at the moment). You can
|
|
||||||
produce a standalone LLVMC-based driver executable by linking the core with your
|
|
||||||
own plugins. The recommended way to do this is by starting with the provided
|
|
||||||
``Skeleton`` example (``$LLVMC_DIR/example/Skeleton``)::
|
|
||||||
|
|
||||||
$ cd $LLVMC_DIR/example/
|
|
||||||
$ cp -r Skeleton mydriver
|
|
||||||
$ cd mydriver
|
|
||||||
$ vim Makefile
|
|
||||||
[...]
|
[...]
|
||||||
$ make
|
include "MyDriver.td"
|
||||||
|
|
||||||
|
If you have more than one TableGen source file, they all should be included from
|
||||||
|
``AutoGenerated.td``, since this file is used by the build system to generate
|
||||||
|
C++ code.
|
||||||
|
|
||||||
|
To build your driver, just ``cd`` to its source directory and run ``make``. The
|
||||||
|
resulting executable will be put into ``$LLVM_OBJ_DIR/$(BuildMode)/bin``.
|
||||||
|
|
||||||
If you're compiling LLVM with different source and object directories, then you
|
If you're compiling LLVM with different source and object directories, then you
|
||||||
must perform the following additional steps before running ``make``::
|
must perform the following additional steps before running ``make``::
|
||||||
|
|
||||||
# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
|
# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
|
||||||
# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
|
# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
|
||||||
$ cp $LLVMC_SRC_DIR/example/mydriver/Makefile \
|
$ mkdir $LLVMC_OBJ_DIR/examples/MyDriver/
|
||||||
$LLVMC_OBJ_DIR/example/mydriver/
|
$ cp $LLVMC_SRC_DIR/examples/MyDriver/Makefile \
|
||||||
$ cd $LLVMC_OBJ_DIR/example/mydriver
|
$LLVMC_OBJ_DIR/examples/MyDriver/
|
||||||
|
$ cd $LLVMC_OBJ_DIR/examples/MyDriver
|
||||||
$ make
|
$ make
|
||||||
|
|
||||||
Another way to do the same thing is by using the following command::
|
|
||||||
|
|
||||||
$ cd $LLVMC_DIR
|
|
||||||
$ make LLVMC_BUILTIN_PLUGINS=MyPlugin LLVMC_BASED_DRIVER_NAME=mydriver
|
|
||||||
|
|
||||||
This works with both srcdir == objdir and srcdir != objdir, but assumes that the
|
|
||||||
plugin source directory was placed under ``$LLVMC_DIR/plugins``.
|
|
||||||
|
|
||||||
Sometimes, you will want a 'bare-bones' version of LLVMC that has no
|
|
||||||
built-in plugins. It can be compiled with the following command::
|
|
||||||
|
|
||||||
$ cd $LLVMC_DIR
|
|
||||||
$ make LLVMC_BUILTIN_PLUGINS=""
|
|
||||||
|
|
||||||
|
|
||||||
Customizing LLVMC: the compilation graph
|
Customizing LLVMC: the compilation graph
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
Each TableGen configuration file should include the common
|
Each TableGen configuration file should include the common definitions::
|
||||||
definitions::
|
|
||||||
|
|
||||||
include "llvm/CompilerDriver/Common.td"
|
include "llvm/CompilerDriver/Common.td"
|
||||||
|
|
||||||
Internally, LLVMC stores information about possible source
|
Internally, LLVMC stores information about possible source transformations in
|
||||||
transformations in form of a graph. Nodes in this graph represent
|
form of a graph. Nodes in this graph represent tools, and edges between two
|
||||||
tools, and edges between two nodes represent a transformation path. A
|
nodes represent a transformation path. A special "root" node is used to mark
|
||||||
special "root" node is used to mark entry points for the
|
entry points for the transformations. LLVMC also assigns a weight to each edge
|
||||||
transformations. LLVMC also assigns a weight to each edge (more on
|
(more on this later) to choose between several alternative edges.
|
||||||
this later) to choose between several alternative edges.
|
|
||||||
|
|
||||||
The definition of the compilation graph (see file
|
The definition of the compilation graph (see file ``llvmc/src/Base.td`` for an
|
||||||
``plugins/Base/Base.td`` for an example) is just a list of edges::
|
example) is just a list of edges::
|
||||||
|
|
||||||
def CompilationGraph : CompilationGraph<[
|
def CompilationGraph : CompilationGraph<[
|
||||||
Edge<"root", "llvm_gcc_c">,
|
Edge<"root", "llvm_gcc_c">,
|
||||||
@ -245,43 +206,37 @@ The definition of the compilation graph (see file
|
|||||||
|
|
||||||
]>;
|
]>;
|
||||||
|
|
||||||
As you can see, the edges can be either default or optional, where
|
As you can see, the edges can be either default or optional, where optional
|
||||||
optional edges are differentiated by an additional ``case`` expression
|
edges are differentiated by an additional ``case`` expression used to calculate
|
||||||
used to calculate the weight of this edge. Notice also that we refer
|
the weight of this edge. Notice also that we refer to tools via their names (as
|
||||||
to tools via their names (as strings). This makes it possible to add
|
strings). This makes it possible to add edges to an existing compilation graph
|
||||||
edges to an existing compilation graph in plugins without having to
|
without having to know about all tool definitions used in the graph.
|
||||||
know about all tool definitions used in the graph.
|
|
||||||
|
|
||||||
The default edges are assigned a weight of 1, and optional edges get a
|
The default edges are assigned a weight of 1, and optional edges get a weight of
|
||||||
weight of 0 + 2*N where N is the number of tests that evaluated to
|
0 + 2*N where N is the number of tests that evaluated to true in the ``case``
|
||||||
true in the ``case`` expression. It is also possible to provide an
|
expression. It is also possible to provide an integer parameter to
|
||||||
integer parameter to ``inc_weight`` and ``dec_weight`` - in this case,
|
``inc_weight`` and ``dec_weight`` - in this case, the weight is increased (or
|
||||||
the weight is increased (or decreased) by the provided value instead
|
decreased) by the provided value instead of the default 2. Default weight of an
|
||||||
of the default 2. It is also possible to change the default weight of
|
optional edge can be changed by using the ``default`` clause of the ``case``
|
||||||
an optional edge by using the ``default`` clause of the ``case``
|
|
||||||
construct.
|
construct.
|
||||||
|
|
||||||
When passing an input file through the graph, LLVMC picks the edge
|
When passing an input file through the graph, LLVMC picks the edge with the
|
||||||
with the maximum weight. To avoid ambiguity, there should be only one
|
maximum weight. To avoid ambiguity, there should be only one default edge
|
||||||
default edge between two nodes (with the exception of the root node,
|
between two nodes (with the exception of the root node, which gets a special
|
||||||
which gets a special treatment - there you are allowed to specify one
|
treatment - there you are allowed to specify one default edge *per language*).
|
||||||
default edge *per language*).
|
|
||||||
|
|
||||||
When multiple plugins are loaded, their compilation graphs are merged
|
When multiple compilation graphs are defined, they are merged together. Multiple
|
||||||
together. Since multiple edges that have the same end nodes are not
|
edges with the same end nodes are not allowed (i.e. the graph is not a
|
||||||
allowed (i.e. the graph is not a multigraph), an edge defined in
|
multigraph), and will lead to a compile-time error.
|
||||||
several plugins will be replaced by the definition from the plugin
|
|
||||||
that was loaded last. Plugin load order can be controlled by using the
|
|
||||||
plugin priority feature described above.
|
|
||||||
|
|
||||||
To get a visual representation of the compilation graph (useful for
|
To get a visual representation of the compilation graph (useful for debugging),
|
||||||
debugging), run ``llvmc --view-graph``. You will need ``dot`` and
|
run ``llvmc --view-graph``. You will need ``dot`` and ``gsview`` installed for
|
||||||
``gsview`` installed for this to work properly.
|
this to work properly.
|
||||||
|
|
||||||
Describing options
|
Describing options
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Command-line options that the plugin supports are defined by using an
|
Command-line options supported by the driver are defined by using an
|
||||||
``OptionList``::
|
``OptionList``::
|
||||||
|
|
||||||
def Options : OptionList<[
|
def Options : OptionList<[
|
||||||
@ -290,11 +245,10 @@ Command-line options that the plugin supports are defined by using an
|
|||||||
...
|
...
|
||||||
]>;
|
]>;
|
||||||
|
|
||||||
As you can see, the option list is just a list of DAGs, where each DAG
|
As you can see, the option list is just a list of DAGs, where each DAG is an
|
||||||
is an option description consisting of the option name and some
|
option description consisting of the option name and some properties. More than
|
||||||
properties. A plugin can define more than one option list (they are
|
one option list can be defined (they are all merged together in the end), which
|
||||||
all merged together in the end), which can be handy if one wants to
|
can be handy if one wants to separate option groups syntactically.
|
||||||
separate option groups syntactically.
|
|
||||||
|
|
||||||
* Possible option types:
|
* Possible option types:
|
||||||
|
|
||||||
@ -380,42 +334,17 @@ separate option groups syntactically.
|
|||||||
Usage examples: ``(switch_option "foo", (init true))``; ``(prefix_option
|
Usage examples: ``(switch_option "foo", (init true))``; ``(prefix_option
|
||||||
"bar", (init "baz"))``.
|
"bar", (init "baz"))``.
|
||||||
|
|
||||||
- ``extern`` - this option is defined in some other plugin, see `below`__.
|
|
||||||
|
|
||||||
__ extern_
|
|
||||||
|
|
||||||
.. _extern:
|
|
||||||
|
|
||||||
External options
|
|
||||||
----------------
|
|
||||||
|
|
||||||
Sometimes, when linking several plugins together, one plugin needs to
|
|
||||||
access options defined in some other plugin. Because of the way
|
|
||||||
options are implemented, such options must be marked as
|
|
||||||
``extern``. This is what the ``extern`` option property is
|
|
||||||
for. Example::
|
|
||||||
|
|
||||||
...
|
|
||||||
(switch_option "E", (extern))
|
|
||||||
...
|
|
||||||
|
|
||||||
If an external option has additional attributes besides 'extern', they are
|
|
||||||
ignored. See also the section on plugin `priorities`__.
|
|
||||||
|
|
||||||
__ priorities_
|
|
||||||
|
|
||||||
.. _case:
|
.. _case:
|
||||||
|
|
||||||
Conditional evaluation
|
Conditional evaluation
|
||||||
======================
|
======================
|
||||||
|
|
||||||
The 'case' construct is the main means by which programmability is
|
The 'case' construct is the main means by which programmability is achieved in
|
||||||
achieved in LLVMC. It can be used to calculate edge weights, program
|
LLVMC. It can be used to calculate edge weights, program actions and modify the
|
||||||
actions and modify the shell commands to be executed. The 'case'
|
shell commands to be executed. The 'case' expression is designed after the
|
||||||
expression is designed after the similarly-named construct in
|
similarly-named construct in functional languages and takes the form ``(case
|
||||||
functional languages and takes the form ``(case (test_1), statement_1,
|
(test_1), statement_1, (test_2), statement_2, ... (test_N), statement_N)``. The
|
||||||
(test_2), statement_2, ... (test_N), statement_N)``. The statements
|
statements are evaluated only if the corresponding tests evaluate to true.
|
||||||
are evaluated only if the corresponding tests evaluate to true.
|
|
||||||
|
|
||||||
Examples::
|
Examples::
|
||||||
|
|
||||||
@ -439,20 +368,19 @@ Examples::
|
|||||||
(switch_on "B"), "cmdline2",
|
(switch_on "B"), "cmdline2",
|
||||||
(default), "cmdline3")
|
(default), "cmdline3")
|
||||||
|
|
||||||
Note the slight difference in 'case' expression handling in contexts
|
Note the slight difference in 'case' expression handling in contexts of edge
|
||||||
of edge weights and command line specification - in the second example
|
weights and command line specification - in the second example the value of the
|
||||||
the value of the ``"B"`` switch is never checked when switch ``"A"`` is
|
``"B"`` switch is never checked when switch ``"A"`` is enabled, and the whole
|
||||||
enabled, and the whole expression always evaluates to ``"cmdline1"`` in
|
expression always evaluates to ``"cmdline1"`` in that case.
|
||||||
that case.
|
|
||||||
|
|
||||||
Case expressions can also be nested, i.e. the following is legal::
|
Case expressions can also be nested, i.e. the following is legal::
|
||||||
|
|
||||||
(case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
|
(case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
|
||||||
(default), ...)
|
(default), ...)
|
||||||
|
|
||||||
You should, however, try to avoid doing that because it hurts
|
You should, however, try to avoid doing that because it hurts readability. It is
|
||||||
readability. It is usually better to split tool descriptions and/or
|
usually better to split tool descriptions and/or use TableGen inheritance
|
||||||
use TableGen inheritance instead.
|
instead.
|
||||||
|
|
||||||
* Possible tests are:
|
* Possible tests are:
|
||||||
|
|
||||||
@ -526,72 +454,75 @@ use TableGen inheritance instead.
|
|||||||
Example: ``(not (or (test1), (test2), ... (testN)))``.
|
Example: ``(not (or (test1), (test2), ... (testN)))``.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Writing a tool description
|
Writing a tool description
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
As was said earlier, nodes in the compilation graph represent tools,
|
As was said earlier, nodes in the compilation graph represent tools, which are
|
||||||
which are described separately. A tool definition looks like this
|
described separately. A tool definition looks like this (taken from the
|
||||||
(taken from the ``include/llvm/CompilerDriver/Tools.td`` file)::
|
``llvmc/src/Base.td`` file)::
|
||||||
|
|
||||||
def llvm_gcc_cpp : Tool<[
|
def llvm_gcc_cpp : Tool<[
|
||||||
(in_language "c++"),
|
(in_language "c++"),
|
||||||
(out_language "llvm-assembler"),
|
(out_language "llvm-assembler"),
|
||||||
(output_suffix "bc"),
|
(output_suffix "bc"),
|
||||||
(cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
|
(command "llvm-g++ -c -emit-llvm"),
|
||||||
(sink)
|
(sink)
|
||||||
]>;
|
]>;
|
||||||
|
|
||||||
This defines a new tool called ``llvm_gcc_cpp``, which is an alias for
|
This defines a new tool called ``llvm_gcc_cpp``, which is an alias for
|
||||||
``llvm-g++``. As you can see, a tool definition is just a list of
|
``llvm-g++``. As you can see, a tool definition is just a list of properties;
|
||||||
properties; most of them should be self-explanatory. The ``sink``
|
most of them should be self-explanatory. The ``sink`` property means that this
|
||||||
property means that this tool should be passed all command-line
|
tool should be passed all command-line options that aren't mentioned in the
|
||||||
options that aren't mentioned in the option list.
|
option list.
|
||||||
|
|
||||||
The complete list of all currently implemented tool properties follows.
|
The complete list of all currently implemented tool properties follows.
|
||||||
|
|
||||||
* Possible tool properties:
|
* Possible tool properties:
|
||||||
|
|
||||||
- ``in_language`` - input language name. Can be given multiple arguments, in
|
- ``in_language`` - input language name. Can be given multiple arguments, in
|
||||||
case the tool supports multiple input languages.
|
case the tool supports multiple input languages. Used for typechecking and
|
||||||
|
mapping file extensions to tools.
|
||||||
|
|
||||||
- ``out_language`` - output language name. Multiple output languages are
|
- ``out_language`` - output language name. Multiple output languages are
|
||||||
allowed.
|
allowed. Used for typechecking the compilation graph.
|
||||||
|
|
||||||
- ``output_suffix`` - output file suffix. Can also be changed
|
- ``output_suffix`` - output file suffix. Can also be changed dynamically, see
|
||||||
dynamically, see documentation on actions.
|
documentation on `actions`__.
|
||||||
|
|
||||||
- ``cmd_line`` - the actual command used to run the tool. You can
|
|
||||||
use ``$INFILE`` and ``$OUTFILE`` variables, output redirection
|
|
||||||
with ``>``, hook invocations (``$CALL``), environment variables
|
|
||||||
(via ``$ENV``) and the ``case`` construct.
|
|
||||||
|
|
||||||
- ``join`` - this tool is a "join node" in the graph, i.e. it gets a
|
|
||||||
list of input files and joins them together. Used for linkers.
|
|
||||||
|
|
||||||
- ``sink`` - all command-line options that are not handled by other
|
|
||||||
tools are passed to this tool.
|
|
||||||
|
|
||||||
- ``actions`` - A single big ``case`` expression that specifies how
|
|
||||||
this tool reacts on command-line options (described in more detail
|
|
||||||
`below`__).
|
|
||||||
|
|
||||||
__ actions_
|
__ actions_
|
||||||
|
|
||||||
|
- ``command`` - the actual command used to run the tool. You can use output
|
||||||
|
redirection with ``>``, hook invocations (``$CALL``), environment variables
|
||||||
|
(via ``$ENV``) and the ``case`` construct.
|
||||||
|
|
||||||
|
- ``join`` - this tool is a "join node" in the graph, i.e. it gets a list of
|
||||||
|
input files and joins them together. Used for linkers.
|
||||||
|
|
||||||
|
- ``sink`` - all command-line options that are not handled by other tools are
|
||||||
|
passed to this tool.
|
||||||
|
|
||||||
|
- ``actions`` - A single big ``case`` expression that specifies how this tool
|
||||||
|
reacts on command-line options (described in more detail `below`__).
|
||||||
|
|
||||||
|
__ actions_
|
||||||
|
|
||||||
|
- ``out_file_option``, ``in_file_option`` - Options appended to the
|
||||||
|
``command`` string to designate output and input files. Default values are
|
||||||
|
``"-o"`` and ``""``, respectively.
|
||||||
|
|
||||||
.. _actions:
|
.. _actions:
|
||||||
|
|
||||||
Actions
|
Actions
|
||||||
-------
|
-------
|
||||||
|
|
||||||
A tool often needs to react to command-line options, and this is
|
A tool often needs to react to command-line options, and this is precisely what
|
||||||
precisely what the ``actions`` property is for. The next example
|
the ``actions`` property is for. The next example illustrates this feature::
|
||||||
illustrates this feature::
|
|
||||||
|
|
||||||
def llvm_gcc_linker : Tool<[
|
def llvm_gcc_linker : Tool<[
|
||||||
(in_language "object-code"),
|
(in_language "object-code"),
|
||||||
(out_language "executable"),
|
(out_language "executable"),
|
||||||
(output_suffix "out"),
|
(output_suffix "out"),
|
||||||
(cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
|
(command "llvm-gcc"),
|
||||||
(join),
|
(join),
|
||||||
(actions (case (not_empty "L"), (forward "L"),
|
(actions (case (not_empty "L"), (forward "L"),
|
||||||
(not_empty "l"), (forward "l"),
|
(not_empty "l"), (forward "l"),
|
||||||
@ -599,18 +530,17 @@ illustrates this feature::
|
|||||||
[(append_cmd "-dummy1"), (append_cmd "-dummy2")])
|
[(append_cmd "-dummy1"), (append_cmd "-dummy2")])
|
||||||
]>;
|
]>;
|
||||||
|
|
||||||
The ``actions`` tool property is implemented on top of the omnipresent
|
The ``actions`` tool property is implemented on top of the omnipresent ``case``
|
||||||
``case`` expression. It associates one or more different *actions*
|
expression. It associates one or more different *actions* with given
|
||||||
with given conditions - in the example, the actions are ``forward``,
|
conditions - in the example, the actions are ``forward``, which forwards a given
|
||||||
which forwards a given option unchanged, and ``append_cmd``, which
|
option unchanged, and ``append_cmd``, which appends a given string to the tool
|
||||||
appends a given string to the tool execution command. Multiple actions
|
execution command. Multiple actions can be associated with a single condition by
|
||||||
can be associated with a single condition by using a list of actions
|
using a list of actions (used in the example to append some dummy options). The
|
||||||
(used in the example to append some dummy options). The same ``case``
|
same ``case`` construct can also be used in the ``cmd_line`` property to modify
|
||||||
construct can also be used in the ``cmd_line`` property to modify the
|
the tool command line.
|
||||||
tool command line.
|
|
||||||
|
|
||||||
The "join" property used in the example means that this tool behaves
|
The "join" property used in the example means that this tool behaves like a
|
||||||
like a linker.
|
linker.
|
||||||
|
|
||||||
The list of all possible actions follows.
|
The list of all possible actions follows.
|
||||||
|
|
||||||
@ -656,10 +586,10 @@ The list of all possible actions follows.
|
|||||||
Language map
|
Language map
|
||||||
============
|
============
|
||||||
|
|
||||||
If you are adding support for a new language to LLVMC, you'll need to
|
If you are adding support for a new language to LLVMC, you'll need to modify the
|
||||||
modify the language map, which defines mappings from file extensions
|
language map, which defines mappings from file extensions to language names. It
|
||||||
to language names. It is used to choose the proper toolchain(s) for a
|
is used to choose the proper toolchain(s) for a given input file set. Language
|
||||||
given input file set. Language map definition looks like this::
|
map definition looks like this::
|
||||||
|
|
||||||
def LanguageMap : LanguageMap<
|
def LanguageMap : LanguageMap<
|
||||||
[LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
|
[LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
|
||||||
@ -673,9 +603,7 @@ For example, without those definitions the following command wouldn't work::
|
|||||||
llvmc: Unknown suffix: cpp
|
llvmc: Unknown suffix: cpp
|
||||||
|
|
||||||
The language map entries are needed only for the tools that are linked from the
|
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
|
root node. A tool can have multiple output languages.
|
||||||
the graph the input and output languages should match. This is enforced at
|
|
||||||
compile-time.
|
|
||||||
|
|
||||||
Option preprocessor
|
Option preprocessor
|
||||||
===================
|
===================
|
||||||
@ -686,7 +614,7 @@ implemented as switches, we might want to output a warning if the user invokes
|
|||||||
the driver with both of these options enabled.
|
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 ``llvm/src/Base.td.in``)::
|
||||||
|
|
||||||
|
|
||||||
def Preprocess : OptionPreprocessor<
|
def Preprocess : OptionPreprocessor<
|
||||||
@ -705,7 +633,7 @@ that they are not forwarded to the compiler. If no optimization options are
|
|||||||
specified, ``-O2`` is enabled.
|
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 driver is started. The only allowed actions
|
||||||
in ``OptionPreprocessor`` are ``error``, ``warning``, and two special actions:
|
in ``OptionPreprocessor`` are ``error``, ``warning``, and two special actions:
|
||||||
``unset_option`` and ``set_option``. As their names suggest, they can be used to
|
``unset_option`` and ``set_option``. As their names suggest, they can be used to
|
||||||
set or unset a given option. To set an option with ``set_option``, use the
|
set or unset a given option. To set an option with ``set_option``, use the
|
||||||
@ -726,30 +654,28 @@ More advanced topics
|
|||||||
Hooks and environment variables
|
Hooks and environment variables
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
Normally, LLVMC executes programs from the system ``PATH``. Sometimes,
|
Normally, LLVMC searches for programs in the system ``PATH``. Sometimes, this is
|
||||||
this is not sufficient: for example, we may want to specify tool paths
|
not sufficient: for example, we may want to specify tool paths or names in the
|
||||||
or names in the configuration file. This can be easily achieved via
|
configuration file. This can be achieved via the hooks mechanism. To write your
|
||||||
the hooks mechanism. To write your own hooks, just add their
|
own hooks, add their definitions to the ``Hooks.cpp`` or drop a ``.cpp`` file
|
||||||
definitions to the ``PluginMain.cpp`` or drop a ``.cpp`` file into the
|
into your driver directory. Hooks should live in the ``hooks`` namespace and
|
||||||
your plugin directory. Hooks should live in the ``hooks`` namespace
|
have the signature ``std::string hooks::MyHookName ([const char* Arg0 [ const
|
||||||
and have the signature ``std::string hooks::MyHookName ([const char*
|
char* Arg2 [, ...]]])``. They can be used from the ``command`` tool property::
|
||||||
Arg0 [ const char* Arg2 [, ...]]])``. They can be used from the
|
|
||||||
``cmd_line`` tool property::
|
|
||||||
|
|
||||||
(cmd_line "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
|
(command "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
|
||||||
|
|
||||||
To pass arguments to hooks, use the following syntax::
|
To pass arguments to hooks, use the following syntax::
|
||||||
|
|
||||||
(cmd_line "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
|
(command "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
|
||||||
|
|
||||||
It is also possible to use environment variables in the same manner::
|
It is also possible to use environment variables in the same manner::
|
||||||
|
|
||||||
(cmd_line "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
|
(command "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
|
||||||
|
|
||||||
To change the command line string based on user-provided options use
|
To change the command line string based on user-provided options use
|
||||||
the ``case`` expression (documented `above`__)::
|
the ``case`` expression (documented `above`__)::
|
||||||
|
|
||||||
(cmd_line
|
(command
|
||||||
(case
|
(case
|
||||||
(switch_on "E"),
|
(switch_on "E"),
|
||||||
"llvm-g++ -E -x c $INFILE -o $OUTFILE",
|
"llvm-g++ -E -x c $INFILE -o $OUTFILE",
|
||||||
@ -758,42 +684,21 @@ the ``case`` expression (documented `above`__)::
|
|||||||
|
|
||||||
__ case_
|
__ case_
|
||||||
|
|
||||||
.. _priorities:
|
|
||||||
|
|
||||||
How plugins are loaded
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
It is possible for LLVMC plugins to depend on each other. For example,
|
|
||||||
one can create edges between nodes defined in some other plugin. To
|
|
||||||
make this work, however, that plugin should be loaded first. To
|
|
||||||
achieve this, the concept of plugin priority was introduced. By
|
|
||||||
default, every plugin has priority zero; to specify the priority
|
|
||||||
explicitly, put the following line in your plugin's TableGen file::
|
|
||||||
|
|
||||||
def Priority : PluginPriority<$PRIORITY_VALUE>;
|
|
||||||
# Where PRIORITY_VALUE is some integer > 0
|
|
||||||
|
|
||||||
Plugins are loaded in order of their (increasing) priority, starting
|
|
||||||
with 0. Therefore, the plugin with the highest priority value will be
|
|
||||||
loaded last.
|
|
||||||
|
|
||||||
Debugging
|
Debugging
|
||||||
---------
|
---------
|
||||||
|
|
||||||
When writing LLVMC plugins, it can be useful to get a visual view of
|
When writing LLVMC-based drivers, it can be useful to get a visual view of the
|
||||||
the resulting compilation graph. This can be achieved via the command
|
resulting compilation graph. This can be achieved via the command line option
|
||||||
line option ``--view-graph``. This command assumes that Graphviz_ and
|
``--view-graph`` (which assumes that Graphviz_ and Ghostview_ are
|
||||||
Ghostview_ are installed. There is also a ``--write-graph`` option that
|
installed). There is also a ``--write-graph`` option that creates a Graphviz
|
||||||
creates a Graphviz source file (``compilation-graph.dot``) in the
|
source file (``compilation-graph.dot``) in the current directory.
|
||||||
current directory.
|
|
||||||
|
|
||||||
Another useful ``llvmc`` option is ``--check-graph``. It checks the
|
Another useful ``llvmc`` option is ``--check-graph``. It checks the compilation
|
||||||
compilation graph for common errors like mismatched output/input
|
graph for common errors like mismatched output/input language names, multiple
|
||||||
language names, multiple default edges and cycles. These checks can't
|
default edges and cycles. When invoked with ``--check-graph``, ``llvmc`` doesn't
|
||||||
be performed at compile-time because the plugins can load code
|
perform any compilation tasks and returns the number of encountered errors as
|
||||||
dynamically. When invoked with ``--check-graph``, ``llvmc`` doesn't
|
its status code. In the future, these checks will be performed at compile-time
|
||||||
perform any compilation tasks and returns the number of encountered
|
and this option will disappear.
|
||||||
errors as its status code.
|
|
||||||
|
|
||||||
.. _Graphviz: http://www.graphviz.org/
|
.. _Graphviz: http://www.graphviz.org/
|
||||||
.. _Ghostview: http://pages.cs.wisc.edu/~ghost/
|
.. _Ghostview: http://pages.cs.wisc.edu/~ghost/
|
||||||
@ -821,7 +726,7 @@ accessible only in the C++ code (i.e. hooks). Use the following code::
|
|||||||
|
|
||||||
In general, you're encouraged not to make the behaviour dependent on the
|
In general, you're encouraged not to make the behaviour dependent on the
|
||||||
executable file name, and use command-line switches instead. See for example how
|
executable file name, and use command-line switches instead. See for example how
|
||||||
the ``Base`` plugin behaves when it needs to choose the correct linker options
|
the ``llvmc`` program behaves when it needs to choose the correct linker options
|
||||||
(think ``g++`` vs. ``gcc``).
|
(think ``g++`` vs. ``gcc``).
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
@ -17,59 +17,54 @@ Tutorial - Using LLVMC
|
|||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
LLVMC is a generic compiler driver, which plays the same role for LLVM
|
LLVMC is a generic compiler driver, which plays the same role for LLVM as the
|
||||||
as the ``gcc`` program does for GCC - the difference being that LLVMC
|
``gcc`` program does for GCC - the difference being that LLVMC is designed to be
|
||||||
is designed to be more adaptable and easier to customize. Most of
|
more adaptable and easier to customize. Most of LLVMC functionality is
|
||||||
LLVMC functionality is implemented via plugins, which can be loaded
|
implemented via high-level TableGen code, from which a corresponding C++ source
|
||||||
dynamically or compiled in. This tutorial describes the basic usage
|
file is automatically generated. This tutorial describes the basic usage and
|
||||||
and configuration of LLVMC.
|
configuration of LLVMC.
|
||||||
|
|
||||||
|
|
||||||
Compiling with LLVMC
|
Using the ``llvmc`` program
|
||||||
====================
|
===========================
|
||||||
|
|
||||||
In general, LLVMC tries to be command-line compatible with ``gcc`` as
|
In general, ``llvmc`` tries to be command-line compatible with ``gcc`` as much
|
||||||
much as possible, so most of the familiar options work::
|
as possible, so most of the familiar options work::
|
||||||
|
|
||||||
$ llvmc -O3 -Wall hello.cpp
|
$ llvmc -O3 -Wall hello.cpp
|
||||||
$ ./a.out
|
$ ./a.out
|
||||||
hello
|
hello
|
||||||
|
|
||||||
This will invoke ``llvm-g++`` under the hood (you can see which
|
This will invoke ``llvm-g++`` under the hood (you can see which commands are
|
||||||
commands are executed by using the ``-v`` option). For further help on
|
executed by using the ``-v`` option). For further help on command-line LLVMC
|
||||||
command-line LLVMC usage, refer to the ``llvmc --help`` output.
|
usage, refer to the ``llvmc --help`` output.
|
||||||
|
|
||||||
|
|
||||||
Using LLVMC to generate toolchain drivers
|
Using LLVMC to generate toolchain drivers
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
LLVMC plugins are written mostly using TableGen_, so you need to
|
LLVMC-based drivers are written mostly using TableGen_, so you need to be
|
||||||
be familiar with it to get anything done.
|
familiar with it to get anything done.
|
||||||
|
|
||||||
.. _TableGen: http://llvm.org/docs/TableGenFundamentals.html
|
.. _TableGen: http://llvm.org/docs/TableGenFundamentals.html
|
||||||
|
|
||||||
Start by compiling ``example/Simple``, which is a primitive wrapper for
|
Start by compiling ``example/Simple``, which is a primitive wrapper for
|
||||||
``gcc``::
|
``gcc``::
|
||||||
|
|
||||||
$ cd $LLVM_DIR/tools/llvmc
|
$ cd $LLVM_OBJ_DIR/tools/examples/Simple
|
||||||
$ cp -r example/Simple plugins/Simple
|
$ make
|
||||||
|
|
||||||
# NB: A less verbose way to compile standalone LLVMC-based drivers is
|
|
||||||
# described in the reference manual.
|
|
||||||
|
|
||||||
$ make LLVMC_BASED_DRIVER_NAME=mygcc LLVMC_BUILTIN_PLUGINS=Simple
|
|
||||||
$ cat > hello.c
|
$ cat > hello.c
|
||||||
[...]
|
#include <stdio.h>
|
||||||
$ mygcc hello.c
|
int main() { printf("Hello\n"); }
|
||||||
|
$ $LLVM_BIN_DIR/Simple -v hello.c
|
||||||
|
gcc hello.c -o hello.out
|
||||||
$ ./hello.out
|
$ ./hello.out
|
||||||
Hello
|
Hello
|
||||||
|
|
||||||
Here we link our plugin with the LLVMC core statically to form an executable
|
We have thus produced a simple driver called, appropriately, ``Simple``, from
|
||||||
file called ``mygcc``. It is also possible to build our plugin as a dynamic
|
the input TableGen file ``Simple.td``. The ``llvmc`` program itself is generated
|
||||||
library to be loaded by the ``llvmc`` executable (or any other LLVMC-based
|
using a similar process (see ``llvmc/src``). Contents of the file ``Simple.td``
|
||||||
standalone driver); this is described in the reference manual.
|
look like this::
|
||||||
|
|
||||||
Contents of the file ``Simple.td`` look like this::
|
|
||||||
|
|
||||||
// Include common definitions
|
// Include common definitions
|
||||||
include "llvm/CompilerDriver/Common.td"
|
include "llvm/CompilerDriver/Common.td"
|
||||||
@ -79,37 +74,40 @@ Contents of the file ``Simple.td`` look like this::
|
|||||||
[(in_language "c"),
|
[(in_language "c"),
|
||||||
(out_language "executable"),
|
(out_language "executable"),
|
||||||
(output_suffix "out"),
|
(output_suffix "out"),
|
||||||
(cmd_line "gcc $INFILE -o $OUTFILE"),
|
(command "gcc"),
|
||||||
(sink)
|
(sink),
|
||||||
|
|
||||||
|
// -o is what is used by default, out_file_option here is included for
|
||||||
|
// instructive purposes.
|
||||||
|
(out_file_option "-o")
|
||||||
]>;
|
]>;
|
||||||
|
|
||||||
// Language map
|
// Language map
|
||||||
def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>;
|
def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
|
||||||
|
|
||||||
// Compilation graph
|
// Compilation graph
|
||||||
def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>;
|
def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
|
||||||
|
|
||||||
As you can see, this file consists of three parts: tool descriptions,
|
As you can see, this file consists of three parts: tool descriptions, language
|
||||||
language map, and the compilation graph definition.
|
map, and the compilation graph definition.
|
||||||
|
|
||||||
At the heart of LLVMC is the idea of a compilation graph: vertices in
|
At the heart of LLVMC is the idea of a compilation graph: vertices in this graph
|
||||||
this graph are tools, and edges represent a transformation path
|
are tools, and edges represent a transformation path between two tools (for
|
||||||
between two tools (for example, assembly source produced by the
|
example, assembly source produced by the compiler can be transformed into
|
||||||
compiler can be transformed into executable code by an assembler). The
|
executable code by an assembler). The compilation graph is basically a list of
|
||||||
compilation graph is basically a list of edges; a special node named
|
edges; a special node named ``root`` is used to mark graph entry points.
|
||||||
``root`` is used to mark graph entry points.
|
|
||||||
|
|
||||||
Tool descriptions are represented as property lists: most properties
|
Tool descriptions are represented as property lists: most properties in the
|
||||||
in the example above should be self-explanatory; the ``sink`` property
|
example above should be self-explanatory; the ``sink`` property means that all
|
||||||
means that all options lacking an explicit description should be
|
options lacking an explicit description should be forwarded to this tool.
|
||||||
forwarded to this tool.
|
|
||||||
|
|
||||||
The ``LanguageMap`` associates a language name with a list of suffixes
|
The ``LanguageMap`` associates a language name with a list of suffixes and is
|
||||||
and is used for deciding which toolchain corresponds to a given input
|
used for deciding which toolchain corresponds to a given input file.
|
||||||
file.
|
|
||||||
|
|
||||||
To learn more about LLVMC customization, refer to the reference
|
To learn more about writing your own drivers with LLVMC, refer to the reference
|
||||||
manual and plugin source code in the ``plugins`` directory.
|
manual and examples in the ``examples`` directory. Of a particular interest is
|
||||||
|
the ``Skeleton`` example, which can serve as a template for your LLVMC-based
|
||||||
|
drivers.
|
||||||
|
|
||||||
.. raw:: html
|
.. raw:: html
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user