mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
Remove more of llvmc and dependencies.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140121 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
400b624e02
commit
eae5a13078
@ -69,9 +69,6 @@ options) arguments to the tool you are interested in.</p>
|
||||
<li><a href="/cmds/llvm-config.html"><b>llvm-config</b></a> -
|
||||
print out LLVM compilation options, libraries, etc. as configured</li>
|
||||
|
||||
<li><a href="/cmds/llvmc.html"><b>llvmc</b></a> -
|
||||
a generic customizable compiler driver</li>
|
||||
|
||||
<li><a href="/cmds/llvm-diff.html"><b>llvm-diff</b></a> -
|
||||
structurally compare two modules</li>
|
||||
|
||||
|
@ -1,190 +0,0 @@
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
llvmc - The LLVM Compiler Driver (WIP)
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<llvmc> [I<options>] I<filenames...>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
B<llvmc> is a configurable driver for invoking other LLVM (and non-LLVM) tools
|
||||
in order to compile, optimize and link software for multiple languages. For
|
||||
those familiar with FSF's B<gcc> tool, it is very similar. Please note that
|
||||
B<llvmc> is considered an experimental tool.
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=head2 Built-in Options
|
||||
|
||||
LLVMC has some built-in options that can't be overridden in the
|
||||
configuration libraries.
|
||||
|
||||
=over
|
||||
|
||||
=item B<-o> I<filename>
|
||||
|
||||
Output file name.
|
||||
|
||||
=item B<-x> I<language>
|
||||
|
||||
Specify the language of the following input files until the next B<-x>
|
||||
option.
|
||||
|
||||
=item B<-load> I<plugin_name>
|
||||
|
||||
Load the specified plugin DLL. Example:
|
||||
S<-load $LLVM_DIR/Release/lib/LLVMCSimple.so>.
|
||||
|
||||
=item B<-v> or B<--verbose>
|
||||
|
||||
Enable verbose mode, i.e. print out all executed commands.
|
||||
|
||||
=item B<--check-graph>
|
||||
|
||||
Check the compilation for common errors like mismatched output/input language
|
||||
names, multiple default edges and cycles. Because of plugins, these checks can't
|
||||
be performed at compile-time. Exit with code zero if no errors were found, and
|
||||
return the number of found errors otherwise. Hidden option, useful for debugging
|
||||
LLVMC plugins.
|
||||
|
||||
=item B<--view-graph>
|
||||
|
||||
Show a graphical representation of the compilation graph and exit. Requires that
|
||||
you have I<dot> and I<gv> programs installed. Hidden option, useful for
|
||||
debugging LLVMC plugins.
|
||||
|
||||
=item B<--write-graph>
|
||||
|
||||
Write a I<compilation-graph.dot> file in the current directory with the
|
||||
compilation graph description in Graphviz format (identical to the file used by
|
||||
the B<--view-graph> option). The B<-o> option can be used to set the output file
|
||||
name. Hidden option, useful for debugging LLVMC plugins.
|
||||
|
||||
=item B<--save-temps>
|
||||
|
||||
Write temporary files to the current directory and do not delete them on
|
||||
exit. This option can also take an argument: the I<--save-temps=obj> switch will
|
||||
write files into the directory specified with the I<-o> option. The
|
||||
I<--save-temps=cwd> and I<--save-temps> switches are both synonyms for the
|
||||
default behaviour.
|
||||
|
||||
=item B<--temp-dir> I<directory>
|
||||
|
||||
Store temporary files in the given directory. This directory is deleted on exit
|
||||
unless I<--save-temps> is specified. If I<--save-temps=obj> is also specified,
|
||||
I<--temp-dir> is given the precedence.
|
||||
|
||||
=item B<-help>
|
||||
|
||||
Print a summary of command-line options and exit.
|
||||
|
||||
=item B<-help-hidden>
|
||||
|
||||
Print a summary of command-line options and exit. Print help even for
|
||||
options intended for developers.
|
||||
|
||||
=item B<--version>
|
||||
|
||||
Print version information and exit.
|
||||
|
||||
=item B<@>I<file>
|
||||
|
||||
Read command-line options from I<file>. The options read are inserted
|
||||
in place of the original @I<file> option. If I<file> does not exist, or
|
||||
cannot be read, then the option will be treated literally, and not
|
||||
removed.
|
||||
|
||||
Options in I<file> are separated by whitespace. A whitespace character
|
||||
may be included in an option by surrounding the entire option in
|
||||
either single or double quotes. Any character (including a backslash)
|
||||
may be included by prefixing the character to be included with a
|
||||
backslash. The file may itself contain additional @I<file> options;
|
||||
any such options will be processed recursively.
|
||||
|
||||
|
||||
=back
|
||||
|
||||
|
||||
=head2 Control Options
|
||||
|
||||
By default, LLVMC is built with some standard configuration libraries
|
||||
that define the following options:
|
||||
|
||||
=over
|
||||
|
||||
=item B<-clang>
|
||||
|
||||
Use Clang instead of llvm-gcc.
|
||||
|
||||
=item B<-opt>
|
||||
|
||||
Enable optimization passes with B<opt>. To pass options to the B<opt> program
|
||||
use the B<-Wo,> option.
|
||||
|
||||
=item B<-I> I<directory>
|
||||
|
||||
Add a directory to the header file search path.
|
||||
|
||||
=item B<-L> I<directory>
|
||||
|
||||
Add I<directory> to the library search path.
|
||||
|
||||
=item B<-F> I<directory>
|
||||
|
||||
Add I<directory> to the framework search path.
|
||||
|
||||
=item B<-l>I<name>
|
||||
|
||||
Link in the library libI<name>.[bc | a | so]. This library should
|
||||
be a bitcode library.
|
||||
|
||||
=item B<-framework> I<name>
|
||||
|
||||
Link in the library libI<name>.[bc | a | so]. This library should
|
||||
be a bitcode library.
|
||||
|
||||
=item B<-emit-llvm>
|
||||
|
||||
Output LLVM bitcode (with B<-c>) or assembly (with B<-S>) instead of native
|
||||
object (or assembly). If B<-emit-llvm> is given without either B<-c> or B<-S>
|
||||
it has no effect.
|
||||
|
||||
=item B<-Wa>
|
||||
|
||||
Pass options to assembler.
|
||||
|
||||
=item B<-Wl>
|
||||
|
||||
Pass options to linker.
|
||||
|
||||
=item B<-Wo>
|
||||
|
||||
Pass options to opt.
|
||||
|
||||
=item B<-Wllc>
|
||||
|
||||
Pass options to llc (code generator).
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXIT STATUS
|
||||
|
||||
If B<llvmc> succeeds, it will exit with code 0. Otherwise, if an
|
||||
error occurs, it will exit with a non-zero value. If one of the
|
||||
compilation tools returns a non-zero status, pending actions will be
|
||||
discarded and B<llvmc> will return the same result code as the failing
|
||||
compilation tool.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<llvm-gcc|llvmgcc>, L<llvm-g++|llvmgxx>, L<llvm-as|llvm-as>,
|
||||
L<llvm-dis|llvm-dis>, L<llc|llc>, L<llvm-link|llvm-link>
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Maintained by the LLVM Team (L<http://llvm.org/>).
|
||||
|
||||
=cut
|
@ -1,687 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Customizing LLVMC: Reference Manual</title>
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="customizing-llvmc-reference-manual">
|
||||
<h1 class="title">Customizing LLVMC: Reference Manual</h1>
|
||||
|
||||
<!-- This file was automatically generated by rst2html.
|
||||
Please do not edit directly!
|
||||
The ReST source lives in the directory 'tools/llvmc/doc'. -->
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#introduction" id="id7">Introduction</a></li>
|
||||
<li><a class="reference internal" href="#compiling-with-llvmc" id="id8">Compiling with <tt class="docutils literal">llvmc</tt></a></li>
|
||||
<li><a class="reference internal" href="#predefined-options" id="id9">Predefined options</a></li>
|
||||
<li><a class="reference internal" href="#compiling-llvmc-based-drivers" id="id10">Compiling LLVMC-based drivers</a></li>
|
||||
<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id11">Customizing LLVMC: the compilation graph</a></li>
|
||||
<li><a class="reference internal" href="#describing-options" id="id12">Describing options</a></li>
|
||||
<li><a class="reference internal" href="#conditional-evaluation" id="id13">Conditional evaluation</a></li>
|
||||
<li><a class="reference internal" href="#writing-a-tool-description" id="id14">Writing a tool description</a><ul>
|
||||
<li><a class="reference internal" href="#id4" id="id15">Actions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#language-map" id="id16">Language map</a></li>
|
||||
<li><a class="reference internal" href="#option-preprocessor" id="id17">Option preprocessor</a></li>
|
||||
<li><a class="reference internal" href="#more-advanced-topics" id="id18">More advanced topics</a><ul>
|
||||
<li><a class="reference internal" href="#hooks-and-environment-variables" id="id19">Hooks and environment variables</a></li>
|
||||
<li><a class="reference internal" href="#debugging" id="id20">Debugging</a></li>
|
||||
<li><a class="reference internal" href="#conditioning-on-the-executable-name" id="id21">Conditioning on the executable name</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="doc_author">
|
||||
<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
|
||||
</div><div class="section" id="introduction">
|
||||
<h1><a class="toc-backref" href="#id7">Introduction</a></h1>
|
||||
<p>LLVMC is a generic compiler driver, designed to be customizable and
|
||||
extensible. It plays the same role for LLVM as the <tt class="docutils literal">gcc</tt> 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 described in
|
||||
high-level TableGen code, from which an efficient C++ representation is
|
||||
automatically derived. This makes it possible to adapt LLVMC for other
|
||||
purposes - for example, as a build tool for game resources.</p>
|
||||
<p>Because LLVMC employs <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a> as its configuration language, you
|
||||
need to be familiar with it to customize LLVMC.</p>
|
||||
</div>
|
||||
<div class="section" id="compiling-with-llvmc">
|
||||
<h1><a class="toc-backref" href="#id8">Compiling with <tt class="docutils literal">llvmc</tt></a></h1>
|
||||
<p>LLVMC tries hard to be as compatible with <tt class="docutils literal">gcc</tt> as possible,
|
||||
although there are some small differences. Most of the time, however,
|
||||
you shouldn't be able to notice them:</p>
|
||||
<pre class="literal-block">
|
||||
$ # This works as expected:
|
||||
$ llvmc -O3 -Wall hello.cpp
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>One nice feature of LLVMC is that one doesn't have to distinguish between
|
||||
different compilers for different languages (think <tt class="docutils literal">g++</tt> vs. <tt class="docutils literal">gcc</tt>) - 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 <tt class="docutils literal"><span class="pre">-x</span></tt> option, just like you would
|
||||
do it with <tt class="docutils literal">gcc</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
$ # hello.c is really a C++ file
|
||||
$ llvmc -x c++ hello.c
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>On the other hand, when using LLVMC as a linker to combine several C++
|
||||
object files you should provide the <tt class="docutils literal"><span class="pre">--linker</span></tt> option since it's
|
||||
impossible for LLVMC to choose the right linker in that case:</p>
|
||||
<pre class="literal-block">
|
||||
$ llvmc -c hello.cpp
|
||||
$ llvmc hello.o
|
||||
[A lot of link-time errors skipped]
|
||||
$ llvmc --linker=c++ hello.o
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>By default, LLVMC uses <tt class="docutils literal"><span class="pre">llvm-gcc</span></tt> to compile the source code. It is also
|
||||
possible to choose the <tt class="docutils literal">clang</tt> compiler with the <tt class="docutils literal"><span class="pre">-clang</span></tt> option.</p>
|
||||
</div>
|
||||
<div class="section" id="predefined-options">
|
||||
<h1><a class="toc-backref" href="#id9">Predefined options</a></h1>
|
||||
<p>LLVMC has some built-in options that can't be overridden in the TableGen code:</p>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">-o</span> FILE</tt> - Output file name.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">-x</span> LANGUAGE</tt> - Specify the language of the following input files
|
||||
until the next -x option.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">-v</span></tt> - Enable verbose mode, i.e. print out all executed commands.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--save-temps</span></tt> - Write temporary files to the current directory and do not
|
||||
delete them on exit. This option can also take an argument: the
|
||||
<tt class="docutils literal"><span class="pre">--save-temps=obj</span></tt> switch will write files into the directory specified with
|
||||
the <tt class="docutils literal"><span class="pre">-o</span></tt> option. The <tt class="docutils literal"><span class="pre">--save-temps=cwd</span></tt> and <tt class="docutils literal"><span class="pre">--save-temps</span></tt> switches are
|
||||
both synonyms for the default behaviour.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--temp-dir</span> DIRECTORY</tt> - Store temporary files in the given directory. This
|
||||
directory is deleted on exit unless <tt class="docutils literal"><span class="pre">--save-temps</span></tt> is specified. If
|
||||
<tt class="docutils literal"><span class="pre">--save-temps=obj</span></tt> is also specified, <tt class="docutils literal"><span class="pre">--temp-dir</span></tt> is given the
|
||||
precedence.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--check-graph</span></tt> - Check the compilation for common errors like mismatched
|
||||
output/input language names, multiple default edges and cycles. Exit with code
|
||||
zero if no errors were found, and return the number of found errors
|
||||
otherwise. Hidden option, useful for debugging.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--view-graph</span></tt> - Show a graphical representation of the compilation graph
|
||||
and exit. Requires that you have <tt class="docutils literal">dot</tt> and <tt class="docutils literal">gv</tt> programs installed. Hidden
|
||||
option, useful for debugging.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--write-graph</span></tt> - Write a <tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt> file in the current
|
||||
directory with the compilation graph description in Graphviz format (identical
|
||||
to the file used by the <tt class="docutils literal"><span class="pre">--view-graph</span></tt> option). The <tt class="docutils literal"><span class="pre">-o</span></tt> option can be
|
||||
used to set the output file name. Hidden option, useful for debugging.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">--help</span></tt>, <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>, <tt class="docutils literal"><span class="pre">--version</span></tt> - These options have
|
||||
their standard meaning.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="compiling-llvmc-based-drivers">
|
||||
<h1><a class="toc-backref" href="#id10">Compiling LLVMC-based drivers</a></h1>
|
||||
<p>It's easiest to start working on your own LLVMC driver by copying the skeleton
|
||||
project which lives under <tt class="docutils literal">$LLVMC_DIR/examples/Skeleton</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
$ cd $LLVMC_DIR/examples
|
||||
$ cp -r Skeleton MyDriver
|
||||
$ cd MyDriver
|
||||
$ ls
|
||||
AutoGenerated.td Hooks.cpp Main.cpp Makefile
|
||||
</pre>
|
||||
<p>As you can see, our basic driver consists of only three files (not counting the
|
||||
build script). <tt class="docutils literal">AutoGenerated.td</tt> contains TableGen description of the
|
||||
compilation graph; its format is documented in the following
|
||||
sections. <tt class="docutils literal">Hooks.cpp</tt> is an empty file that should be used for hook
|
||||
definitions (see <a class="reference internal" href="#hooks">below</a>). <tt class="docutils literal">Main.cpp</tt> is just a helper used to compile the
|
||||
auto-generated C++ code produced from TableGen source.</p>
|
||||
<p>The first thing that you should do is to change the <tt class="docutils literal">LLVMC_BASED_DRIVER</tt>
|
||||
variable in the <tt class="docutils literal">Makefile</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
LLVMC_BASED_DRIVER=MyDriver
|
||||
</pre>
|
||||
<p>It can also be a good idea to put your TableGen code into a file with a less
|
||||
generic name:</p>
|
||||
<pre class="literal-block">
|
||||
$ touch MyDriver.td
|
||||
$ vim AutoGenerated.td
|
||||
[...]
|
||||
include "MyDriver.td"
|
||||
</pre>
|
||||
<p>If you have more than one TableGen source file, they all should be included from
|
||||
<tt class="docutils literal">AutoGenerated.td</tt>, since this file is used by the build system to generate
|
||||
C++ code.</p>
|
||||
<p>To build your driver, just <tt class="docutils literal">cd</tt> to its source directory and run <tt class="docutils literal">make</tt>. The
|
||||
resulting executable will be put into <tt class="docutils literal"><span class="pre">$LLVM_OBJ_DIR/$(BuildMode)/bin</span></tt>.</p>
|
||||
<p>If you're compiling LLVM with different source and object directories, then you
|
||||
must perform the following additional steps before running <tt class="docutils literal">make</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
|
||||
# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
|
||||
$ mkdir $LLVMC_OBJ_DIR/examples/MyDriver/
|
||||
$ cp $LLVMC_SRC_DIR/examples/MyDriver/Makefile \
|
||||
$LLVMC_OBJ_DIR/examples/MyDriver/
|
||||
$ cd $LLVMC_OBJ_DIR/examples/MyDriver
|
||||
$ make
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="customizing-llvmc-the-compilation-graph">
|
||||
<h1><a class="toc-backref" href="#id11">Customizing LLVMC: the compilation graph</a></h1>
|
||||
<p>Each TableGen configuration file should include the common definitions:</p>
|
||||
<pre class="literal-block">
|
||||
include "llvm/CompilerDriver/Common.td"
|
||||
</pre>
|
||||
<p>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.</p>
|
||||
<p>The definition of the compilation graph (see file <tt class="docutils literal">llvmc/src/Base.td</tt> for an
|
||||
example) is just a list of edges:</p>
|
||||
<pre class="literal-block">
|
||||
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))>,
|
||||
...
|
||||
|
||||
]>;
|
||||
</pre>
|
||||
<p>As you can see, the edges can be either default or optional, where optional
|
||||
edges are differentiated by an additional <tt class="docutils literal">case</tt> 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
|
||||
without having to know about all tool definitions used in the graph.</p>
|
||||
<p>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 <tt class="docutils literal">case</tt>
|
||||
expression. It is also possible to provide an integer parameter to
|
||||
<tt class="docutils literal">inc_weight</tt> and <tt class="docutils literal">dec_weight</tt> - in this case, the weight is increased (or
|
||||
decreased) by the provided value instead of the default 2. Default weight of an
|
||||
optional edge can be changed by using the <tt class="docutils literal">default</tt> clause of the <tt class="docutils literal">case</tt>
|
||||
construct.</p>
|
||||
<p>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 <em>per language</em>).</p>
|
||||
<p>When multiple compilation graphs are defined, they are merged together. Multiple
|
||||
edges with the same end nodes are not allowed (i.e. the graph is not a
|
||||
multigraph), and will lead to a compile-time error.</p>
|
||||
<p>To get a visual representation of the compilation graph (useful for debugging),
|
||||
run <tt class="docutils literal">llvmc <span class="pre">--view-graph</span></tt>. You will need <tt class="docutils literal">dot</tt> and <tt class="docutils literal">gsview</tt> installed for
|
||||
this to work properly.</p>
|
||||
</div>
|
||||
<div class="section" id="describing-options">
|
||||
<h1><a class="toc-backref" href="#id12">Describing options</a></h1>
|
||||
<p>Command-line options supported by the driver are defined by using an
|
||||
<tt class="docutils literal">OptionList</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
def Options : OptionList<[
|
||||
(switch_option "E", (help "Help string")),
|
||||
(alias_option "quiet", "q")
|
||||
...
|
||||
]>;
|
||||
</pre>
|
||||
<p>As you can see, the option list is just a list of DAGs, where each DAG is an
|
||||
option description consisting of the option name and some properties. More than
|
||||
one option list can be defined (they are all merged together in the end), which
|
||||
can be handy if one wants to separate option groups syntactically.</p>
|
||||
<ul>
|
||||
<li><p class="first">Possible option types:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">switch_option</tt> - a simple boolean switch without arguments, for example
|
||||
<tt class="docutils literal"><span class="pre">-O2</span></tt> or <tt class="docutils literal"><span class="pre">-time</span></tt>. At most one occurrence is allowed by default.</li>
|
||||
<li><tt class="docutils literal">parameter_option</tt> - option that takes one argument, for example
|
||||
<tt class="docutils literal"><span class="pre">-std=c99</span></tt>. It is also allowed to use spaces instead of the equality
|
||||
sign: <tt class="docutils literal"><span class="pre">-std</span> c99</tt>. At most one occurrence is allowed.</li>
|
||||
<li><tt class="docutils literal">parameter_list_option</tt> - same as the above, but more than one option
|
||||
occurrence is allowed.</li>
|
||||
<li><tt class="docutils literal">prefix_option</tt> - same as the parameter_option, but the option name and
|
||||
argument do not have to be separated. Example: <tt class="docutils literal"><span class="pre">-ofile</span></tt>. This can be also
|
||||
specified as <tt class="docutils literal"><span class="pre">-o</span> file</tt>; however, <tt class="docutils literal"><span class="pre">-o=file</span></tt> will be parsed incorrectly
|
||||
(<tt class="docutils literal">=file</tt> will be interpreted as option value). At most one occurrence is
|
||||
allowed.</li>
|
||||
<li><tt class="docutils literal">prefix_list_option</tt> - same as the above, but more than one occurrence of
|
||||
the option is allowed; example: <tt class="docutils literal"><span class="pre">-lm</span> <span class="pre">-lpthread</span></tt>.</li>
|
||||
<li><tt class="docutils literal">alias_option</tt> - 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: <tt class="docutils literal">(alias_option "preprocess", "E")</tt></li>
|
||||
<li><tt class="docutils literal">switch_list_option</tt> - like <tt class="docutils literal">switch_option</tt> with the <tt class="docutils literal">zero_or_more</tt>
|
||||
property, but remembers how many times the switch was turned on. Useful
|
||||
mostly for forwarding. Example: when <tt class="docutils literal"><span class="pre">-foo</span></tt> is a switch option (with the
|
||||
<tt class="docutils literal">zero_or_more</tt> property), the command <tt class="docutils literal">driver <span class="pre">-foo</span> <span class="pre">-foo</span></tt> is forwarded
|
||||
as <tt class="docutils literal"><span class="pre">some-tool</span> <span class="pre">-foo</span></tt>, but when <tt class="docutils literal"><span class="pre">-foo</span></tt> is a switch list, the same command
|
||||
is forwarded as <tt class="docutils literal"><span class="pre">some-tool</span> <span class="pre">-foo</span> <span class="pre">-foo</span></tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
<li><p class="first">Possible option properties:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">help</tt> - help string associated with this option. Used for <tt class="docutils literal"><span class="pre">--help</span></tt>
|
||||
output.</li>
|
||||
<li><tt class="docutils literal">required</tt> - this option must be specified exactly once (or, in case of
|
||||
the list options without the <tt class="docutils literal">multi_val</tt> property, at least
|
||||
once). Incompatible with <tt class="docutils literal">optional</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">optional</tt> - the option can be specified either zero times or exactly
|
||||
once. The default for switch options. Useful only for list options in
|
||||
conjunction with <tt class="docutils literal">multi_val</tt>. Incompatible with <tt class="docutils literal">required</tt>,
|
||||
<tt class="docutils literal">zero_or_more</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">one_or_more</tt> - the option must be specified at least once. Can be useful
|
||||
to allow switch options be both obligatory and be specified multiple
|
||||
times. For list options is useful only in conjunction with <tt class="docutils literal">multi_val</tt>;
|
||||
for ordinary it is synonymous with <tt class="docutils literal">required</tt>. Incompatible with
|
||||
<tt class="docutils literal">required</tt>, <tt class="docutils literal">optional</tt> and <tt class="docutils literal">zero_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">zero_or_more</tt> - the option can be specified zero or more times. Useful
|
||||
to allow a single switch option to be specified more than
|
||||
once. Incompatible with <tt class="docutils literal">required</tt>, <tt class="docutils literal">optional</tt> and <tt class="docutils literal">one_or_more</tt>.</li>
|
||||
<li><tt class="docutils literal">hidden</tt> - the description of this option will not appear in
|
||||
the <tt class="docutils literal"><span class="pre">--help</span></tt> output (but will appear in the <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>
|
||||
output).</li>
|
||||
<li><tt class="docutils literal">really_hidden</tt> - the option will not be mentioned in any help
|
||||
output.</li>
|
||||
<li><tt class="docutils literal">comma_separated</tt> - Indicates that any commas specified for an option's
|
||||
value should be used to split the value up into multiple values for the
|
||||
option. This property is valid only for list options. In conjunction with
|
||||
<tt class="docutils literal">forward_value</tt> can be used to implement option forwarding in style of
|
||||
gcc's <tt class="docutils literal"><span class="pre">-Wa,</span></tt>.</li>
|
||||
<li><tt class="docutils literal">multi_val n</tt> - this option takes <em>n</em> arguments (can be useful in some
|
||||
special cases). Usage example: <tt class="docutils literal">(parameter_list_option "foo", (multi_val
|
||||
3))</tt>; the command-line syntax is '-foo a b c'. Only list options can have
|
||||
this attribute; you can, however, use the <tt class="docutils literal">one_or_more</tt>, <tt class="docutils literal">optional</tt>
|
||||
and <tt class="docutils literal">required</tt> properties.</li>
|
||||
<li><tt class="docutils literal">init</tt> - this option has a default value, either a string (if it is a
|
||||
parameter), or a boolean (if it is a switch; as in C++, boolean constants
|
||||
are called <tt class="docutils literal">true</tt> and <tt class="docutils literal">false</tt>). List options can't have <tt class="docutils literal">init</tt>
|
||||
attribute.
|
||||
Usage examples: <tt class="docutils literal">(switch_option "foo", (init true))</tt>; <tt class="docutils literal">(prefix_option
|
||||
"bar", (init <span class="pre">"baz"))</span></tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="conditional-evaluation">
|
||||
<span id="case"></span><h1><a class="toc-backref" href="#id13">Conditional evaluation</a></h1>
|
||||
<p>The 'case' construct is the main means by which programmability is achieved in
|
||||
LLVMC. It can be used to calculate edge weights, program actions and modify the
|
||||
shell commands to be executed. The 'case' expression is designed after the
|
||||
similarly-named construct in functional languages and takes the form <tt class="docutils literal">(case
|
||||
(test_1), statement_1, (test_2), statement_2, ... (test_N), statement_N)</tt>. The
|
||||
statements are evaluated only if the corresponding tests evaluate to true.</p>
|
||||
<p>Examples:</p>
|
||||
<pre class="literal-block">
|
||||
// Edge weight calculation
|
||||
|
||||
// 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))
|
||||
|
||||
|
||||
// Tool command line specification
|
||||
|
||||
// Evaluates to "cmdline1" if the option "-A" is provided on the
|
||||
// command line; to "cmdline2" if "-B" is provided;
|
||||
// otherwise to "cmdline3".
|
||||
|
||||
(case
|
||||
(switch_on "A"), "cmdline1",
|
||||
(switch_on "B"), "cmdline2",
|
||||
(default), "cmdline3")
|
||||
</pre>
|
||||
<p>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
|
||||
<tt class="docutils literal">"B"</tt> switch is never checked when switch <tt class="docutils literal">"A"</tt> is enabled, and the whole
|
||||
expression always evaluates to <tt class="docutils literal">"cmdline1"</tt> in that case.</p>
|
||||
<p>Case expressions can also be nested, i.e. the following is legal:</p>
|
||||
<pre class="literal-block">
|
||||
(case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
|
||||
(default), ...)
|
||||
</pre>
|
||||
<p>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.</p>
|
||||
<ul class="simple">
|
||||
<li>Possible tests are:<ul>
|
||||
<li><tt class="docutils literal">switch_on</tt> - Returns true if a given command-line switch is provided by
|
||||
the user. Can be given multiple arguments, in that case <tt class="docutils literal">(switch_on "foo",
|
||||
"bar", "baz")</tt> is equivalent to <tt class="docutils literal">(and (switch_on <span class="pre">"foo"),</span> (switch_on
|
||||
<span class="pre">"bar"),</span> (switch_on <span class="pre">"baz"))</span></tt>.
|
||||
Example: <tt class="docutils literal">(switch_on "opt")</tt>.</li>
|
||||
<li><tt class="docutils literal">any_switch_on</tt> - Given a number of switch options, returns true if any of
|
||||
the switches is turned on.
|
||||
Example: <tt class="docutils literal">(any_switch_on "foo", "bar", "baz")</tt> is equivalent to <tt class="docutils literal">(or
|
||||
(switch_on <span class="pre">"foo"),</span> (switch_on <span class="pre">"bar"),</span> (switch_on <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">parameter_equals</tt> - Returns true if a command-line parameter (first
|
||||
argument) equals a given value (second argument).
|
||||
Example: <tt class="docutils literal">(parameter_equals "W", "all")</tt>.</li>
|
||||
<li><tt class="docutils literal">element_in_list</tt> - Returns true if a command-line parameter list (first
|
||||
argument) contains a given value (second argument).
|
||||
Example: <tt class="docutils literal">(element_in_list "l", "pthread")</tt>.</li>
|
||||
<li><tt class="docutils literal">input_languages_contain</tt> - Returns true if a given language
|
||||
belongs to the current input language set.
|
||||
Example: <tt class="docutils literal">(input_languages_contain <span class="pre">"c++")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">in_language</tt> - Evaluates to true if the input file language is equal to
|
||||
the argument. At the moment works only with <tt class="docutils literal">command</tt> and <tt class="docutils literal">actions</tt> (on
|
||||
non-join nodes).
|
||||
Example: <tt class="docutils literal">(in_language <span class="pre">"c++")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">not_empty</tt> - Returns true if a given option (which should be either a
|
||||
parameter or a parameter list) is set by the user. Like <tt class="docutils literal">switch_on</tt>, can
|
||||
be also given multiple arguments.
|
||||
Examples: <tt class="docutils literal">(not_empty "o")</tt>, <tt class="docutils literal">(not_empty "o", "l")</tt>.</li>
|
||||
<li><tt class="docutils literal">any_not_empty</tt> - Returns true if <tt class="docutils literal">not_empty</tt> returns true for any of
|
||||
the provided options.
|
||||
Example: <tt class="docutils literal">(any_not_empty "foo", "bar", "baz")</tt> is equivalent to <tt class="docutils literal">(or
|
||||
(not_empty <span class="pre">"foo"),</span> (not_empty <span class="pre">"bar"),</span> (not_empty <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">empty</tt> - The opposite of <tt class="docutils literal">not_empty</tt>. Equivalent to <tt class="docutils literal">(not (not_empty
|
||||
X))</tt>. Can be given multiple arguments.</li>
|
||||
<li><tt class="docutils literal">any_not_empty</tt> - Returns true if <tt class="docutils literal">not_empty</tt> returns true for any of
|
||||
the provided options.
|
||||
Example: <tt class="docutils literal">(any_empty "foo", "bar", "baz")</tt> is equivalent to <tt class="docutils literal">(or
|
||||
(not_empty <span class="pre">"foo"),</span> (not_empty <span class="pre">"bar"),</span> (not_empty <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">single_input_file</tt> - Returns true if there was only one input file
|
||||
provided on the command-line. Used without arguments:
|
||||
<tt class="docutils literal">(single_input_file)</tt>.</li>
|
||||
<li><tt class="docutils literal">multiple_input_files</tt> - Equivalent to <tt class="docutils literal">(not (single_input_file))</tt> (the
|
||||
case of zero input files is considered an error).</li>
|
||||
<li><tt class="docutils literal">default</tt> - Always evaluates to true. Should always be the last
|
||||
test in the <tt class="docutils literal">case</tt> expression.</li>
|
||||
<li><tt class="docutils literal">and</tt> - A standard logical combinator that returns true iff all of
|
||||
its arguments return true. Used like this: <tt class="docutils literal">(and (test1), (test2),
|
||||
... (testN))</tt>. Nesting of <tt class="docutils literal">and</tt> and <tt class="docutils literal">or</tt> is allowed, but not
|
||||
encouraged.</li>
|
||||
<li><tt class="docutils literal">or</tt> - A logical combinator that returns true iff any of its arguments
|
||||
return true.
|
||||
Example: <tt class="docutils literal">(or (test1), (test2), ... (testN))</tt>.</li>
|
||||
<li><tt class="docutils literal">not</tt> - Standard unary logical combinator that negates its
|
||||
argument.
|
||||
Example: <tt class="docutils literal">(not (or (test1), (test2), ... <span class="pre">(testN)))</span></tt>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="writing-a-tool-description">
|
||||
<h1><a class="toc-backref" href="#id14">Writing a tool description</a></h1>
|
||||
<p>As was said earlier, nodes in the compilation graph represent tools, which are
|
||||
described separately. A tool definition looks like this (taken from the
|
||||
<tt class="docutils literal">llvmc/src/Base.td</tt> file):</p>
|
||||
<pre class="literal-block">
|
||||
def llvm_gcc_cpp : Tool<[
|
||||
(in_language "c++"),
|
||||
(out_language "llvm-assembler"),
|
||||
(output_suffix "bc"),
|
||||
(command "llvm-g++ -c -emit-llvm"),
|
||||
(sink)
|
||||
]>;
|
||||
</pre>
|
||||
<p>This defines a new tool called <tt class="docutils literal">llvm_gcc_cpp</tt>, which is an alias for
|
||||
<tt class="docutils literal"><span class="pre">llvm-g++</span></tt>. As you can see, a tool definition is just a list of properties;
|
||||
most of them should be self-explanatory. The <tt class="docutils literal">sink</tt> property means that this
|
||||
tool should be passed all command-line options that aren't mentioned in the
|
||||
option list.</p>
|
||||
<p>The complete list of all currently implemented tool properties follows.</p>
|
||||
<ul class="simple">
|
||||
<li>Possible tool properties:<ul>
|
||||
<li><tt class="docutils literal">in_language</tt> - input language name. Can be given multiple arguments, in
|
||||
case the tool supports multiple input languages. Used for typechecking and
|
||||
mapping file extensions to tools.</li>
|
||||
<li><tt class="docutils literal">out_language</tt> - output language name. Multiple output languages are
|
||||
allowed. Used for typechecking the compilation graph.</li>
|
||||
<li><tt class="docutils literal">output_suffix</tt> - output file suffix. Can also be changed dynamically, see
|
||||
documentation on <a class="reference internal" href="#actions">actions</a>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">command</tt> - the actual command used to run the tool. You can use output
|
||||
redirection with <tt class="docutils literal">></tt>, hook invocations (<tt class="docutils literal">$CALL</tt>), environment variables
|
||||
(via <tt class="docutils literal">$ENV</tt>) and the <tt class="docutils literal">case</tt> construct.</li>
|
||||
<li><tt class="docutils literal">join</tt> - 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.</li>
|
||||
<li><tt class="docutils literal">sink</tt> - all command-line options that are not handled by other tools are
|
||||
passed to this tool.</li>
|
||||
<li><tt class="docutils literal">actions</tt> - A single big <tt class="docutils literal">case</tt> expression that specifies how this tool
|
||||
reacts on command-line options (described in more detail <a class="reference internal" href="#actions">below</a>).</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">out_file_option</tt>, <tt class="docutils literal">in_file_option</tt> - Options appended to the
|
||||
<tt class="docutils literal">command</tt> string to designate output and input files. Default values are
|
||||
<tt class="docutils literal"><span class="pre">"-o"</span></tt> and <tt class="docutils literal">""</tt>, respectively.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<div class="section" id="id4">
|
||||
<span id="actions"></span><h2><a class="toc-backref" href="#id15">Actions</a></h2>
|
||||
<p>A tool often needs to react to command-line options, and this is precisely what
|
||||
the <tt class="docutils literal">actions</tt> property is for. The next example illustrates this feature:</p>
|
||||
<pre class="literal-block">
|
||||
def llvm_gcc_linker : Tool<[
|
||||
(in_language "object-code"),
|
||||
(out_language "executable"),
|
||||
(output_suffix "out"),
|
||||
(command "llvm-gcc"),
|
||||
(join),
|
||||
(actions (case (not_empty "L"), (forward "L"),
|
||||
(not_empty "l"), (forward "l"),
|
||||
(not_empty "dummy"),
|
||||
[(append_cmd "-dummy1"), (append_cmd "-dummy2")])
|
||||
]>;
|
||||
</pre>
|
||||
<p>The <tt class="docutils literal">actions</tt> tool property is implemented on top of the omnipresent <tt class="docutils literal">case</tt>
|
||||
expression. It associates one or more different <em>actions</em> with given
|
||||
conditions - in the example, the actions are <tt class="docutils literal">forward</tt>, which forwards a given
|
||||
option unchanged, and <tt class="docutils literal">append_cmd</tt>, which appends a given string to the tool
|
||||
execution command. Multiple actions can be associated with a single condition by
|
||||
using a list of actions (used in the example to append some dummy options). The
|
||||
same <tt class="docutils literal">case</tt> construct can also be used in the <tt class="docutils literal">cmd_line</tt> property to modify
|
||||
the tool command line.</p>
|
||||
<p>The "join" property used in the example means that this tool behaves like a
|
||||
linker.</p>
|
||||
<p>The list of all possible actions follows.</p>
|
||||
<ul>
|
||||
<li><p class="first">Possible actions:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal">append_cmd</tt> - Append a string to the tool invocation command.
|
||||
Example: <tt class="docutils literal">(case (switch_on <span class="pre">"pthread"),</span> (append_cmd <span class="pre">"-lpthread"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal">error</tt> - Exit with error.
|
||||
Example: <tt class="docutils literal">(error "Mixing <span class="pre">-c</span> and <span class="pre">-S</span> is not <span class="pre">allowed!")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">warning</tt> - Print a warning.
|
||||
Example: <tt class="docutils literal">(warning "Specifying both <span class="pre">-O1</span> and <span class="pre">-O2</span> is <span class="pre">meaningless!")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">forward</tt> - Forward the option unchanged.
|
||||
Example: <tt class="docutils literal">(forward "Wall")</tt>.</li>
|
||||
<li><tt class="docutils literal">forward_as</tt> - Change the option's name, but forward the argument
|
||||
unchanged.
|
||||
Example: <tt class="docutils literal">(forward_as "O0", <span class="pre">"--disable-optimization")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">forward_value</tt> - Forward only option's value. Cannot be used with switch
|
||||
options (since they don't have values), but works fine with lists.
|
||||
Example: <tt class="docutils literal">(forward_value <span class="pre">"Wa,")</span></tt>.</li>
|
||||
<li><tt class="docutils literal">forward_transformed_value</tt> - As above, but applies a hook to the
|
||||
option's value before forwarding (see <a class="reference internal" href="#hooks">below</a>). When
|
||||
<tt class="docutils literal">forward_transformed_value</tt> is applied to a list
|
||||
option, the hook must have signature
|
||||
<tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::HookName</span> (const <span class="pre">std::vector<std::string>&)</span></tt>.
|
||||
Example: <tt class="docutils literal">(forward_transformed_value "m", "ConvertToMAttr")</tt>.</li>
|
||||
<li><tt class="docutils literal">output_suffix</tt> - Modify the output suffix of this tool.
|
||||
Example: <tt class="docutils literal">(output_suffix "i")</tt>.</li>
|
||||
<li><tt class="docutils literal">stop_compilation</tt> - Stop compilation after this tool processes its
|
||||
input. Used without arguments.
|
||||
Example: <tt class="docutils literal">(stop_compilation)</tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="language-map">
|
||||
<h1><a class="toc-backref" href="#id16">Language map</a></h1>
|
||||
<p>If you are adding support for a new language to LLVMC, you'll need to modify 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:</p>
|
||||
<pre class="literal-block">
|
||||
def LanguageMap : LanguageMap<
|
||||
[LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
|
||||
LangToSuffixes<"c", ["c"]>,
|
||||
...
|
||||
]>;
|
||||
</pre>
|
||||
<p>For example, without those definitions the following command wouldn't work:</p>
|
||||
<pre class="literal-block">
|
||||
$ llvmc hello.cpp
|
||||
llvmc: Unknown suffix: cpp
|
||||
</pre>
|
||||
<p>The language map entries are needed only for the tools that are linked from the
|
||||
root node. A tool can have multiple output languages.</p>
|
||||
</div>
|
||||
<div class="section" id="option-preprocessor">
|
||||
<h1><a class="toc-backref" href="#id17">Option preprocessor</a></h1>
|
||||
<p>It is sometimes useful to run error-checking code before processing the
|
||||
compilation graph. For example, if optimization options "-O1" and "-O2" are
|
||||
implemented as switches, we might want to output a warning if the user invokes
|
||||
the driver with both of these options enabled.</p>
|
||||
<p>The <tt class="docutils literal">OptionPreprocessor</tt> feature is reserved specially for these
|
||||
occasions. Example (adapted from <tt class="docutils literal">llvm/src/Base.td.in</tt>):</p>
|
||||
<pre class="literal-block">
|
||||
def Preprocess : OptionPreprocessor<
|
||||
(case (not (any_switch_on "O0", "O1", "O2", "O3")),
|
||||
(set_option "O2"),
|
||||
(and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")),
|
||||
(unset_option "O0", "O1", "O2"),
|
||||
(and (switch_on "O2"), (any_switch_on "O0", "O1")),
|
||||
(unset_option "O0", "O1"),
|
||||
(and (switch_on "O1"), (switch_on "O0")),
|
||||
(unset_option "O0"))
|
||||
>;
|
||||
</pre>
|
||||
<p>Here, <tt class="docutils literal">OptionPreprocessor</tt> is used to unset all spurious <tt class="docutils literal"><span class="pre">-O</span></tt> options so
|
||||
that they are not forwarded to the compiler. If no optimization options are
|
||||
specified, <tt class="docutils literal"><span class="pre">-O2</span></tt> is enabled.</p>
|
||||
<p><tt class="docutils literal">OptionPreprocessor</tt> is basically a single big <tt class="docutils literal">case</tt> expression, which is
|
||||
evaluated only once right after the driver is started. The only allowed actions
|
||||
in <tt class="docutils literal">OptionPreprocessor</tt> are <tt class="docutils literal">error</tt>, <tt class="docutils literal">warning</tt>, and two special actions:
|
||||
<tt class="docutils literal">unset_option</tt> and <tt class="docutils literal">set_option</tt>. As their names suggest, they can be used to
|
||||
set or unset a given option. To set an option with <tt class="docutils literal">set_option</tt>, use the
|
||||
two-argument form: <tt class="docutils literal">(set_option "parameter", VALUE)</tt>. Here, <tt class="docutils literal">VALUE</tt> can be
|
||||
either a string, a string list, or a boolean constant.</p>
|
||||
<p>For convenience, <tt class="docutils literal">set_option</tt> and <tt class="docutils literal">unset_option</tt> also work with multiple
|
||||
arguments. That is, instead of <tt class="docutils literal">[(unset_option <span class="pre">"A"),</span> (unset_option <span class="pre">"B")]</span></tt> you
|
||||
can use <tt class="docutils literal">(unset_option "A", "B")</tt>. Obviously, <tt class="docutils literal">(set_option "A", "B")</tt> is
|
||||
only valid if both <tt class="docutils literal">A</tt> and <tt class="docutils literal">B</tt> are switches.</p>
|
||||
</div>
|
||||
<div class="section" id="more-advanced-topics">
|
||||
<h1><a class="toc-backref" href="#id18">More advanced topics</a></h1>
|
||||
<div class="section" id="hooks-and-environment-variables">
|
||||
<span id="hooks"></span><h2><a class="toc-backref" href="#id19">Hooks and environment variables</a></h2>
|
||||
<p>Normally, LLVMC searches for programs in the system <tt class="docutils literal">PATH</tt>. Sometimes, this is
|
||||
not sufficient: for example, we may want to specify tool paths or names in the
|
||||
configuration file. This can be achieved via the hooks mechanism. To write your
|
||||
own hooks, add their definitions to the <tt class="docutils literal">Hooks.cpp</tt> or drop a <tt class="docutils literal">.cpp</tt> file
|
||||
into your driver directory. Hooks should live in the <tt class="docutils literal">hooks</tt> namespace and
|
||||
have the signature <tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::MyHookName</span> ([const char* Arg0 [ const
|
||||
char* Arg2 [, <span class="pre">...]]])</span></tt>. They can be used from the <tt class="docutils literal">command</tt> tool property:</p>
|
||||
<pre class="literal-block">
|
||||
(command "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
|
||||
</pre>
|
||||
<p>To pass arguments to hooks, use the following syntax:</p>
|
||||
<pre class="literal-block">
|
||||
(command "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
|
||||
</pre>
|
||||
<p>It is also possible to use environment variables in the same manner:</p>
|
||||
<pre class="literal-block">
|
||||
(command "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
|
||||
</pre>
|
||||
<p>To change the command line string based on user-provided options use
|
||||
the <tt class="docutils literal">case</tt> expression (documented <a class="reference internal" href="#case">above</a>):</p>
|
||||
<pre class="literal-block">
|
||||
(command
|
||||
(case
|
||||
(switch_on "E"),
|
||||
"llvm-g++ -E -x c $INFILE -o $OUTFILE",
|
||||
(default),
|
||||
"llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="debugging">
|
||||
<h2><a class="toc-backref" href="#id20">Debugging</a></h2>
|
||||
<p>When writing LLVMC-based drivers, it can be useful to get a visual view of the
|
||||
resulting compilation graph. This can be achieved via the command line option
|
||||
<tt class="docutils literal"><span class="pre">--view-graph</span></tt> (which assumes that <a class="reference external" href="http://www.graphviz.org/">Graphviz</a> and <a class="reference external" href="http://pages.cs.wisc.edu/~ghost/">Ghostview</a> are
|
||||
installed). There is also a <tt class="docutils literal"><span class="pre">--write-graph</span></tt> option that creates a Graphviz
|
||||
source file (<tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt>) in the current directory.</p>
|
||||
<p>Another useful <tt class="docutils literal">llvmc</tt> option is <tt class="docutils literal"><span class="pre">--check-graph</span></tt>. It checks the compilation
|
||||
graph for common errors like mismatched output/input language names, multiple
|
||||
default edges and cycles. When invoked with <tt class="docutils literal"><span class="pre">--check-graph</span></tt>, <tt class="docutils literal">llvmc</tt> doesn't
|
||||
perform any compilation tasks and returns the number of encountered errors as
|
||||
its status code. In the future, these checks will be performed at compile-time
|
||||
and this option will disappear.</p>
|
||||
</div>
|
||||
<div class="section" id="conditioning-on-the-executable-name">
|
||||
<h2><a class="toc-backref" href="#id21">Conditioning on the executable name</a></h2>
|
||||
<p>For now, the executable name (the value passed to the driver in <tt class="docutils literal">argv[0]</tt>) is
|
||||
accessible only in the C++ code (i.e. hooks). Use the following code:</p>
|
||||
<pre class="literal-block">
|
||||
namespace llvmc {
|
||||
extern const char* ProgramName;
|
||||
}
|
||||
|
||||
namespace hooks {
|
||||
|
||||
std::string MyHook() {
|
||||
//...
|
||||
if (strcmp(ProgramName, "mydriver") == 0) {
|
||||
//...
|
||||
|
||||
}
|
||||
|
||||
} // end namespace hooks
|
||||
</pre>
|
||||
<p>In general, you're encouraged not to make the behaviour dependent on the
|
||||
executable file name, and use command-line switches instead. See for example how
|
||||
the <tt class="docutils literal">llvmc</tt> program behaves when it needs to choose the correct linker options
|
||||
(think <tt class="docutils literal">g++</tt> vs. <tt class="docutils literal">gcc</tt>).</p>
|
||||
<hr />
|
||||
<address>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer">
|
||||
<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
|
||||
alt="Valid CSS" /></a>
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
|
||||
alt="Valid XHTML 1.0 Transitional"/></a>
|
||||
|
||||
<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
|
||||
|
||||
Last modified: $Date$
|
||||
</address></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,125 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />
|
||||
<title>Tutorial - Using LLVMC</title>
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="tutorial-using-llvmc">
|
||||
<h1 class="title">Tutorial - Using LLVMC</h1>
|
||||
|
||||
<!-- This file was automatically generated by rst2html.
|
||||
Please do not edit directly!
|
||||
The ReST source lives in the directory 'tools/llvmc/doc'. -->
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#introduction" id="id1">Introduction</a></li>
|
||||
<li><a class="reference internal" href="#using-the-llvmc-program" id="id2">Using the <tt class="docutils literal">llvmc</tt> program</a></li>
|
||||
<li><a class="reference internal" href="#using-llvmc-to-generate-toolchain-drivers" id="id3">Using LLVMC to generate toolchain drivers</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="doc_author">
|
||||
<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
|
||||
</div><div class="section" id="introduction">
|
||||
<h1><a class="toc-backref" href="#id1">Introduction</a></h1>
|
||||
<p>LLVMC is a generic compiler driver, which plays the same role for LLVM as the
|
||||
<tt class="docutils literal">gcc</tt> 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 high-level TableGen code, from which a corresponding C++ source
|
||||
file is automatically generated. This tutorial describes the basic usage and
|
||||
configuration of LLVMC.</p>
|
||||
</div>
|
||||
<div class="section" id="using-the-llvmc-program">
|
||||
<h1><a class="toc-backref" href="#id2">Using the <tt class="docutils literal">llvmc</tt> program</a></h1>
|
||||
<p>In general, <tt class="docutils literal">llvmc</tt> tries to be command-line compatible with <tt class="docutils literal">gcc</tt> as much
|
||||
as possible, so most of the familiar options work:</p>
|
||||
<pre class="literal-block">
|
||||
$ llvmc -O3 -Wall hello.cpp
|
||||
$ ./a.out
|
||||
hello
|
||||
</pre>
|
||||
<p>This will invoke <tt class="docutils literal"><span class="pre">llvm-g++</span></tt> under the hood (you can see which commands are
|
||||
executed by using the <tt class="docutils literal"><span class="pre">-v</span></tt> option). For further help on command-line LLVMC
|
||||
usage, refer to the <tt class="docutils literal">llvmc <span class="pre">--help</span></tt> output.</p>
|
||||
</div>
|
||||
<div class="section" id="using-llvmc-to-generate-toolchain-drivers">
|
||||
<h1><a class="toc-backref" href="#id3">Using LLVMC to generate toolchain drivers</a></h1>
|
||||
<p>LLVMC-based drivers are written mostly using <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a>, so you need to be
|
||||
familiar with it to get anything done.</p>
|
||||
<p>Start by compiling <tt class="docutils literal">example/Simple</tt>, which is a primitive wrapper for
|
||||
<tt class="docutils literal">gcc</tt>:</p>
|
||||
<pre class="literal-block">
|
||||
$ cd $LLVM_OBJ_DIR/tools/examples/Simple
|
||||
$ make
|
||||
$ cat > hello.c
|
||||
#include <stdio.h>
|
||||
int main() { printf("Hello\n"); }
|
||||
$ $LLVM_BIN_DIR/Simple -v hello.c
|
||||
gcc hello.c -o hello.out
|
||||
$ ./hello.out
|
||||
Hello
|
||||
</pre>
|
||||
<p>We have thus produced a simple driver called, appropriately, <tt class="docutils literal">Simple</tt>, from
|
||||
the input TableGen file <tt class="docutils literal">Simple.td</tt>. The <tt class="docutils literal">llvmc</tt> program itself is generated
|
||||
using a similar process (see <tt class="docutils literal">llvmc/src</tt>). Contents of the file <tt class="docutils literal">Simple.td</tt>
|
||||
look like this:</p>
|
||||
<pre class="literal-block">
|
||||
// Include common definitions
|
||||
include "llvm/CompilerDriver/Common.td"
|
||||
|
||||
// Tool descriptions
|
||||
def gcc : Tool<
|
||||
[(in_language "c"),
|
||||
(out_language "executable"),
|
||||
(output_suffix "out"),
|
||||
(command "gcc"),
|
||||
(sink),
|
||||
|
||||
// -o is what is used by default, out_file_option here is included for
|
||||
// instructive purposes.
|
||||
(out_file_option "-o")
|
||||
]>;
|
||||
|
||||
// Language map
|
||||
def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
|
||||
|
||||
// Compilation graph
|
||||
def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
|
||||
</pre>
|
||||
<p>As you can see, this file consists of three parts: tool descriptions, language
|
||||
map, and the compilation graph definition.</p>
|
||||
<p>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 <tt class="docutils literal">root</tt> is used to mark graph entry points.</p>
|
||||
<p>Tool descriptions are represented as property lists: most properties in the
|
||||
example above should be self-explanatory; the <tt class="docutils literal">sink</tt> property means that all
|
||||
options lacking an explicit description should be forwarded to this tool.</p>
|
||||
<p>The <tt class="docutils literal">LanguageMap</tt> associates a language name with a list of suffixes and is
|
||||
used for deciding which toolchain corresponds to a given input file.</p>
|
||||
<p>To learn more about writing your own drivers with LLVMC, refer to the reference
|
||||
manual and examples in the <tt class="docutils literal">examples</tt> directory. Of a particular interest is
|
||||
the <tt class="docutils literal">Skeleton</tt> example, which can serve as a template for your LLVMC-based
|
||||
drivers.</p>
|
||||
<hr />
|
||||
<address>
|
||||
<a href="http://jigsaw.w3.org/css-validator/check/referer">
|
||||
<img src="http://jigsaw.w3.org/css-validator/images/vcss-blue"
|
||||
alt="Valid CSS" /></a>
|
||||
<a href="http://validator.w3.org/check?uri=referer">
|
||||
<img src="http://www.w3.org/Icons/valid-xhtml10-blue"
|
||||
alt="Valid XHTML 1.0 Transitional"/></a>
|
||||
|
||||
<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
|
||||
|
||||
Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
|
||||
</address></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -540,10 +540,7 @@ Stop.
|
||||
<p>Currently, there isn't much. LLVM supports an intermediate representation
|
||||
which is useful for code representation but will not support the high level
|
||||
(abstract syntax tree) representation needed by most compilers. There are no
|
||||
facilities for lexical nor semantic analysis. There is, however, a <i>mostly
|
||||
implemented</i> configuration-driven
|
||||
<a href="CompilerDriver.html">compiler driver</a> which simplifies the task
|
||||
of running optimizations, linking, and executable generation.</p>
|
||||
facilities for lexical nor semantic analysis.</p>
|
||||
</div>
|
||||
|
||||
<div class="question">
|
||||
|
@ -216,14 +216,6 @@ in LLVM.</li>
|
||||
<li><a href="Bugpoint.html">Bugpoint</a> - automatic bug finder and test-case
|
||||
reducer description and usage information.</li>
|
||||
|
||||
<li><a href="CompilerDriverTutorial.html">Compiler Driver (llvmc) Tutorial</a>
|
||||
- This document is a tutorial introduction to the usage and
|
||||
configuration of the LLVM compiler driver tool, <tt>llvmc</tt>.</li>
|
||||
|
||||
<li><a href="CompilerDriver.html">Compiler Driver (llvmc)
|
||||
Reference</a> - This document describes the design and configuration
|
||||
of <tt>llvmc</tt> in more detail.</li>
|
||||
|
||||
<li><a href="BitCodeFormat.html">LLVM Bitcode File Format</a> - This describes
|
||||
the file format and encoding used for LLVM "bc" files.</li>
|
||||
|
||||
|
@ -1,54 +0,0 @@
|
||||
//===--- Action.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Action - encapsulates a single shell command.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
typedef std::vector<std::string> StrVector;
|
||||
|
||||
/// Action - A class that encapsulates a single shell command.
|
||||
class Action {
|
||||
/// Command_ - The actual command (for example, 'ls').
|
||||
std::string Command_;
|
||||
/// Args_ - Command arguments. Stdout redirection ("> file") is allowed.
|
||||
std::vector<std::string> Args_;
|
||||
/// StopCompilation_ - Should we stop compilation after executing
|
||||
/// this action?
|
||||
bool StopCompilation_;
|
||||
/// OutFile_ - The output file name.
|
||||
std::string OutFile_;
|
||||
|
||||
public:
|
||||
void Construct (const std::string& C, const StrVector& A,
|
||||
bool S, const std::string& O) {
|
||||
Command_ = C;
|
||||
Args_ = A;
|
||||
StopCompilation_ = S;
|
||||
OutFile_ = O;
|
||||
}
|
||||
bool IsConstructed () { return (Command_.size() != 0);}
|
||||
|
||||
/// Execute - Executes the command. Returns -1 on error.
|
||||
int Execute () const;
|
||||
bool StopCompilation () const { return StopCompilation_; }
|
||||
const std::string& OutFile() { return OutFile_; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H
|
@ -1,40 +0,0 @@
|
||||
//===--- AutoGenerated.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Interface to the autogenerated driver code.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H
|
||||
|
||||
namespace llvmc {
|
||||
class LanguageMap;
|
||||
class CompilationGraph;
|
||||
|
||||
namespace autogenerated {
|
||||
|
||||
int PreprocessOptions();
|
||||
int PopulateLanguageMap(LanguageMap& langMap);
|
||||
int PopulateCompilationGraph(CompilationGraph& graph);
|
||||
|
||||
inline int RunInitialization (LanguageMap& M, CompilationGraph& G) {
|
||||
if (int ret = PreprocessOptions())
|
||||
return ret;
|
||||
if (int ret = PopulateLanguageMap(M))
|
||||
return ret;
|
||||
if (int ret = PopulateCompilationGraph(G))
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H
|
@ -1,39 +0,0 @@
|
||||
//===--- BuiltinOptions.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Declarations of all global command-line option variables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
namespace SaveTempsEnum { enum Values { Cwd, Obj, Unset }; }
|
||||
|
||||
extern llvm::cl::list<std::string> InputFilenames;
|
||||
extern llvm::cl::opt<std::string> OutputFilename;
|
||||
extern llvm::cl::opt<std::string> TempDirname;
|
||||
extern llvm::cl::list<std::string> Languages;
|
||||
extern llvm::cl::opt<bool> DryRun;
|
||||
extern llvm::cl::opt<bool> Time;
|
||||
extern llvm::cl::opt<bool> VerboseMode;
|
||||
extern llvm::cl::opt<bool> CheckGraph;
|
||||
extern llvm::cl::opt<bool> ViewGraph;
|
||||
extern llvm::cl::opt<bool> WriteGraph;
|
||||
extern llvm::cl::opt<SaveTempsEnum::Values> SaveTemps;
|
||||
|
||||
} // End namespace llvmc.
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
|
@ -1,127 +0,0 @@
|
||||
//===- Common.td - Common definitions for LLVMC2 ----------*- 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 common definitions used in llvmc tool description files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Tool<list<dag> l> {
|
||||
list<dag> properties = l;
|
||||
}
|
||||
|
||||
// Possible Tool properties.
|
||||
|
||||
def in_language;
|
||||
def out_language;
|
||||
def output_suffix;
|
||||
def command;
|
||||
def out_file_option;
|
||||
def in_file_option;
|
||||
def join;
|
||||
def sink;
|
||||
def works_on_empty;
|
||||
def actions;
|
||||
|
||||
// Possible option types.
|
||||
|
||||
def alias_option;
|
||||
def switch_option;
|
||||
def switch_list_option;
|
||||
def parameter_option;
|
||||
def parameter_list_option;
|
||||
def prefix_option;
|
||||
def prefix_list_option;
|
||||
|
||||
// Possible option properties.
|
||||
|
||||
def help;
|
||||
def hidden;
|
||||
def init;
|
||||
def multi_val;
|
||||
def one_or_more;
|
||||
def zero_or_more;
|
||||
def optional;
|
||||
def really_hidden;
|
||||
def required;
|
||||
def comma_separated;
|
||||
def forward_not_split;
|
||||
|
||||
// The 'case' construct.
|
||||
def case;
|
||||
|
||||
// Boolean constants.
|
||||
class Bool<bit val> {
|
||||
bit Value = val;
|
||||
}
|
||||
def true : Bool<1>;
|
||||
def false : Bool<0>;
|
||||
|
||||
// Boolean operators.
|
||||
def and;
|
||||
def or;
|
||||
def not;
|
||||
|
||||
// Primitive tests.
|
||||
def switch_on;
|
||||
def parameter_equals;
|
||||
def element_in_list;
|
||||
def input_languages_contain;
|
||||
def empty;
|
||||
def not_empty;
|
||||
def default;
|
||||
def single_input_file;
|
||||
def multiple_input_files;
|
||||
def any_switch_on;
|
||||
def any_not_empty;
|
||||
def any_empty;
|
||||
|
||||
// Possible actions.
|
||||
|
||||
def append_cmd;
|
||||
def forward;
|
||||
def forward_as;
|
||||
def forward_value;
|
||||
def forward_transformed_value;
|
||||
def stop_compilation;
|
||||
def no_out_file;
|
||||
def unpack_values;
|
||||
def warning;
|
||||
def error;
|
||||
def set_option;
|
||||
def unset_option;
|
||||
|
||||
// Increase the edge weight.
|
||||
def inc_weight;
|
||||
|
||||
// Option list - a single place to specify options.
|
||||
class OptionList<list<dag> l> {
|
||||
list<dag> options = l;
|
||||
}
|
||||
|
||||
// Option preprocessor - actions taken during plugin loading.
|
||||
class OptionPreprocessor<dag d> {
|
||||
dag preprocessor = d;
|
||||
}
|
||||
|
||||
// Map from suffixes to language names
|
||||
|
||||
def lang_to_suffixes;
|
||||
|
||||
class LanguageMap<list<dag> l> {
|
||||
list<dag> map = l;
|
||||
}
|
||||
|
||||
// Compilation graph
|
||||
|
||||
def edge;
|
||||
def optional_edge;
|
||||
|
||||
class CompilationGraph<list<dag> l> {
|
||||
list<dag> edges = l;
|
||||
}
|
@ -1,330 +0,0 @@
|
||||
//===--- CompilationGraph.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Compilation graph - definition.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H
|
||||
|
||||
#include "llvm/CompilerDriver/Tool.h"
|
||||
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
class CompilationGraph;
|
||||
typedef llvm::StringSet<> InputLanguagesSet;
|
||||
|
||||
/// LanguageMap - Maps from extensions to language names.
|
||||
class LanguageMap : public llvm::StringMap<std::string> {
|
||||
public:
|
||||
|
||||
/// GetLanguage - Find the language name corresponding to a given file.
|
||||
const std::string* GetLanguage(const llvm::sys::Path&) const;
|
||||
};
|
||||
|
||||
/// Edge - Represents an edge of the compilation graph.
|
||||
class Edge : public llvm::RefCountedBaseVPTR {
|
||||
public:
|
||||
Edge(const std::string& T) : ToolName_(T) {}
|
||||
virtual ~Edge() {}
|
||||
|
||||
const std::string& ToolName() const { return ToolName_; }
|
||||
virtual int Weight(const InputLanguagesSet& InLangs) const = 0;
|
||||
private:
|
||||
std::string ToolName_;
|
||||
};
|
||||
|
||||
/// SimpleEdge - An edge that has no properties.
|
||||
class SimpleEdge : public Edge {
|
||||
public:
|
||||
SimpleEdge(const std::string& T) : Edge(T) {}
|
||||
int Weight(const InputLanguagesSet&) const { return 1; }
|
||||
};
|
||||
|
||||
/// Node - A node (vertex) of the compilation graph.
|
||||
struct Node {
|
||||
// A Node holds a list of the outward edges.
|
||||
typedef llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> container_type;
|
||||
typedef container_type::iterator iterator;
|
||||
typedef container_type::const_iterator const_iterator;
|
||||
|
||||
Node() : OwningGraph(0), InEdges(0) {}
|
||||
Node(CompilationGraph* G) : OwningGraph(G), InEdges(0) {}
|
||||
Node(CompilationGraph* G, Tool* T) :
|
||||
OwningGraph(G), ToolPtr(T), InEdges(0) {}
|
||||
|
||||
bool HasChildren() const { return !OutEdges.empty(); }
|
||||
const std::string Name() const
|
||||
{ return ToolPtr ? ToolPtr->Name() : "root"; }
|
||||
|
||||
// Iteration.
|
||||
iterator EdgesBegin() { return OutEdges.begin(); }
|
||||
const_iterator EdgesBegin() const { return OutEdges.begin(); }
|
||||
iterator EdgesEnd() { return OutEdges.end(); }
|
||||
const_iterator EdgesEnd() const { return OutEdges.end(); }
|
||||
|
||||
/// AddEdge - Add an outward edge. Takes ownership of the provided
|
||||
/// Edge object.
|
||||
void AddEdge(Edge* E);
|
||||
|
||||
// Inward edge counter. Used to implement topological sort.
|
||||
void IncrInEdges() { ++InEdges; }
|
||||
void DecrInEdges() { --InEdges; }
|
||||
bool HasNoInEdges() const { return InEdges == 0; }
|
||||
|
||||
// Needed to implement NodeChildIterator/GraphTraits
|
||||
CompilationGraph* OwningGraph;
|
||||
// The corresponding Tool.
|
||||
// WARNING: ToolPtr can be NULL (for the root node).
|
||||
llvm::IntrusiveRefCntPtr<Tool> ToolPtr;
|
||||
// Links to children.
|
||||
container_type OutEdges;
|
||||
// Inward edge counter. Updated in
|
||||
// CompilationGraph::insertEdge(). Used for topological sorting.
|
||||
unsigned InEdges;
|
||||
};
|
||||
|
||||
class NodesIterator;
|
||||
|
||||
/// CompilationGraph - The compilation graph itself.
|
||||
class CompilationGraph {
|
||||
/// nodes_map_type - The main data structure.
|
||||
typedef llvm::StringMap<Node> nodes_map_type;
|
||||
/// tools_vector_type, tools_map_type - Data structures used to
|
||||
/// map from language names to tools. (We can have several tools
|
||||
/// associated with each language name, hence the need for a
|
||||
/// vector.)
|
||||
typedef
|
||||
llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> tools_vector_type;
|
||||
typedef llvm::StringMap<tools_vector_type> tools_map_type;
|
||||
|
||||
/// ToolsMap - Map from language names to lists of tool names.
|
||||
tools_map_type ToolsMap;
|
||||
/// NodesMap - Map from tool names to Tool objects.
|
||||
nodes_map_type NodesMap;
|
||||
|
||||
public:
|
||||
|
||||
typedef nodes_map_type::iterator nodes_iterator;
|
||||
typedef nodes_map_type::const_iterator const_nodes_iterator;
|
||||
|
||||
CompilationGraph();
|
||||
|
||||
/// insertNode - Insert a new node into the graph. Takes
|
||||
/// ownership of the object.
|
||||
void insertNode(Tool* T);
|
||||
|
||||
/// insertEdge - Insert a new edge into the graph. Takes ownership
|
||||
/// of the Edge object. Returns non-zero value on error.
|
||||
int insertEdge(const std::string& A, Edge* E);
|
||||
|
||||
/// Build - Build target(s) from the input file set. Command-line options
|
||||
/// are passed implicitly as global variables. Returns non-zero value on
|
||||
/// error (usually the failed program's exit code).
|
||||
int Build(llvm::sys::Path const& TempDir, const LanguageMap& LangMap);
|
||||
|
||||
/// Check - Check the compilation graph for common errors like cycles,
|
||||
/// input/output language mismatch and multiple default edges. Prints error
|
||||
/// messages and in case it finds any errors.
|
||||
int Check();
|
||||
|
||||
/// getNode - Return a reference to the node corresponding to the given tool
|
||||
/// name. Returns 0 on error.
|
||||
Node* getNode(const std::string& ToolName);
|
||||
const Node* getNode(const std::string& ToolName) const;
|
||||
|
||||
/// viewGraph - This function is meant for use from the debugger. You can
|
||||
/// just say 'call G->viewGraph()' and a ghostview window should pop up from
|
||||
/// the program, displaying the compilation graph. This depends on there
|
||||
/// being a 'dot' and 'gv' program in your path.
|
||||
void viewGraph();
|
||||
|
||||
/// writeGraph - Write Graphviz .dot source file to the current direcotry.
|
||||
int writeGraph(const std::string& OutputFilename);
|
||||
|
||||
// GraphTraits support.
|
||||
friend NodesIterator GraphBegin(CompilationGraph*);
|
||||
friend NodesIterator GraphEnd(CompilationGraph*);
|
||||
|
||||
private:
|
||||
// Helper functions.
|
||||
|
||||
/// getToolsVector - Return a reference to the list of tool names
|
||||
/// corresponding to the given language name. Returns 0 on error.
|
||||
const tools_vector_type* getToolsVector(const std::string& LangName) const;
|
||||
|
||||
/// PassThroughGraph - Pass the input file through the toolchain starting at
|
||||
/// StartNode.
|
||||
int PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode,
|
||||
const InputLanguagesSet& InLangs,
|
||||
const llvm::sys::Path& TempDir,
|
||||
const LanguageMap& LangMap) const;
|
||||
|
||||
/// FindToolChain - Find head of the toolchain corresponding to
|
||||
/// the given file.
|
||||
const Node* FindToolChain(const llvm::sys::Path& In,
|
||||
const std::string* ForceLanguage,
|
||||
InputLanguagesSet& InLangs,
|
||||
const LanguageMap& LangMap) const;
|
||||
|
||||
/// BuildInitial - Traverse the initial parts of the toolchains. Returns
|
||||
/// non-zero value on error.
|
||||
int BuildInitial(InputLanguagesSet& InLangs,
|
||||
const llvm::sys::Path& TempDir,
|
||||
const LanguageMap& LangMap);
|
||||
|
||||
/// TopologicalSort - Sort the nodes in topological order. Returns non-zero
|
||||
/// value on error.
|
||||
int TopologicalSort(std::vector<const Node*>& Out);
|
||||
/// TopologicalSortFilterJoinNodes - Call TopologicalSort and filter the
|
||||
/// resulting list to include only Join nodes. Returns non-zero value on
|
||||
/// error.
|
||||
int TopologicalSortFilterJoinNodes(std::vector<const Node*>& Out);
|
||||
|
||||
// Functions used to implement Check().
|
||||
|
||||
/// CheckLanguageNames - Check that output/input language names match for
|
||||
/// all nodes. Returns non-zero value on error (number of errors
|
||||
/// encountered).
|
||||
int CheckLanguageNames() const;
|
||||
/// CheckMultipleDefaultEdges - check that there are no multiple default
|
||||
/// default edges. Returns non-zero value on error (number of errors
|
||||
/// encountered).
|
||||
int CheckMultipleDefaultEdges() const;
|
||||
/// CheckCycles - Check that there are no cycles in the graph. Returns
|
||||
/// non-zero value on error (number of errors encountered).
|
||||
int CheckCycles();
|
||||
|
||||
};
|
||||
|
||||
// GraphTraits support code.
|
||||
|
||||
/// NodesIterator - Auxiliary class needed to implement GraphTraits
|
||||
/// support. Can be generalised to something like value_iterator
|
||||
/// for map-like containers.
|
||||
class NodesIterator : public CompilationGraph::nodes_iterator {
|
||||
typedef CompilationGraph::nodes_iterator super;
|
||||
typedef NodesIterator ThisType;
|
||||
typedef Node* pointer;
|
||||
typedef Node& reference;
|
||||
|
||||
public:
|
||||
NodesIterator(super I) : super(I) {}
|
||||
|
||||
inline reference operator*() const {
|
||||
return super::operator->()->second;
|
||||
}
|
||||
inline pointer operator->() const {
|
||||
return &super::operator->()->second;
|
||||
}
|
||||
};
|
||||
|
||||
inline NodesIterator GraphBegin(CompilationGraph* G) {
|
||||
return NodesIterator(G->NodesMap.begin());
|
||||
}
|
||||
|
||||
inline NodesIterator GraphEnd(CompilationGraph* G) {
|
||||
return NodesIterator(G->NodesMap.end());
|
||||
}
|
||||
|
||||
|
||||
/// NodeChildIterator - Another auxiliary class needed by GraphTraits.
|
||||
class NodeChildIterator : public
|
||||
std::iterator<std::bidirectional_iterator_tag, Node, ptrdiff_t> {
|
||||
typedef NodeChildIterator ThisType;
|
||||
typedef Node::container_type::iterator iterator;
|
||||
|
||||
CompilationGraph* OwningGraph;
|
||||
iterator EdgeIter;
|
||||
public:
|
||||
typedef Node* pointer;
|
||||
typedef Node& reference;
|
||||
|
||||
NodeChildIterator(Node* N, iterator I) :
|
||||
OwningGraph(N->OwningGraph), EdgeIter(I) {}
|
||||
|
||||
const ThisType& operator=(const ThisType& I) {
|
||||
assert(OwningGraph == I.OwningGraph);
|
||||
EdgeIter = I.EdgeIter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==(const ThisType& I) const {
|
||||
assert(OwningGraph == I.OwningGraph);
|
||||
return EdgeIter == I.EdgeIter;
|
||||
}
|
||||
inline bool operator!=(const ThisType& I) const {
|
||||
return !this->operator==(I);
|
||||
}
|
||||
|
||||
inline pointer operator*() const {
|
||||
return OwningGraph->getNode((*EdgeIter)->ToolName());
|
||||
}
|
||||
inline pointer operator->() const {
|
||||
return this->operator*();
|
||||
}
|
||||
|
||||
ThisType& operator++() { ++EdgeIter; return *this; } // Preincrement
|
||||
ThisType operator++(int) { // Postincrement
|
||||
ThisType tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline ThisType& operator--() { --EdgeIter; return *this; } // Predecrement
|
||||
inline ThisType operator--(int) { // Postdecrement
|
||||
ThisType tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
template <>
|
||||
struct GraphTraits<llvmc::CompilationGraph*> {
|
||||
typedef llvmc::CompilationGraph GraphType;
|
||||
typedef llvmc::Node NodeType;
|
||||
typedef llvmc::NodeChildIterator ChildIteratorType;
|
||||
|
||||
static NodeType* getEntryNode(GraphType* G) {
|
||||
return G->getNode("root");
|
||||
}
|
||||
|
||||
static ChildIteratorType child_begin(NodeType* N) {
|
||||
return ChildIteratorType(N, N->OutEdges.begin());
|
||||
}
|
||||
static ChildIteratorType child_end(NodeType* N) {
|
||||
return ChildIteratorType(N, N->OutEdges.end());
|
||||
}
|
||||
|
||||
typedef llvmc::NodesIterator nodes_iterator;
|
||||
static nodes_iterator nodes_begin(GraphType *G) {
|
||||
return GraphBegin(G);
|
||||
}
|
||||
static nodes_iterator nodes_end(GraphType *G) {
|
||||
return GraphEnd(G);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H
|
@ -1,29 +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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Error handling.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
inline void PrintError(llvm::StringRef Err) {
|
||||
extern const char* ProgramName;
|
||||
llvm::errs() << ProgramName << ": " << Err << '\n';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H
|
@ -1,21 +0,0 @@
|
||||
//===--- Main.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Entry point for the driver executable.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H
|
||||
|
||||
namespace llvmc {
|
||||
int Main(int argc, char** argv);
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H
|
@ -1,23 +0,0 @@
|
||||
//===--- Main.inc - 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Default main() for the driver executable.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC
|
||||
|
||||
#include "llvm/CompilerDriver/Main.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
return llvmc::Main(argc, argv);
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC
|
@ -1,100 +0,0 @@
|
||||
//===--- Tool.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Tool abstract base class - an interface to tool descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H
|
||||
#define LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H
|
||||
|
||||
#include "llvm/CompilerDriver/Action.h"
|
||||
|
||||
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
class LanguageMap;
|
||||
typedef std::vector<std::pair<unsigned, std::string> > ArgsVector;
|
||||
typedef std::vector<llvm::sys::Path> PathVector;
|
||||
typedef std::vector<std::string> StrVector;
|
||||
typedef llvm::StringSet<> InputLanguagesSet;
|
||||
|
||||
/// Tool - Represents a single tool.
|
||||
class Tool : public llvm::RefCountedBaseVPTR {
|
||||
public:
|
||||
|
||||
virtual ~Tool() {}
|
||||
|
||||
/// GenerateAction - Generate an Action given particular command-line
|
||||
/// options. Returns non-zero value on error.
|
||||
virtual int GenerateAction (Action& Out,
|
||||
const PathVector& inFiles,
|
||||
const bool HasChildren,
|
||||
const llvm::sys::Path& TempDir,
|
||||
const InputLanguagesSet& InLangs,
|
||||
const LanguageMap& LangMap) const = 0;
|
||||
|
||||
/// GenerateAction - Generate an Action given particular command-line
|
||||
/// options. Returns non-zero value on error.
|
||||
virtual int GenerateAction (Action& Out,
|
||||
const llvm::sys::Path& inFile,
|
||||
const bool HasChildren,
|
||||
const llvm::sys::Path& TempDir,
|
||||
const InputLanguagesSet& InLangs,
|
||||
const LanguageMap& LangMap) const = 0;
|
||||
|
||||
virtual const char* Name() const = 0;
|
||||
virtual const char** InputLanguages() const = 0;
|
||||
virtual const char** OutputLanguages() const = 0;
|
||||
|
||||
virtual bool IsJoin() const = 0;
|
||||
virtual bool WorksOnEmpty() const = 0;
|
||||
|
||||
protected:
|
||||
/// OutFileName - Generate the output file name.
|
||||
llvm::sys::Path OutFilename(const llvm::sys::Path& In,
|
||||
const llvm::sys::Path& TempDir,
|
||||
bool StopCompilation,
|
||||
const char* OutputSuffix) const;
|
||||
|
||||
StrVector SortArgs(ArgsVector& Args) const;
|
||||
};
|
||||
|
||||
/// JoinTool - A Tool that has an associated input file list.
|
||||
class JoinTool : public Tool {
|
||||
public:
|
||||
void AddToJoinList(const llvm::sys::Path& P) { JoinList_.push_back(P); }
|
||||
void ClearJoinList() { JoinList_.clear(); }
|
||||
bool JoinListEmpty() const { return JoinList_.empty(); }
|
||||
|
||||
int GenerateAction(Action& Out,
|
||||
const bool HasChildren,
|
||||
const llvm::sys::Path& TempDir,
|
||||
const InputLanguagesSet& InLangs,
|
||||
const LanguageMap& LangMap) const {
|
||||
return GenerateAction(Out, JoinList_, HasChildren, TempDir, InLangs,
|
||||
LangMap);
|
||||
}
|
||||
// We shouldn't shadow base class's version of GenerateAction.
|
||||
using Tool::GenerateAction;
|
||||
|
||||
private:
|
||||
PathVector JoinList_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H
|
@ -1,134 +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/CompilerDriver/BuiltinOptions.h"
|
||||
#include "llvm/CompilerDriver/Error.h"
|
||||
#include "llvm/CompilerDriver/Main.h"
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/SystemUtils.h"
|
||||
#include "llvm/Support/Program.h"
|
||||
#include "llvm/Support/TimeValue.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvmc;
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
extern const char* ProgramName;
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void PrintString (const std::string& str) {
|
||||
errs() << str << ' ';
|
||||
}
|
||||
|
||||
void PrintCommand (const std::string& Cmd, const StrVector& Args) {
|
||||
errs() << Cmd << ' ';
|
||||
std::for_each(Args.begin(), Args.end(), &PrintString);
|
||||
errs() << '\n';
|
||||
}
|
||||
|
||||
bool IsSegmentationFault (int returnCode) {
|
||||
#ifdef LLVM_ON_WIN32
|
||||
return (returnCode >= 0xc0000000UL)
|
||||
#else
|
||||
return (returnCode < 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ExecuteProgram (const std::string& name, const StrVector& args) {
|
||||
sys::Path prog(name);
|
||||
|
||||
if (sys::path::is_relative(prog.str())) {
|
||||
prog = PrependMainExecutablePath(name, ProgramName,
|
||||
(void *)(intptr_t)&Main);
|
||||
|
||||
if (!prog.canExecute()) {
|
||||
prog = sys::Program::FindProgramByName(name);
|
||||
if (prog.isEmpty()) {
|
||||
PrintError("Can't find program '" + name + "'");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!prog.canExecute()) {
|
||||
PrintError("Program '" + name + "' is not executable.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Build the command line vector and the redirects array.
|
||||
const sys::Path* redirects[3] = {0,0,0};
|
||||
sys::Path stdout_redirect;
|
||||
|
||||
std::vector<const char*> 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.
|
||||
int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
|
||||
|
||||
if (IsSegmentationFault(ret)) {
|
||||
errs() << "Segmentation fault: ";
|
||||
PrintCommand(name, args);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvmc {
|
||||
void AppendToGlobalTimeLog (const std::string& cmd, double time);
|
||||
}
|
||||
|
||||
int llvmc::Action::Execute () const {
|
||||
if (DryRun || VerboseMode)
|
||||
PrintCommand(Command_, Args_);
|
||||
|
||||
if (!DryRun) {
|
||||
if (Time) {
|
||||
sys::TimeValue now = sys::TimeValue::now();
|
||||
int ret = ExecuteProgram(Command_, Args_);
|
||||
sys::TimeValue now2 = sys::TimeValue::now();
|
||||
now2 -= now;
|
||||
double elapsed = now2.seconds() + now2.microseconds() / 1000000.0;
|
||||
AppendToGlobalTimeLog(Command_, elapsed);
|
||||
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
return ExecuteProgram(Command_, Args_);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
//===--- BuiltinOptions.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Definitions of all global command-line option variables.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CompilerDriver/BuiltinOptions.h"
|
||||
|
||||
#ifdef ENABLE_LLVMC_DYNAMIC_PLUGINS
|
||||
#include "llvm/Support/PluginLoader.h"
|
||||
#endif
|
||||
|
||||
namespace cl = llvm::cl;
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input file>"),
|
||||
cl::ZeroOrMore);
|
||||
cl::opt<std::string> OutputFilename("o", cl::desc("Output file name"),
|
||||
cl::value_desc("file"), cl::Prefix);
|
||||
cl::opt<std::string> TempDirname("temp-dir", cl::desc("Temp dir name"),
|
||||
cl::value_desc("<directory>"), cl::Prefix);
|
||||
cl::list<std::string> Languages("x",
|
||||
cl::desc("Specify the language of the following input files"),
|
||||
cl::ZeroOrMore);
|
||||
|
||||
cl::opt<bool> DryRun("dry-run",
|
||||
cl::desc("Only pretend to run commands"));
|
||||
cl::opt<bool> Time("time", cl::desc("Time individual commands"));
|
||||
cl::opt<bool> VerboseMode("v",
|
||||
cl::desc("Enable verbose mode"));
|
||||
|
||||
cl::opt<bool> CheckGraph("check-graph",
|
||||
cl::desc("Check the compilation graph for errors"),
|
||||
cl::Hidden);
|
||||
cl::opt<bool> WriteGraph("write-graph",
|
||||
cl::desc("Write compilation-graph.dot file"),
|
||||
cl::Hidden);
|
||||
cl::opt<bool> ViewGraph("view-graph",
|
||||
cl::desc("Show compilation graph in GhostView"),
|
||||
cl::Hidden);
|
||||
|
||||
cl::opt<SaveTempsEnum::Values> SaveTemps
|
||||
("save-temps", cl::desc("Keep temporary files"),
|
||||
cl::init(SaveTempsEnum::Unset),
|
||||
cl::values(clEnumValN(SaveTempsEnum::Obj, "obj",
|
||||
"Save files in the directory specified with -o"),
|
||||
clEnumValN(SaveTempsEnum::Cwd, "cwd",
|
||||
"Use current working directory"),
|
||||
clEnumValN(SaveTempsEnum::Obj, "", "Same as 'cwd'"),
|
||||
clEnumValEnd),
|
||||
cl::ValueOptional);
|
||||
|
||||
} // End namespace llvmc.
|
@ -1,12 +0,0 @@
|
||||
set(LLVM_LINK_COMPONENTS support)
|
||||
|
||||
# We don't want this library to appear in `llvm-config --libs` output,
|
||||
# so its name doesn't start with "LLVM".
|
||||
|
||||
add_llvm_library(CompilerDriver
|
||||
Action.cpp
|
||||
BuiltinOptions.cpp
|
||||
CompilationGraph.cpp
|
||||
Main.cpp
|
||||
Tool.cpp
|
||||
)
|
@ -1,655 +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 "llvm/CompilerDriver/BuiltinOptions.h"
|
||||
#include "llvm/CompilerDriver/CompilationGraph.h"
|
||||
#include "llvm/CompilerDriver/Error.h"
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/DOTGraphTraits.h"
|
||||
#include "llvm/Support/GraphWriter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <queue>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvmc;
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
const std::string* LanguageMap::GetLanguage(const sys::Path& File) const {
|
||||
// Remove the '.'.
|
||||
StringRef suf = sys::path::extension(File.str()).substr(1);
|
||||
LanguageMap::const_iterator Lang =
|
||||
this->find(suf.empty() ? "*empty*" : suf);
|
||||
if (Lang == this->end()) {
|
||||
PrintError("File '" + File.str() + "' has unknown suffix '"
|
||||
+ suf.str() + '\'');
|
||||
return 0;
|
||||
}
|
||||
return &Lang->second;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// ChooseEdge - Return the edge with the maximum weight. Returns 0 on error.
|
||||
template <class C>
|
||||
const Edge* ChooseEdge(const C& EdgesContainer,
|
||||
const InputLanguagesSet& InLangs,
|
||||
const std::string& NodeName = "root") {
|
||||
const Edge* MaxEdge = 0;
|
||||
int MaxWeight = 0;
|
||||
bool SingleMax = true;
|
||||
|
||||
// TODO: fix calculation of SingleMax.
|
||||
for (typename C::const_iterator B = EdgesContainer.begin(),
|
||||
E = EdgesContainer.end(); B != E; ++B) {
|
||||
const Edge* e = B->getPtr();
|
||||
int EW = e->Weight(InLangs);
|
||||
if (EW < 0) {
|
||||
// (error) invocation in TableGen -> we don't need to print an error
|
||||
// message.
|
||||
return 0;
|
||||
}
|
||||
if (EW > MaxWeight) {
|
||||
MaxEdge = e;
|
||||
MaxWeight = EW;
|
||||
SingleMax = true;
|
||||
} else if (EW == MaxWeight) {
|
||||
SingleMax = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SingleMax) {
|
||||
PrintError("Node " + NodeName + ": multiple maximal outward edges found!"
|
||||
" Most probably a specification error.");
|
||||
return 0;
|
||||
}
|
||||
if (!MaxEdge) {
|
||||
PrintError("Node " + NodeName + ": no maximal outward edge found!"
|
||||
" Most probably a specification error.");
|
||||
return 0;
|
||||
}
|
||||
return MaxEdge;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Node::AddEdge(Edge* Edg) {
|
||||
// If there already was an edge between two nodes, modify it instead
|
||||
// of adding a new edge.
|
||||
const std::string& ToolName = Edg->ToolName();
|
||||
for (container_type::iterator B = OutEdges.begin(), E = OutEdges.end();
|
||||
B != E; ++B) {
|
||||
if ((*B)->ToolName() == ToolName) {
|
||||
llvm::IntrusiveRefCntPtr<Edge>(Edg).swap(*B);
|
||||
return;
|
||||
}
|
||||
}
|
||||
OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(Edg));
|
||||
}
|
||||
|
||||
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()) {
|
||||
PrintError("Node " + ToolName + " is not in the graph");
|
||||
return 0;
|
||||
}
|
||||
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()) {
|
||||
PrintError("Node " + ToolName + " is not in the graph!");
|
||||
return 0;
|
||||
}
|
||||
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()) {
|
||||
PrintError("No tool corresponding to the language " + LangName + " found");
|
||||
return 0;
|
||||
}
|
||||
return &I->second;
|
||||
}
|
||||
|
||||
void CompilationGraph::insertNode(Tool* V) {
|
||||
if (NodesMap.count(V->Name()) == 0)
|
||||
NodesMap[V->Name()] = Node(this, V);
|
||||
}
|
||||
|
||||
int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
|
||||
Node* B = getNode(Edg->ToolName());
|
||||
if (B == 0)
|
||||
return 1;
|
||||
|
||||
if (A == "root") {
|
||||
const char** InLangs = B->ToolPtr->InputLanguages();
|
||||
for (;*InLangs; ++InLangs)
|
||||
ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr<Edge>(Edg));
|
||||
NodesMap["root"].AddEdge(Edg);
|
||||
}
|
||||
else {
|
||||
Node* N = getNode(A);
|
||||
if (N == 0)
|
||||
return 1;
|
||||
|
||||
N->AddEdge(Edg);
|
||||
}
|
||||
// Increase the inward edge counter.
|
||||
B->IncrInEdges();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pass input file through the chain until we bump into a Join node or
|
||||
// a node that says that it is the last.
|
||||
int CompilationGraph::PassThroughGraph (const sys::Path& InFile,
|
||||
const Node* StartNode,
|
||||
const InputLanguagesSet& InLangs,
|
||||
const sys::Path& TempDir,
|
||||
const LanguageMap& LangMap) const {
|
||||
sys::Path In = InFile;
|
||||
const Node* CurNode = StartNode;
|
||||
|
||||
while(true) {
|
||||
Tool* CurTool = CurNode->ToolPtr.getPtr();
|
||||
|
||||
if (CurTool->IsJoin()) {
|
||||
JoinTool& JT = static_cast<JoinTool&>(*CurTool);
|
||||
JT.AddToJoinList(In);
|
||||
break;
|
||||
}
|
||||
|
||||
Action CurAction;
|
||||
if (int ret = CurTool->GenerateAction(CurAction, In, CurNode->HasChildren(),
|
||||
TempDir, InLangs, LangMap)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (int ret = CurAction.Execute())
|
||||
return ret;
|
||||
|
||||
if (CurAction.StopCompilation())
|
||||
return 0;
|
||||
|
||||
const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name());
|
||||
if (Edg == 0)
|
||||
return 1;
|
||||
|
||||
CurNode = getNode(Edg->ToolName());
|
||||
if (CurNode == 0)
|
||||
return 1;
|
||||
|
||||
In = CurAction.OutFile();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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* InLang = (ForceLanguage ? ForceLanguage
|
||||
: LangMap.GetLanguage(In));
|
||||
if (InLang == 0)
|
||||
return 0;
|
||||
const std::string& InLanguage = *InLang;
|
||||
|
||||
// Add the current input language to the input language set.
|
||||
InLangs.insert(InLanguage);
|
||||
|
||||
// Find the toolchain for the input language.
|
||||
const tools_vector_type* pTV = getToolsVector(InLanguage);
|
||||
if (pTV == 0)
|
||||
return 0;
|
||||
|
||||
const tools_vector_type& TV = *pTV;
|
||||
if (TV.empty()) {
|
||||
PrintError("No toolchain corresponding to language "
|
||||
+ InLanguage + " found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Edge* Edg = ChooseEdge(TV, InLangs);
|
||||
if (Edg == 0)
|
||||
return 0;
|
||||
|
||||
return getNode(Edg->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.
|
||||
int CompilationGraph::BuildInitial (InputLanguagesSet& InLangs,
|
||||
const sys::Path& TempDir,
|
||||
const LanguageMap& LangMap) {
|
||||
// This is related to -x option handling.
|
||||
cl::list<std::string>::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<std::string>::const_iterator xNext = llvm::next(xIter);
|
||||
xPosNext = (xNext == xEnd) ? std::numeric_limits<unsigned>::max()
|
||||
: Languages.getPosition(xNext - xBegin);
|
||||
xLanguage = (*xIter == "none") ? 0 : &(*xIter);
|
||||
}
|
||||
|
||||
// For each input file:
|
||||
for (cl::list<std::string>::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<std::string>::const_iterator xNext = llvm::next(xIter);
|
||||
if (xNext == xEnd)
|
||||
xPosNext = std::numeric_limits<unsigned>::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);
|
||||
if (N == 0)
|
||||
return 1;
|
||||
// Pass file through the chain starting at head.
|
||||
if (int ret = PassThroughGraph(In, N, InLangs, TempDir, LangMap))
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sort the nodes in topological order.
|
||||
int CompilationGraph::TopologicalSort(std::vector<const Node*>& Out) {
|
||||
std::queue<const Node*> Q;
|
||||
|
||||
Node* Root = getNode("root");
|
||||
if (Root == 0)
|
||||
return 1;
|
||||
|
||||
Q.push(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());
|
||||
if (B == 0)
|
||||
return 1;
|
||||
|
||||
B->DecrInEdges();
|
||||
if (B->HasNoInEdges())
|
||||
Q.push(B);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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.
|
||||
int CompilationGraph::
|
||||
TopologicalSortFilterJoinNodes(std::vector<const Node*>& Out) {
|
||||
std::vector<const Node*> TopSorted;
|
||||
if (int ret = TopologicalSort(TopSorted))
|
||||
return ret;
|
||||
std::remove_copy_if(TopSorted.begin(), TopSorted.end(),
|
||||
std::back_inserter(Out), NotJoinNode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CompilationGraph::Build (const sys::Path& TempDir,
|
||||
const LanguageMap& LangMap) {
|
||||
InputLanguagesSet InLangs;
|
||||
bool WasSomeActionGenerated = !InputFilenames.empty();
|
||||
|
||||
// Traverse initial parts of the toolchains and fill in InLangs.
|
||||
if (int ret = BuildInitial(InLangs, TempDir, LangMap))
|
||||
return ret;
|
||||
|
||||
std::vector<const Node*> JTV;
|
||||
if (int ret = TopologicalSortFilterJoinNodes(JTV))
|
||||
return ret;
|
||||
|
||||
// For all join nodes in topological order:
|
||||
for (std::vector<const Node*>::iterator B = JTV.begin(), E = JTV.end();
|
||||
B != E; ++B) {
|
||||
|
||||
const Node* CurNode = *B;
|
||||
JoinTool* JT = &static_cast<JoinTool&>(*CurNode->ToolPtr.getPtr());
|
||||
|
||||
// Are there any files in the join list?
|
||||
if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty()))
|
||||
continue;
|
||||
|
||||
WasSomeActionGenerated = true;
|
||||
Action CurAction;
|
||||
if (int ret = JT->GenerateAction(CurAction, CurNode->HasChildren(),
|
||||
TempDir, InLangs, LangMap)) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (int ret = CurAction.Execute())
|
||||
return ret;
|
||||
|
||||
if (CurAction.StopCompilation())
|
||||
return 0;
|
||||
|
||||
const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name());
|
||||
if (Edg == 0)
|
||||
return 1;
|
||||
|
||||
const Node* NextNode = getNode(Edg->ToolName());
|
||||
if (NextNode == 0)
|
||||
return 1;
|
||||
|
||||
if (int ret = PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode,
|
||||
InLangs, TempDir, LangMap)) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WasSomeActionGenerated) {
|
||||
PrintError("no input files");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CompilationGraph::CheckLanguageNames() const {
|
||||
int ret = 0;
|
||||
|
||||
// Check that names for output and input languages on all edges do match.
|
||||
for (const_nodes_iterator B = this->NodesMap.begin(),
|
||||
E = this->NodesMap.end(); B != E; ++B) {
|
||||
|
||||
const Node & N1 = B->second;
|
||||
if (N1.ToolPtr) {
|
||||
for (Node::const_iterator EB = N1.EdgesBegin(), EE = N1.EdgesEnd();
|
||||
EB != EE; ++EB) {
|
||||
const Node* N2 = this->getNode((*EB)->ToolName());
|
||||
if (N2 == 0)
|
||||
return 1;
|
||||
|
||||
if (!N2->ToolPtr) {
|
||||
++ret;
|
||||
errs() << "Error: there is an edge from '" << N1.ToolPtr->Name()
|
||||
<< "' back to the root!\n\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
const char** OutLangs = N1.ToolPtr->OutputLanguages();
|
||||
const char** InLangs = N2->ToolPtr->InputLanguages();
|
||||
bool eq = false;
|
||||
const char* OutLang = 0;
|
||||
for (;*OutLangs; ++OutLangs) {
|
||||
OutLang = *OutLangs;
|
||||
for (;*InLangs; ++InLangs) {
|
||||
if (std::strcmp(OutLang, *InLangs) == 0) {
|
||||
eq = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!eq) {
|
||||
++ret;
|
||||
errs() << "Error: Output->input language mismatch in the edge '"
|
||||
<< N1.ToolPtr->Name() << "' -> '" << N2->ToolPtr->Name()
|
||||
<< "'!\n"
|
||||
<< "Expected one of { ";
|
||||
|
||||
InLangs = N2->ToolPtr->InputLanguages();
|
||||
for (;*InLangs; ++InLangs) {
|
||||
errs() << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'");
|
||||
}
|
||||
|
||||
errs() << " }, but got '" << OutLang << "'!\n\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CompilationGraph::CheckMultipleDefaultEdges() const {
|
||||
int ret = 0;
|
||||
InputLanguagesSet Dummy;
|
||||
|
||||
// For all nodes, just iterate over the outgoing edges and check if there is
|
||||
// more than one edge with maximum weight.
|
||||
for (const_nodes_iterator B = this->NodesMap.begin(),
|
||||
E = this->NodesMap.end(); B != E; ++B) {
|
||||
const Node& N = B->second;
|
||||
int MaxWeight = -1024;
|
||||
|
||||
// Ignore the root node.
|
||||
if (!N.ToolPtr)
|
||||
continue;
|
||||
|
||||
for (Node::const_iterator EB = N.EdgesBegin(), EE = N.EdgesEnd();
|
||||
EB != EE; ++EB) {
|
||||
int EdgeWeight = (*EB)->Weight(Dummy);
|
||||
if (EdgeWeight > MaxWeight) {
|
||||
MaxWeight = EdgeWeight;
|
||||
}
|
||||
else if (EdgeWeight == MaxWeight) {
|
||||
++ret;
|
||||
errs() << "Error: there are multiple maximal edges stemming from the '"
|
||||
<< N.ToolPtr->Name() << "' node!\n\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int CompilationGraph::CheckCycles() {
|
||||
unsigned deleted = 0;
|
||||
std::queue<Node*> Q;
|
||||
|
||||
Node* Root = getNode("root");
|
||||
if (Root == 0)
|
||||
return 1;
|
||||
|
||||
Q.push(Root);
|
||||
|
||||
// Try to delete all nodes that have no ingoing edges, starting from the
|
||||
// root. If there are any nodes left after this operation, then we have a
|
||||
// cycle. This relies on '--check-graph' not performing the topological sort.
|
||||
while (!Q.empty()) {
|
||||
Node* A = Q.front();
|
||||
Q.pop();
|
||||
++deleted;
|
||||
|
||||
for (Node::iterator EB = A->EdgesBegin(), EE = A->EdgesEnd();
|
||||
EB != EE; ++EB) {
|
||||
Node* B = getNode((*EB)->ToolName());
|
||||
if (B == 0)
|
||||
return 1;
|
||||
|
||||
B->DecrInEdges();
|
||||
if (B->HasNoInEdges())
|
||||
Q.push(B);
|
||||
}
|
||||
}
|
||||
|
||||
if (deleted != NodesMap.size()) {
|
||||
errs() << "Error: there are cycles in the compilation graph!\n"
|
||||
<< "Try inspecting the diagram produced by "
|
||||
<< "'llvmc --view-graph'.\n\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CompilationGraph::Check () {
|
||||
// We try to catch as many errors as we can in one go.
|
||||
int errs = 0;
|
||||
int ret = 0;
|
||||
|
||||
// Check that output/input language names match.
|
||||
ret = this->CheckLanguageNames();
|
||||
if (ret < 0)
|
||||
return 1;
|
||||
errs += ret;
|
||||
|
||||
// Check for multiple default edges.
|
||||
ret = this->CheckMultipleDefaultEdges();
|
||||
if (ret < 0)
|
||||
return 1;
|
||||
errs += ret;
|
||||
|
||||
// Check for cycles.
|
||||
ret = this->CheckCycles();
|
||||
if (ret < 0)
|
||||
return 1;
|
||||
errs += ret;
|
||||
|
||||
return errs;
|
||||
}
|
||||
|
||||
// Code related to graph visualization.
|
||||
|
||||
namespace {
|
||||
|
||||
std::string SquashStrArray (const char** StrArr) {
|
||||
std::string ret;
|
||||
|
||||
for (; *StrArr; ++StrArr) {
|
||||
if (*(StrArr + 1)) {
|
||||
ret += *StrArr;
|
||||
ret += ", ";
|
||||
}
|
||||
else {
|
||||
ret += *StrArr;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // End anonymous namespace.
|
||||
|
||||
namespace llvm {
|
||||
template <>
|
||||
struct DOTGraphTraits<llvmc::CompilationGraph*>
|
||||
: public DefaultDOTGraphTraits
|
||||
{
|
||||
DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
template<typename GraphType>
|
||||
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(": ") +
|
||||
SquashStrArray(N->ToolPtr->OutputLanguages()) + ')');
|
||||
else
|
||||
return N->Name();
|
||||
else
|
||||
return "root";
|
||||
}
|
||||
|
||||
template<typename EdgeIter>
|
||||
static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) {
|
||||
if (N->ToolPtr) {
|
||||
return SquashStrArray(N->ToolPtr->OutputLanguages());
|
||||
}
|
||||
else {
|
||||
return SquashStrArray(I->ToolPtr->InputLanguages());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // End namespace llvm
|
||||
|
||||
int CompilationGraph::writeGraph(const std::string& OutputFilename) {
|
||||
std::string ErrorInfo;
|
||||
raw_fd_ostream O(OutputFilename.c_str(), ErrorInfo);
|
||||
|
||||
if (ErrorInfo.empty()) {
|
||||
errs() << "Writing '"<< OutputFilename << "' file...";
|
||||
llvm::WriteGraph(O, this);
|
||||
errs() << "done.\n";
|
||||
}
|
||||
else {
|
||||
PrintError("Error opening file '" + OutputFilename + "' for writing!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CompilationGraph::viewGraph() {
|
||||
llvm::ViewGraph(this, "compilation-graph");
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
//===--- Main.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// llvmc::Main function - driver entry point.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CompilerDriver/AutoGenerated.h"
|
||||
#include "llvm/CompilerDriver/BuiltinOptions.h"
|
||||
#include "llvm/CompilerDriver/CompilationGraph.h"
|
||||
#include "llvm/CompilerDriver/Error.h"
|
||||
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace cl = llvm::cl;
|
||||
namespace sys = llvm::sys;
|
||||
using namespace llvmc;
|
||||
|
||||
namespace {
|
||||
|
||||
std::stringstream* GlobalTimeLog;
|
||||
|
||||
/// GetTempDir - Get the temporary directory location. Returns non-zero value
|
||||
/// on error.
|
||||
int GetTempDir(sys::Path& tempDir) {
|
||||
// The --temp-dir option.
|
||||
if (!TempDirname.empty()) {
|
||||
tempDir = TempDirname;
|
||||
}
|
||||
// GCC 4.5-style -save-temps handling.
|
||||
else if (SaveTemps == SaveTempsEnum::Unset) {
|
||||
tempDir = sys::Path::GetTemporaryDirectory();
|
||||
return 0;
|
||||
}
|
||||
else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) {
|
||||
tempDir = sys::path::parent_path(OutputFilename);
|
||||
}
|
||||
else {
|
||||
// SaveTemps == Cwd --> use current dir (leave tempDir empty).
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Exists;
|
||||
if (llvm::sys::fs::exists(tempDir.str(), Exists) || !Exists) {
|
||||
std::string ErrMsg;
|
||||
if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) {
|
||||
PrintError(ErrMsg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// BuildTargets - A small wrapper for CompilationGraph::Build. Returns
|
||||
/// non-zero value in case of error.
|
||||
int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) {
|
||||
int ret;
|
||||
sys::Path tempDir;
|
||||
bool toDelete = (SaveTemps == SaveTempsEnum::Unset);
|
||||
|
||||
if (int ret = GetTempDir(tempDir))
|
||||
return ret;
|
||||
|
||||
ret = graph.Build(tempDir, langMap);
|
||||
|
||||
if (toDelete)
|
||||
tempDir.eraseFromDisk(true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvmc {
|
||||
|
||||
// Used to implement -time option. External linkage is intentional.
|
||||
void AppendToGlobalTimeLog(const std::string& cmd, double time) {
|
||||
*GlobalTimeLog << "# " << cmd << ' ' << time << '\n';
|
||||
}
|
||||
|
||||
// Sometimes user code wants to access the argv[0] value.
|
||||
const char* ProgramName;
|
||||
|
||||
int Main(int argc, char** argv) {
|
||||
int ret = 0;
|
||||
LanguageMap langMap;
|
||||
CompilationGraph graph;
|
||||
|
||||
ProgramName = argv[0];
|
||||
|
||||
cl::ParseCommandLineOptions
|
||||
(argc, argv,
|
||||
/* Overview = */ "LLVM Compiler Driver (Work In Progress)",
|
||||
/* ReadResponseFiles = */ false);
|
||||
|
||||
if (int ret = autogenerated::RunInitialization(langMap, graph))
|
||||
return ret;
|
||||
|
||||
if (CheckGraph) {
|
||||
ret = graph.Check();
|
||||
if (!ret)
|
||||
llvm::errs() << "check-graph: no errors found.\n";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ViewGraph) {
|
||||
graph.viewGraph();
|
||||
if (!WriteGraph)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (WriteGraph) {
|
||||
const std::string& Out = (OutputFilename.empty()
|
||||
? std::string("compilation-graph.dot")
|
||||
: OutputFilename);
|
||||
return graph.writeGraph(Out);
|
||||
}
|
||||
|
||||
if (Time) {
|
||||
GlobalTimeLog = new std::stringstream;
|
||||
GlobalTimeLog->precision(2);
|
||||
}
|
||||
|
||||
ret = BuildTargets(graph, langMap);
|
||||
|
||||
if (Time) {
|
||||
llvm::errs() << GlobalTimeLog->str();
|
||||
delete GlobalTimeLog;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end namespace llvmc
|
@ -1,20 +0,0 @@
|
||||
##===- lib/CompilerDriver/Makefile -------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open
|
||||
# Source License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
|
||||
LEVEL = ../..
|
||||
|
||||
# We don't want this library to appear in `llvm-config --libs` output, so its
|
||||
# name doesn't start with "LLVM" and NO_LLVM_CONFIG is set.
|
||||
|
||||
LIBRARYNAME = CompilerDriver
|
||||
LINK_COMPONENTS = support
|
||||
NO_LLVM_CONFIG = 1
|
||||
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -1,95 +0,0 @@
|
||||
//===--- Tool.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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Tool base class - implementation details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CompilerDriver/BuiltinOptions.h"
|
||||
#include "llvm/CompilerDriver/Tool.h"
|
||||
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvmc;
|
||||
|
||||
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 need to be placated with -f or something like that.
|
||||
Out.makeUnique(true, NULL);
|
||||
return Out;
|
||||
}
|
||||
}
|
||||
|
||||
sys::Path Tool::OutFilename(const sys::Path& In,
|
||||
const sys::Path& TempDir,
|
||||
bool StopCompilation,
|
||||
const char* OutputSuffix) const {
|
||||
sys::Path Out;
|
||||
|
||||
if (StopCompilation) {
|
||||
if (!OutputFilename.empty()) {
|
||||
Out.set(OutputFilename);
|
||||
}
|
||||
else if (IsJoin()) {
|
||||
Out.set("a");
|
||||
Out.appendSuffix(OutputSuffix);
|
||||
}
|
||||
else {
|
||||
Out.set(sys::path::stem(In.str()));
|
||||
Out.appendSuffix(OutputSuffix);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (IsJoin())
|
||||
Out = MakeTempFile(TempDir, "tmp", OutputSuffix);
|
||||
else
|
||||
Out = MakeTempFile(TempDir, sys::path::stem(In.str()), OutputSuffix);
|
||||
}
|
||||
return Out;
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <class A, class B>
|
||||
bool CompareFirst (std::pair<A,B> p1, std::pair<A,B> p2) {
|
||||
return std::less<A>()(p1.first, p2.first);
|
||||
}
|
||||
}
|
||||
|
||||
StrVector Tool::SortArgs(ArgsVector& Args) const {
|
||||
StrVector Out;
|
||||
|
||||
// HACK: this won't be needed when we'll migrate away from CommandLine.
|
||||
std::stable_sort(Args.begin(), Args.end(),
|
||||
&CompareFirst<unsigned, std::string>);
|
||||
for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B) {
|
||||
Out.push_back(B->second);
|
||||
}
|
||||
|
||||
return Out;
|
||||
}
|
@ -11,7 +11,7 @@ LEVEL = ..
|
||||
include $(LEVEL)/Makefile.config
|
||||
|
||||
PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
|
||||
Target ExecutionEngine Linker MC CompilerDriver Object DebugInfo
|
||||
Target ExecutionEngine Linker MC Object DebugInfo
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
||||
|
@ -31,7 +31,6 @@ add_llvm_utility(tblgen
|
||||
InstrEnumEmitter.cpp
|
||||
InstrInfoEmitter.cpp
|
||||
IntrinsicEmitter.cpp
|
||||
LLVMCConfigurationEmitter.cpp
|
||||
NeonEmitter.cpp
|
||||
OptParserEmitter.cpp
|
||||
PseudoLoweringEmitter.cpp
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,34 +0,0 @@
|
||||
//===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open
|
||||
// Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This tablegen backend is responsible for emitting LLVMCC configuration code.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
|
||||
#define LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
|
||||
|
||||
#include "TableGenBackend.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// LLVMCConfigurationEmitter - TableGen backend that generates
|
||||
/// configuration code for LLVMC.
|
||||
class LLVMCConfigurationEmitter : public TableGenBackend {
|
||||
RecordKeeper &Records;
|
||||
public:
|
||||
explicit LLVMCConfigurationEmitter(RecordKeeper &records) :
|
||||
Records(records) {}
|
||||
|
||||
// run - Output the asmwriter, returning true on failure.
|
||||
void run(raw_ostream &o);
|
||||
};
|
||||
}
|
||||
|
||||
#endif //LLVM_UTILS_TABLEGEN_LLVMCCONF_EMITTER_H
|
@ -30,7 +30,6 @@
|
||||
#include "FastISelEmitter.h"
|
||||
#include "InstrInfoEmitter.h"
|
||||
#include "IntrinsicEmitter.h"
|
||||
#include "LLVMCConfigurationEmitter.h"
|
||||
#include "NeonEmitter.h"
|
||||
#include "OptParserEmitter.h"
|
||||
#include "PseudoLoweringEmitter.h"
|
||||
@ -81,7 +80,6 @@ enum ActionType {
|
||||
GenSubtarget,
|
||||
GenIntrinsic,
|
||||
GenTgtIntrinsic,
|
||||
GenLLVMCConf,
|
||||
GenEDInfo,
|
||||
GenArmNeon,
|
||||
GenArmNeonSema,
|
||||
@ -156,8 +154,6 @@ namespace {
|
||||
"Generate Clang AST statement nodes"),
|
||||
clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
|
||||
"Generate Clang Static Analyzer checkers"),
|
||||
clEnumValN(GenLLVMCConf, "gen-llvmc",
|
||||
"Generate LLVMC configuration library"),
|
||||
clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
|
||||
"Generate enhanced disassembly info"),
|
||||
clEnumValN(GenArmNeon, "gen-arm-neon",
|
||||
@ -349,9 +345,6 @@ int main(int argc, char **argv) {
|
||||
case GenTgtIntrinsic:
|
||||
IntrinsicEmitter(Records, true).run(Out.os());
|
||||
break;
|
||||
case GenLLVMCConf:
|
||||
LLVMCConfigurationEmitter(Records).run(Out.os());
|
||||
break;
|
||||
case GenEDInfo:
|
||||
EDEmitter(Records).run(Out.os());
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user