2008-03-23 08:57:20 +00:00
|
|
|
Introduction
|
|
|
|
============
|
|
|
|
|
2008-03-26 21:37:43 +00:00
|
|
|
Disclaimer: this document is currently somewhat out-of-date and is
|
|
|
|
retained for reference; for documentation, refer to
|
|
|
|
LLVMC-Tutorial.rst.
|
|
|
|
|
2008-03-23 08:57:20 +00:00
|
|
|
A complete rewrite of the LLVMC compiler driver is proposed, aimed at
|
|
|
|
making it more configurable and useful.
|
|
|
|
|
|
|
|
Motivation
|
|
|
|
==========
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
As it stands, the current version of LLVMC does not meet its stated goals
|
|
|
|
of configurability and extensibility, and is therefore not used
|
|
|
|
much. The need for enhancements to LLVMC is also reflected in [1]_. The
|
2008-03-23 08:57:20 +00:00
|
|
|
proposed rewrite will fix the aforementioned deficiences and provide
|
|
|
|
an extensible, future-proof solution.
|
|
|
|
|
|
|
|
Design
|
|
|
|
======
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
A compiler driver's job is essentially to find a way to transform a set
|
|
|
|
of input files into a set of targets, depending on the user-provided
|
|
|
|
options. Since several methods of transformation can potentially exist,
|
|
|
|
it's natural to use a directed graph to represent all of them. In this
|
|
|
|
graph, nodes are tools -- e.g., ``gcc -S`` is a tool that generates
|
|
|
|
assembly from C language files -- and edges between the nodes indicate
|
|
|
|
that the output of one tool can be given as input to another -- i.e.,
|
|
|
|
``gcc -S -o - file.c | as``. We'll call this graph the compilation graph.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
The proposed design revolves around the compilation graph and the
|
|
|
|
following core abstractions:
|
|
|
|
|
|
|
|
- Target - An (intermediate) compilation target.
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
- Action - A shell command template that represents a basic compilation
|
|
|
|
transformation -- example: ``gcc -S $INPUT_FILE -o $OUTPUT_FILE``.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
- Tool - Encapsulates information about a concrete tool used in the
|
2008-03-24 05:55:54 +00:00
|
|
|
compilation process, produces Actions. Its operation depends on
|
2008-03-23 08:57:20 +00:00
|
|
|
command-line options provided by the user.
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
- GraphBuilder - Constructs the compilation graph. Its operation
|
|
|
|
depends on command-line options.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
- GraphTraverser - Traverses the compilation graph and constructs a
|
2008-03-24 05:55:54 +00:00
|
|
|
sequence of Actions needed to build the target file. Its operation
|
2008-03-23 08:57:20 +00:00
|
|
|
depends on command-line options.
|
|
|
|
|
|
|
|
A high-level view of the compilation process:
|
|
|
|
|
|
|
|
1. Configuration libraries (see below) are loaded in and the
|
2008-03-24 05:55:54 +00:00
|
|
|
compilation graph is constructed from the tool descriptions.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
2. Information about possible options is gathered from (the nodes of)
|
2008-03-24 05:55:54 +00:00
|
|
|
the compilation graph.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
3. Options are parsed based on data gathered in step 2.
|
|
|
|
|
|
|
|
4. A sequence of Actions needed to build the target is constructed
|
2008-03-24 05:55:54 +00:00
|
|
|
using the compilation graph and provided options.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
5. The resulting action sequence is executed.
|
|
|
|
|
|
|
|
Extensibility
|
|
|
|
==============
|
|
|
|
|
|
|
|
To make this design extensible, TableGen [2]_ will be used for
|
|
|
|
automatic generation of the Tool classes. Users wanting to customize
|
2008-03-24 05:55:54 +00:00
|
|
|
LLVMC need to write a configuration library consisting of a set of
|
|
|
|
TableGen descriptions of compilation tools plus a number of hooks
|
2008-03-23 08:57:20 +00:00
|
|
|
that influence compilation graph construction and traversal. LLVMC
|
|
|
|
will have the ability to load user configuration libraries at runtime;
|
|
|
|
in fact, its own basic functionality will be implemented as a
|
|
|
|
configuration library.
|
|
|
|
|
|
|
|
TableGen specification example
|
|
|
|
------------------------------
|
|
|
|
|
|
|
|
This small example specifies a Tool that converts C source to object
|
2008-03-24 05:55:54 +00:00
|
|
|
files. Note that it is only a mock-up of intended functionality, not a
|
2008-03-23 08:57:20 +00:00
|
|
|
final specification::
|
|
|
|
|
|
|
|
def GCC : Tool<
|
|
|
|
GCCProperties, // Properties of this tool
|
|
|
|
GCCOptions // Options description for this tool
|
|
|
|
>;
|
|
|
|
|
|
|
|
def GCCProperties : ToolProperties<[
|
|
|
|
ToolName<"GCC">,
|
|
|
|
InputLanguageName<"C">,
|
|
|
|
OutputLanguageName<"Object-Code">
|
|
|
|
InputFileExtension<"c">,
|
|
|
|
OutputFileExtension<"o">,
|
|
|
|
CommandFormat<"gcc -c $OPTIONS $FILES">
|
|
|
|
]>;
|
|
|
|
|
|
|
|
def GCCOptions : ToolOptions<[
|
|
|
|
Option<
|
|
|
|
"-Wall", // Option name
|
|
|
|
[None], // Allowed values
|
|
|
|
[AddOption<"-Wall">]>, // Action
|
|
|
|
|
|
|
|
Option<
|
|
|
|
"-Wextra", // Option name
|
|
|
|
[None], // Allowed values
|
|
|
|
[AddOption<"-Wextra">]>, // Action
|
|
|
|
|
|
|
|
Option<
|
|
|
|
"-W", // Option name
|
|
|
|
[None], // Allowed values
|
|
|
|
[AddOption<"-W">]>, // Action
|
|
|
|
|
|
|
|
Option<
|
|
|
|
"-D", // Option name
|
|
|
|
[AnyString], // Allowed values
|
|
|
|
|
|
|
|
[AddOptionWithArgument<"-D",GetOptionArgument<"-D">>]
|
|
|
|
// Action:
|
|
|
|
// If the driver was given option "-D<argument>", add
|
|
|
|
// option "-D" with the same argument to the invocation string of
|
|
|
|
// this tool.
|
|
|
|
>
|
|
|
|
|
|
|
|
]>;
|
|
|
|
|
|
|
|
Example of generated code
|
|
|
|
-------------------------
|
|
|
|
|
|
|
|
The specification above compiles to the following code (again, it's a
|
|
|
|
mock-up)::
|
|
|
|
|
|
|
|
class GCC : public Tool {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
GCC() { //... }
|
|
|
|
|
|
|
|
// Properties
|
|
|
|
|
|
|
|
static const char* ToolName = "GCC";
|
|
|
|
static const char* InputLanguageName = "C";
|
|
|
|
static const char* OutputLanguageName = "Object-Code";
|
|
|
|
static const char* InputFileExtension = "c";
|
|
|
|
static const char* OutputFileExtension = "o";
|
|
|
|
static const char* CommandFormat = "gcc -c $OPTIONS $FILES";
|
|
|
|
|
|
|
|
// Options
|
|
|
|
|
|
|
|
OptionsDescription SupportedOptions() {
|
|
|
|
OptionsDescription supportedOptions;
|
|
|
|
|
|
|
|
supportedOptions.Add(Option("-Wall"));
|
|
|
|
supportedOptions.Add(Option("-Wextra"));
|
|
|
|
supportedOptions.Add(Option("-W"));
|
|
|
|
supportedOptions.Add(Option("-D", AllowedArgs::ANY_STRING));
|
|
|
|
|
|
|
|
return supportedOptions;
|
|
|
|
}
|
|
|
|
|
|
|
|
Action GenerateAction(Options providedOptions) {
|
|
|
|
Action generatedAction(CommandFormat); Option curOpt;
|
|
|
|
|
|
|
|
curOpt = providedOptions.Get("-D");
|
|
|
|
if (curOpt) {
|
|
|
|
assert(curOpt.HasArgument());
|
|
|
|
generatedAction.AddOption(Option("-D", curOpt.GetArgument()));
|
|
|
|
}
|
|
|
|
|
|
|
|
curOpt = providedOptions.Get("-Wall");
|
|
|
|
if (curOpt)
|
|
|
|
generatedAction.AddOption(Option("-Wall"));
|
|
|
|
|
|
|
|
curOpt = providedOptions.Get("-Wextra");
|
|
|
|
if (curOpt)
|
|
|
|
generatedAction.AddOption(Option("-Wall"));
|
|
|
|
|
|
|
|
curOpt = providedOptions.Get("-W");
|
|
|
|
if (curOpt)
|
|
|
|
generatedAction.AddOption(Option("-Wall")); }
|
|
|
|
|
|
|
|
return generatedAction;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// defined somewhere...
|
|
|
|
|
|
|
|
class Action { public: void AddOption(const Option& opt) {...}
|
|
|
|
int Run(const Filenames& fnms) {...}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Option handling
|
|
|
|
===============
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
Because one of the main tasks of the compiler driver is to correctly
|
2008-03-23 08:57:20 +00:00
|
|
|
handle user-provided options, it is important to define this process
|
2008-03-24 05:55:54 +00:00
|
|
|
in an exact way. The intent of the proposed scheme is to function as
|
|
|
|
a drop-in replacement for GCC.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
Option syntax
|
|
|
|
-------------
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
The option syntax is specified by the following formal grammar::
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
<command-line> ::= <option>*
|
|
|
|
<option> ::= <positional-option> | <named-option>
|
|
|
|
<named-option> ::= -[-]<option-name>[<delimeter><option-argument>]
|
|
|
|
<delimeter> ::= ',' | '=' | ' '
|
|
|
|
<positional-option> ::= <string>
|
|
|
|
<option-name> ::= <string>
|
|
|
|
<option-argument> ::= <string>
|
|
|
|
|
|
|
|
This roughly corresponds to the GCC option syntax. Note that grouping
|
2008-03-24 05:55:54 +00:00
|
|
|
of short options (as in ``ls -la``) is forbidden.
|
2008-03-23 08:57:20 +00:00
|
|
|
|
|
|
|
Example::
|
|
|
|
|
|
|
|
llvmc -O3 -Wa,-foo,-bar -pedantic -std=c++0x a.c b.c c.c
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
Option arguments can also have special forms. For example, an argument
|
2008-03-23 08:57:20 +00:00
|
|
|
can be a comma-separated list (like in -Wa,-foo,-bar). In such cases,
|
|
|
|
it's up to the option handler to parse the argument.
|
|
|
|
|
|
|
|
Option semantics
|
|
|
|
----------------
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
According to their meaning, options are classified into the following
|
2008-03-23 08:57:20 +00:00
|
|
|
categories:
|
|
|
|
|
|
|
|
- Global options - Options that influence compilation graph
|
|
|
|
construction/traversal. Example: -E (stop after preprocessing).
|
|
|
|
|
|
|
|
- Local options - Options that influence one or several Actions in
|
|
|
|
the generated action sequence. Example: -O3 (turn on optimization).
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
- Prefix options - Options that influence the meaning of the following
|
2008-03-23 08:57:20 +00:00
|
|
|
command-line arguments. Example: -x language (specify language for
|
|
|
|
the input files explicitly). Prefix options can be local or global.
|
|
|
|
|
2008-03-24 05:55:54 +00:00
|
|
|
- Built-in options - Options that are hard-coded into the
|
2008-03-23 08:57:20 +00:00
|
|
|
driver. Examples: --help, -o file/-pipe (redirect output). Can be
|
|
|
|
local or global.
|
|
|
|
|
|
|
|
Issues
|
|
|
|
======
|
|
|
|
|
|
|
|
1. Should global-options-influencing hooks be written by hand or
|
|
|
|
auto-generated from TableGen specifications?
|
|
|
|
|
|
|
|
2. More?
|
|
|
|
|
|
|
|
References
|
|
|
|
==========
|
|
|
|
|
|
|
|
.. [1] LLVM Bug#686
|
|
|
|
|
|
|
|
http://llvm.org/bugs/show_bug.cgi?id=686
|
|
|
|
|
|
|
|
.. [2] TableGen Fundamentals
|
|
|
|
|
|
|
|
http://llvm.org/docs/TableGenFundamentals.html
|