From 113ec35f7f69bd66c0fbab7b42e2b9d59eddb946 Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Tue, 25 Nov 2008 21:38:12 +0000 Subject: Since the old llvmc was removed, rename llvmc2 to llvmc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60048 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/Makefile | 10 +- tools/llvmc/CMakeLists.txt | 4 + tools/llvmc/Makefile | 19 ++ tools/llvmc/doc/LLVMC-Reference.rst | 517 +++++++++++++++++++++++++++++ tools/llvmc/doc/LLVMC-Tutorial.rst | 100 ++++++ tools/llvmc/doc/Makefile | 21 ++ tools/llvmc/doc/img/lines.gif | Bin 0 -> 91 bytes tools/llvmc/doc/llvm.css | 86 +++++ tools/llvmc/driver/Action.cpp | 78 +++++ tools/llvmc/driver/CMakeLists.txt | 9 + tools/llvmc/driver/CompilationGraph.cpp | 438 ++++++++++++++++++++++++ tools/llvmc/driver/Error.h | 33 ++ tools/llvmc/driver/Makefile | 19 ++ tools/llvmc/driver/Plugin.cpp | 73 ++++ tools/llvmc/driver/llvmc.cpp | 119 +++++++ tools/llvmc/plugins/Base/Base.td | 59 ++++ tools/llvmc/plugins/Base/Makefile | 13 + tools/llvmc/plugins/Base/PluginMain.cpp | 1 + tools/llvmc/plugins/Clang/Clang.td | 85 +++++ tools/llvmc/plugins/Clang/Makefile | 13 + tools/llvmc/plugins/Clang/PluginMain.cpp | 1 + tools/llvmc/plugins/Hello/Hello.cpp | 30 ++ tools/llvmc/plugins/Hello/Makefile | 12 + tools/llvmc/plugins/Makefile | 55 +++ tools/llvmc/plugins/Simple/Makefile | 13 + tools/llvmc/plugins/Simple/PluginMain.cpp | 1 + tools/llvmc/plugins/Simple/Simple.td | 30 ++ tools/llvmc2/CMakeLists.txt | 4 - tools/llvmc2/Makefile | 19 -- tools/llvmc2/doc/LLVMC-Reference.rst | 517 ----------------------------- tools/llvmc2/doc/LLVMC-Tutorial.rst | 101 ------ tools/llvmc2/doc/Makefile | 13 - tools/llvmc2/doc/img/lines.gif | Bin 91 -> 0 bytes tools/llvmc2/doc/llvm.css | 86 ----- tools/llvmc2/driver/Action.cpp | 78 ----- tools/llvmc2/driver/CMakeLists.txt | 9 - tools/llvmc2/driver/CompilationGraph.cpp | 438 ------------------------ tools/llvmc2/driver/Error.h | 33 -- tools/llvmc2/driver/Makefile | 19 -- tools/llvmc2/driver/Plugin.cpp | 73 ---- tools/llvmc2/driver/llvmc.cpp | 119 ------- tools/llvmc2/plugins/Base/Base.td | 59 ---- tools/llvmc2/plugins/Base/Makefile | 13 - tools/llvmc2/plugins/Base/PluginMain.cpp | 1 - tools/llvmc2/plugins/Clang/Clang.td | 86 ----- tools/llvmc2/plugins/Clang/Makefile | 14 - tools/llvmc2/plugins/Clang/PluginMain.cpp | 1 - tools/llvmc2/plugins/Hello/Hello.cpp | 32 -- tools/llvmc2/plugins/Hello/Makefile | 12 - tools/llvmc2/plugins/Makefile | 55 --- tools/llvmc2/plugins/Simple/Makefile | 13 - tools/llvmc2/plugins/Simple/PluginMain.cpp | 1 - tools/llvmc2/plugins/Simple/Simple.td | 30 -- 53 files changed, 1834 insertions(+), 1831 deletions(-) create mode 100644 tools/llvmc/CMakeLists.txt create mode 100644 tools/llvmc/Makefile create mode 100644 tools/llvmc/doc/LLVMC-Reference.rst create mode 100644 tools/llvmc/doc/LLVMC-Tutorial.rst create mode 100644 tools/llvmc/doc/Makefile create mode 100644 tools/llvmc/doc/img/lines.gif create mode 100644 tools/llvmc/doc/llvm.css create mode 100644 tools/llvmc/driver/Action.cpp create mode 100644 tools/llvmc/driver/CMakeLists.txt create mode 100644 tools/llvmc/driver/CompilationGraph.cpp create mode 100644 tools/llvmc/driver/Error.h create mode 100644 tools/llvmc/driver/Makefile create mode 100644 tools/llvmc/driver/Plugin.cpp create mode 100644 tools/llvmc/driver/llvmc.cpp create mode 100644 tools/llvmc/plugins/Base/Base.td create mode 100644 tools/llvmc/plugins/Base/Makefile create mode 100644 tools/llvmc/plugins/Base/PluginMain.cpp create mode 100644 tools/llvmc/plugins/Clang/Clang.td create mode 100644 tools/llvmc/plugins/Clang/Makefile create mode 100644 tools/llvmc/plugins/Clang/PluginMain.cpp create mode 100644 tools/llvmc/plugins/Hello/Hello.cpp create mode 100644 tools/llvmc/plugins/Hello/Makefile create mode 100644 tools/llvmc/plugins/Makefile create mode 100644 tools/llvmc/plugins/Simple/Makefile create mode 100644 tools/llvmc/plugins/Simple/PluginMain.cpp create mode 100644 tools/llvmc/plugins/Simple/Simple.td delete mode 100644 tools/llvmc2/CMakeLists.txt delete mode 100644 tools/llvmc2/Makefile delete mode 100644 tools/llvmc2/doc/LLVMC-Reference.rst delete mode 100644 tools/llvmc2/doc/LLVMC-Tutorial.rst delete mode 100644 tools/llvmc2/doc/Makefile delete mode 100644 tools/llvmc2/doc/img/lines.gif delete mode 100644 tools/llvmc2/doc/llvm.css delete mode 100644 tools/llvmc2/driver/Action.cpp delete mode 100644 tools/llvmc2/driver/CMakeLists.txt delete mode 100644 tools/llvmc2/driver/CompilationGraph.cpp delete mode 100644 tools/llvmc2/driver/Error.h delete mode 100644 tools/llvmc2/driver/Makefile delete mode 100644 tools/llvmc2/driver/Plugin.cpp delete mode 100644 tools/llvmc2/driver/llvmc.cpp delete mode 100644 tools/llvmc2/plugins/Base/Base.td delete mode 100644 tools/llvmc2/plugins/Base/Makefile delete mode 100644 tools/llvmc2/plugins/Base/PluginMain.cpp delete mode 100644 tools/llvmc2/plugins/Clang/Clang.td delete mode 100644 tools/llvmc2/plugins/Clang/Makefile delete mode 100644 tools/llvmc2/plugins/Clang/PluginMain.cpp delete mode 100644 tools/llvmc2/plugins/Hello/Hello.cpp delete mode 100644 tools/llvmc2/plugins/Hello/Makefile delete mode 100644 tools/llvmc2/plugins/Makefile delete mode 100644 tools/llvmc2/plugins/Simple/Makefile delete mode 100644 tools/llvmc2/plugins/Simple/PluginMain.cpp delete mode 100644 tools/llvmc2/plugins/Simple/Simple.td (limited to 'tools') diff --git a/tools/Makefile b/tools/Makefile index 30da522..2726c1f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,22 +1,22 @@ ##===- tools/Makefile --------------------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## LEVEL := .. -# NOTE: The tools are organized into five groups of four consisting of one -# large and three small executables. This is done to minimize memory load +# NOTE: The tools are organized into five groups of four consisting of one +# large and three small executables. This is done to minimize memory load # in parallel builds. Please retain this ordering. PARALLEL_DIRS := llvm-config \ opt llvm-as llvm-dis \ llc llvm-ranlib llvm-ar llvm-nm \ llvm-ld llvm-prof llvm-link \ lli gccas gccld llvm-extract llvm-db \ - bugpoint llvm-bcanalyzer llvm-stub llvmc2 + bugpoint llvm-bcanalyzer llvm-stub llvmc include $(LEVEL)/Makefile.config diff --git a/tools/llvmc/CMakeLists.txt b/tools/llvmc/CMakeLists.txt new file mode 100644 index 0000000..f820419 --- /dev/null +++ b/tools/llvmc/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(driver) + +# TODO: support plugins and user-configured builds. +# See ./doc/LLVMC-Reference.rst "Customizing LLVMC: the compilation graph" diff --git a/tools/llvmc/Makefile b/tools/llvmc/Makefile new file mode 100644 index 0000000..8eb35cb --- /dev/null +++ b/tools/llvmc/Makefile @@ -0,0 +1,19 @@ +##===- tools/llvmc/Makefile --------------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. + +BUILTIN_PLUGINS = Base +DRIVER_NAME = llvmc +DIRS = plugins driver + +export BUILTIN_PLUGINS +export DRIVER_NAME + +include $(LEVEL)/Makefile.common diff --git a/tools/llvmc/doc/LLVMC-Reference.rst b/tools/llvmc/doc/LLVMC-Reference.rst new file mode 100644 index 0000000..77d9d2b --- /dev/null +++ b/tools/llvmc/doc/LLVMC-Reference.rst @@ -0,0 +1,517 @@ +=================================== +Customizing LLVMC: Reference Manual +=================================== +:Author: Mikhail Glushenkov + +LLVMC is a generic compiler driver, designed to be customizable and +extensible. It plays the same role for LLVM as the ``gcc`` program +does for GCC - LLVMC's job is essentially to transform a set of input +files into a set of targets depending on configuration rules and user +options. What makes LLVMC different is that these transformation rules +are completely customizable - in fact, LLVMC knows nothing about the +specifics of transformation (even the command-line options are mostly +not hard-coded) and regards the transformation structure as an +abstract graph. The structure of this graph is completely determined +by plugins, which can be either statically or dynamically linked. This +makes it possible to easily adapt LLVMC for other purposes - for +example, as a build tool for game resources. + +Because LLVMC employs TableGen [1]_ as its configuration language, you +need to be familiar with it to customize LLVMC. + + +.. contents:: + + +Compiling with LLVMC +==================== + +LLVMC tries hard to be as compatible with ``gcc`` as possible, +although there are some small differences. Most of the time, however, +you shouldn't be able to notice them:: + + $ # This works as expected: + $ llvmc -O3 -Wall hello.cpp + $ ./a.out + hello + +One nice feature of LLVMC is that one doesn't have to distinguish +between different compilers for different languages (think ``g++`` and +``gcc``) - the right toolchain is chosen automatically based on input +language names (which are, in turn, determined from file +extensions). If you want to force files ending with ".c" to compile as +C++, use the ``-x`` option, just like you would do it with ``gcc``:: + + $ # hello.c is really a C++ file + $ llvmc -x c++ hello.c + $ ./a.out + hello + +On the other hand, when using LLVMC as a linker to combine several C++ +object files you should provide the ``--linker`` option since it's +impossible for LLVMC to choose the right linker in that case:: + + $ llvmc -c hello.cpp + $ llvmc hello.o + [A lot of link-time errors skipped] + $ llvmc --linker=c++ hello.o + $ ./a.out + hello + + +Predefined options +================== + +LLVMC has some built-in options that can't be overridden in the +configuration files: + +* ``-o FILE`` - Output file name. + +* ``-x LANGUAGE`` - Specify the language of the following input files + 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. + +* ``--view-graph`` - Show a graphical representation of the compilation + graph. Requires that you have ``dot`` and ``gv`` programs + installed. Hidden option, useful for debugging. + +* ``--write-graph`` - Write a ``compilation-graph.dot`` file in the + current directory with the compilation graph description in the + Graphviz format. Hidden option, useful for debugging. + +* ``--save-temps`` - Write temporary files to the current directory + and do not delete them on exit. Hidden option, useful for debugging. + +* ``--help``, ``--help-hidden``, ``--version`` - These options have + their standard meaning. + + +Compiling LLVMC plugins +======================= + +It's easiest to start working on your own LLVMC plugin by copying the +skeleton project which lives under ``$LLVMC_DIR/plugins/Simple``:: + + $ cd $LLVMC_DIR/plugins + $ cp -r Simple MyPlugin + $ cd MyPlugin + $ ls + Makefile PluginMain.cpp Simple.td + +As you can see, our basic plugin consists of only two files (not +counting the build script). ``Simple.td`` contains TableGen +description of the compilation graph; its format is documented in the +following sections. ``PluginMain.cpp`` is just a helper file used to +compile the auto-generated C++ code produced from TableGen source. It +can also contain hook definitions (see `below`__). + +__ hooks_ + +The first thing that you should do is to change the ``LLVMC_PLUGIN`` +variable in the ``Makefile`` to avoid conflicts (since this variable +is used to name the resulting library):: + + LLVMC_PLUGIN=MyPlugin + +It is also a good idea to rename ``Simple.td`` to something less +generic:: + + $ mv Simple.td MyPlugin.td + +Note that the plugin source directory must be placed under +``$LLVMC_DIR/plugins`` to make use of the existing build +infrastructure. To build a version of the LLVMC executable called +``mydriver`` with your plugin compiled in, use the following command:: + + $ cd $LLVMC_DIR + $ make BUILTIN_PLUGINS=MyPlugin DRIVER_NAME=mydriver + +To build your plugin as a dynamic library, just ``cd`` to its source +directory and run ``make``. The resulting file will be called +``LLVMC$(LLVMC_PLUGIN).$(DLL_EXTENSION)`` (in our case, +``LLVMCMyPlugin.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/LLVMCSimple.so + +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 BUILTIN_PLUGINS="" + +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 ``.td`` 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. + + +Customizing LLVMC: the compilation graph +======================================== + +Each TableGen configuration file should include the common +definitions:: + + include "llvm/CompilerDriver/Common.td" + // And optionally: + // include "llvm/CompilerDriver/Tools.td" + // which contains some useful tool definitions. + +Internally, LLVMC stores information about possible source +transformations in form of a graph. Nodes in this graph represent +tools, and edges between two nodes represent a transformation path. A +special "root" node is used to mark entry points for the +transformations. LLVMC also assigns a weight to each edge (more on +this later) to choose between several alternative edges. + +The definition of the compilation graph (see file +``plugins/Base/Base.td`` for an example) is just a list of edges:: + + def CompilationGraph : CompilationGraph<[ + Edge<"root", "llvm_gcc_c">, + Edge<"root", "llvm_gcc_assembler">, + ... + + Edge<"llvm_gcc_c", "llc">, + Edge<"llvm_gcc_cpp", "llc">, + ... + + OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), + (inc_weight))>, + OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), + (inc_weight))>, + ... + + OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker", + (case (input_languages_contain "c++"), (inc_weight), + (or (parameter_equals "linker", "g++"), + (parameter_equals "linker", "c++")), (inc_weight))>, + ... + + ]>; + +As you can see, the edges can be either default or optional, where +optional edges are differentiated by an additional ``case`` expression +used to calculate the weight of this edge. Notice also that we refer +to tools via their names (as strings). This makes it possible to add +edges to an existing compilation graph in plugins without having to +know about all tool definitions used in the graph. + +The default edges are assigned a weight of 1, and optional edges get a +weight of 0 + 2*N where N is the number of tests that evaluated to +true in the ``case`` expression. It is also possible to provide an +integer parameter to ``inc_weight`` and ``dec_weight`` - in this case, +the weight is increased (or decreased) by the provided value instead +of the default 2. + +When passing an input file through the graph, LLVMC picks the edge +with the maximum weight. To avoid ambiguity, there should be only one +default edge between two nodes (with the exception of the root node, +which gets a special treatment - there you are allowed to specify one +default edge *per language*). + +To get a visual representation of the compilation graph (useful for +debugging), run ``llvmc --view-graph``. You will need ``dot`` and +``gsview`` installed for this to work properly. + + +Writing a tool description +========================== + +As was said earlier, nodes in the compilation graph represent tools, +which are described separately. A tool definition looks like this +(taken from the ``include/llvm/CompilerDriver/Tools.td`` file):: + + def llvm_gcc_cpp : Tool<[ + (in_language "c++"), + (out_language "llvm-assembler"), + (output_suffix "bc"), + (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"), + (sink) + ]>; + +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 +properties; most of them should be self-explanatory. The ``sink`` +property means that this tool should be passed all command-line +options that lack explicit descriptions. + +The complete list of the currently implemented tool properties follows: + +* Possible tool properties: + + - ``in_language`` - input language name. Can be either a string or a + list, in case the tool supports multiple input languages. + + - ``out_language`` - output language name. + + - ``output_suffix`` - output file suffix. + + - ``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 (more on this below). + + - ``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. + +The next tool definition is slightly more complex:: + + def llvm_gcc_linker : Tool<[ + (in_language "object-code"), + (out_language "executable"), + (output_suffix "out"), + (cmd_line "llvm-gcc $INFILE -o $OUTFILE"), + (join), + (prefix_list_option "L", (forward), + (help "add a directory to link path")), + (prefix_list_option "l", (forward), + (help "search a library when linking")), + (prefix_list_option "Wl", (unpack_values), + (help "pass options to linker")) + ]>; + +This tool has a "join" property, which means that it behaves like a +linker. This tool also defines several command-line options: ``-l``, +``-L`` and ``-Wl`` which have their usual meaning. An option has two +attributes: a name and a (possibly empty) list of properties. All +currently implemented option types and properties are described below: + +* Possible option types: + + - ``switch_option`` - a simple boolean switch, for example ``-time``. + + - ``parameter_option`` - option that takes an argument, for example + ``-std=c99``; + + - ``parameter_list_option`` - same as the above, but more than one + occurence of the option is allowed. + + - ``prefix_option`` - same as the parameter_option, but the option name + and parameter value are not separated. + + - ``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")`` + + +* Possible option properties: + + - ``append_cmd`` - append a string to the tool invocation command. + + - ``forward`` - forward this option unchanged. + + - ``forward_as`` - Change the name of this option, but forward the + argument unchanged. Example: ``(forward_as "--disable-optimize")``. + + - ``output_suffix`` - modify the output suffix of this + tool. Example: ``(switch "E", (output_suffix "i")``. + + - ``stop_compilation`` - stop compilation after this phase. + + - ``unpack_values`` - used for for splitting and forwarding + comma-separated lists of options, e.g. ``-Wa,-foo=bar,-baz`` is + converted to ``-foo=bar -baz`` and appended to the tool invocation + command. + + - ``help`` - help string associated with this option. Used for + ``--help`` output. + + - ``required`` - this option is obligatory. + + +Option list - specifying all options in a single place +====================================================== + +It can be handy to have all information about options gathered in a +single place to provide an overview. This can be achieved by using a +so-called ``OptionList``:: + + def Options : OptionList<[ + (switch_option "E", (help "Help string")), + (alias_option "quiet", "q") + ... + ]>; + +``OptionList`` is also a good place to specify option aliases. + +Tool-specific option properties like ``append_cmd`` have (obviously) +no meaning in the context of ``OptionList``, so the only properties +allowed there are ``help`` and ``required``. + +Option lists are used at file scope. See the file +``plugins/Clang/Clang.td`` for an example of ``OptionList`` usage. + +.. _hooks: + +Using hooks and environment variables in the ``cmd_line`` property +================================================================== + +Normally, LLVMC executes programs from the system ``PATH``. Sometimes, +this is not sufficient: for example, we may want to specify tool names +in the configuration file. This can be achieved via the mechanism of +hooks - to write your own hooks, just add their definitions to the +``PluginMain.cpp`` or drop a ``.cpp`` file into the +``$LLVMC_DIR/driver`` directory. Hooks should live in the ``hooks`` +namespace and have the signature ``std::string hooks::MyHookName +(void)``. They can be used from the ``cmd_line`` tool property:: + + (cmd_line "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)") + +It is also possible to use environment variables in the same manner:: + + (cmd_line "$ENV(VAR1)/path/to/file -o $ENV(VAR2)") + +To change the command line string based on user-provided options use +the ``case`` expression (documented below):: + + (cmd_line + (case + (switch_on "E"), + "llvm-g++ -E -x c $INFILE -o $OUTFILE", + (default), + "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm")) + +Conditional evaluation: the ``case`` expression +=============================================== + +The 'case' construct can be used to calculate weights of the optional +edges and to choose between several alternative command line strings +in the ``cmd_line`` tool property. It is designed after the +similarly-named construct in functional languages and takes the form +``(case (test_1), statement_1, (test_2), statement_2, ... (test_N), +statement_N)``. The statements are evaluated only if the corresponding +tests evaluate to true. + +Examples:: + + // Increases edge weight by 5 if "-A" is provided on the + // command-line, and by 5 more if "-B" is also provided. + (case + (switch_on "A"), (inc_weight 5), + (switch_on "B"), (inc_weight 5)) + + // Evaluates to "cmdline1" if option "-A" is provided on the + // command line, otherwise to "cmdline2" + (case + (switch_on "A"), "cmdline1", + (switch_on "B"), "cmdline2", + (default), "cmdline3") + +Note the slight difference in 'case' expression handling in contexts +of edge weights and command line specification - in the second example +the value of the ``"B"`` switch is never checked when switch ``"A"`` is +enabled, and the whole expression always evaluates to ``"cmdline1"`` in +that case. + +Case expressions can also be nested, i.e. the following is legal:: + + (case (switch_on "E"), (case (switch_on "o"), ..., (default), ...) + (default), ...) + +You should, however, try to avoid doing that because it hurts +readability. It is usually better to split tool descriptions and/or +use TableGen inheritance instead. + +* Possible tests are: + + - ``switch_on`` - Returns true if a given command-line switch is + provided by the user. Example: ``(switch_on "opt")``. Note that + you have to define all possible command-line options separately in + the tool descriptions. See the next section for the discussion of + different kinds of command-line options. + + - ``parameter_equals`` - Returns true if a command-line parameter equals + a given value. Example: ``(parameter_equals "W", "all")``. + + - ``element_in_list`` - Returns true if a command-line parameter list + includes a given value. Example: ``(parameter_in_list "l", "pthread")``. + + - ``input_languages_contain`` - Returns true if a given language + belongs to the current input language set. Example: + ``(input_languages_contain "c++")``. + + - ``in_language`` - Evaluates to true if the language of the input + file equals to the argument. At the moment works only with + ``cmd_line`` property on non-join nodes. Example: ``(in_language + "c++")``. + + - ``not_empty`` - Returns true if a given option (which should be + either a parameter or a parameter list) is set by the + user. Example: ``(not_empty "o")``. + + - ``default`` - Always evaluates to true. Should always be the last + test in the ``case`` expression. + + - ``and`` - A standard logical combinator that returns true iff all + of its arguments return true. Used like this: ``(and (test1), + (test2), ... (testN))``. Nesting of ``and`` and ``or`` is allowed, + but not encouraged. + + - ``or`` - Another logical combinator that returns true only if any + one of its arguments returns true. Example: ``(or (test1), + (test2), ... (testN))``. + + +Language map +============ + +One last thing that you will need to modify when adding support for a +new language to LLVMC is the language map, which defines mappings from +file extensions to language names. It is used to choose the proper +toolchain(s) for a given input file set. Language map definition looks +like this:: + + def LanguageMap : LanguageMap< + [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>, + LangToSuffixes<"c", ["c"]>, + ... + ]>; + +Debugging +========= + +When writing LLVMC plugins, it can be useful to get a visual view of +the resulting compilation graph. This can be achieved via the command +line option ``--view-graph``. This command assumes that Graphviz [2]_ and +Ghostview [3]_ are installed. There is also a ``--dump-graph`` option that +creates a Graphviz source file(``compilation-graph.dot``) in the +current directory. + + +References +========== + +.. [1] TableGen Fundamentals + http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html + +.. [2] Graphviz + http://www.graphviz.org/ + +.. [3] Ghostview + http://pages.cs.wisc.edu/~ghost/ diff --git a/tools/llvmc/doc/LLVMC-Tutorial.rst b/tools/llvmc/doc/LLVMC-Tutorial.rst new file mode 100644 index 0000000..d41f90d --- /dev/null +++ b/tools/llvmc/doc/LLVMC-Tutorial.rst @@ -0,0 +1,100 @@ +====================== +Tutorial - Using LLVMC +====================== +:Author: Mikhail Glushenkov + +LLVMC is a generic compiler driver, which plays the same role for LLVM +as the ``gcc`` program does for GCC - the difference being that LLVMC +is designed to be more adaptable and easier to customize. Most of +LLVMC functionality is implemented via plugins, which can be loaded +dynamically or compiled in. This tutorial describes the basic usage +and configuration of LLVMC. + + +.. contents:: + + +Compiling with LLVMC +==================== + +In general, LLVMC tries to be command-line compatible with ``gcc`` as +much as possible, so most of the familiar options work:: + + $ llvmc -O3 -Wall hello.cpp + $ ./a.out + hello + +This will invoke ``llvm-g++`` under the hood (you can see which +commands are executed by using the ``-v`` option). For further help on +command-line LLVMC usage, refer to the ``llvmc --help`` output. + + +Using LLVMC to generate toolchain drivers +========================================= + +LLVMC plugins are written mostly using TableGen [1]_, so you need to +be familiar with it to get anything done. + +Start by compiling ``plugins/Simple/Simple.td``, which is a primitive +wrapper for ``gcc``:: + + $ cd $LLVM_DIR/tools/llvmc + $ make DRIVER_NAME=mygcc BUILTIN_PLUGINS=Simple + $ cat > hello.c + [...] + $ mygcc hello.c + $ ./hello.out + Hello + +Here we link our plugin with the LLVMC core statically to form an +executable file called ``mygcc``. It is also possible to build our +plugin as a standalone dynamic library; this is described in the +reference manual. + +Contents of the file ``Simple.td`` look like this:: + + // Include common definitions + include "llvm/CompilerDriver/Common.td" + + // Tool descriptions + def gcc : Tool< + [(in_language "c"), + (out_language "executable"), + (output_suffix "out"), + (cmd_line "gcc $INFILE -o $OUTFILE"), + (sink) + ]>; + + // Language map + def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>; + + // Compilation graph + def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>; + +As you can see, this file consists of three parts: tool descriptions, +language map, and the compilation graph definition. + +At the heart of LLVMC is the idea of a compilation graph: vertices in +this graph are tools, and edges represent a transformation path +between two tools (for example, assembly source produced by the +compiler can be transformed into executable code by an assembler). The +compilation graph is basically a list of edges; a special node named +``root`` is used to mark graph entry points. + +Tool descriptions are represented as property lists: most properties +in the example above should be self-explanatory; the ``sink`` property +means that all options lacking an explicit description should be +forwarded to this tool. + +The ``LanguageMap`` associates a language name with a list of suffixes +and is used for deciding which toolchain corresponds to a given input +file. + +To learn more about LLVMC customization, refer to the reference +manual and plugin source code in the ``plugins`` directory. + +References +========== + +.. [1] TableGen Fundamentals + http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html diff --git a/tools/llvmc/doc/Makefile b/tools/llvmc/doc/Makefile new file mode 100644 index 0000000..864376f --- /dev/null +++ b/tools/llvmc/doc/Makefile @@ -0,0 +1,21 @@ +##===- tools/llvmc/doc/Makefile ----------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +RST2HTML=rst2html --stylesheet=llvm.css --link-stylesheet + +all : LLVMC-Reference.html LLVMC-Tutorial.html + +LLVMC-Tutorial.html : LLVMC-Tutorial.rst llvm.css + $(RST2HTML) $< $@ + +LLVMC-Reference.html : LLVMC-Reference.rst llvm.css + $(RST2HTML) $< $@ + +clean : + rm *.html diff --git a/tools/llvmc/doc/img/lines.gif b/tools/llvmc/doc/img/lines.gif new file mode 100644 index 0000000..88f491e Binary files /dev/null and b/tools/llvmc/doc/img/lines.gif differ diff --git a/tools/llvmc/doc/llvm.css b/tools/llvmc/doc/llvm.css new file mode 100644 index 0000000..1c7e5cc --- /dev/null +++ b/tools/llvmc/doc/llvm.css @@ -0,0 +1,86 @@ +/* + * LLVM documentation style sheet + */ + +/* Common styles */ +.body { color: black; background: white; margin: 0 0 0 0 } + +/* No borders on image links */ +a:link img, a:visited img {border-style: none} + +address img { float: right; width: 88px; height: 31px; } +address { clear: right; } + +TR, TD { border: 2px solid gray; padding: 4pt 4pt 2pt 2pt; } +TH { border: 2px solid gray; font-weight: bold; font-size: 105%; + background: url("img/lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; text-align:center; + vertical-align: middle; } +TABLE { text-align: center; border: 2px solid black; + border-collapse: collapse; margin-top: 1em; margin-left: 1em; + margin-right: 1em; margin-bottom: 1em; } +/* + * Documentation + */ +/* Common for title and header */ +h1 { + color: black; background: url("img/lines.gif"); + font-family: "Georgia,Palatino,Times,Roman,SanSerif"; font-weight: bold; + border-width: 1px; + border-style: solid none solid none; + text-align: center; + vertical-align: middle; + padding-left: 8pt; + padding-top: 1px; + padding-bottom: 2px +} + +.doc_title { text-align: left; font-size: 25pt } +.doc_section { text-align: center; font-size: 22pt; + margin: 20pt 0pt 5pt 0pt; } +.doc_subsection { width: 75%; + text-align: left; font-size: 12pt; padding: 4pt 4pt 4pt 4pt; + margin: 1.5em 0.5em 0.5em 0.5em } + +.doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em; + font-weight: bold; font-style: oblique; + border-bottom: 1px solid #999999; font-size: 12pt; + width: 75%; } +.doc_author { text-align: left; font-weight: bold; padding-left: 20pt } +.doc_text { text-align: left; padding-left: 20pt; padding-right: 10pt } + +.doc_footer { text-align: left; padding: 0 0 0 0 } + +.doc_hilite { color: blue; font-weight: bold; } + +.doc_table { text-align: center; width: 90%; + padding: 1px 1px 1px 1px; border: 1px; } + +.doc_table_nw { text-align: center; border: 1px; + padding: 1px 1px 1px 1px; } + +.doc_warning { color: red; font-weight: bold } + +.literal-block { border: solid 1px gray; background: #eeeeee; + margin: 0 1em 0 1em; + padding: 0 1em 0 1em; + display:table; + } +.doc_notes { background: #fafafa; border: 1px solid #cecece; padding: 0.1em } + +TABLE.layout { text-align: left; border: none; border-collapse: collapse; + padding: 4px 4px 4px 4px; } +TR.layout { border: none; padding: 4pt 4pt 2pt 2pt; } +TD.layout { border: none; padding: 4pt 4pt 2pt 2pt; + vertical-align: top;} +TD.left { border: none; padding: 4pt 4pt 2pt 2pt; text-align: left; + vertical-align: top;} +TD.right { border: none; padding: 4pt 4pt 2pt 2pt; text-align: right; + vertical-align: top;} +TH.layout { border: none; font-weight: bold; font-size: 105%; + text-align:center; vertical-align: middle; } + +/* Left align table cell */ +.td_left { border: 2px solid gray; text-align: left; } + +.toc-backref { color: black; } diff --git a/tools/llvmc/driver/Action.cpp b/tools/llvmc/driver/Action.cpp new file mode 100644 index 0000000..c0a1b84 --- /dev/null +++ b/tools/llvmc/driver/Action.cpp @@ -0,0 +1,78 @@ +//===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Action class - implementation and auxiliary functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/Action.h" + +#include "llvm/Support/CommandLine.h" +#include "llvm/System/Program.h" + +#include +#include + +using namespace llvm; +using namespace llvmc; + +extern cl::opt DryRun; +extern cl::opt VerboseMode; + +namespace { + int ExecuteProgram(const std::string& name, + const StrVector& args) { + sys::Path prog = sys::Program::FindProgramByName(name); + + if (prog.isEmpty()) + throw std::runtime_error("Can't find program '" + name + "'"); + if (!prog.canExecute()) + throw std::runtime_error("Program '" + name + "' is not executable."); + + // Build the command line vector and the redirects array. + const sys::Path* redirects[3] = {0,0,0}; + sys::Path stdout_redirect; + + std::vector argv; + argv.reserve((args.size()+2)); + argv.push_back(name.c_str()); + + for (StrVector::const_iterator B = args.begin(), E = args.end(); + B!=E; ++B) { + if (*B == ">") { + ++B; + stdout_redirect.set(*B); + redirects[1] = &stdout_redirect; + } + else { + argv.push_back((*B).c_str()); + } + } + argv.push_back(0); // null terminate list. + + // Invoke the program. + return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]); + } + + void print_string (const std::string& str) { + std::cerr << str << ' '; + } +} + +int llvmc::Action::Execute() const { + if (DryRun || VerboseMode) { + std::cerr << Command_ << " "; + std::for_each(Args_.begin(), Args_.end(), print_string); + std::cerr << '\n'; + } + if (DryRun) + return 0; + else + return ExecuteProgram(Command_, Args_); +} diff --git a/tools/llvmc/driver/CMakeLists.txt b/tools/llvmc/driver/CMakeLists.txt new file mode 100644 index 0000000..7d4e967 --- /dev/null +++ b/tools/llvmc/driver/CMakeLists.txt @@ -0,0 +1,9 @@ +set(LLVM_LINK_COMPONENTS support system) +set(LLVM_REQUIRES_EH 1) + +add_llvm_tool(llvmc2 + Action.cpp + CompilationGraph.cpp + llvmc.cpp + Plugin.cpp + ) diff --git a/tools/llvmc/driver/CompilationGraph.cpp b/tools/llvmc/driver/CompilationGraph.cpp new file mode 100644 index 0000000..81283ba --- /dev/null +++ b/tools/llvmc/driver/CompilationGraph.cpp @@ -0,0 +1,438 @@ +//===--- CompilationGraph.cpp - The LLVM Compiler Driver --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Compilation graph - implementation. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "llvm/CompilerDriver/CompilationGraph.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/DOTGraphTraits.h" +#include "llvm/Support/GraphWriter.h" + +#include +#include +#include +#include +#include + +using namespace llvm; +using namespace llvmc; + +extern cl::list InputFilenames; +extern cl::opt OutputFilename; +extern cl::list Languages; + +namespace llvmc { + + const std::string& LanguageMap::GetLanguage(const sys::Path& File) const { + LanguageMap::const_iterator Lang = this->find(File.getSuffix()); + if (Lang == this->end()) + throw std::runtime_error("Unknown suffix: " + File.getSuffix()); + return Lang->second; + } +} + +namespace { + + /// ChooseEdge - Return the edge with the maximum weight. + template + const Edge* ChooseEdge(const C& EdgesContainer, + const InputLanguagesSet& InLangs, + const std::string& NodeName = "root") { + const Edge* MaxEdge = 0; + unsigned MaxWeight = 0; + bool SingleMax = true; + + for (typename C::const_iterator B = EdgesContainer.begin(), + E = EdgesContainer.end(); B != E; ++B) { + const Edge* e = B->getPtr(); + unsigned EW = e->Weight(InLangs); + if (EW > MaxWeight) { + MaxEdge = e; + MaxWeight = EW; + SingleMax = true; + } else if (EW == MaxWeight) { + SingleMax = false; + } + } + + if (!SingleMax) + throw std::runtime_error("Node " + NodeName + + ": multiple maximal outward edges found!" + " Most probably a specification error."); + if (!MaxEdge) + throw std::runtime_error("Node " + NodeName + + ": no maximal outward edge found!" + " Most probably a specification error."); + return MaxEdge; + } + +} + +CompilationGraph::CompilationGraph() { + NodesMap["root"] = Node(this); +} + +Node& CompilationGraph::getNode(const std::string& ToolName) { + nodes_map_type::iterator I = NodesMap.find(ToolName); + if (I == NodesMap.end()) + throw std::runtime_error("Node " + ToolName + " is not in the graph"); + return I->second; +} + +const Node& CompilationGraph::getNode(const std::string& ToolName) const { + nodes_map_type::const_iterator I = NodesMap.find(ToolName); + if (I == NodesMap.end()) + throw std::runtime_error("Node " + ToolName + " is not in the graph!"); + return I->second; +} + +// Find the tools list corresponding to the given language name. +const CompilationGraph::tools_vector_type& +CompilationGraph::getToolsVector(const std::string& LangName) const +{ + tools_map_type::const_iterator I = ToolsMap.find(LangName); + if (I == ToolsMap.end()) + throw std::runtime_error("No tool corresponding to the language " + + LangName + " found"); + return I->second; +} + +void CompilationGraph::insertNode(Tool* V) { + if (NodesMap.count(V->Name()) == 0) + NodesMap[V->Name()] = Node(this, V); +} + +void CompilationGraph::insertEdge(const std::string& A, Edge* Edg) { + Node& B = getNode(Edg->ToolName()); + if (A == "root") { + const char** InLangs = B.ToolPtr->InputLanguages(); + for (;*InLangs; ++InLangs) + ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr(Edg)); + NodesMap["root"].AddEdge(Edg); + } + else { + Node& N = getNode(A); + N.AddEdge(Edg); + } + // Increase the inward edge counter. + B.IncrInEdges(); +} + +namespace { + sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName, + const std::string& Suffix) { + sys::Path Out; + + // Make sure we don't end up with path names like '/file.o' if the + // TempDir is empty. + if (TempDir.empty()) { + Out.set(BaseName); + } + else { + Out = TempDir; + Out.appendComponent(BaseName); + } + Out.appendSuffix(Suffix); + // NOTE: makeUnique always *creates* a unique temporary file, + // which is good, since there will be no races. However, some + // tools do not like it when the output file already exists, so + // they have to be placated with -f or something like that. + Out.makeUnique(true, NULL); + return Out; + } +} + +// Pass input file through the chain until we bump into a Join node or +// a node that says that it is the last. +void CompilationGraph::PassThroughGraph (const sys::Path& InFile, + const Node* StartNode, + const InputLanguagesSet& InLangs, + const sys::Path& TempDir, + const LanguageMap& LangMap) const { + bool Last = false; + sys::Path In = InFile; + const Node* CurNode = StartNode; + + while(!Last) { + sys::Path Out; + Tool* CurTool = CurNode->ToolPtr.getPtr(); + + if (CurTool->IsJoin()) { + JoinTool& JT = dynamic_cast(*CurTool); + JT.AddToJoinList(In); + break; + } + + // Since toolchains do not have to end with a Join node, we should + // check if this Node is the last. + if (!CurNode->HasChildren() || CurTool->IsLast()) { + if (!OutputFilename.empty()) { + Out.set(OutputFilename); + } + else { + Out.set(In.getBasename()); + Out.appendSuffix(CurTool->OutputSuffix()); + } + Last = true; + } + else { + Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix()); + } + + if (int ret = CurTool->GenerateAction(In, Out, InLangs, LangMap).Execute()) + throw error_code(ret); + + if (Last) + return; + + CurNode = &getNode(ChooseEdge(CurNode->OutEdges, + InLangs, + CurNode->Name())->ToolName()); + In = Out; Out.clear(); + } +} + +// Find the head of the toolchain corresponding to the given file. +// Also, insert an input language into InLangs. +const Node* CompilationGraph:: +FindToolChain(const sys::Path& In, const std::string* ForceLanguage, + InputLanguagesSet& InLangs, const LanguageMap& LangMap) const { + + // Determine the input language. + const std::string& InLanguage = + ForceLanguage ? *ForceLanguage : LangMap.GetLanguage(In); + + // Add the current input language to the input language set. + InLangs.insert(InLanguage); + + // Find the toolchain for the input language. + const tools_vector_type& TV = getToolsVector(InLanguage); + if (TV.empty()) + throw std::runtime_error("No toolchain corresponding to language " + + InLanguage + " found"); + return &getNode(ChooseEdge(TV, InLangs)->ToolName()); +} + +// Helper function used by Build(). +// Traverses initial portions of the toolchains (up to the first Join node). +// This function is also responsible for handling the -x option. +void CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, + const sys::Path& TempDir, + const LanguageMap& LangMap) { + // This is related to -x option handling. + cl::list::const_iterator xIter = Languages.begin(), + xBegin = xIter, xEnd = Languages.end(); + bool xEmpty = true; + const std::string* xLanguage = 0; + unsigned xPos = 0, xPosNext = 0, filePos = 0; + + if (xIter != xEnd) { + xEmpty = false; + xPos = Languages.getPosition(xIter - xBegin); + cl::list::const_iterator xNext = llvm::next(xIter); + xPosNext = (xNext == xEnd) ? std::numeric_limits::max() + : Languages.getPosition(xNext - xBegin); + xLanguage = (*xIter == "none") ? 0 : &(*xIter); + } + + // For each input file: + for (cl::list::const_iterator B = InputFilenames.begin(), + CB = B, E = InputFilenames.end(); B != E; ++B) { + sys::Path In = sys::Path(*B); + + // Code for handling the -x option. + // Output: std::string* xLanguage (can be NULL). + if (!xEmpty) { + filePos = InputFilenames.getPosition(B - CB); + + if (xPos < filePos) { + if (filePos < xPosNext) { + xLanguage = (*xIter == "none") ? 0 : &(*xIter); + } + else { // filePos >= xPosNext + // Skip xIters while filePos > xPosNext + while (filePos > xPosNext) { + ++xIter; + xPos = xPosNext; + + cl::list::const_iterator xNext = llvm::next(xIter); + if (xNext == xEnd) + xPosNext = std::numeric_limits::max(); + else + xPosNext = Languages.getPosition(xNext - xBegin); + xLanguage = (*xIter == "none") ? 0 : &(*xIter); + } + } + } + } + + // Find the toolchain corresponding to this file. + const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap); + // Pass file through the chain starting at head. + PassThroughGraph(In, N, InLangs, TempDir, LangMap); + } +} + +// Sort the nodes in topological order. +void CompilationGraph::TopologicalSort(std::vector& Out) { + std::queue Q; + Q.push(&getNode("root")); + + while (!Q.empty()) { + const Node* A = Q.front(); + Q.pop(); + Out.push_back(A); + for (Node::const_iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); + EB != EE; ++EB) { + Node* B = &getNode((*EB)->ToolName()); + B->DecrInEdges(); + if (B->HasNoInEdges()) + Q.push(B); + } + } +} + +namespace { + bool NotJoinNode(const Node* N) { + return N->ToolPtr ? !N->ToolPtr->IsJoin() : true; + } +} + +// Call TopologicalSort and filter the resulting list to include +// only Join nodes. +void CompilationGraph:: +TopologicalSortFilterJoinNodes(std::vector& Out) { + std::vector TopSorted; + TopologicalSort(TopSorted); + std::remove_copy_if(TopSorted.begin(), TopSorted.end(), + std::back_inserter(Out), NotJoinNode); +} + +int CompilationGraph::Build (const sys::Path& TempDir, + const LanguageMap& LangMap) { + + InputLanguagesSet InLangs; + + // Traverse initial parts of the toolchains and fill in InLangs. + BuildInitial(InLangs, TempDir, LangMap); + + std::vector JTV; + TopologicalSortFilterJoinNodes(JTV); + + // For all join nodes in topological order: + for (std::vector::iterator B = JTV.begin(), E = JTV.end(); + B != E; ++B) { + + sys::Path Out; + const Node* CurNode = *B; + JoinTool* JT = &dynamic_cast(*CurNode->ToolPtr.getPtr()); + bool IsLast = false; + + // Are there any files in the join list? + if (JT->JoinListEmpty()) + continue; + + // Is this the last tool in the toolchain? + // NOTE: we can process several toolchains in parallel. + if (!CurNode->HasChildren() || JT->IsLast()) { + if (OutputFilename.empty()) { + Out.set("a"); + Out.appendSuffix(JT->OutputSuffix()); + } + else + Out.set(OutputFilename); + IsLast = true; + } + else { + Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix()); + } + + if (int ret = JT->GenerateAction(Out, InLangs, LangMap).Execute()) + throw error_code(ret); + + if (!IsLast) { + const Node* NextNode = + &getNode(ChooseEdge(CurNode->OutEdges, InLangs, + CurNode->Name())->ToolName()); + PassThroughGraph(Out, NextNode, InLangs, TempDir, LangMap); + } + } + + return 0; +} + +// Code related to graph visualization. + +namespace llvm { + template <> + struct DOTGraphTraits + : public DefaultDOTGraphTraits + { + + template + static std::string getNodeLabel(const Node* N, const GraphType&) + { + if (N->ToolPtr) + if (N->ToolPtr->IsJoin()) + return N->Name() + "\n (join" + + (N->HasChildren() ? ")" + : std::string(": ") + N->ToolPtr->OutputLanguage() + ')'); + else + return N->Name(); + else + return "root"; + } + + template + static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) { + if (N->ToolPtr) { + return N->ToolPtr->OutputLanguage(); + } + else { + const char** InLangs = I->ToolPtr->InputLanguages(); + std::string ret; + + for (; *InLangs; ++InLangs) { + if (*(InLangs + 1)) { + ret += *InLangs; + ret += ", "; + } + else { + ret += *InLangs; + } + } + + return ret; + } + } + }; + +} + +void CompilationGraph::writeGraph() { + std::ofstream O("compilation-graph.dot"); + + if (O.good()) { + llvm::WriteGraph(this, "compilation-graph"); + O.close(); + } + else { + throw std::runtime_error("Error opening file 'compilation-graph.dot'" + " for writing!"); + } +} + +void CompilationGraph::viewGraph() { + llvm::ViewGraph(this, "compilation-graph"); +} diff --git a/tools/llvmc/driver/Error.h b/tools/llvmc/driver/Error.h new file mode 100644 index 0000000..c0aaff1 --- /dev/null +++ b/tools/llvmc/driver/Error.h @@ -0,0 +1,33 @@ +//===--- Error.h - The LLVM Compiler Driver ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Exception classes for LLVMC. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVMC2_ERROR_H +#define LLVM_TOOLS_LLVMC2_ERROR_H + +#include + +namespace llvmc { + + class error_code: public std::runtime_error { + int Code_; + public: + error_code (int c) + : std::runtime_error("Tool returned error code"), Code_(c) + {} + + int code() const { return Code_; } + }; + +} + +#endif //LLVM_TOOLS_LLVMC2_ERROR_H diff --git a/tools/llvmc/driver/Makefile b/tools/llvmc/driver/Makefile new file mode 100644 index 0000000..d3aa2cd --- /dev/null +++ b/tools/llvmc/driver/Makefile @@ -0,0 +1,19 @@ +##===- tools/llvmc/driver/Makefile -------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TOOLNAME = $(DRIVER_NAME) +LINK_COMPONENTS = support system +REQUIRES_EH := 1 + +ifneq ($(BUILTIN_PLUGINS),) +USEDLIBS = $(patsubst %,LLVMC%,$(BUILTIN_PLUGINS)) +endif + +include $(LEVEL)/Makefile.common diff --git a/tools/llvmc/driver/Plugin.cpp b/tools/llvmc/driver/Plugin.cpp new file mode 100644 index 0000000..75abbd0 --- /dev/null +++ b/tools/llvmc/driver/Plugin.cpp @@ -0,0 +1,73 @@ +//===--- Plugin.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Plugin support. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/Plugin.h" + +#include +#include + +namespace { + + // Registry::Add<> does not do lifetime management (probably issues + // with static constructor/destructor ordering), so we have to + // implement it here. + // + // All this static registration/life-before-main model seems + // unnecessary convoluted to me. + + static bool pluginListInitialized = false; + typedef std::vector PluginList; + static PluginList Plugins; + + struct ByPriority { + bool operator()(const llvmc::BasePlugin* lhs, + const llvmc::BasePlugin* rhs) { + return lhs->Priority() < rhs->Priority(); + } + }; +} + +namespace llvmc { + + PluginLoader::PluginLoader() { + if (!pluginListInitialized) { + for (PluginRegistry::iterator B = PluginRegistry::begin(), + E = PluginRegistry::end(); B != E; ++B) + Plugins.push_back(B->instantiate()); + std::sort(Plugins.begin(), Plugins.end(), ByPriority()); + } + pluginListInitialized = true; + } + + PluginLoader::~PluginLoader() { + if (pluginListInitialized) { + for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); + B != E; ++B) + delete (*B); + } + pluginListInitialized = false; + } + + void PluginLoader::PopulateLanguageMap(LanguageMap& langMap) { + for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); + B != E; ++B) + (*B)->PopulateLanguageMap(langMap); + } + + void PluginLoader::PopulateCompilationGraph(CompilationGraph& graph) { + for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); + B != E; ++B) + (*B)->PopulateCompilationGraph(graph); + } + +} diff --git a/tools/llvmc/driver/llvmc.cpp b/tools/llvmc/driver/llvmc.cpp new file mode 100644 index 0000000..f3a1e57 --- /dev/null +++ b/tools/llvmc/driver/llvmc.cpp @@ -0,0 +1,119 @@ +//===--- llvmc.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open +// Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This tool provides a single point of access to the LLVM +// compilation tools. It has many options. To discover the options +// supported please refer to the tools' manual page or run the tool +// with the --help option. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" + +#include "llvm/CompilerDriver/CompilationGraph.h" +#include "llvm/CompilerDriver/Plugin.h" + +#include "llvm/System/Path.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/PluginLoader.h" + +#include +#include +#include + +namespace cl = llvm::cl; +namespace sys = llvm::sys; +using namespace llvmc; + +// Built-in command-line options. +// External linkage here is intentional. + +cl::list InputFilenames(cl::Positional, cl::desc(""), + cl::ZeroOrMore); +cl::opt OutputFilename("o", cl::desc("Output file name"), + cl::value_desc("file")); +cl::list Languages("x", + cl::desc("Specify the language of the following input files"), + cl::ZeroOrMore); +cl::opt DryRun("dry-run", + cl::desc("Only pretend to run commands")); +cl::opt VerboseMode("v", + cl::desc("Enable verbose mode")); +cl::opt WriteGraph("write-graph", + cl::desc("Write compilation-graph.dot file"), + cl::Hidden); +cl::opt ViewGraph("view-graph", + cl::desc("Show compilation graph in GhostView"), + cl::Hidden); +cl::opt SaveTemps("save-temps", + cl::desc("Keep temporary files"), + cl::Hidden); + +namespace { + /// BuildTargets - A small wrapper for CompilationGraph::Build. + int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) { + int ret; + const sys::Path& tempDir = SaveTemps + ? sys::Path("") + : sys::Path(sys::Path::GetTemporaryDirectory()); + + try { + ret = graph.Build(tempDir, langMap); + } + catch(...) { + tempDir.eraseFromDisk(true); + throw; + } + + if (!SaveTemps) + tempDir.eraseFromDisk(true); + return ret; + } +} + +int main(int argc, char** argv) { + try { + LanguageMap langMap; + CompilationGraph graph; + + cl::ParseCommandLineOptions + (argc, argv, "LLVM Compiler Driver (Work In Progress)", true); + + PluginLoader Plugins; + Plugins.PopulateLanguageMap(langMap); + Plugins.PopulateCompilationGraph(graph); + + if (WriteGraph) { + graph.writeGraph(); + if (!ViewGraph) + return 0; + } + + if (ViewGraph) { + graph.viewGraph(); + return 0; + } + + if (InputFilenames.empty()) { + throw std::runtime_error("no input files"); + } + + return BuildTargets(graph, langMap); + } + catch(llvmc::error_code& ec) { + return ec.code(); + } + catch(const std::exception& ex) { + std::cerr << argv[0] << ": " << ex.what() << '\n'; + } + catch(...) { + std::cerr << argv[0] << ": unknown error!\n"; + } + return 1; +} diff --git a/tools/llvmc/plugins/Base/Base.td b/tools/llvmc/plugins/Base/Base.td new file mode 100644 index 0000000..85a37cb --- /dev/null +++ b/tools/llvmc/plugins/Base/Base.td @@ -0,0 +1,59 @@ +//===- Base.td - LLVMC2 toolchain descriptions -------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains compilation graph description used by llvmc2. +// +//===----------------------------------------------------------------------===// + +include "llvm/CompilerDriver/Common.td" +include "llvm/CompilerDriver/Tools.td" + +// Toolchains + +def CompilationGraph : CompilationGraph<[ + Edge<"root", "llvm_gcc_c">, + Edge<"root", "llvm_gcc_assembler">, + Edge<"root", "llvm_gcc_cpp">, + Edge<"root", "llvm_gcc_m">, + Edge<"root", "llvm_gcc_mxx">, + Edge<"root", "llvm_as">, + + Edge<"llvm_gcc_c", "llc">, + Edge<"llvm_gcc_cpp", "llc">, + Edge<"llvm_gcc_m", "llc">, + Edge<"llvm_gcc_mxx", "llc">, + Edge<"llvm_as", "llc">, + + OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_gcc_m", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_gcc_mxx", "opt", (case (switch_on "opt"), (inc_weight))>, + OptionalEdge<"llvm_as", "opt", (case (switch_on "opt"), (inc_weight))>, + Edge<"opt", "llc">, + + Edge<"llc", "llvm_gcc_assembler">, + Edge<"llvm_gcc_assembler", "llvm_gcc_linker">, + OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker", + (case + (or (input_languages_contain "c++"), + (input_languages_contain "objective-c++")), + (inc_weight), + (or (parameter_equals "linker", "g++"), + (parameter_equals "linker", "c++")), (inc_weight))>, + + + Edge<"root", "llvm_gcc_linker">, + OptionalEdge<"root", "llvm_gcc_cpp_linker", + (case + (or (input_languages_contain "c++"), + (input_languages_contain "objective-c++")), + (inc_weight), + (or (parameter_equals "linker", "g++"), + (parameter_equals "linker", "c++")), (inc_weight))> + ]>; diff --git a/tools/llvmc/plugins/Base/Makefile b/tools/llvmc/plugins/Base/Makefile new file mode 100644 index 0000000..5ca6048 --- /dev/null +++ b/tools/llvmc/plugins/Base/Makefile @@ -0,0 +1,13 @@ +##===- tools/llvmc/plugins/Base/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLVMC_PLUGIN = Base +BUILT_SOURCES = AutoGenerated.inc + +include ../Makefile diff --git a/tools/llvmc/plugins/Base/PluginMain.cpp b/tools/llvmc/plugins/Base/PluginMain.cpp new file mode 100644 index 0000000..add8acb --- /dev/null +++ b/tools/llvmc/plugins/Base/PluginMain.cpp @@ -0,0 +1 @@ +#include "AutoGenerated.inc" diff --git a/tools/llvmc/plugins/Clang/Clang.td b/tools/llvmc/plugins/Clang/Clang.td new file mode 100644 index 0000000..0f5d8cd --- /dev/null +++ b/tools/llvmc/plugins/Clang/Clang.td @@ -0,0 +1,85 @@ +// A (first stab at a) replacement for the Clang's ccc script. +// To compile, use this command: +// cd $LLVMC2_DIR +// make DRIVER_NAME=ccc2 BUILTIN_PLUGINS=Clang + +include "llvm/CompilerDriver/Common.td" + + +def Options : OptionList<[ +(switch_option "E", + (help "Stop after the preprocessing stage, do not run the compiler")) +]>; + +class clang_base : Tool< +[(in_language language), + (out_language "llvm-bitcode"), + (output_suffix "bc"), + (cmd_line cmdline), + (switch_option "E", (stop_compilation), (output_suffix "i")), + (sink) +]>; + +def clang_c : clang_base<"c", +(case +(switch_on "E"), + (case + (not_empty "o"), + "clang -E -x c $INFILE -o $OUTFILE", + (default), + "clang -E -x c $INFILE"), +(default), + "clang -emit-llvm-bc -x c $INFILE -o $OUTFILE")>; + +def clang_cpp : clang_base<"c++", +(case +(switch_on "E"), + (case + (not_empty "o"), + "clang -E -x c++ $INFILE -o $OUTFILE", + (default), + "clang -E -x c++ $INFILE"), +(default), + "clang -emit-llvm-bc -x c++ $INFILE -o $OUTFILE")>; + +def clang_objective_c : clang_base<"objective-c", +(case +(switch_on "E"), + (case + (not_empty "o"), + "clang -E -x objective-c $INFILE -o $OUTFILE", + (default), + "clang -E -x objective-c $INFILE"), +(default), + "clang -emit-llvm-bc -x objective-c $INFILE -o $OUTFILE")>; + +// Default linker +def llvm_ld : Tool< +[(in_language "llvm-bitcode"), + (out_language "executable"), + (output_suffix "out"), + (cmd_line "llvm-ld -native -disable-internalize $INFILE -o $OUTFILE"), + (prefix_list_option "L", (forward), (help "Specify a library search path")), + (join) +]>; + +// Language map + +def LanguageMap : LanguageMap< + [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>, + LangToSuffixes<"c", ["c"]>, + LangToSuffixes<"objective-c", ["m"]>, + LangToSuffixes<"c-cpp-output", ["i"]>, + LangToSuffixes<"objective-c-cpp-output", ["mi"]> + ]>; + +// Compilation graph + +def CompilationGraph : CompilationGraph<[ + Edge<"root", "clang_c">, + Edge<"root", "clang_cpp">, + Edge<"root", "clang_objective_c">, + Edge<"clang_c", "llvm_ld">, + Edge<"clang_cpp", "llvm_ld">, + Edge<"clang_objective_c", "llvm_ld"> + ]>; diff --git a/tools/llvmc/plugins/Clang/Makefile b/tools/llvmc/plugins/Clang/Makefile new file mode 100644 index 0000000..3206013 --- /dev/null +++ b/tools/llvmc/plugins/Clang/Makefile @@ -0,0 +1,13 @@ +##===- tools/llvmc/plugins/Clang/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLVMC_PLUGIN = Clang +BUILT_SOURCES = AutoGenerated.inc + +include ../Makefile diff --git a/tools/llvmc/plugins/Clang/PluginMain.cpp b/tools/llvmc/plugins/Clang/PluginMain.cpp new file mode 100644 index 0000000..add8acb --- /dev/null +++ b/tools/llvmc/plugins/Clang/PluginMain.cpp @@ -0,0 +1 @@ +#include "AutoGenerated.inc" diff --git a/tools/llvmc/plugins/Hello/Hello.cpp b/tools/llvmc/plugins/Hello/Hello.cpp new file mode 100644 index 0000000..2ecd2f1 --- /dev/null +++ b/tools/llvmc/plugins/Hello/Hello.cpp @@ -0,0 +1,30 @@ +//===- Hello.cpp - Example code from "Writing an LLVM Pass" ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Test plugin for LLVMC. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CompilerDriver/CompilationGraph.h" +#include "llvm/CompilerDriver/Plugin.h" + +#include + +namespace { +struct MyPlugin : public llvmc::BasePlugin { + void PopulateLanguageMap(llvmc::LanguageMap&) const + { std::cout << "Hello!\n"; } + + void PopulateCompilationGraph(llvmc::CompilationGraph&) const + {} +}; + +static llvmc::RegisterPlugin RP("Hello", "Hello World plugin"); + +} diff --git a/tools/llvmc/plugins/Hello/Makefile b/tools/llvmc/plugins/Hello/Makefile new file mode 100644 index 0000000..181dd0c --- /dev/null +++ b/tools/llvmc/plugins/Hello/Makefile @@ -0,0 +1,12 @@ +##===- tools/llvmc/plugins/Hello/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLVMC_PLUGIN = Hello + +include ../Makefile diff --git a/tools/llvmc/plugins/Makefile b/tools/llvmc/plugins/Makefile new file mode 100644 index 0000000..dab58e0 --- /dev/null +++ b/tools/llvmc/plugins/Makefile @@ -0,0 +1,55 @@ +##===- tools/llvmc/plugins/Makefile.plugins ----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open +# Source License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +ifndef LLVMC_PLUGIN + +LEVEL = ../../.. +DIRS = $(BUILTIN_PLUGINS) + +# TOFIX: Should we also build DSO versions of plugins? +export BUILTIN_LLVMC_PLUGIN=1 + +include $(LEVEL)/Makefile.common + +else # LLVMC_PLUGIN + +LEVEL = ../../../.. + +LIBRARYNAME := $(patsubst %,LLVMC%,$(LLVMC_PLUGIN)) +REQUIRES_EH = 1 + +ifndef BUILTIN_LLVMC_PLUGIN +LOADABLE_MODULE = 1 +endif + +ifneq ($(BUILT_SOURCES),) +BUILD_AUTOGENERATED_INC=1 +endif + +include $(LEVEL)/Makefile.common + +# TOFIX: This probably should go into Makefile.rules + +ifdef BUILD_AUTOGENERATED_INC + +TOOLS_SOURCE := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td)) + +TD_COMMON :=$(strip $(wildcard \ + $(LLVM_SRC_ROOT)/include/llvm/CompilerDriver/*.td)) + +$(ObjDir)/AutoGenerated.inc.tmp: $(TOOLS_SOURCE) $(ObjDir)/.dir \ + $(TBLGEN) $(TD_COMMON) + $(Echo) "Building LLVMC configuration library with tblgen" + $(Verb) $(TableGen) -gen-llvmc -o $(call SYSPATH, $@) $< + +AutoGenerated.inc : $(ObjDir)/AutoGenerated.inc.tmp + $(Verb) $(CMP) -s $@ $< || $(CP) $< $@ +endif # BUILD_AUTOGENERATED_INC + +endif # LLVMC_PLUGIN diff --git a/tools/llvmc/plugins/Simple/Makefile b/tools/llvmc/plugins/Simple/Makefile new file mode 100644 index 0000000..1cd5af7 --- /dev/null +++ b/tools/llvmc/plugins/Simple/Makefile @@ -0,0 +1,13 @@ +##===- tools/llvmc/plugins/Simple/Makefile -----------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LLVMC_PLUGIN = Simple +BUILT_SOURCES = AutoGenerated.inc + +include ../Makefile diff --git a/tools/llvmc/plugins/Simple/PluginMain.cpp b/tools/llvmc/plugins/Simple/PluginMain.cpp new file mode 100644 index 0000000..add8acb --- /dev/null +++ b/tools/llvmc/plugins/Simple/PluginMain.cpp @@ -0,0 +1 @@ +#include "AutoGenerated.inc" diff --git a/tools/llvmc/plugins/Simple/Simple.td b/tools/llvmc/plugins/Simple/Simple.td new file mode 100644 index 0000000..b974cbc --- /dev/null +++ b/tools/llvmc/plugins/Simple/Simple.td @@ -0,0 +1,30 @@ +// A simple wrapper for gcc. +// To compile, use this command: +// +// $ cd $LLVMC2_DIR +// $ make DRIVER_NAME=mygcc BUILTIN_PLUGINS=Simple +// +// To build this plugin as a dynamic library: +// +// $ cd $LLVMC2_DIR +// $ make BUILTIN_PLUGINS="" +// $ cd plugins/Simple +// $ make +// +// Run as: +// +// $ llvmc2 -load $LLVM_DIR/Release/lib/LLVMCSimple.so + +include "llvm/CompilerDriver/Common.td" + +def gcc : Tool< +[(in_language "c"), + (out_language "executable"), + (output_suffix "out"), + (cmd_line "gcc $INFILE -o $OUTFILE"), + (sink) +]>; + +def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>; + +def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>; diff --git a/tools/llvmc2/CMakeLists.txt b/tools/llvmc2/CMakeLists.txt deleted file mode 100644 index f820419..0000000 --- a/tools/llvmc2/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -add_subdirectory(driver) - -# TODO: support plugins and user-configured builds. -# See ./doc/LLVMC-Reference.rst "Customizing LLVMC: the compilation graph" diff --git a/tools/llvmc2/Makefile b/tools/llvmc2/Makefile deleted file mode 100644 index 22ca29e..0000000 --- a/tools/llvmc2/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -##===- tools/llvmc2/Makefile -------------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open -# Source License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. - -BUILTIN_PLUGINS = Base -DRIVER_NAME = llvmc2 -DIRS = plugins driver - -export BUILTIN_PLUGINS -export DRIVER_NAME - -include $(LEVEL)/Makefile.common diff --git a/tools/llvmc2/doc/LLVMC-Reference.rst b/tools/llvmc2/doc/LLVMC-Reference.rst deleted file mode 100644 index 01a8be0..0000000 --- a/tools/llvmc2/doc/LLVMC-Reference.rst +++ /dev/null @@ -1,517 +0,0 @@ -=================================== -Customizing LLVMC: Reference Manual -=================================== -:Author: Mikhail Glushenkov - -LLVMC is a generic compiler driver, designed to be customizable and -extensible. It plays the same role for LLVM as the ``gcc`` program -does for GCC - LLVMC's job is essentially to transform a set of input -files into a set of targets depending on configuration rules and user -options. What makes LLVMC different is that these transformation rules -are completely customizable - in fact, LLVMC knows nothing about the -specifics of transformation (even the command-line options are mostly -not hard-coded) and regards the transformation structure as an -abstract graph. The structure of this graph is completely determined -by plugins, which can be either statically or dynamically linked. This -makes it possible to easily adapt LLVMC for other purposes - for -example, as a build tool for game resources. - -Because LLVMC employs TableGen [1]_ as its configuration language, you -need to be familiar with it to customize LLVMC. - - -.. contents:: - - -Compiling with LLVMC -==================== - -LLVMC tries hard to be as compatible with ``gcc`` as possible, -although there are some small differences. Most of the time, however, -you shouldn't be able to notice them:: - - $ # This works as expected: - $ llvmc2 -O3 -Wall hello.cpp - $ ./a.out - hello - -One nice feature of LLVMC is that one doesn't have to distinguish -between different compilers for different languages (think ``g++`` and -``gcc``) - the right toolchain is chosen automatically based on input -language names (which are, in turn, determined from file -extensions). If you want to force files ending with ".c" to compile as -C++, use the ``-x`` option, just like you would do it with ``gcc``:: - - $ # hello.c is really a C++ file - $ llvmc2 -x c++ hello.c - $ ./a.out - hello - -On the other hand, when using LLVMC as a linker to combine several C++ -object files you should provide the ``--linker`` option since it's -impossible for LLVMC to choose the right linker in that case:: - - $ llvmc2 -c hello.cpp - $ llvmc2 hello.o - [A lot of link-time errors skipped] - $ llvmc2 --linker=c++ hello.o - $ ./a.out - hello - - -Predefined options -================== - -LLVMC has some built-in options that can't be overridden in the -configuration files: - -* ``-o FILE`` - Output file name. - -* ``-x LANGUAGE`` - Specify the language of the following input files - 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. - -* ``--view-graph`` - Show a graphical representation of the compilation - graph. Requires that you have ``dot`` and ``gv`` programs - installed. Hidden option, useful for debugging. - -* ``--write-graph`` - Write a ``compilation-graph.dot`` file in the - current directory with the compilation graph description in the - Graphviz format. Hidden option, useful for debugging. - -* ``--save-temps`` - Write temporary files to the current directory - and do not delete them on exit. Hidden option, useful for debugging. - -* ``--help``, ``--help-hidden``, ``--version`` - These options have - their standard meaning. - - -Compiling LLVMC plugins -======================= - -It's easiest to start working on your own LLVMC plugin by copying the -skeleton project which lives under ``$LLVMC_DIR/plugins/Simple``:: - - $ cd $LLVMC_DIR/plugins - $ cp -r Simple MyPlugin - $ cd MyPlugin - $ ls - Makefile PluginMain.cpp Simple.td - -As you can see, our basic plugin consists of only two files (not -counting the build script). ``Simple.td`` contains TableGen -description of the compilation graph; its format is documented in the -following sections. ``PluginMain.cpp`` is just a helper file used to -compile the auto-generated C++ code produced from TableGen source. It -can also contain hook definitions (see `below`__). - -__ hooks_ - -The first thing that you should do is to change the ``LLVMC_PLUGIN`` -variable in the ``Makefile`` to avoid conflicts (since this variable -is used to name the resulting library):: - - LLVMC_PLUGIN=MyPlugin - -It is also a good idea to rename ``Simple.td`` to something less -generic:: - - $ mv Simple.td MyPlugin.td - -Note that the plugin source directory must be placed under -``$LLVMC_DIR/plugins`` to make use of the existing build -infrastructure. To build a version of the LLVMC executable called -``mydriver`` with your plugin compiled in, use the following command:: - - $ cd $LLVMC_DIR - $ make BUILTIN_PLUGINS=MyPlugin DRIVER_NAME=mydriver - -To build your plugin as a dynamic library, just ``cd`` to its source -directory and run ``make``. The resulting file will be called -``LLVMC$(LLVMC_PLUGIN).$(DLL_EXTENSION)`` (in our case, -``LLVMCMyPlugin.so``). This library can be then loaded in with the -``-load`` option. Example:: - - $ cd $LLVMC_DIR/plugins/Simple - $ make - $ llvmc2 -load $LLVM_DIR/Release/lib/LLVMCSimple.so - -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 BUILTIN_PLUGINS="" - -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 ``.td`` 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. - - -Customizing LLVMC: the compilation graph -======================================== - -Each TableGen configuration file should include the common -definitions:: - - include "llvm/CompilerDriver/Common.td" - // And optionally: - // include "llvm/CompilerDriver/Tools.td" - // which contains some useful tool definitions. - -Internally, LLVMC stores information about possible source -transformations in form of a graph. Nodes in this graph represent -tools, and edges between two nodes represent a transformation path. A -special "root" node is used to mark entry points for the -transformations. LLVMC also assigns a weight to each edge (more on -this later) to choose between several alternative edges. - -The definition of the compilation graph (see file -``plugins/Base/Base.td`` for an example) is just a list of edges:: - - def CompilationGraph : CompilationGraph<[ - Edge<"root", "llvm_gcc_c">, - Edge<"root", "llvm_gcc_assembler">, - ... - - Edge<"llvm_gcc_c", "llc">, - Edge<"llvm_gcc_cpp", "llc">, - ... - - OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), - (inc_weight))>, - OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), - (inc_weight))>, - ... - - OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker", - (case (input_languages_contain "c++"), (inc_weight), - (or (parameter_equals "linker", "g++"), - (parameter_equals "linker", "c++")), (inc_weight))>, - ... - - ]>; - -As you can see, the edges can be either default or optional, where -optional edges are differentiated by an additional ``case`` expression -used to calculate the weight of this edge. Notice also that we refer -to tools via their names (as strings). This makes it possible to add -edges to an existing compilation graph in plugins without having to -know about all tool definitions used in the graph. - -The default edges are assigned a weight of 1, and optional edges get a -weight of 0 + 2*N where N is the number of tests that evaluated to -true in the ``case`` expression. It is also possible to provide an -integer parameter to ``inc_weight`` and ``dec_weight`` - in this case, -the weight is increased (or decreased) by the provided value instead -of the default 2. - -When passing an input file through the graph, LLVMC picks the edge -with the maximum weight. To avoid ambiguity, there should be only one -default edge between two nodes (with the exception of the root node, -which gets a special treatment - there you are allowed to specify one -default edge *per language*). - -To get a visual representation of the compilation graph (useful for -debugging), run ``llvmc2 --view-graph``. You will need ``dot`` and -``gsview`` installed for this to work properly. - - -Writing a tool description -========================== - -As was said earlier, nodes in the compilation graph represent tools, -which are described separately. A tool definition looks like this -(taken from the ``include/llvm/CompilerDriver/Tools.td`` file):: - - def llvm_gcc_cpp : Tool<[ - (in_language "c++"), - (out_language "llvm-assembler"), - (output_suffix "bc"), - (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"), - (sink) - ]>; - -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 -properties; most of them should be self-explanatory. The ``sink`` -property means that this tool should be passed all command-line -options that lack explicit descriptions. - -The complete list of the currently implemented tool properties follows: - -* Possible tool properties: - - - ``in_language`` - input language name. Can be either a string or a - list, in case the tool supports multiple input languages. - - - ``out_language`` - output language name. - - - ``output_suffix`` - output file suffix. - - - ``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 (more on this below). - - - ``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. - -The next tool definition is slightly more complex:: - - def llvm_gcc_linker : Tool<[ - (in_language "object-code"), - (out_language "executable"), - (output_suffix "out"), - (cmd_line "llvm-gcc $INFILE -o $OUTFILE"), - (join), - (prefix_list_option "L", (forward), - (help "add a directory to link path")), - (prefix_list_option "l", (forward), - (help "search a library when linking")), - (prefix_list_option "Wl", (unpack_values), - (help "pass options to linker")) - ]>; - -This tool has a "join" property, which means that it behaves like a -linker. This tool also defines several command-line options: ``-l``, -``-L`` and ``-Wl`` which have their usual meaning. An option has two -attributes: a name and a (possibly empty) list of properties. All -currently implemented option types and properties are described below: - -* Possible option types: - - - ``switch_option`` - a simple boolean switch, for example ``-time``. - - - ``parameter_option`` - option that takes an argument, for example - ``-std=c99``; - - - ``parameter_list_option`` - same as the above, but more than one - occurence of the option is allowed. - - - ``prefix_option`` - same as the parameter_option, but the option name - and parameter value are not separated. - - - ``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")`` - - -* Possible option properties: - - - ``append_cmd`` - append a string to the tool invocation command. - - - ``forward`` - forward this option unchanged. - - - ``forward_as`` - Change the name of this option, but forward the - argument unchanged. Example: ``(forward_as "--disable-optimize")``. - - - ``output_suffix`` - modify the output suffix of this - tool. Example: ``(switch "E", (output_suffix "i")``. - - - ``stop_compilation`` - stop compilation after this phase. - - - ``unpack_values`` - used for for splitting and forwarding - comma-separated lists of options, e.g. ``-Wa,-foo=bar,-baz`` is - converted to ``-foo=bar -baz`` and appended to the tool invocation - command. - - - ``help`` - help string associated with this option. Used for - ``--help`` output. - - - ``required`` - this option is obligatory. - - -Option list - specifying all options in a single place -====================================================== - -It can be handy to have all information about options gathered in a -single place to provide an overview. This can be achieved by using a -so-called ``OptionList``:: - - def Options : OptionList<[ - (switch_option "E", (help "Help string")), - (alias_option "quiet", "q") - ... - ]>; - -``OptionList`` is also a good place to specify option aliases. - -Tool-specific option properties like ``append_cmd`` have (obviously) -no meaning in the context of ``OptionList``, so the only properties -allowed there are ``help`` and ``required``. - -Option lists are used at file scope. See the file -``plugins/Clang/Clang.td`` for an example of ``OptionList`` usage. - -.. _hooks: - -Using hooks and environment variables in the ``cmd_line`` property -================================================================== - -Normally, LLVMC executes programs from the system ``PATH``. Sometimes, -this is not sufficient: for example, we may want to specify tool names -in the configuration file. This can be achieved via the mechanism of -hooks - to write your own hooks, just add their definitions to the -``PluginMain.cpp`` or drop a ``.cpp`` file into the -``$LLVMC_DIR/driver`` directory. Hooks should live in the ``hooks`` -namespace and have the signature ``std::string hooks::MyHookName -(void)``. They can be used from the ``cmd_line`` tool property:: - - (cmd_line "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)") - -It is also possible to use environment variables in the same manner:: - - (cmd_line "$ENV(VAR1)/path/to/file -o $ENV(VAR2)") - -To change the command line string based on user-provided options use -the ``case`` expression (documented below):: - - (cmd_line - (case - (switch_on "E"), - "llvm-g++ -E -x c $INFILE -o $OUTFILE", - (default), - "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm")) - -Conditional evaluation: the ``case`` expression -=============================================== - -The 'case' construct can be used to calculate weights of the optional -edges and to choose between several alternative command line strings -in the ``cmd_line`` tool property. It is designed after the -similarly-named construct in functional languages and takes the form -``(case (test_1), statement_1, (test_2), statement_2, ... (test_N), -statement_N)``. The statements are evaluated only if the corresponding -tests evaluate to true. - -Examples:: - - // Increases edge weight by 5 if "-A" is provided on the - // command-line, and by 5 more if "-B" is also provided. - (case - (switch_on "A"), (inc_weight 5), - (switch_on "B"), (inc_weight 5)) - - // Evaluates to "cmdline1" if option "-A" is provided on the - // command line, otherwise to "cmdline2" - (case - (switch_on "A"), "cmdline1", - (switch_on "B"), "cmdline2", - (default), "cmdline3") - -Note the slight difference in 'case' expression handling in contexts -of edge weights and command line specification - in the second example -the value of the ``"B"`` switch is never checked when switch ``"A"`` is -enabled, and the whole expression always evaluates to ``"cmdline1"`` in -that case. - -Case expressions can also be nested, i.e. the following is legal:: - - (case (switch_on "E"), (case (switch_on "o"), ..., (default), ...) - (default), ...) - -You should, however, try to avoid doing that because it hurts -readability. It is usually better to split tool descriptions and/or -use TableGen inheritance instead. - -* Possible tests are: - - - ``switch_on`` - Returns true if a given command-line switch is - provided by the user. Example: ``(switch_on "opt")``. Note that - you have to define all possible command-line options separately in - the tool descriptions. See the next section for the discussion of - different kinds of command-line options. - - - ``parameter_equals`` - Returns true if a command-line parameter equals - a given value. Example: ``(parameter_equals "W", "all")``. - - - ``element_in_list`` - Returns true if a command-line parameter list - includes a given value. Example: ``(parameter_in_list "l", "pthread")``. - - - ``input_languages_contain`` - Returns true if a given language - belongs to the current input language set. Example: - ``(input_languages_contain "c++")``. - - - ``in_language`` - Evaluates to true if the language of the input - file equals to the argument. At the moment works only with - ``cmd_line`` property on non-join nodes. Example: ``(in_language - "c++")``. - - - ``not_empty`` - Returns true if a given option (which should be - either a parameter or a parameter list) is set by the - user. Example: ``(not_empty "o")``. - - - ``default`` - Always evaluates to true. Should always be the last - test in the ``case`` expression. - - - ``and`` - A standard logical combinator that returns true iff all - of its arguments return true. Used like this: ``(and (test1), - (test2), ... (testN))``. Nesting of ``and`` and ``or`` is allowed, - but not encouraged. - - - ``or`` - Another logical combinator that returns true only if any - one of its arguments returns true. Example: ``(or (test1), - (test2), ... (testN))``. - - -Language map -============ - -One last thing that you will need to modify when adding support for a -new language to LLVMC is the language map, which defines mappings from -file extensions to language names. It is used to choose the proper -toolchain(s) for a given input file set. Language map definition looks -like this:: - - def LanguageMap : LanguageMap< - [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>, - LangToSuffixes<"c", ["c"]>, - ... - ]>; - -Debugging -========= - -When writing LLVMC plugins, it can be useful to get a visual view of -the resulting compilation graph. This can be achieved via the command -line option ``--view-graph``. This command assumes that Graphviz [2]_ and -Ghostview [3]_ are installed. There is also a ``--dump-graph`` option that -creates a Graphviz source file(``compilation-graph.dot``) in the -current directory. - - -References -========== - -.. [1] TableGen Fundamentals - http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html - -.. [2] Graphviz - http://www.graphviz.org/ - -.. [3] Ghostview - http://pages.cs.wisc.edu/~ghost/ diff --git a/tools/llvmc2/doc/LLVMC-Tutorial.rst b/tools/llvmc2/doc/LLVMC-Tutorial.rst deleted file mode 100644 index 724fd4d..0000000 --- a/tools/llvmc2/doc/LLVMC-Tutorial.rst +++ /dev/null @@ -1,101 +0,0 @@ -====================== -Tutorial - Using LLVMC -====================== -:Author: Mikhail Glushenkov - -LLVMC is a generic compiler driver, which plays the same role for LLVM -as the ``gcc`` program does for GCC - the difference being that LLVMC -is designed to be more adaptable and easier to customize. Most of -LLVMC functionality is implemented via plugins, which can be loaded -dynamically or compiled in. This tutorial describes the basic usage -and configuration of LLVMC. - - -.. contents:: - - -Compiling with LLVMC -==================== - -In general, LLVMC tries to be command-line compatible with ``gcc`` as -much as possible, so most of the familiar options work:: - - $ llvmc2 -O3 -Wall hello.cpp - $ ./a.out - hello - -This will invoke ``llvm-g++`` under the hood (you can see which -commands are executed by using the ``-v`` option). For further help on -command-line LLVMC usage, refer to the ``llvmc --help`` output. - - -Using LLVMC to generate toolchain drivers -========================================= - -LLVMC plugins are written mostly using TableGen [1]_, so you need to -be familiar with it to get anything done. - -Start by compiling ``plugins/Simple/Simple.td``, which is a primitive -wrapper for ``gcc``:: - - $ cd $LLVM_DIR/tools/llvmc2 - $ make DRIVER_NAME=mygcc BUILTIN_PLUGINS=Simple - $ cat > hello.c - [...] - $ mygcc hello.c - $ ./hello.out - Hello - -Here we link our plugin with the LLVMC core statically to form an -executable file called ``mygcc``. It is also possible to build our -plugin as a standalone dynamic library; this is described in the -reference manual. - -Contents of the file ``Simple.td`` look like this:: - - // Include common definitions - include "llvm/CompilerDriver/Common.td" - - // Tool descriptions - def gcc : Tool< - [(in_language "c"), - (out_language "executable"), - (output_suffix "out"), - (cmd_line "gcc $INFILE -o $OUTFILE"), - (sink) - ]>; - - // Language map - def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>; - - // Compilation graph - def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>; - -As you can see, this file consists of three parts: tool descriptions, -language map, and the compilation graph definition. - -At the heart of LLVMC is the idea of a compilation graph: vertices in -this graph are tools, and edges represent a transformation path -between two tools (for example, assembly source produced by the -compiler can be transformed into executable code by an assembler). The -compilation graph is basically a list of edges; a special node named -``root`` is used to mark graph entry points. - -Tool descriptions are represented as property lists: most properties -in the example above should be self-explanatory; the ``sink`` property -means that all options lacking an explicit description should be -forwarded to this tool. - -The ``LanguageMap`` associates a language name with a list of suffixes -and is used for deciding which toolchain corresponds to a given input -file. - -To learn more about LLVMC customization, refer to the reference -manual and plugin source code in the ``plugins`` directory. - -References -========== - -.. [1] TableGen Fundamentals - http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html - diff --git a/tools/llvmc2/doc/Makefile b/tools/llvmc2/doc/Makefile deleted file mode 100644 index c71f662..0000000 --- a/tools/llvmc2/doc/Makefile +++ /dev/null @@ -1,13 +0,0 @@ - -RST2HTML=rst2html --stylesheet=llvm.css --link-stylesheet - -all : LLVMC-Reference.html LLVMC-Tutorial.html - -LLVMC-Tutorial.html : LLVMC-Tutorial.rst llvm.css - $(RST2HTML) $< $@ - -LLVMC-Reference.html : LLVMC-Reference.rst llvm.css - $(RST2HTML) $< $@ - -clean : - rm *.html diff --git a/tools/llvmc2/doc/img/lines.gif b/tools/llvmc2/doc/img/lines.gif deleted file mode 100644 index 88f491e..0000000 Binary files a/tools/llvmc2/doc/img/lines.gif and /dev/null differ diff --git a/tools/llvmc2/doc/llvm.css b/tools/llvmc2/doc/llvm.css deleted file mode 100644 index 1c7e5cc..0000000 --- a/tools/llvmc2/doc/llvm.css +++ /dev/null @@ -1,86 +0,0 @@ -/* - * LLVM documentation style sheet - */ - -/* Common styles */ -.body { color: black; background: white; margin: 0 0 0 0 } - -/* No borders on image links */ -a:link img, a:visited img {border-style: none} - -address img { float: right; width: 88px; height: 31px; } -address { clear: right; } - -TR, TD { border: 2px solid gray; padding: 4pt 4pt 2pt 2pt; } -TH { border: 2px solid gray; font-weight: bold; font-size: 105%; - background: url("img/lines.gif"); - font-family: "Georgia,Palatino,Times,Roman,SanSerif"; text-align:center; - vertical-align: middle; } -TABLE { text-align: center; border: 2px solid black; - border-collapse: collapse; margin-top: 1em; margin-left: 1em; - margin-right: 1em; margin-bottom: 1em; } -/* - * Documentation - */ -/* Common for title and header */ -h1 { - color: black; background: url("img/lines.gif"); - font-family: "Georgia,Palatino,Times,Roman,SanSerif"; font-weight: bold; - border-width: 1px; - border-style: solid none solid none; - text-align: center; - vertical-align: middle; - padding-left: 8pt; - padding-top: 1px; - padding-bottom: 2px -} - -.doc_title { text-align: left; font-size: 25pt } -.doc_section { text-align: center; font-size: 22pt; - margin: 20pt 0pt 5pt 0pt; } -.doc_subsection { width: 75%; - text-align: left; font-size: 12pt; padding: 4pt 4pt 4pt 4pt; - margin: 1.5em 0.5em 0.5em 0.5em } - -.doc_subsubsection { margin: 2.0em 0.5em 0.5em 0.5em; - font-weight: bold; font-style: oblique; - border-bottom: 1px solid #999999; font-size: 12pt; - width: 75%; } -.doc_author { text-align: left; font-weight: bold; padding-left: 20pt } -.doc_text { text-align: left; padding-left: 20pt; padding-right: 10pt } - -.doc_footer { text-align: left; padding: 0 0 0 0 } - -.doc_hilite { color: blue; font-weight: bold; } - -.doc_table { text-align: center; width: 90%; - padding: 1px 1px 1px 1px; border: 1px; } - -.doc_table_nw { text-align: center; border: 1px; - padding: 1px 1px 1px 1px; } - -.doc_warning { color: red; font-weight: bold } - -.literal-block { border: solid 1px gray; background: #eeeeee; - margin: 0 1em 0 1em; - padding: 0 1em 0 1em; - display:table; - } -.doc_notes { background: #fafafa; border: 1px solid #cecece; padding: 0.1em } - -TABLE.layout { text-align: left; border: none; border-collapse: collapse; - padding: 4px 4px 4px 4px; } -TR.layout { border: none; padding: 4pt 4pt 2pt 2pt; } -TD.layout { border: none; padding: 4pt 4pt 2pt 2pt; - vertical-align: top;} -TD.left { border: none; padding: 4pt 4pt 2pt 2pt; text-align: left; - vertical-align: top;} -TD.right { border: none; padding: 4pt 4pt 2pt 2pt; text-align: right; - vertical-align: top;} -TH.layout { border: none; font-weight: bold; font-size: 105%; - text-align:center; vertical-align: middle; } - -/* Left align table cell */ -.td_left { border: 2px solid gray; text-align: left; } - -.toc-backref { color: black; } diff --git a/tools/llvmc2/driver/Action.cpp b/tools/llvmc2/driver/Action.cpp deleted file mode 100644 index c0a1b84..0000000 --- a/tools/llvmc2/driver/Action.cpp +++ /dev/null @@ -1,78 +0,0 @@ -//===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Action class - implementation and auxiliary functions. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/Action.h" - -#include "llvm/Support/CommandLine.h" -#include "llvm/System/Program.h" - -#include -#include - -using namespace llvm; -using namespace llvmc; - -extern cl::opt DryRun; -extern cl::opt VerboseMode; - -namespace { - int ExecuteProgram(const std::string& name, - const StrVector& args) { - sys::Path prog = sys::Program::FindProgramByName(name); - - if (prog.isEmpty()) - throw std::runtime_error("Can't find program '" + name + "'"); - if (!prog.canExecute()) - throw std::runtime_error("Program '" + name + "' is not executable."); - - // Build the command line vector and the redirects array. - const sys::Path* redirects[3] = {0,0,0}; - sys::Path stdout_redirect; - - std::vector argv; - argv.reserve((args.size()+2)); - argv.push_back(name.c_str()); - - for (StrVector::const_iterator B = args.begin(), E = args.end(); - B!=E; ++B) { - if (*B == ">") { - ++B; - stdout_redirect.set(*B); - redirects[1] = &stdout_redirect; - } - else { - argv.push_back((*B).c_str()); - } - } - argv.push_back(0); // null terminate list. - - // Invoke the program. - return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]); - } - - void print_string (const std::string& str) { - std::cerr << str << ' '; - } -} - -int llvmc::Action::Execute() const { - if (DryRun || VerboseMode) { - std::cerr << Command_ << " "; - std::for_each(Args_.begin(), Args_.end(), print_string); - std::cerr << '\n'; - } - if (DryRun) - return 0; - else - return ExecuteProgram(Command_, Args_); -} diff --git a/tools/llvmc2/driver/CMakeLists.txt b/tools/llvmc2/driver/CMakeLists.txt deleted file mode 100644 index 7d4e967..0000000 --- a/tools/llvmc2/driver/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(LLVM_LINK_COMPONENTS support system) -set(LLVM_REQUIRES_EH 1) - -add_llvm_tool(llvmc2 - Action.cpp - CompilationGraph.cpp - llvmc.cpp - Plugin.cpp - ) diff --git a/tools/llvmc2/driver/CompilationGraph.cpp b/tools/llvmc2/driver/CompilationGraph.cpp deleted file mode 100644 index 81283ba..0000000 --- a/tools/llvmc2/driver/CompilationGraph.cpp +++ /dev/null @@ -1,438 +0,0 @@ -//===--- CompilationGraph.cpp - The LLVM Compiler Driver --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Compilation graph - implementation. -// -//===----------------------------------------------------------------------===// - -#include "Error.h" -#include "llvm/CompilerDriver/CompilationGraph.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/GraphWriter.h" - -#include -#include -#include -#include -#include - -using namespace llvm; -using namespace llvmc; - -extern cl::list InputFilenames; -extern cl::opt OutputFilename; -extern cl::list Languages; - -namespace llvmc { - - const std::string& LanguageMap::GetLanguage(const sys::Path& File) const { - LanguageMap::const_iterator Lang = this->find(File.getSuffix()); - if (Lang == this->end()) - throw std::runtime_error("Unknown suffix: " + File.getSuffix()); - return Lang->second; - } -} - -namespace { - - /// ChooseEdge - Return the edge with the maximum weight. - template - const Edge* ChooseEdge(const C& EdgesContainer, - const InputLanguagesSet& InLangs, - const std::string& NodeName = "root") { - const Edge* MaxEdge = 0; - unsigned MaxWeight = 0; - bool SingleMax = true; - - for (typename C::const_iterator B = EdgesContainer.begin(), - E = EdgesContainer.end(); B != E; ++B) { - const Edge* e = B->getPtr(); - unsigned EW = e->Weight(InLangs); - if (EW > MaxWeight) { - MaxEdge = e; - MaxWeight = EW; - SingleMax = true; - } else if (EW == MaxWeight) { - SingleMax = false; - } - } - - if (!SingleMax) - throw std::runtime_error("Node " + NodeName + - ": multiple maximal outward edges found!" - " Most probably a specification error."); - if (!MaxEdge) - throw std::runtime_error("Node " + NodeName + - ": no maximal outward edge found!" - " Most probably a specification error."); - return MaxEdge; - } - -} - -CompilationGraph::CompilationGraph() { - NodesMap["root"] = Node(this); -} - -Node& CompilationGraph::getNode(const std::string& ToolName) { - nodes_map_type::iterator I = NodesMap.find(ToolName); - if (I == NodesMap.end()) - throw std::runtime_error("Node " + ToolName + " is not in the graph"); - return I->second; -} - -const Node& CompilationGraph::getNode(const std::string& ToolName) const { - nodes_map_type::const_iterator I = NodesMap.find(ToolName); - if (I == NodesMap.end()) - throw std::runtime_error("Node " + ToolName + " is not in the graph!"); - return I->second; -} - -// Find the tools list corresponding to the given language name. -const CompilationGraph::tools_vector_type& -CompilationGraph::getToolsVector(const std::string& LangName) const -{ - tools_map_type::const_iterator I = ToolsMap.find(LangName); - if (I == ToolsMap.end()) - throw std::runtime_error("No tool corresponding to the language " - + LangName + " found"); - return I->second; -} - -void CompilationGraph::insertNode(Tool* V) { - if (NodesMap.count(V->Name()) == 0) - NodesMap[V->Name()] = Node(this, V); -} - -void CompilationGraph::insertEdge(const std::string& A, Edge* Edg) { - Node& B = getNode(Edg->ToolName()); - if (A == "root") { - const char** InLangs = B.ToolPtr->InputLanguages(); - for (;*InLangs; ++InLangs) - ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr(Edg)); - NodesMap["root"].AddEdge(Edg); - } - else { - Node& N = getNode(A); - N.AddEdge(Edg); - } - // Increase the inward edge counter. - B.IncrInEdges(); -} - -namespace { - sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName, - const std::string& Suffix) { - sys::Path Out; - - // Make sure we don't end up with path names like '/file.o' if the - // TempDir is empty. - if (TempDir.empty()) { - Out.set(BaseName); - } - else { - Out = TempDir; - Out.appendComponent(BaseName); - } - Out.appendSuffix(Suffix); - // NOTE: makeUnique always *creates* a unique temporary file, - // which is good, since there will be no races. However, some - // tools do not like it when the output file already exists, so - // they have to be placated with -f or something like that. - Out.makeUnique(true, NULL); - return Out; - } -} - -// Pass input file through the chain until we bump into a Join node or -// a node that says that it is the last. -void CompilationGraph::PassThroughGraph (const sys::Path& InFile, - const Node* StartNode, - const InputLanguagesSet& InLangs, - const sys::Path& TempDir, - const LanguageMap& LangMap) const { - bool Last = false; - sys::Path In = InFile; - const Node* CurNode = StartNode; - - while(!Last) { - sys::Path Out; - Tool* CurTool = CurNode->ToolPtr.getPtr(); - - if (CurTool->IsJoin()) { - JoinTool& JT = dynamic_cast(*CurTool); - JT.AddToJoinList(In); - break; - } - - // Since toolchains do not have to end with a Join node, we should - // check if this Node is the last. - if (!CurNode->HasChildren() || CurTool->IsLast()) { - if (!OutputFilename.empty()) { - Out.set(OutputFilename); - } - else { - Out.set(In.getBasename()); - Out.appendSuffix(CurTool->OutputSuffix()); - } - Last = true; - } - else { - Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix()); - } - - if (int ret = CurTool->GenerateAction(In, Out, InLangs, LangMap).Execute()) - throw error_code(ret); - - if (Last) - return; - - CurNode = &getNode(ChooseEdge(CurNode->OutEdges, - InLangs, - CurNode->Name())->ToolName()); - In = Out; Out.clear(); - } -} - -// Find the head of the toolchain corresponding to the given file. -// Also, insert an input language into InLangs. -const Node* CompilationGraph:: -FindToolChain(const sys::Path& In, const std::string* ForceLanguage, - InputLanguagesSet& InLangs, const LanguageMap& LangMap) const { - - // Determine the input language. - const std::string& InLanguage = - ForceLanguage ? *ForceLanguage : LangMap.GetLanguage(In); - - // Add the current input language to the input language set. - InLangs.insert(InLanguage); - - // Find the toolchain for the input language. - const tools_vector_type& TV = getToolsVector(InLanguage); - if (TV.empty()) - throw std::runtime_error("No toolchain corresponding to language " - + InLanguage + " found"); - return &getNode(ChooseEdge(TV, InLangs)->ToolName()); -} - -// Helper function used by Build(). -// Traverses initial portions of the toolchains (up to the first Join node). -// This function is also responsible for handling the -x option. -void CompilationGraph::BuildInitial (InputLanguagesSet& InLangs, - const sys::Path& TempDir, - const LanguageMap& LangMap) { - // This is related to -x option handling. - cl::list::const_iterator xIter = Languages.begin(), - xBegin = xIter, xEnd = Languages.end(); - bool xEmpty = true; - const std::string* xLanguage = 0; - unsigned xPos = 0, xPosNext = 0, filePos = 0; - - if (xIter != xEnd) { - xEmpty = false; - xPos = Languages.getPosition(xIter - xBegin); - cl::list::const_iterator xNext = llvm::next(xIter); - xPosNext = (xNext == xEnd) ? std::numeric_limits::max() - : Languages.getPosition(xNext - xBegin); - xLanguage = (*xIter == "none") ? 0 : &(*xIter); - } - - // For each input file: - for (cl::list::const_iterator B = InputFilenames.begin(), - CB = B, E = InputFilenames.end(); B != E; ++B) { - sys::Path In = sys::Path(*B); - - // Code for handling the -x option. - // Output: std::string* xLanguage (can be NULL). - if (!xEmpty) { - filePos = InputFilenames.getPosition(B - CB); - - if (xPos < filePos) { - if (filePos < xPosNext) { - xLanguage = (*xIter == "none") ? 0 : &(*xIter); - } - else { // filePos >= xPosNext - // Skip xIters while filePos > xPosNext - while (filePos > xPosNext) { - ++xIter; - xPos = xPosNext; - - cl::list::const_iterator xNext = llvm::next(xIter); - if (xNext == xEnd) - xPosNext = std::numeric_limits::max(); - else - xPosNext = Languages.getPosition(xNext - xBegin); - xLanguage = (*xIter == "none") ? 0 : &(*xIter); - } - } - } - } - - // Find the toolchain corresponding to this file. - const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap); - // Pass file through the chain starting at head. - PassThroughGraph(In, N, InLangs, TempDir, LangMap); - } -} - -// Sort the nodes in topological order. -void CompilationGraph::TopologicalSort(std::vector& Out) { - std::queue Q; - Q.push(&getNode("root")); - - while (!Q.empty()) { - const Node* A = Q.front(); - Q.pop(); - Out.push_back(A); - for (Node::const_iterator EB = A->EdgesBegin(), EE = A->EdgesEnd(); - EB != EE; ++EB) { - Node* B = &getNode((*EB)->ToolName()); - B->DecrInEdges(); - if (B->HasNoInEdges()) - Q.push(B); - } - } -} - -namespace { - bool NotJoinNode(const Node* N) { - return N->ToolPtr ? !N->ToolPtr->IsJoin() : true; - } -} - -// Call TopologicalSort and filter the resulting list to include -// only Join nodes. -void CompilationGraph:: -TopologicalSortFilterJoinNodes(std::vector& Out) { - std::vector TopSorted; - TopologicalSort(TopSorted); - std::remove_copy_if(TopSorted.begin(), TopSorted.end(), - std::back_inserter(Out), NotJoinNode); -} - -int CompilationGraph::Build (const sys::Path& TempDir, - const LanguageMap& LangMap) { - - InputLanguagesSet InLangs; - - // Traverse initial parts of the toolchains and fill in InLangs. - BuildInitial(InLangs, TempDir, LangMap); - - std::vector JTV; - TopologicalSortFilterJoinNodes(JTV); - - // For all join nodes in topological order: - for (std::vector::iterator B = JTV.begin(), E = JTV.end(); - B != E; ++B) { - - sys::Path Out; - const Node* CurNode = *B; - JoinTool* JT = &dynamic_cast(*CurNode->ToolPtr.getPtr()); - bool IsLast = false; - - // Are there any files in the join list? - if (JT->JoinListEmpty()) - continue; - - // Is this the last tool in the toolchain? - // NOTE: we can process several toolchains in parallel. - if (!CurNode->HasChildren() || JT->IsLast()) { - if (OutputFilename.empty()) { - Out.set("a"); - Out.appendSuffix(JT->OutputSuffix()); - } - else - Out.set(OutputFilename); - IsLast = true; - } - else { - Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix()); - } - - if (int ret = JT->GenerateAction(Out, InLangs, LangMap).Execute()) - throw error_code(ret); - - if (!IsLast) { - const Node* NextNode = - &getNode(ChooseEdge(CurNode->OutEdges, InLangs, - CurNode->Name())->ToolName()); - PassThroughGraph(Out, NextNode, InLangs, TempDir, LangMap); - } - } - - return 0; -} - -// Code related to graph visualization. - -namespace llvm { - template <> - struct DOTGraphTraits - : public DefaultDOTGraphTraits - { - - template - static std::string getNodeLabel(const Node* N, const GraphType&) - { - if (N->ToolPtr) - if (N->ToolPtr->IsJoin()) - return N->Name() + "\n (join" + - (N->HasChildren() ? ")" - : std::string(": ") + N->ToolPtr->OutputLanguage() + ')'); - else - return N->Name(); - else - return "root"; - } - - template - static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) { - if (N->ToolPtr) { - return N->ToolPtr->OutputLanguage(); - } - else { - const char** InLangs = I->ToolPtr->InputLanguages(); - std::string ret; - - for (; *InLangs; ++InLangs) { - if (*(InLangs + 1)) { - ret += *InLangs; - ret += ", "; - } - else { - ret += *InLangs; - } - } - - return ret; - } - } - }; - -} - -void CompilationGraph::writeGraph() { - std::ofstream O("compilation-graph.dot"); - - if (O.good()) { - llvm::WriteGraph(this, "compilation-graph"); - O.close(); - } - else { - throw std::runtime_error("Error opening file 'compilation-graph.dot'" - " for writing!"); - } -} - -void CompilationGraph::viewGraph() { - llvm::ViewGraph(this, "compilation-graph"); -} diff --git a/tools/llvmc2/driver/Error.h b/tools/llvmc2/driver/Error.h deleted file mode 100644 index c0aaff1..0000000 --- a/tools/llvmc2/driver/Error.h +++ /dev/null @@ -1,33 +0,0 @@ -//===--- Error.h - The LLVM Compiler Driver ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Exception classes for LLVMC. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVMC2_ERROR_H -#define LLVM_TOOLS_LLVMC2_ERROR_H - -#include - -namespace llvmc { - - class error_code: public std::runtime_error { - int Code_; - public: - error_code (int c) - : std::runtime_error("Tool returned error code"), Code_(c) - {} - - int code() const { return Code_; } - }; - -} - -#endif //LLVM_TOOLS_LLVMC2_ERROR_H diff --git a/tools/llvmc2/driver/Makefile b/tools/llvmc2/driver/Makefile deleted file mode 100644 index 7c04fe4..0000000 --- a/tools/llvmc2/driver/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -##===- tools/llvmc2/src/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open -# Source License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -TOOLNAME = $(DRIVER_NAME) -LINK_COMPONENTS = support system -REQUIRES_EH := 1 - -ifneq ($(BUILTIN_PLUGINS),) -USEDLIBS = $(patsubst %,LLVMC%,$(BUILTIN_PLUGINS)) -endif - -include $(LEVEL)/Makefile.common diff --git a/tools/llvmc2/driver/Plugin.cpp b/tools/llvmc2/driver/Plugin.cpp deleted file mode 100644 index 17c7086..0000000 --- a/tools/llvmc2/driver/Plugin.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===--- Plugin.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Plugin support for llvmc2. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/Plugin.h" - -#include -#include - -namespace { - - // Registry::Add<> does not do lifetime management (probably issues - // with static constructor/destructor ordering), so we have to - // implement it here. - // - // All this static registration/life-before-main model seems - // unnecessary convoluted to me. - - static bool pluginListInitialized = false; - typedef std::vector PluginList; - static PluginList Plugins; - - struct ByPriority { - bool operator()(const llvmc::BasePlugin* lhs, - const llvmc::BasePlugin* rhs) { - return lhs->Priority() < rhs->Priority(); - } - }; -} - -namespace llvmc { - - PluginLoader::PluginLoader() { - if (!pluginListInitialized) { - for (PluginRegistry::iterator B = PluginRegistry::begin(), - E = PluginRegistry::end(); B != E; ++B) - Plugins.push_back(B->instantiate()); - std::sort(Plugins.begin(), Plugins.end(), ByPriority()); - } - pluginListInitialized = true; - } - - PluginLoader::~PluginLoader() { - if (pluginListInitialized) { - for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); - B != E; ++B) - delete (*B); - } - pluginListInitialized = false; - } - - void PluginLoader::PopulateLanguageMap(LanguageMap& langMap) { - for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); - B != E; ++B) - (*B)->PopulateLanguageMap(langMap); - } - - void PluginLoader::PopulateCompilationGraph(CompilationGraph& graph) { - for (PluginList::iterator B = Plugins.begin(), E = Plugins.end(); - B != E; ++B) - (*B)->PopulateCompilationGraph(graph); - } - -} diff --git a/tools/llvmc2/driver/llvmc.cpp b/tools/llvmc2/driver/llvmc.cpp deleted file mode 100644 index f3a1e57..0000000 --- a/tools/llvmc2/driver/llvmc.cpp +++ /dev/null @@ -1,119 +0,0 @@ -//===--- llvmc.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open -// Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This tool provides a single point of access to the LLVM -// compilation tools. It has many options. To discover the options -// supported please refer to the tools' manual page or run the tool -// with the --help option. -// -//===----------------------------------------------------------------------===// - -#include "Error.h" - -#include "llvm/CompilerDriver/CompilationGraph.h" -#include "llvm/CompilerDriver/Plugin.h" - -#include "llvm/System/Path.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/PluginLoader.h" - -#include -#include -#include - -namespace cl = llvm::cl; -namespace sys = llvm::sys; -using namespace llvmc; - -// Built-in command-line options. -// External linkage here is intentional. - -cl::list InputFilenames(cl::Positional, cl::desc(""), - cl::ZeroOrMore); -cl::opt OutputFilename("o", cl::desc("Output file name"), - cl::value_desc("file")); -cl::list Languages("x", - cl::desc("Specify the language of the following input files"), - cl::ZeroOrMore); -cl::opt DryRun("dry-run", - cl::desc("Only pretend to run commands")); -cl::opt VerboseMode("v", - cl::desc("Enable verbose mode")); -cl::opt WriteGraph("write-graph", - cl::desc("Write compilation-graph.dot file"), - cl::Hidden); -cl::opt ViewGraph("view-graph", - cl::desc("Show compilation graph in GhostView"), - cl::Hidden); -cl::opt SaveTemps("save-temps", - cl::desc("Keep temporary files"), - cl::Hidden); - -namespace { - /// BuildTargets - A small wrapper for CompilationGraph::Build. - int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) { - int ret; - const sys::Path& tempDir = SaveTemps - ? sys::Path("") - : sys::Path(sys::Path::GetTemporaryDirectory()); - - try { - ret = graph.Build(tempDir, langMap); - } - catch(...) { - tempDir.eraseFromDisk(true); - throw; - } - - if (!SaveTemps) - tempDir.eraseFromDisk(true); - return ret; - } -} - -int main(int argc, char** argv) { - try { - LanguageMap langMap; - CompilationGraph graph; - - cl::ParseCommandLineOptions - (argc, argv, "LLVM Compiler Driver (Work In Progress)", true); - - PluginLoader Plugins; - Plugins.PopulateLanguageMap(langMap); - Plugins.PopulateCompilationGraph(graph); - - if (WriteGraph) { - graph.writeGraph(); - if (!ViewGraph) - return 0; - } - - if (ViewGraph) { - graph.viewGraph(); - return 0; - } - - if (InputFilenames.empty()) { - throw std::runtime_error("no input files"); - } - - return BuildTargets(graph, langMap); - } - catch(llvmc::error_code& ec) { - return ec.code(); - } - catch(const std::exception& ex) { - std::cerr << argv[0] << ": " << ex.what() << '\n'; - } - catch(...) { - std::cerr << argv[0] << ": unknown error!\n"; - } - return 1; -} diff --git a/tools/llvmc2/plugins/Base/Base.td b/tools/llvmc2/plugins/Base/Base.td deleted file mode 100644 index 85a37cb..0000000 --- a/tools/llvmc2/plugins/Base/Base.td +++ /dev/null @@ -1,59 +0,0 @@ -//===- Base.td - LLVMC2 toolchain descriptions -------------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains compilation graph description used by llvmc2. -// -//===----------------------------------------------------------------------===// - -include "llvm/CompilerDriver/Common.td" -include "llvm/CompilerDriver/Tools.td" - -// Toolchains - -def CompilationGraph : CompilationGraph<[ - Edge<"root", "llvm_gcc_c">, - Edge<"root", "llvm_gcc_assembler">, - Edge<"root", "llvm_gcc_cpp">, - Edge<"root", "llvm_gcc_m">, - Edge<"root", "llvm_gcc_mxx">, - Edge<"root", "llvm_as">, - - Edge<"llvm_gcc_c", "llc">, - Edge<"llvm_gcc_cpp", "llc">, - Edge<"llvm_gcc_m", "llc">, - Edge<"llvm_gcc_mxx", "llc">, - Edge<"llvm_as", "llc">, - - OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_gcc_m", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_gcc_mxx", "opt", (case (switch_on "opt"), (inc_weight))>, - OptionalEdge<"llvm_as", "opt", (case (switch_on "opt"), (inc_weight))>, - Edge<"opt", "llc">, - - Edge<"llc", "llvm_gcc_assembler">, - Edge<"llvm_gcc_assembler", "llvm_gcc_linker">, - OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker", - (case - (or (input_languages_contain "c++"), - (input_languages_contain "objective-c++")), - (inc_weight), - (or (parameter_equals "linker", "g++"), - (parameter_equals "linker", "c++")), (inc_weight))>, - - - Edge<"root", "llvm_gcc_linker">, - OptionalEdge<"root", "llvm_gcc_cpp_linker", - (case - (or (input_languages_contain "c++"), - (input_languages_contain "objective-c++")), - (inc_weight), - (or (parameter_equals "linker", "g++"), - (parameter_equals "linker", "c++")), (inc_weight))> - ]>; diff --git a/tools/llvmc2/plugins/Base/Makefile b/tools/llvmc2/plugins/Base/Makefile deleted file mode 100644 index c1579d1..0000000 --- a/tools/llvmc2/plugins/Base/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- tools/llvmc2/plugins/Base/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLVMC_PLUGIN = Base -BUILT_SOURCES = AutoGenerated.inc - -include ../Makefile diff --git a/tools/llvmc2/plugins/Base/PluginMain.cpp b/tools/llvmc2/plugins/Base/PluginMain.cpp deleted file mode 100644 index add8acb..0000000 --- a/tools/llvmc2/plugins/Base/PluginMain.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "AutoGenerated.inc" diff --git a/tools/llvmc2/plugins/Clang/Clang.td b/tools/llvmc2/plugins/Clang/Clang.td deleted file mode 100644 index ee6987f..0000000 --- a/tools/llvmc2/plugins/Clang/Clang.td +++ /dev/null @@ -1,86 +0,0 @@ -// A (first stab at a) replacement for the Clang's ccc script. -// To compile, use this command: -// cd $LLVMC2_DIR -// make DRIVER_NAME=ccc2 BUILTIN_PLUGINS=Clang - -include "llvm/CompilerDriver/Common.td" - - -def Options : OptionList<[ -(switch_option "E", - (help "Stop after the preprocessing stage, do not run the compiler")) -]>; - -class clang_base : Tool< -[(in_language language), - (out_language "llvm-bitcode"), - (output_suffix "bc"), - (cmd_line cmdline), - (switch_option "E", (stop_compilation), (output_suffix "i")), - (sink) -]>; - -def clang_c : clang_base<"c", -(case -(switch_on "E"), - (case - (not_empty "o"), - "clang -E -x c $INFILE -o $OUTFILE", - (default), - "clang -E -x c $INFILE"), -(default), - "clang -emit-llvm-bc -x c $INFILE -o $OUTFILE")>; - -def clang_cpp : clang_base<"c++", -(case -(switch_on "E"), - (case - (not_empty "o"), - "clang -E -x c++ $INFILE -o $OUTFILE", - (default), - "clang -E -x c++ $INFILE"), -(default), - "clang -emit-llvm-bc -x c++ $INFILE -o $OUTFILE")>; - -def clang_objective_c : clang_base<"objective-c", -(case -(switch_on "E"), - (case - (not_empty "o"), - "clang -E -x objective-c $INFILE -o $OUTFILE", - (default), - "clang -E -x objective-c $INFILE"), -(default), - "clang -emit-llvm-bc -x objective-c $INFILE -o $OUTFILE")>; - -// Default linker -def llvm_ld : Tool< -[(in_language "llvm-bitcode"), - (out_language "executable"), - (output_suffix "out"), - (cmd_line "llvm-ld -native -disable-internalize $INFILE -o $OUTFILE"), - (prefix_list_option "L", (forward), (help "Specify a library search path")), - (join) -]>; - -// Language map - -def LanguageMap : LanguageMap< - [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>, - LangToSuffixes<"c", ["c"]>, - LangToSuffixes<"objective-c", ["m"]>, - LangToSuffixes<"c-cpp-output", ["i"]>, - LangToSuffixes<"objective-c-cpp-output", ["mi"]> - ]>; - -// Compilation graph - -def CompilationGraph : CompilationGraph<[ - Edge<"root", "clang_c">, - Edge<"root", "clang_cpp">, - Edge<"root", "clang_objective_c">, - Edge<"clang_c", "llvm_ld">, - Edge<"clang_cpp", "llvm_ld">, - Edge<"clang_objective_c", "llvm_ld"> - ]>; - diff --git a/tools/llvmc2/plugins/Clang/Makefile b/tools/llvmc2/plugins/Clang/Makefile deleted file mode 100644 index 237cc73..0000000 --- a/tools/llvmc2/plugins/Clang/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- tools/llvmc2/plugins/Clang/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLVMC_PLUGIN = Clang -BUILT_SOURCES = AutoGenerated.inc - -include ../Makefile - diff --git a/tools/llvmc2/plugins/Clang/PluginMain.cpp b/tools/llvmc2/plugins/Clang/PluginMain.cpp deleted file mode 100644 index add8acb..0000000 --- a/tools/llvmc2/plugins/Clang/PluginMain.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "AutoGenerated.inc" diff --git a/tools/llvmc2/plugins/Hello/Hello.cpp b/tools/llvmc2/plugins/Hello/Hello.cpp deleted file mode 100644 index eb52d24..0000000 --- a/tools/llvmc2/plugins/Hello/Hello.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//===- Hello.cpp - Example code from "Writing an LLVM Pass" ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Test plugin for LLVMC. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CompilerDriver/CompilationGraph.h" -#include "llvm/CompilerDriver/Plugin.h" - -#include - -namespace { -struct MyPlugin : public llvmc::BasePlugin { - void PopulateLanguageMap(llvmc::LanguageMap&) const - { std::cout << "Hello!\n"; } - - void PopulateCompilationGraph(llvmc::CompilationGraph&) const - {} -}; - -static llvmc::RegisterPlugin RP("Hello", "Hello World plugin"); - -} - - diff --git a/tools/llvmc2/plugins/Hello/Makefile b/tools/llvmc2/plugins/Hello/Makefile deleted file mode 100644 index f0d51dd..0000000 --- a/tools/llvmc2/plugins/Hello/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -##===- tools/llvmc2/plugins/Hello/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLVMC_PLUGIN = Hello - -include ../Makefile diff --git a/tools/llvmc2/plugins/Makefile b/tools/llvmc2/plugins/Makefile deleted file mode 100644 index 041b045..0000000 --- a/tools/llvmc2/plugins/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -##===- tools/llvmc2/plugins/Makefile.plugins ----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open -# Source License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -ifndef LLVMC_PLUGIN - -LEVEL = ../../.. -DIRS = $(BUILTIN_PLUGINS) - -# TOFIX: Should we also build DSO versions of plugins? -export BUILTIN_LLVMC_PLUGIN=1 - -include $(LEVEL)/Makefile.common - -else # LLVMC_PLUGIN - -LEVEL = ../../../.. - -LIBRARYNAME := $(patsubst %,LLVMC%,$(LLVMC_PLUGIN)) -REQUIRES_EH = 1 - -ifndef BUILTIN_LLVMC_PLUGIN -LOADABLE_MODULE = 1 -endif - -ifneq ($(BUILT_SOURCES),) -BUILD_AUTOGENERATED_INC=1 -endif - -include $(LEVEL)/Makefile.common - -# TOFIX: This probably should go into Makefile.rules - -ifdef BUILD_AUTOGENERATED_INC - -TOOLS_SOURCE := $(strip $(wildcard $(PROJ_SRC_DIR)/*.td)) - -TD_COMMON :=$(strip $(wildcard \ - $(LLVM_SRC_ROOT)/include/llvm/CompilerDriver/*.td)) - -$(ObjDir)/AutoGenerated.inc.tmp: $(TOOLS_SOURCE) $(ObjDir)/.dir \ - $(TBLGEN) $(TD_COMMON) - $(Echo) "Building LLVMC configuration library with tblgen" - $(Verb) $(TableGen) -gen-llvmc -o $(call SYSPATH, $@) $< - -AutoGenerated.inc : $(ObjDir)/AutoGenerated.inc.tmp - $(Verb) $(CMP) -s $@ $< || $(CP) $< $@ -endif # BUILD_AUTOGENERATED_INC - -endif # LLVMC_PLUGIN diff --git a/tools/llvmc2/plugins/Simple/Makefile b/tools/llvmc2/plugins/Simple/Makefile deleted file mode 100644 index 4a16256..0000000 --- a/tools/llvmc2/plugins/Simple/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- tools/llvmc2/plugins/Simple/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLVMC_PLUGIN = Simple -BUILT_SOURCES = AutoGenerated.inc - -include ../Makefile diff --git a/tools/llvmc2/plugins/Simple/PluginMain.cpp b/tools/llvmc2/plugins/Simple/PluginMain.cpp deleted file mode 100644 index add8acb..0000000 --- a/tools/llvmc2/plugins/Simple/PluginMain.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "AutoGenerated.inc" diff --git a/tools/llvmc2/plugins/Simple/Simple.td b/tools/llvmc2/plugins/Simple/Simple.td deleted file mode 100644 index b974cbc..0000000 --- a/tools/llvmc2/plugins/Simple/Simple.td +++ /dev/null @@ -1,30 +0,0 @@ -// A simple wrapper for gcc. -// To compile, use this command: -// -// $ cd $LLVMC2_DIR -// $ make DRIVER_NAME=mygcc BUILTIN_PLUGINS=Simple -// -// To build this plugin as a dynamic library: -// -// $ cd $LLVMC2_DIR -// $ make BUILTIN_PLUGINS="" -// $ cd plugins/Simple -// $ make -// -// Run as: -// -// $ llvmc2 -load $LLVM_DIR/Release/lib/LLVMCSimple.so - -include "llvm/CompilerDriver/Common.td" - -def gcc : Tool< -[(in_language "c"), - (out_language "executable"), - (output_suffix "out"), - (cmd_line "gcc $INFILE -o $OUTFILE"), - (sink) -]>; - -def LanguageMap : LanguageMap<[LangToSuffixes<"c", ["c"]>]>; - -def CompilationGraph : CompilationGraph<[Edge<"root", "gcc">]>; -- cgit v1.1