llvm.org GIT mirror llvm / eae5a13
Remove more of llvmc and dependencies. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140121 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Christopher 8 years ago
27 changed file(s) with 2 addition(s) and 6080 deletion(s). Raw diff Collapse all Expand all
6767
6868
  • llvm-config -
  • 6969 print out LLVM compilation options, libraries, etc. as configured
    70
    71
  • llvmc -
  • 72 a generic customizable compiler driver
    7370
    7471
  • llvm-diff -
  • 7572 structurally compare two modules
    +0
    -190
    docs/CommandGuide/llvmc.pod less more
    None =pod
    1
    2 =head1 NAME
    3
    4 llvmc - The LLVM Compiler Driver (WIP)
    5
    6 =head1 SYNOPSIS
    7
    8 B [I] I
    9
    10 =head1 DESCRIPTION
    11
    12 B is a configurable driver for invoking other LLVM (and non-LLVM) tools
    13 in order to compile, optimize and link software for multiple languages. For
    14 those familiar with FSF's B tool, it is very similar. Please note that
    15 B is considered an experimental tool.
    16
    17 =head1 OPTIONS
    18
    19 =head2 Built-in Options
    20
    21 LLVMC has some built-in options that can't be overridden in the
    22 configuration libraries.
    23
    24 =over
    25
    26 =item B<-o> I
    27
    28 Output file name.
    29
    30 =item B<-x> I
    31
    32 Specify the language of the following input files until the next B<-x>
    33 option.
    34
    35 =item B<-load> I
    36
    37 Load the specified plugin DLL. Example:
    38 S<-load $LLVM_DIR/Release/lib/LLVMCSimple.so>.
    39
    40 =item B<-v> or B<--verbose>
    41
    42 Enable verbose mode, i.e. print out all executed commands.
    43
    44 =item B<--check-graph>
    45
    46 Check the compilation for common errors like mismatched output/input language
    47 names, multiple default edges and cycles. Because of plugins, these checks can't
    48 be performed at compile-time. Exit with code zero if no errors were found, and
    49 return the number of found errors otherwise. Hidden option, useful for debugging
    50 LLVMC plugins.
    51
    52 =item B<--view-graph>
    53
    54 Show a graphical representation of the compilation graph and exit. Requires that
    55 you have I and I programs installed. Hidden option, useful for
    56 debugging LLVMC plugins.
    57
    58 =item B<--write-graph>
    59
    60 Write a I file in the current directory with the
    61 compilation graph description in Graphviz format (identical to the file used by
    62 the B<--view-graph> option). The B<-o> option can be used to set the output file
    63 name. Hidden option, useful for debugging LLVMC plugins.
    64
    65 =item B<--save-temps>
    66
    67 Write temporary files to the current directory and do not delete them on
    68 exit. This option can also take an argument: the I<--save-temps=obj> switch will
    69 write files into the directory specified with the I<-o> option. The
    70 I<--save-temps=cwd> and I<--save-temps> switches are both synonyms for the
    71 default behaviour.
    72
    73 =item B<--temp-dir> I
    74
    75 Store temporary files in the given directory. This directory is deleted on exit
    76 unless I<--save-temps> is specified. If I<--save-temps=obj> is also specified,
    77 I<--temp-dir> is given the precedence.
    78
    79 =item B<-help>
    80
    81 Print a summary of command-line options and exit.
    82
    83 =item B<-help-hidden>
    84
    85 Print a summary of command-line options and exit. Print help even for
    86 options intended for developers.
    87
    88 =item B<--version>
    89
    90 Print version information and exit.
    91
    92 =item B<@>I
    93
    94 Read command-line options from I. The options read are inserted
    95 in place of the original @I option. If I does not exist, or
    96 cannot be read, then the option will be treated literally, and not
    97 removed.
    98
    99 Options in I are separated by whitespace. A whitespace character
    100 may be included in an option by surrounding the entire option in
    101 either single or double quotes. Any character (including a backslash)
    102 may be included by prefixing the character to be included with a
    103 backslash. The file may itself contain additional @I options;
    104 any such options will be processed recursively.
    105
    106
    107 =back
    108
    109
    110 =head2 Control Options
    111
    112 By default, LLVMC is built with some standard configuration libraries
    113 that define the following options:
    114
    115 =over
    116
    117 =item B<-clang>
    118
    119 Use Clang instead of llvm-gcc.
    120
    121 =item B<-opt>
    122
    123 Enable optimization passes with B. To pass options to the B program
    124 use the B<-Wo,> option.
    125
    126 =item B<-I> I
    127
    128 Add a directory to the header file search path.
    129
    130 =item B<-L> I
    131
    132 Add I to the library search path.
    133
    134 =item B<-F> I
    135
    136 Add I to the framework search path.
    137
    138 =item B<-l>I
    139
    140 Link in the library libI.[bc | a | so]. This library should
    141 be a bitcode library.
    142
    143 =item B<-framework> I
    144
    145 Link in the library libI.[bc | a | so]. This library should
    146 be a bitcode library.
    147
    148 =item B<-emit-llvm>
    149
    150 Output LLVM bitcode (with B<-c>) or assembly (with B<-S>) instead of native
    151 object (or assembly). If B<-emit-llvm> is given without either B<-c> or B<-S>
    152 it has no effect.
    153
    154 =item B<-Wa>
    155
    156 Pass options to assembler.
    157
    158 =item B<-Wl>
    159
    160 Pass options to linker.
    161
    162 =item B<-Wo>
    163
    164 Pass options to opt.
    165
    166 =item B<-Wllc>
    167
    168 Pass options to llc (code generator).
    169
    170 =back
    171
    172 =head1 EXIT STATUS
    173
    174 If B succeeds, it will exit with code 0. Otherwise, if an
    175 error occurs, it will exit with a non-zero value. If one of the
    176 compilation tools returns a non-zero status, pending actions will be
    177 discarded and B will return the same result code as the failing
    178 compilation tool.
    179
    180 =head1 SEE ALSO
    181
    182 L, L, L,
    183 L, L, L
    184
    185 =head1 AUTHORS
    186
    187 Maintained by the LLVM Team (L).
    188
    189 =cut
    +0
    -687
    docs/CompilerDriver.html less more
    None
    1
    2
    3
    4
    5
    6 Customizing LLVMC: Reference Manual
    7
    8
    9
    10
    11

    Customizing LLVMC: Reference Manual

    12
    13
    16
    17

    Contents

    18
    19
  • Introduction
  • 20
  • Compiling with llvmc
  • 21
  • Predefined options
  • 22
  • Compiling LLVMC-based drivers
  • 23
  • Customizing LLVMC: the compilation graph
  • 24
  • Describing options
  • 25
  • Conditional evaluation
  • 26
  • Writing a tool description
  • 27
  • Actions
  • 28
    29
    30
  • Language map
  • 31
  • Option preprocessor
  • 32
  • More advanced topics
  • 33
  • Hooks and environment variables
  • 34
  • Debugging
  • 35
  • Conditioning on the executable name
  • 36
    37
    38
    39
    40
    41

    Written by Mikhail Glushenkov

    42
    43

    Introduction

    44

    LLVMC is a generic compiler driver, designed to be customizable and

    45 extensible. It plays the same role for LLVM as the gcc program does for
    46 GCC - LLVMC's job is essentially to transform a set of input files into a set of
    47 targets depending on configuration rules and user options. What makes LLVMC
    48 different is that these transformation rules are completely customizable - in
    49 fact, LLVMC knows nothing about the specifics of transformation (even the
    50 command-line options are mostly not hard-coded) and regards the transformation
    51 structure as an abstract graph. The structure of this graph is described in
    52 high-level TableGen code, from which an efficient C++ representation is
    53 automatically derived. This makes it possible to adapt LLVMC for other
    54 purposes - for example, as a build tool for game resources.

    55

    Because LLVMC employs TableGen as its configuration language, you

    56 need to be familiar with it to customize LLVMC.

    57
    58
    59

    Compiling with llvmc

    60

    LLVMC tries hard to be as compatible with gcc as possible,

    61 although there are some small differences. Most of the time, however,
    62 you shouldn't be able to notice them:

    63
    
                      
                    
    64 $ # This works as expected:
    65 $ llvmc -O3 -Wall hello.cpp
    66 $ ./a.out
    67 hello
    68
    69

    One nice feature of LLVMC is that one doesn't have to distinguish between

    70 different compilers for different languages (think g++ vs. gcc) - the
    71 right toolchain is chosen automatically based on input language names (which
    72 are, in turn, determined from file extensions). If you want to force files
    73 ending with ".c" to compile as C++, use the -x option, just like you would
    74 do it with gcc:

    75
    
                      
                    
    76 $ # hello.c is really a C++ file
    77 $ llvmc -x c++ hello.c
    78 $ ./a.out
    79 hello
    80
    81

    On the other hand, when using LLVMC as a linker to combine several C++

    82 object files you should provide the --linker option since it's
    83 impossible for LLVMC to choose the right linker in that case:

    84
    
                      
                    
    85 $ llvmc -c hello.cpp
    86 $ llvmc hello.o
    87 [A lot of link-time errors skipped]
    88 $ llvmc --linker=c++ hello.o
    89 $ ./a.out
    90 hello
    91
    92

    By default, LLVMC uses llvm-gcc to compile the source code. It is also

    93 possible to choose the clang compiler with the -clang option.

    94
    95
    96

    Predefined options

    97

    LLVMC has some built-in options that can't be overridden in the TableGen code:

    98
    99
  • -o FILE - Output file name.
  • 100
  • -x LANGUAGE - Specify the language of the following input files
  • 101 until the next -x option.
    102
  • -v - Enable verbose mode, i.e. print out all executed commands.
  • 103
  • --save-temps - Write temporary files to the current directory and do not
  • 104 delete them on exit. This option can also take an argument: the
    105 --save-temps=obj switch will write files into the directory specified with
    106 the -o option. The --save-temps=cwd and --save-temps switches are
    107 both synonyms for the default behaviour.
    108
  • --temp-dir DIRECTORY - Store temporary files in the given directory. This
  • 109 directory is deleted on exit unless --save-temps is specified. If
    110 --save-temps=obj is also specified, --temp-dir is given the
    111 precedence.
    112
  • --check-graph - Check the compilation for common errors like mismatched
  • 113 output/input language names, multiple default edges and cycles. Exit with code
    114 zero if no errors were found, and return the number of found errors
    115 otherwise. Hidden option, useful for debugging.
    116
  • --view-graph - Show a graphical representation of the compilation graph
  • 117 and exit. Requires that you have dot and gv programs installed. Hidden
    118 option, useful for debugging.
    119
  • --write-graph - Write a compilation-graph.dot file in the current
  • 120 directory with the compilation graph description in Graphviz format (identical
    121 to the file used by the --view-graph option). The -o option can be
    122 used to set the output file name. Hidden option, useful for debugging.
    123
  • --help, --help-hidden, --version - These options have
  • 124 their standard meaning.
    125
    126
    127
    128

    Compiling LLVMC-based drivers

    129

    It's easiest to start working on your own LLVMC driver by copying the skeleton

    130 project which lives under $LLVMC_DIR/examples/Skeleton:

    131
    
                      
                    
    132 $ cd $LLVMC_DIR/examples
    133 $ cp -r Skeleton MyDriver
    134 $ cd MyDriver
    135 $ ls
    136 AutoGenerated.td Hooks.cpp Main.cpp Makefile
    137
    138

    As you can see, our basic driver consists of only three files (not counting the

    139 build script). AutoGenerated.td contains TableGen description of the
    140 compilation graph; its format is documented in the following
    141 sections. Hooks.cpp is an empty file that should be used for hook
    142 definitions (see below). Main.cpp is just a helper used to compile the
    143 auto-generated C++ code produced from TableGen source.

    144

    The first thing that you should do is to change the LLVMC_BASED_DRIVER

    145 variable in the Makefile:

    146
    
                      
                    
    147 LLVMC_BASED_DRIVER=MyDriver
    148
    149

    It can also be a good idea to put your TableGen code into a file with a less

    150 generic name:

    151
    
                      
                    
    152 $ touch MyDriver.td
    153 $ vim AutoGenerated.td
    154 [...]
    155 include "MyDriver.td"
    156
    157

    If you have more than one TableGen source file, they all should be included from

    158 AutoGenerated.td, since this file is used by the build system to generate
    159 C++ code.

    160

    To build your driver, just cd to its source directory and run make. The

    161 resulting executable will be put into $LLVM_OBJ_DIR/$(BuildMode)/bin.

    162

    If you're compiling LLVM with different source and object directories, then you

    163 must perform the following additional steps before running make:

    164
    
                      
                    
    165 # LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
    166 # LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
    167 $ mkdir $LLVMC_OBJ_DIR/examples/MyDriver/
    168 $ cp $LLVMC_SRC_DIR/examples/MyDriver/Makefile \
    169 $LLVMC_OBJ_DIR/examples/MyDriver/
    170 $ cd $LLVMC_OBJ_DIR/examples/MyDriver
    171 $ make
    172
    173
    174
    175

    Customizing LLVMC: the compilation graph

    176

    Each TableGen configuration file should include the common definitions:

    177
    
                      
                    
    178 include "llvm/CompilerDriver/Common.td"
    179
    180

    Internally, LLVMC stores information about possible source transformations in

    181 form of a graph. Nodes in this graph represent tools, and edges between two
    182 nodes represent a transformation path. A special "root" node is used to mark
    183 entry points for the transformations. LLVMC also assigns a weight to each edge
    184 (more on this later) to choose between several alternative edges.

    185

    The definition of the compilation graph (see file llvmc/src/Base.td for an

    186 example) is just a list of edges:

    187
    
                      
                    
    188 def CompilationGraph : CompilationGraph<[
    189 Edge<"root", "llvm_gcc_c">,
    190 Edge<"root", "llvm_gcc_assembler">,
    191 ...
    192
    193 Edge<"llvm_gcc_c", "llc">,
    194 Edge<"llvm_gcc_cpp", "llc">,
    195 ...
    196
    197 OptionalEdge<"llvm_gcc_c", "opt", (case (switch_on "opt"),
    198 (inc_weight))>,
    199 OptionalEdge<"llvm_gcc_cpp", "opt", (case (switch_on "opt"),
    200 (inc_weight))>,
    201 ...
    202
    203 OptionalEdge<"llvm_gcc_assembler", "llvm_gcc_cpp_linker",
    204 (case (input_languages_contain "c++"), (inc_weight),
    205 (or (parameter_equals "linker", "g++"),
    206 (parameter_equals "linker", "c++")), (inc_weight))>,
    207 ...
    208
    209 ]>;
    210
    211

    As you can see, the edges can be either default or optional, where optional

    212 edges are differentiated by an additional case expression used to calculate
    213 the weight of this edge. Notice also that we refer to tools via their names (as
    214 strings). This makes it possible to add edges to an existing compilation graph
    215 without having to know about all tool definitions used in the graph.

    216

    The default edges are assigned a weight of 1, and optional edges get a weight of

    217 0 + 2*N where N is the number of tests that evaluated to true in the case
    218 expression. It is also possible to provide an integer parameter to
    219 inc_weight and dec_weight - in this case, the weight is increased (or
    220 decreased) by the provided value instead of the default 2. Default weight of an
    221 optional edge can be changed by using the default clause of the case
    222 construct.

    223

    When passing an input file through the graph, LLVMC picks the edge with the

    224 maximum weight. To avoid ambiguity, there should be only one default edge
    225 between two nodes (with the exception of the root node, which gets a special
    226 treatment - there you are allowed to specify one default edge per language).

    227

    When multiple compilation graphs are defined, they are merged together. Multiple

    228 edges with the same end nodes are not allowed (i.e. the graph is not a
    229 multigraph), and will lead to a compile-time error.

    230

    To get a visual representation of the compilation graph (useful for debugging),

    231 run llvmc --view-graph. You will need dot and gsview installed for
    232 this to work properly.

    233
    234
    235

    Describing options

    236

    Command-line options supported by the driver are defined by using an

    237 OptionList:

    238
    
                      
                    
    239 def Options : OptionList<[
    240 (switch_option "E", (help "Help string")),
    241 (alias_option "quiet", "q")
    242 ...
    243 ]>;
    244
    245

    As you can see, the option list is just a list of DAGs, where each DAG is an

    246 option description consisting of the option name and some properties. More than
    247 one option list can be defined (they are all merged together in the end), which
    248 can be handy if one wants to separate option groups syntactically.

    249
    250
  • Possible option types:

  • 251
    252
    253
  • switch_option - a simple boolean switch without arguments, for example
  • 254 -O2 or -time. At most one occurrence is allowed by default.
    255
  • parameter_option - option that takes one argument, for example
  • 256 -std=c99. It is also allowed to use spaces instead of the equality
    257 sign: -std c99. At most one occurrence is allowed.
    258
  • parameter_list_option - same as the above, but more than one option
  • 259 occurrence is allowed.
    260
  • prefix_option - same as the parameter_option, but the option name and
  • 261 argument do not have to be separated. Example: -ofile. This can be also
    262 specified as -o file; however, -o=file will be parsed incorrectly
    263 (=file will be interpreted as option value). At most one occurrence is
    264 allowed.
    265
  • prefix_list_option - same as the above, but more than one occurrence of
  • 266 the option is allowed; example: -lm -lpthread.
    267
  • alias_option - a special option type for creating aliases. Unlike other
  • 268 option types, aliases are not allowed to have any properties besides the
    269 aliased option name.
    270 Usage example: (alias_option "preprocess", "E")
    271
  • switch_list_option - like switch_option with the zero_or_more
  • 272 property, but remembers how many times the switch was turned on. Useful
    273 mostly for forwarding. Example: when -foo is a switch option (with the
    274 zero_or_more property), the command driver -foo -foo is forwarded
    275 as some-tool -foo, but when -foo is a switch list, the same command
    276 is forwarded as some-tool -foo -foo.
    277
    278
    279
    280
  • Possible option properties:

  • 281
    282
    283
  • help - help string associated with this option. Used for --help
  • 284 output.
    285
  • required - this option must be specified exactly once (or, in case of
  • 286 the list options without the multi_val property, at least
    287 once). Incompatible with optional and one_or_more.
    288
  • optional - the option can be specified either zero times or exactly
  • 289 once. The default for switch options. Useful only for list options in
    290 conjunction with multi_val. Incompatible with required,
    291 zero_or_more and one_or_more.
    292
  • one_or_more - the option must be specified at least once. Can be useful
  • 293 to allow switch options be both obligatory and be specified multiple
    294 times. For list options is useful only in conjunction with multi_val;
    295 for ordinary it is synonymous with required. Incompatible with
    296 required, optional and zero_or_more.
    297
  • zero_or_more - the option can be specified zero or more times. Useful
  • 298 to allow a single switch option to be specified more than
    299 once. Incompatible with required, optional and one_or_more.
    300
  • hidden - the description of this option will not appear in
  • 301 the --help output (but will appear in the --help-hidden
    302 output).
    303
  • really_hidden - the option will not be mentioned in any help
  • 304 output.
    305
  • comma_separated - Indicates that any commas specified for an option's
  • 306 value should be used to split the value up into multiple values for the
    307 option. This property is valid only for list options. In conjunction with
    308 forward_value can be used to implement option forwarding in style of
    309 gcc's -Wa,.
    310
  • multi_val n - this option takes n arguments (can be useful in some
  • 311 special cases). Usage example: (parameter_list_option "foo", (multi_val
    312 3)); the command-line syntax is '-foo a b c'. Only list options can have
    313 this attribute; you can, however, use the one_or_more, optional
    314 and required properties.
    315
  • init - this option has a default value, either a string (if it is a
  • 316 parameter), or a boolean (if it is a switch; as in C++, boolean constants
    317 are called true and false). List options can't have init
    318 attribute.
    319 Usage examples: (switch_option "foo", (init true)); (prefix_option
    320 "bar", (init "baz")).
    321
    322
    323
    324
    325
    326
    327

    Conditional evaluation

    328

    The 'case' construct is the main means by which programmability is achieved in

    329 LLVMC. It can be used to calculate edge weights, program actions and modify the
    330 shell commands to be executed. The 'case' expression is designed after the
    331 similarly-named construct in functional languages and takes the form (case
    332 (test_1), statement_1, (test_2), statement_2, ... (test_N), statement_N). The
    333 statements are evaluated only if the corresponding tests evaluate to true.

    334

    Examples:

    335
    
                      
                    
    336 // Edge weight calculation
    337
    338 // Increases edge weight by 5 if "-A" is provided on the
    339 // command-line, and by 5 more if "-B" is also provided.
    340 (case
    341 (switch_on "A"), (inc_weight 5),
    342 (switch_on "B"), (inc_weight 5))
    343
    344
    345 // Tool command line specification
    346
    347 // Evaluates to "cmdline1" if the option "-A" is provided on the
    348 // command line; to "cmdline2" if "-B" is provided;
    349 // otherwise to "cmdline3".
    350
    351 (case
    352 (switch_on "A"), "cmdline1",
    353 (switch_on "B"), "cmdline2",
    354 (default), "cmdline3")
    355
    356

    Note the slight difference in 'case' expression handling in contexts of edge

    357 weights and command line specification - in the second example the value of the
    358 "B" switch is never checked when switch "A" is enabled, and the whole
    359 expression always evaluates to "cmdline1" in that case.

    360

    Case expressions can also be nested, i.e. the following is legal:

    361
    
                      
                    
    362 (case (switch_on "E"), (case (switch_on "o"), ..., (default), ...)
    363 (default), ...)
    364
    365

    You should, however, try to avoid doing that because it hurts readability. It is

    366 usually better to split tool descriptions and/or use TableGen inheritance
    367 instead.

    368
    369
  • Possible tests are:
  • 370
  • switch_on - Returns true if a given command-line switch is provided by
  • 371 the user. Can be given multiple arguments, in that case (switch_on "foo",
    372 "bar", "baz") is equivalent to (and (switch_on "foo"), (switch_on
    373 "bar"), (switch_on "baz")).
    374 Example: (switch_on "opt").
    375
  • any_switch_on - Given a number of switch options, returns true if any of
  • 376 the switches is turned on.
    377 Example: (any_switch_on "foo", "bar", "baz") is equivalent to (or
    378 (switch_on "foo"), (switch_on "bar"), (switch_on "baz")).
    379
  • parameter_equals - Returns true if a command-line parameter (first
  • 380 argument) equals a given value (second argument).
    381 Example: (parameter_equals "W", "all").
    382
  • element_in_list - Returns true if a command-line parameter list (first
  • 383 argument) contains a given value (second argument).
    384 Example: (element_in_list "l", "pthread").
    385
  • input_languages_contain - Returns true if a given language
  • 386 belongs to the current input language set.
    387 Example: (input_languages_contain "c++").
    388
  • in_language - Evaluates to true if the input file language is equal to
  • 389 the argument. At the moment works only with command and actions (on
    390 non-join nodes).
    391 Example: (in_language "c++").
    392
  • not_empty - Returns true if a given option (which should be either a
  • 393 parameter or a parameter list) is set by the user. Like switch_on, can
    394 be also given multiple arguments.
    395 Examples: (not_empty "o"), (not_empty "o", "l").
    396
  • any_not_empty - Returns true if not_empty returns true for any of
  • 397 the provided options.
    398 Example: (any_not_empty "foo", "bar", "baz") is equivalent to (or
    399 (not_empty "foo"), (not_empty "bar"), (not_empty "baz")).
    400
  • empty - The opposite of not_empty. Equivalent to (not (not_empty
  • 401 X)). Can be given multiple arguments.
    402
  • any_not_empty - Returns true if not_empty returns true for any of
  • 403 the provided options.
    404 Example: (any_empty "foo", "bar", "baz") is equivalent to (or
    405 (not_empty "foo"), (not_empty "bar"), (not_empty "baz")).
    406
  • single_input_file - Returns true if there was only one input file
  • 407 provided on the command-line. Used without arguments:
    408 (single_input_file).
    409
  • multiple_input_files - Equivalent to (not (single_input_file)) (the
  • 410 case of zero input files is considered an error).
    411
  • default - Always evaluates to true. Should always be the last
  • 412 test in the case expression.
    413
  • and - A standard logical combinator that returns true iff all of
  • 414 its arguments return true. Used like this: (and (test1), (test2),
    415 ... (testN)). Nesting of and and or is allowed, but not
    416 encouraged.
    417
  • or - A logical combinator that returns true iff any of its arguments
  • 418 return true.
    419 Example: (or (test1), (test2), ... (testN)).
    420
  • not - Standard unary logical combinator that negates its
  • 421 argument.
    422 Example: (not (or (test1), (test2), ... (testN))).
    423
    424
    425
    426
    427
    428

    Writing a tool description

    429

    As was said earlier, nodes in the compilation graph represent tools, which are

    430 described separately. A tool definition looks like this (taken from the
    431 llvmc/src/Base.td file):

    432
    
                      
                    
    433 def llvm_gcc_cpp : Tool<[
    434 (in_language "c++"),
    435 (out_language "llvm-assembler"),
    436 (output_suffix "bc"),
    437 (command "llvm-g++ -c -emit-llvm"),
    438 (sink)
    439 ]>;
    440
    441

    This defines a new tool called llvm_gcc_cpp, which is an alias for

    442 llvm-g++. As you can see, a tool definition is just a list of properties;
    443 most of them should be self-explanatory. The sink property means that this
    444 tool should be passed all command-line options that aren't mentioned in the
    445 option list.

    446

    The complete list of all currently implemented tool properties follows.

    447
    448
  • Possible tool properties:
  • 449
  • in_language - input language name. Can be given multiple arguments, in
  • 450 case the tool supports multiple input languages. Used for typechecking and
    451 mapping file extensions to tools.
    452
  • out_language - output language name. Multiple output languages are
  • 453 allowed. Used for typechecking the compilation graph.
    454
  • output_suffix - output file suffix. Can also be changed dynamically, see
  • 455 documentation on actions.
    456
    457
    458
    459
    460
    461
  • command - the actual command used to run the tool. You can use output
  • 462 redirection with >, hook invocations ($CALL), environment variables
    463 (via $ENV) and the case construct.
    464
  • join - this tool is a "join node" in the graph, i.e. it gets a list of
  • 465 input files and joins them together. Used for linkers.
    466
  • sink - all command-line options that are not handled by other tools are
  • 467 passed to this tool.
    468
  • actions - A single big case expression that specifies how this tool
  • 469 reacts on command-line options (described in more detail below).
    470
    471
    472
    473
    474
  • out_file_option, in_file_option - Options appended to the
  • 475 command string to designate output and input files. Default values are
    476 "-o" and "", respectively.
    477
    478
    479
    480

    Actions

    481

    A tool often needs to react to command-line options, and this is precisely what

    482 the actions property is for. The next example illustrates this feature:

    483
    
                      
                    
    484 def llvm_gcc_linker : Tool<[
    485 (in_language "object-code"),
    486 (out_language "executable"),
    487 (output_suffix "out"),
    488 (command "llvm-gcc"),
    489 (join),
    490 (actions (case (not_empty "L"), (forward "L"),
    491 (not_empty "l"), (forward "l"),
    492 (not_empty "dummy"),
    493 [(append_cmd "-dummy1"), (append_cmd "-dummy2")])
    494 ]>;
    495
    496

    The actions tool property is implemented on top of the omnipresent case

    497 expression. It associates one or more different actions with given
    498 conditions - in the example, the actions are forward, which forwards a given
    499 option unchanged, and append_cmd, which appends a given string to the tool
    500 execution command. Multiple actions can be associated with a single condition by
    501 using a list of actions (used in the example to append some dummy options). The
    502 same case construct can also be used in the cmd_line property to modify
    503 the tool command line.

    504

    The "join" property used in the example means that this tool behaves like a

    505 linker.

    506

    The list of all possible actions follows.

    507
    508
  • Possible actions:

  • 509
    510
    511
  • append_cmd - Append a string to the tool invocation command.
  • 512 Example: (case (switch_on "pthread"), (append_cmd "-lpthread")).
    513
  • error - Exit with error.
  • 514 Example: (error "Mixing -c and -S is not allowed!").
    515
  • warning - Print a warning.
  • 516 Example: (warning "Specifying both -O1 and -O2 is meaningless!").
    517
  • forward - Forward the option unchanged.
  • 518 Example: (forward "Wall").
    519
  • forward_as - Change the option's name, but forward the argument
  • 520 unchanged.
    521 Example: (forward_as "O0", "--disable-optimization").
    522
  • forward_value - Forward only option's value. Cannot be used with switch
  • 523 options (since they don't have values), but works fine with lists.
    524 Example: (forward_value "Wa,").
    525
  • forward_transformed_value - As above, but applies a hook to the
  • 526 option's value before forwarding (see below). When
    527 forward_transformed_value is applied to a list
    528 option, the hook must have signature
    529 std::string hooks::HookName (const std::vector<std::string>&).
    530 Example: (forward_transformed_value "m", "ConvertToMAttr").
    531
  • output_suffix - Modify the output suffix of this tool.
  • 532 Example: (output_suffix "i").
    533
  • stop_compilation - Stop compilation after this tool processes its
  • 534 input. Used without arguments.
    535 Example: (stop_compilation).
    536
    537
    538
    539
    540
    541
    542
    543

    Language map

    544

    If you are adding support for a new language to LLVMC, you'll need to modify the

    545 language map, which defines mappings from file extensions to language names. It
    546 is used to choose the proper toolchain(s) for a given input file set. Language
    547 map definition looks like this:

    548
    
                      
                    
    549 def LanguageMap : LanguageMap<
    550 [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
    551 LangToSuffixes<"c", ["c"]>,
    552 ...
    553 ]>;
    554
    555

    For example, without those definitions the following command wouldn't work:

    556
    
                      
                    
    557 $ llvmc hello.cpp
    558 llvmc: Unknown suffix: cpp
    559
    560

    The language map entries are needed only for the tools that are linked from the

    561 root node. A tool can have multiple output languages.

    562
    563
    564

    Option preprocessor

    565

    It is sometimes useful to run error-checking code before processing the

    566 compilation graph. For example, if optimization options "-O1" and "-O2" are
    567 implemented as switches, we might want to output a warning if the user invokes
    568 the driver with both of these options enabled.

    569

    The OptionPreprocessor feature is reserved specially for these

    570 occasions. Example (adapted from llvm/src/Base.td.in):

    571
    
                      
                    
    572 def Preprocess : OptionPreprocessor<
    573 (case (not (any_switch_on "O0", "O1", "O2", "O3")),
    574 (set_option "O2"),
    575 (and (switch_on "O3"), (any_switch_on "O0", "O1", "O2")),
    576 (unset_option "O0", "O1", "O2"),
    577 (and (switch_on "O2"), (any_switch_on "O0", "O1")),
    578 (unset_option "O0", "O1"),
    579 (and (switch_on "O1"), (switch_on "O0")),
    580 (unset_option "O0"))
    581 >;
    582
    583

    Here, OptionPreprocessor is used to unset all spurious -O options so

    584 that they are not forwarded to the compiler. If no optimization options are
    585 specified, -O2 is enabled.

    586

    OptionPreprocessor is basically a single big case expression, which is

    587 evaluated only once right after the driver is started. The only allowed actions
    588 in OptionPreprocessor are error, warning, and two special actions:
    589 unset_option and set_option. As their names suggest, they can be used to
    590 set or unset a given option. To set an option with set_option, use the
    591 two-argument form: (set_option "parameter", VALUE). Here, VALUE can be
    592 either a string, a string list, or a boolean constant.

    593

    For convenience, set_option and unset_option also work with multiple

    594 arguments. That is, instead of [(unset_option "A"), (unset_option "B")] you
    595 can use (unset_option "A", "B"). Obviously, (set_option "A", "B") is
    596 only valid if both A and B are switches.

    597
    598
    599

    More advanced topics

    600
    601

    Hooks and environment variables

    602

    Normally, LLVMC searches for programs in the system PATH. Sometimes, this is

    603 not sufficient: for example, we may want to specify tool paths or names in the
    604 configuration file. This can be achieved via the hooks mechanism. To write your
    605 own hooks, add their definitions to the Hooks.cpp or drop a .cpp file
    606 into your driver directory. Hooks should live in the hooks namespace and
    607 have the signature std::string hooks::MyHookName ([const char* Arg0 [ const
    608 char* Arg2 [, ...]]]). They can be used from the command tool property:

    609
    
                      
                    
    610 (command "$CALL(MyHook)/path/to/file -o $CALL(AnotherHook)")
    611
    612

    To pass arguments to hooks, use the following syntax:

    613
    
                      
                    
    614 (command "$CALL(MyHook, 'Arg1', 'Arg2', 'Arg # 3')/path/to/file -o1 -o2")
    615
    616

    It is also possible to use environment variables in the same manner:

    617
    
                      
                    
    618 (command "$ENV(VAR1)/path/to/file -o $ENV(VAR2)")
    619
    620

    To change the command line string based on user-provided options use

    621 the case expression (documented above):

    622
    
                      
                    
    623 (command
    624 (case
    625 (switch_on "E"),
    626 "llvm-g++ -E -x c $INFILE -o $OUTFILE",
    627 (default),
    628 "llvm-g++ -c -x c $INFILE -o $OUTFILE -emit-llvm"))
    629
    630
    631
    632

    Debugging

    633

    When writing LLVMC-based drivers, it can be useful to get a visual view of the

    634 resulting compilation graph. This can be achieved via the command line option
    635 --view-graph (which assumes that Graphviz and Ghostview are
    636 installed). There is also a --write-graph option that creates a Graphviz
    637 source file (compilation-graph.dot) in the current directory.

    638

    Another useful llvmc option is --check-graph. It checks the compilation

    639 graph for common errors like mismatched output/input language names, multiple
    640 default edges and cycles. When invoked with --check-graph, llvmc doesn't
    641 perform any compilation tasks and returns the number of encountered errors as
    642 its status code. In the future, these checks will be performed at compile-time
    643 and this option will disappear.

    644
    645
    646

    Conditioning on the executable name

    647

    For now, the executable name (the value passed to the driver in argv[0]) is

    648 accessible only in the C++ code (i.e. hooks). Use the following code:

    649
    
                      
                    
    650 namespace llvmc {
    651 extern const char* ProgramName;
    652 }
    653
    654 namespace hooks {
    655
    656 std::string MyHook() {
    657 //...
    658 if (strcmp(ProgramName, "mydriver") == 0) {
    659 //...
    660
    661 }
    662
    663 } // end namespace hooks
    664
    665

    In general, you're encouraged not to make the behaviour dependent on the

    666 executable file name, and use command-line switches instead. See for example how
    667 the llvmc program behaves when it needs to choose the correct linker options
    668 (think g++ vs. gcc).

    669
    670
    671
    672
    673 alt="Valid CSS" />
    674
    675
    676 alt="Valid XHTML 1.0 Transitional"/>
    677
    678 Mikhail Glushenkov
    679 LLVM Compiler Infrastructure
    680
    681 Last modified: $Date$
    682
    683
    684
    685
    686
    +0
    -125
    docs/CompilerDriverTutorial.html less more
    None
    1
    2
    3
    4
    5
    6 Tutorial - Using LLVMC
    7
    8
    9
    10
    11

    Tutorial - Using LLVMC

    12
    13
    16
    17

    Contents

    18
    19
  • Introduction
  • 20
  • Using the llvmc program
  • 21
  • Using LLVMC to generate toolchain drivers
  • 22
    23
    24
    25

    Written by Mikhail Glushenkov

    26
    27

    Introduction

    28

    LLVMC is a generic compiler driver, which plays the same role for LLVM as the

    29 gcc program does for GCC - the difference being that LLVMC is designed to be
    30 more adaptable and easier to customize. Most of LLVMC functionality is
    31 implemented via high-level TableGen code, from which a corresponding C++ source
    32 file is automatically generated. This tutorial describes the basic usage and
    33 configuration of LLVMC.

    34
    35
    36

    Using the llvmc program

    37

    In general, llvmc tries to be command-line compatible with gcc as much

    38 as possible, so most of the familiar options work:

    39
    
                      
                    
    40 $ llvmc -O3 -Wall hello.cpp
    41 $ ./a.out
    42 hello
    43
    44

    This will invoke llvm-g++ under the hood (you can see which commands are

    45 executed by using the -v option). For further help on command-line LLVMC
    46 usage, refer to the llvmc --help output.

    47
    48
    49

    Using LLVMC to generate toolchain drivers

    50

    LLVMC-based drivers are written mostly using TableGen, so you need to be

    51 familiar with it to get anything done.

    52

    Start by compiling example/Simple, which is a primitive wrapper for

    53 gcc:

    54
    
                      
                    
    55 $ cd $LLVM_OBJ_DIR/tools/examples/Simple
    56 $ make
    57 $ cat > hello.c
    58 #include <stdio.h>
    59 int main() { printf("Hello\n"); }
    60 $ $LLVM_BIN_DIR/Simple -v hello.c
    61 gcc hello.c -o hello.out
    62 $ ./hello.out
    63 Hello
    64
    65

    We have thus produced a simple driver called, appropriately, Simple, from

    66 the input TableGen file Simple.td. The llvmc program itself is generated
    67 using a similar process (see llvmc/src). Contents of the file Simple.td
    68 look like this:

    69
    
                      
                    
    70 // Include common definitions
    71 include "llvm/CompilerDriver/Common.td"
    72
    73 // Tool descriptions
    74 def gcc : Tool<
    75 [(in_language "c"),
    76 (out_language "executable"),
    77 (output_suffix "out"),
    78 (command "gcc"),
    79 (sink),
    80
    81 // -o is what is used by default, out_file_option here is included for
    82 // instructive purposes.
    83 (out_file_option "-o")
    84 ]>;
    85
    86 // Language map
    87 def LanguageMap : LanguageMap<[(lang_to_suffixes "c", "c")]>;
    88
    89 // Compilation graph
    90 def CompilationGraph : CompilationGraph<[(edge "root", "gcc")]>;
    91
    92

    As you can see, this file consists of three parts: tool descriptions, language

    93 map, and the compilation graph definition.

    94

    At the heart of LLVMC is the idea of a compilation graph: vertices in this graph

    95 are tools, and edges represent a transformation path between two tools (for
    96 example, assembly source produced by the compiler can be transformed into
    97 executable code by an assembler). The compilation graph is basically a list of
    98 edges; a special node named root is used to mark graph entry points.

    99

    Tool descriptions are represented as property lists: most properties in the

    100 example above should be self-explanatory; the sink property means that all
    101 options lacking an explicit description should be forwarded to this tool.

    102

    The LanguageMap associates a language name with a list of suffixes and is

    103 used for deciding which toolchain corresponds to a given input file.

    104

    To learn more about writing your own drivers with LLVMC, refer to the reference

    105 manual and examples in the examples directory. Of a particular interest is
    106 the Skeleton example, which can serve as a template for your LLVMC-based
    107 drivers.

    108
    109
    110
    111
    112 alt="Valid CSS" />
    113
    114
    115 alt="Valid XHTML 1.0 Transitional"/>
    116
    117 Mikhail Glushenkov
    118 LLVM Compiler Infrastructure
    119
    120 Last modified: $Date: 2008-12-11 11:34:48 -0600 (Thu, 11 Dec 2008) $
    121
    122
    123
    124
    539539

    Currently, there isn't much. LLVM supports an intermediate representation

    540540 which is useful for code representation but will not support the high level
    541541 (abstract syntax tree) representation needed by most compilers. There are no
    542 facilities for lexical nor semantic analysis. There is, however, a mostly
    543 implemented configuration-driven
    544 compiler driver which simplifies the task
    545 of running optimizations, linking, and executable generation.

    542 facilities for lexical nor semantic analysis.

    546543
    547544
    548545
    215215
  • Bugpoint - automatic bug finder and test-case
  • 216216 reducer description and usage information.
    217217
    218
  • Compiler Driver (llvmc) Tutorial
  • 219 - This document is a tutorial introduction to the usage and
    220 configuration of the LLVM compiler driver tool, llvmc.
    221
    222
  • Compiler Driver (llvmc)
  • 223 Reference - This document describes the design and configuration
    224 of llvmc in more detail.
    225
    226218
  • LLVM Bitcode File Format - This describes
  • 227219 the file format and encoding used for LLVM "bc" files.
    228220
    +0
    -54
    include/llvm/CompilerDriver/Action.h less more
    None //===--- Action.h - The LLVM Compiler Driver --------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Action - encapsulates a single shell command.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H
    15
    16 #include
    17 #include
    18
    19 namespace llvmc {
    20
    21 typedef std::vector StrVector;
    22
    23 /// Action - A class that encapsulates a single shell command.
    24 class Action {
    25 /// Command_ - The actual command (for example, 'ls').
    26 std::string Command_;
    27 /// Args_ - Command arguments. Stdout redirection ("> file") is allowed.
    28 std::vector Args_;
    29 /// StopCompilation_ - Should we stop compilation after executing
    30 /// this action?
    31 bool StopCompilation_;
    32 /// OutFile_ - The output file name.
    33 std::string OutFile_;
    34
    35 public:
    36 void Construct (const std::string& C, const StrVector& A,
    37 bool S, const std::string& O) {
    38 Command_ = C;
    39 Args_ = A;
    40 StopCompilation_ = S;
    41 OutFile_ = O;
    42 }
    43 bool IsConstructed () { return (Command_.size() != 0);}
    44
    45 /// Execute - Executes the command. Returns -1 on error.
    46 int Execute () const;
    47 bool StopCompilation () const { return StopCompilation_; }
    48 const std::string& OutFile() { return OutFile_; }
    49 };
    50
    51 }
    52
    53 #endif // LLVM_INCLUDE_COMPILER_DRIVER_ACTION_H
    +0
    -40
    include/llvm/CompilerDriver/AutoGenerated.h less more
    None //===--- AutoGenerated.h - The LLVM Compiler Driver -------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Interface to the autogenerated driver code.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H
    15
    16 namespace llvmc {
    17 class LanguageMap;
    18 class CompilationGraph;
    19
    20 namespace autogenerated {
    21
    22 int PreprocessOptions();
    23 int PopulateLanguageMap(LanguageMap& langMap);
    24 int PopulateCompilationGraph(CompilationGraph& graph);
    25
    26 inline int RunInitialization (LanguageMap& M, CompilationGraph& G) {
    27 if (int ret = PreprocessOptions())
    28 return ret;
    29 if (int ret = PopulateLanguageMap(M))
    30 return ret;
    31 if (int ret = PopulateCompilationGraph(G))
    32 return ret;
    33
    34 return 0;
    35 }
    36 }
    37 }
    38
    39 #endif // LLVM_INCLUDE_COMPILER_DRIVER_AUTOGENERATED_H
    +0
    -39
    include/llvm/CompilerDriver/BuiltinOptions.h less more
    None //===--- BuiltinOptions.h - The LLVM Compiler Driver ------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Declarations of all global command-line option variables.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
    15
    16 #include "llvm/Support/CommandLine.h"
    17
    18 #include
    19
    20 namespace llvmc {
    21
    22 namespace SaveTempsEnum { enum Values { Cwd, Obj, Unset }; }
    23
    24 extern llvm::cl::list InputFilenames;
    25 extern llvm::cl::opt OutputFilename;
    26 extern llvm::cl::opt TempDirname;
    27 extern llvm::cl::list Languages;
    28 extern llvm::cl::opt DryRun;
    29 extern llvm::cl::opt Time;
    30 extern llvm::cl::opt VerboseMode;
    31 extern llvm::cl::opt CheckGraph;
    32 extern llvm::cl::opt ViewGraph;
    33 extern llvm::cl::opt WriteGraph;
    34 extern llvm::cl::opt SaveTemps;
    35
    36 } // End namespace llvmc.
    37
    38 #endif // LLVM_INCLUDE_COMPILER_DRIVER_BUILTIN_OPTIONS_H
    +0
    -127
    include/llvm/CompilerDriver/Common.td less more
    None //===- Common.td - Common definitions for LLVMC2 ----------*- tablegen -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open Source
    5 // License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // This file contains common definitions used in llvmc tool description files.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 class Tool l> {
    14 list properties = l;
    15 }
    16
    17 // Possible Tool properties.
    18
    19 def in_language;
    20 def out_language;
    21 def output_suffix;
    22 def command;
    23 def out_file_option;
    24 def in_file_option;
    25 def join;
    26 def sink;
    27 def works_on_empty;
    28 def actions;
    29
    30 // Possible option types.
    31
    32 def alias_option;
    33 def switch_option;
    34 def switch_list_option;
    35 def parameter_option;
    36 def parameter_list_option;
    37 def prefix_option;
    38 def prefix_list_option;
    39
    40 // Possible option properties.
    41
    42 def help;
    43 def hidden;
    44 def init;
    45 def multi_val;
    46 def one_or_more;
    47 def zero_or_more;
    48 def optional;
    49 def really_hidden;
    50 def required;
    51 def comma_separated;
    52 def forward_not_split;
    53
    54 // The 'case' construct.
    55 def case;
    56
    57 // Boolean constants.
    58 class Bool {
    59 bit Value = val;
    60 }
    61 def true : Bool<1>;
    62 def false : Bool<0>;
    63
    64 // Boolean operators.
    65 def and;
    66 def or;
    67 def not;
    68
    69 // Primitive tests.
    70 def switch_on;
    71 def parameter_equals;
    72 def element_in_list;
    73 def input_languages_contain;
    74 def empty;
    75 def not_empty;
    76 def default;
    77 def single_input_file;
    78 def multiple_input_files;
    79 def any_switch_on;
    80 def any_not_empty;
    81 def any_empty;
    82
    83 // Possible actions.
    84
    85 def append_cmd;
    86 def forward;
    87 def forward_as;
    88 def forward_value;
    89 def forward_transformed_value;
    90 def stop_compilation;
    91 def no_out_file;
    92 def unpack_values;
    93 def warning;
    94 def error;
    95 def set_option;
    96 def unset_option;
    97
    98 // Increase the edge weight.
    99 def inc_weight;
    100
    101 // Option list - a single place to specify options.
    102 class OptionList l> {
    103 list options = l;
    104 }
    105
    106 // Option preprocessor - actions taken during plugin loading.
    107 class OptionPreprocessor {
    108 dag preprocessor = d;
    109 }
    110
    111 // Map from suffixes to language names
    112
    113 def lang_to_suffixes;
    114
    115 class LanguageMap l> {
    116 list map = l;
    117 }
    118
    119 // Compilation graph
    120
    121 def edge;
    122 def optional_edge;
    123
    124 class CompilationGraph l> {
    125 list edges = l;
    126 }
    +0
    -330
    include/llvm/CompilerDriver/CompilationGraph.h less more
    None //===--- CompilationGraph.h - The LLVM Compiler Driver ----------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Compilation graph - definition.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H
    15
    16 #include "llvm/CompilerDriver/Tool.h"
    17
    18 #include "llvm/ADT/GraphTraits.h"
    19 #include "llvm/ADT/IntrusiveRefCntPtr.h"
    20 #include "llvm/ADT/SmallVector.h"
    21 #include "llvm/ADT/StringMap.h"
    22 #include "llvm/ADT/StringSet.h"
    23 #include "llvm/Support/Path.h"
    24
    25 #include
    26 #include
    27
    28 namespace llvmc {
    29
    30 class CompilationGraph;
    31 typedef llvm::StringSet<> InputLanguagesSet;
    32
    33 /// LanguageMap - Maps from extensions to language names.
    34 class LanguageMap : public llvm::StringMap {
    35 public:
    36
    37 /// GetLanguage - Find the language name corresponding to a given file.
    38 const std::string* GetLanguage(const llvm::sys::Path&) const;
    39 };
    40
    41 /// Edge - Represents an edge of the compilation graph.
    42 class Edge : public llvm::RefCountedBaseVPTR {
    43 public:
    44 Edge(const std::string& T) : ToolName_(T) {}
    45 virtual ~Edge() {}
    46
    47 const std::string& ToolName() const { return ToolName_; }
    48 virtual int Weight(const InputLanguagesSet& InLangs) const = 0;
    49 private:
    50 std::string ToolName_;
    51 };
    52
    53 /// SimpleEdge - An edge that has no properties.
    54 class SimpleEdge : public Edge {
    55 public:
    56 SimpleEdge(const std::string& T) : Edge(T) {}
    57 int Weight(const InputLanguagesSet&) const { return 1; }
    58 };
    59
    60 /// Node - A node (vertex) of the compilation graph.
    61 struct Node {
    62 // A Node holds a list of the outward edges.
    63 typedef llvm::SmallVector, 3> container_type;
    64 typedef container_type::iterator iterator;
    65 typedef container_type::const_iterator const_iterator;
    66
    67 Node() : OwningGraph(0), InEdges(0) {}
    68 Node(CompilationGraph* G) : OwningGraph(G), InEdges(0) {}
    69 Node(CompilationGraph* G, Tool* T) :
    70 OwningGraph(G), ToolPtr(T), InEdges(0) {}
    71
    72 bool HasChildren() const { return !OutEdges.empty(); }
    73 const std::string Name() const
    74 { return ToolPtr ? ToolPtr->Name() : "root"; }
    75
    76 // Iteration.
    77 iterator EdgesBegin() { return OutEdges.begin(); }
    78 const_iterator EdgesBegin() const { return OutEdges.begin(); }
    79 iterator EdgesEnd() { return OutEdges.end(); }
    80 const_iterator EdgesEnd() const { return OutEdges.end(); }
    81
    82 /// AddEdge - Add an outward edge. Takes ownership of the provided
    83 /// Edge object.
    84 void AddEdge(Edge* E);
    85
    86 // Inward edge counter. Used to implement topological sort.
    87 void IncrInEdges() { ++InEdges; }
    88 void DecrInEdges() { --InEdges; }
    89 bool HasNoInEdges() const { return InEdges == 0; }
    90
    91 // Needed to implement NodeChildIterator/GraphTraits
    92 CompilationGraph* OwningGraph;
    93 // The corresponding Tool.
    94 // WARNING: ToolPtr can be NULL (for the root node).
    95 llvm::IntrusiveRefCntPtr ToolPtr;
    96 // Links to children.
    97 container_type OutEdges;
    98 // Inward edge counter. Updated in
    99 // CompilationGraph::insertEdge(). Used for topological sorting.
    100 unsigned InEdges;
    101 };
    102
    103 class NodesIterator;
    104
    105 /// CompilationGraph - The compilation graph itself.
    106 class CompilationGraph {
    107 /// nodes_map_type - The main data structure.
    108 typedef llvm::StringMap nodes_map_type;
    109 /// tools_vector_type, tools_map_type - Data structures used to
    110 /// map from language names to tools. (We can have several tools
    111 /// associated with each language name, hence the need for a
    112 /// vector.)
    113 typedef
    114 llvm::SmallVector, 3> tools_vector_type;
    115 typedef llvm::StringMap tools_map_type;
    116
    117 /// ToolsMap - Map from language names to lists of tool names.
    118 tools_map_type ToolsMap;
    119 /// NodesMap - Map from tool names to Tool objects.
    120 nodes_map_type NodesMap;
    121
    122 public:
    123
    124 typedef nodes_map_type::iterator nodes_iterator;
    125 typedef nodes_map_type::const_iterator const_nodes_iterator;
    126
    127 CompilationGraph();
    128
    129 /// insertNode - Insert a new node into the graph. Takes
    130 /// ownership of the object.
    131 void insertNode(Tool* T);
    132
    133 /// insertEdge - Insert a new edge into the graph. Takes ownership
    134 /// of the Edge object. Returns non-zero value on error.
    135 int insertEdge(const std::string& A, Edge* E);
    136
    137 /// Build - Build target(s) from the input file set. Command-line options
    138 /// are passed implicitly as global variables. Returns non-zero value on
    139 /// error (usually the failed program's exit code).
    140 int Build(llvm::sys::Path const& TempDir, const LanguageMap& LangMap);
    141
    142 /// Check - Check the compilation graph for common errors like cycles,
    143 /// input/output language mismatch and multiple default edges. Prints error
    144 /// messages and in case it finds any errors.
    145 int Check();
    146
    147 /// getNode - Return a reference to the node corresponding to the given tool
    148 /// name. Returns 0 on error.
    149 Node* getNode(const std::string& ToolName);
    150 const Node* getNode(const std::string& ToolName) const;
    151
    152 /// viewGraph - This function is meant for use from the debugger. You can
    153 /// just say 'call G->viewGraph()' and a ghostview window should pop up from
    154 /// the program, displaying the compilation graph. This depends on there
    155 /// being a 'dot' and 'gv' program in your path.
    156 void viewGraph();
    157
    158 /// writeGraph - Write Graphviz .dot source file to the current direcotry.
    159 int writeGraph(const std::string& OutputFilename);
    160
    161 // GraphTraits support.
    162 friend NodesIterator GraphBegin(CompilationGraph*);
    163 friend NodesIterator GraphEnd(CompilationGraph*);
    164
    165 private:
    166 // Helper functions.
    167
    168 /// getToolsVector - Return a reference to the list of tool names
    169 /// corresponding to the given language name. Returns 0 on error.
    170 const tools_vector_type* getToolsVector(const std::string& LangName) const;
    171
    172 /// PassThroughGraph - Pass the input file through the toolchain starting at
    173 /// StartNode.
    174 int PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode,
    175 const InputLanguagesSet& InLangs,
    176 const llvm::sys::Path& TempDir,
    177 const LanguageMap& LangMap) const;
    178
    179 /// FindToolChain - Find head of the toolchain corresponding to
    180 /// the given file.
    181 const Node* FindToolChain(const llvm::sys::Path& In,
    182 const std::string* ForceLanguage,
    183 InputLanguagesSet& InLangs,
    184 const LanguageMap& LangMap) const;
    185
    186 /// BuildInitial - Traverse the initial parts of the toolchains. Returns
    187 /// non-zero value on error.
    188 int BuildInitial(InputLanguagesSet& InLangs,
    189 const llvm::sys::Path& TempDir,
    190 const LanguageMap& LangMap);
    191
    192 /// TopologicalSort - Sort the nodes in topological order. Returns non-zero
    193 /// value on error.
    194 int TopologicalSort(std::vector& Out);
    195 /// TopologicalSortFilterJoinNodes - Call TopologicalSort and filter the
    196 /// resulting list to include only Join nodes. Returns non-zero value on
    197 /// error.
    198 int TopologicalSortFilterJoinNodes(std::vector& Out);
    199
    200 // Functions used to implement Check().
    201
    202 /// CheckLanguageNames - Check that output/input language names match for
    203 /// all nodes. Returns non-zero value on error (number of errors
    204 /// encountered).
    205 int CheckLanguageNames() const;
    206 /// CheckMultipleDefaultEdges - check that there are no multiple default
    207 /// default edges. Returns non-zero value on error (number of errors
    208 /// encountered).
    209 int CheckMultipleDefaultEdges() const;
    210 /// CheckCycles - Check that there are no cycles in the graph. Returns
    211 /// non-zero value on error (number of errors encountered).
    212 int CheckCycles();
    213
    214 };
    215
    216 // GraphTraits support code.
    217
    218 /// NodesIterator - Auxiliary class needed to implement GraphTraits
    219 /// support. Can be generalised to something like value_iterator
    220 /// for map-like containers.
    221 class NodesIterator : public CompilationGraph::nodes_iterator {
    222 typedef CompilationGraph::nodes_iterator super;
    223 typedef NodesIterator ThisType;
    224 typedef Node* pointer;
    225 typedef Node& reference;
    226
    227 public:
    228 NodesIterator(super I) : super(I) {}
    229
    230 inline reference operator*() const {
    231 return super::operator->()->second;
    232 }
    233 inline pointer operator->() const {
    234 return &super::operator->()->second;
    235 }
    236 };
    237
    238 inline NodesIterator GraphBegin(CompilationGraph* G) {
    239 return NodesIterator(G->NodesMap.begin());
    240 }
    241
    242 inline NodesIterator GraphEnd(CompilationGraph* G) {
    243 return NodesIterator(G->NodesMap.end());
    244 }
    245
    246
    247 /// NodeChildIterator - Another auxiliary class needed by GraphTraits.
    248 class NodeChildIterator : public
    249 std::iterator {
    250 typedef NodeChildIterator ThisType;
    251 typedef Node::container_type::iterator iterator;
    252
    253 CompilationGraph* OwningGraph;
    254 iterator EdgeIter;
    255 public:
    256 typedef Node* pointer;
    257 typedef Node& reference;
    258
    259 NodeChildIterator(Node* N, iterator I) :
    260 OwningGraph(N->OwningGraph), EdgeIter(I) {}
    261
    262 const ThisType& operator=(const ThisType& I) {
    263 assert(OwningGraph == I.OwningGraph);
    264 EdgeIter = I.EdgeIter;
    265 return *this;
    266 }
    267
    268 inline bool operator==(const ThisType& I) const {
    269 assert(OwningGraph == I.OwningGraph);
    270 return EdgeIter == I.EdgeIter;
    271 }
    272 inline bool operator!=(const ThisType& I) const {
    273 return !this->operator==(I);
    274 }
    275
    276 inline pointer operator*() const {
    277 return OwningGraph->getNode((*EdgeIter)->ToolName());
    278 }
    279 inline pointer operator->() const {
    280 return this->operator*();
    281 }
    282
    283 ThisType& operator++() { ++EdgeIter; return *this; } // Preincrement
    284 ThisType operator++(int) { // Postincrement
    285 ThisType tmp = *this;
    286 ++*this;
    287 return tmp;
    288 }
    289
    290 inline ThisType& operator--() { --EdgeIter; return *this; } // Predecrement
    291 inline ThisType operator--(int) { // Postdecrement
    292 ThisType tmp = *this;
    293 --*this;
    294 return tmp;
    295 }
    296
    297 };
    298 }
    299
    300 namespace llvm {
    301 template <>
    302 struct GraphTraits {
    303 typedef llvmc::CompilationGraph GraphType;
    304 typedef llvmc::Node NodeType;
    305 typedef llvmc::NodeChildIterator ChildIteratorType;
    306
    307 static NodeType* getEntryNode(GraphType* G) {
    308 return G->getNode("root");
    309 }
    310
    311 static ChildIteratorType child_begin(NodeType* N) {
    312 return ChildIteratorType(N, N->OutEdges.begin());
    313 }
    314 static ChildIteratorType child_end(NodeType* N) {
    315 return ChildIteratorType(N, N->OutEdges.end());
    316 }
    317
    318 typedef llvmc::NodesIterator nodes_iterator;
    319 static nodes_iterator nodes_begin(GraphType *G) {
    320 return GraphBegin(G);
    321 }
    322 static nodes_iterator nodes_end(GraphType *G) {
    323 return GraphEnd(G);
    324 }
    325 };
    326
    327 }
    328
    329 #endif // LLVM_INCLUDE_COMPILER_DRIVER_COMPILATION_GRAPH_H
    +0
    -29
    include/llvm/CompilerDriver/Error.h less more
    None //===--- Error.h - The LLVM Compiler Driver ---------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Error handling.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H
    15
    16 #include "llvm/ADT/StringRef.h"
    17 #include "llvm/Support/raw_ostream.h"
    18
    19 namespace llvmc {
    20
    21 inline void PrintError(llvm::StringRef Err) {
    22 extern const char* ProgramName;
    23 llvm::errs() << ProgramName << ": " << Err << '\n';
    24 }
    25
    26 }
    27
    28 #endif // LLVM_INCLUDE_COMPILER_DRIVER_ERROR_H
    +0
    -21
    include/llvm/CompilerDriver/Main.h less more
    None //===--- Main.h - The LLVM Compiler Driver ----------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Entry point for the driver executable.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H
    15
    16 namespace llvmc {
    17 int Main(int argc, char** argv);
    18 }
    19
    20 #endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_H
    +0
    -23
    include/llvm/CompilerDriver/Main.inc less more
    None //===--- Main.inc - The LLVM Compiler Driver --------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Default main() for the driver executable.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC
    15
    16 #include "llvm/CompilerDriver/Main.h"
    17
    18 int main(int argc, char** argv) {
    19 return llvmc::Main(argc, argv);
    20 }
    21
    22 #endif // LLVM_INCLUDE_COMPILER_DRIVER_MAIN_INC
    +0
    -100
    include/llvm/CompilerDriver/Tool.h less more
    None //===--- Tool.h - The LLVM Compiler Driver ----------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Tool abstract base class - an interface to tool descriptions.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #ifndef LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H
    14 #define LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H
    15
    16 #include "llvm/CompilerDriver/Action.h"
    17
    18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
    19 #include "llvm/ADT/StringSet.h"
    20 #include "llvm/Support/Path.h"
    21
    22 #include
    23 #include
    24 #include
    25
    26 namespace llvmc {
    27
    28 class LanguageMap;
    29 typedef std::vector > ArgsVector;
    30 typedef std::vector PathVector;
    31 typedef std::vector StrVector;
    32 typedef llvm::StringSet<> InputLanguagesSet;
    33
    34 /// Tool - Represents a single tool.
    35 class Tool : public llvm::RefCountedBaseVPTR {
    36 public:
    37
    38 virtual ~Tool() {}
    39
    40 /// GenerateAction - Generate an Action given particular command-line
    41 /// options. Returns non-zero value on error.
    42 virtual int GenerateAction (Action& Out,
    43 const PathVector& inFiles,
    44 const bool HasChildren,
    45 const llvm::sys::Path& TempDir,
    46 const InputLanguagesSet& InLangs,
    47 const LanguageMap& LangMap) const = 0;
    48
    49 /// GenerateAction - Generate an Action given particular command-line
    50 /// options. Returns non-zero value on error.
    51 virtual int GenerateAction (Action& Out,
    52 const llvm::sys::Path& inFile,
    53 const bool HasChildren,
    54 const llvm::sys::Path& TempDir,
    55 const InputLanguagesSet& InLangs,
    56 const LanguageMap& LangMap) const = 0;
    57
    58 virtual const char* Name() const = 0;
    59 virtual const char** InputLanguages() const = 0;
    60 virtual const char** OutputLanguages() const = 0;
    61
    62 virtual bool IsJoin() const = 0;
    63 virtual bool WorksOnEmpty() const = 0;
    64
    65 protected:
    66 /// OutFileName - Generate the output file name.
    67 llvm::sys::Path OutFilename(const llvm::sys::Path& In,
    68 const llvm::sys::Path& TempDir,
    69 bool StopCompilation,
    70 const char* OutputSuffix) const;
    71
    72 StrVector SortArgs(ArgsVector& Args) const;
    73 };
    74
    75 /// JoinTool - A Tool that has an associated input file list.
    76 class JoinTool : public Tool {
    77 public:
    78 void AddToJoinList(const llvm::sys::Path& P) { JoinList_.push_back(P); }
    79 void ClearJoinList() { JoinList_.clear(); }
    80 bool JoinListEmpty() const { return JoinList_.empty(); }
    81
    82 int GenerateAction(Action& Out,
    83 const bool HasChildren,
    84 const llvm::sys::Path& TempDir,
    85 const InputLanguagesSet& InLangs,
    86 const LanguageMap& LangMap) const {
    87 return GenerateAction(Out, JoinList_, HasChildren, TempDir, InLangs,
    88 LangMap);
    89 }
    90 // We shouldn't shadow base class's version of GenerateAction.
    91 using Tool::GenerateAction;
    92
    93 private:
    94 PathVector JoinList_;
    95 };
    96
    97 }
    98
    99 #endif // LLVM_INCLUDE_COMPILER_DRIVER_TOOL_H
    +0
    -134
    lib/CompilerDriver/Action.cpp less more
    None //===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Action class - implementation and auxiliary functions.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #include "llvm/CompilerDriver/Action.h"
    14 #include "llvm/CompilerDriver/BuiltinOptions.h"
    15 #include "llvm/CompilerDriver/Error.h"
    16 #include "llvm/CompilerDriver/Main.h"
    17
    18 #include "llvm/Support/raw_ostream.h"
    19 #include "llvm/Support/SystemUtils.h"
    20 #include "llvm/Support/Program.h"
    21 #include "llvm/Support/TimeValue.h"
    22
    23 #include
    24 #include
    25
    26 using namespace llvm;
    27 using namespace llvmc;
    28
    29 namespace llvmc {
    30
    31 extern const char* ProgramName;
    32
    33 }
    34
    35 namespace {
    36
    37 void PrintString (const std::string& str) {
    38 errs() << str << ' ';
    39 }
    40
    41 void PrintCommand (const std::string& Cmd, const StrVector& Args) {
    42 errs() << Cmd << ' ';
    43 std::for_each(Args.begin(), Args.end(), &PrintString);
    44 errs() << '\n';
    45 }
    46
    47 bool IsSegmentationFault (int returnCode) {
    48 #ifdef LLVM_ON_WIN32
    49 return (returnCode >= 0xc0000000UL)
    50 #else
    51 return (returnCode < 0);
    52 #endif
    53 }
    54
    55 int ExecuteProgram (const std::string& name, const StrVector& args) {
    56 sys::Path prog(name);
    57
    58 if (sys::path::is_relative(prog.str())) {
    59 prog = PrependMainExecutablePath(name, ProgramName,
    60 (void *)(intptr_t)&Main);
    61
    62 if (!prog.canExecute()) {
    63 prog = sys::Program::FindProgramByName(name);
    64 if (prog.isEmpty()) {
    65 PrintError("Can't find program '" + name + "'");
    66 return -1;
    67 }
    68 }
    69 }
    70 if (!prog.canExecute()) {
    71 PrintError("Program '" + name + "' is not executable.");
    72 return -1;
    73 }
    74
    75 // Build the command line vector and the redirects array.
    76 const sys::Path* redirects[3] = {0,0,0};
    77 sys::Path stdout_redirect;
    78
    79 std::vector argv;
    80 argv.reserve((args.size()+2));
    81 argv.push_back(name.c_str());
    82
    83 for (StrVector::const_iterator B = args.begin(), E = args.end();
    84 B!=E; ++B) {
    85 if (*B == ">") {
    86 ++B;
    87 stdout_redirect.set(*B);
    88 redirects[1] = &stdout_redirect;
    89 }
    90 else {
    91 argv.push_back((*B).c_str());
    92 }
    93 }
    94 argv.push_back(0); // null terminate list.
    95
    96 // Invoke the program.
    97 int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
    98
    99 if (IsSegmentationFault(ret)) {
    100 errs() << "Segmentation fault: ";
    101 PrintCommand(name, args);
    102 }
    103
    104 return ret;
    105 }
    106 }
    107
    108 namespace llvmc {
    109 void AppendToGlobalTimeLog (const std::string& cmd, double time);
    110 }
    111
    112 int llvmc::Action::Execute () const {
    113 if (DryRun || VerboseMode)
    114 PrintCommand(Command_, Args_);
    115
    116 if (!DryRun) {
    117 if (Time) {
    118 sys::TimeValue now = sys::TimeValue::now();
    119 int ret = ExecuteProgram(Command_, Args_);
    120 sys::TimeValue now2 = sys::TimeValue::now();
    121 now2 -= now;
    122 double elapsed = now2.seconds() + now2.microseconds() / 1000000.0;
    123 AppendToGlobalTimeLog(Command_, elapsed);
    124
    125 return ret;
    126 }
    127 else {
    128 return ExecuteProgram(Command_, Args_);
    129 }
    130 }
    131
    132 return 0;
    133 }
    +0
    -61
    lib/CompilerDriver/BuiltinOptions.cpp less more
    None //===--- BuiltinOptions.cpp - The LLVM Compiler Driver ----------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Definitions of all global command-line option variables.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #include "llvm/CompilerDriver/BuiltinOptions.h"
    14
    15 #ifdef ENABLE_LLVMC_DYNAMIC_PLUGINS
    16 #include "llvm/Support/PluginLoader.h"
    17 #endif
    18
    19 namespace cl = llvm::cl;
    20
    21 namespace llvmc {
    22
    23 cl::list InputFilenames(cl::Positional, cl::desc(""),
    24 cl::ZeroOrMore);
    25 cl::opt OutputFilename("o", cl::desc("Output file name"),
    26 cl::value_desc("file"), cl::Prefix);
    27 cl::opt TempDirname("temp-dir", cl::desc("Temp dir name"),
    28 cl::value_desc(""), cl::Prefix);
    29 cl::list Languages("x",
    30 cl::desc("Specify the language of the following input files"),
    31 cl::ZeroOrMore);
    32
    33 cl::opt DryRun("dry-run",
    34 cl::desc("Only pretend to run commands"));
    35 cl::opt Time("time", cl::desc("Time individual commands"));
    36 cl::opt VerboseMode("v",
    37 cl::desc("Enable verbose mode"));
    38
    39 cl::opt CheckGraph("check-graph",
    40 cl::desc("Check the compilation graph for errors"),
    41 cl::Hidden);
    42 cl::opt WriteGraph("write-graph",
    43 cl::desc("Write compilation-graph.dot file"),
    44 cl::Hidden);
    45 cl::opt ViewGraph("view-graph",
    46 cl::desc("Show compilation graph in GhostView"),
    47 cl::Hidden);
    48
    49 cl::opt SaveTemps
    50 ("save-temps", cl::desc("Keep temporary files"),
    51 cl::init(SaveTempsEnum::Unset),
    52 cl::values(clEnumValN(SaveTempsEnum::Obj, "obj",
    53 "Save files in the directory specified with -o"),
    54 clEnumValN(SaveTempsEnum::Cwd, "cwd",
    55 "Use current working directory"),
    56 clEnumValN(SaveTempsEnum::Obj, "", "Same as 'cwd'"),
    57 clEnumValEnd),
    58 cl::ValueOptional);
    59
    60 } // End namespace llvmc.
    +0
    -12
    lib/CompilerDriver/CMakeLists.txt less more
    None set(LLVM_LINK_COMPONENTS support)
    1
    2 # We don't want this library to appear in `llvm-config --libs` output,
    3 # so its name doesn't start with "LLVM".
    4
    5 add_llvm_library(CompilerDriver
    6 Action.cpp
    7 BuiltinOptions.cpp
    8 CompilationGraph.cpp
    9 Main.cpp
    10 Tool.cpp
    11 )
    +0
    -655
    lib/CompilerDriver/CompilationGraph.cpp less more
    None //===--- CompilationGraph.cpp - The LLVM Compiler Driver --------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Compilation graph - implementation.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #include "llvm/CompilerDriver/BuiltinOptions.h"
    14 #include "llvm/CompilerDriver/CompilationGraph.h"
    15 #include "llvm/CompilerDriver/Error.h"
    16
    17 #include "llvm/ADT/STLExtras.h"
    18 #include "llvm/Support/DOTGraphTraits.h"
    19 #include "llvm/Support/GraphWriter.h"
    20 #include "llvm/Support/raw_ostream.h"
    21
    22 #include
    23 #include
    24 #include
    25 #include
    26 #include
    27
    28 using namespace llvm;
    29 using namespace llvmc;
    30
    31 namespace llvmc {
    32
    33 const std::string* LanguageMap::GetLanguage(const sys::Path& File) const {
    34 // Remove the '.'.
    35 StringRef suf = sys::path::extension(File.str()).substr(1);
    36 LanguageMap::const_iterator Lang =
    37 this->find(suf.empty() ? "*empty*" : suf);
    38 if (Lang == this->end()) {
    39 PrintError("File '" + File.str() + "' has unknown suffix '"
    40 + suf.str() + '\'');
    41 return 0;
    42 }
    43 return &Lang->second;
    44 }
    45 }
    46
    47 namespace {
    48
    49 /// ChooseEdge - Return the edge with the maximum weight. Returns 0 on error.
    50 template
    51 const Edge* ChooseEdge(const C& EdgesContainer,
    52 const InputLanguagesSet& InLangs,
    53 const std::string& NodeName = "root") {
    54 const Edge* MaxEdge = 0;
    55 int MaxWeight = 0;
    56 bool SingleMax = true;
    57
    58 // TODO: fix calculation of SingleMax.
    59 for (typename C::const_iterator B = EdgesContainer.begin(),
    60 E = EdgesContainer.end(); B != E; ++B) {
    61 const Edge* e = B->getPtr();
    62 int EW = e->Weight(InLangs);
    63 if (EW < 0) {
    64 // (error) invocation in TableGen -> we don't need to print an error
    65 // message.
    66 return 0;
    67 }
    68 if (EW > MaxWeight) {
    69 MaxEdge = e;
    70 MaxWeight = EW;
    71 SingleMax = true;
    72 } else if (EW == MaxWeight) {
    73 SingleMax = false;
    74 }
    75 }
    76
    77 if (!SingleMax) {
    78 PrintError("Node " + NodeName + ": multiple maximal outward edges found!"
    79 " Most probably a specification error.");
    80 return 0;
    81 }
    82 if (!MaxEdge) {
    83 PrintError("Node " + NodeName + ": no maximal outward edge found!"
    84 " Most probably a specification error.");
    85 return 0;
    86 }
    87 return MaxEdge;
    88 }
    89
    90 }
    91
    92 void Node::AddEdge(Edge* Edg) {
    93 // If there already was an edge between two nodes, modify it instead
    94 // of adding a new edge.
    95 const std::string& ToolName = Edg->ToolName();
    96 for (container_type::iterator B = OutEdges.begin(), E = OutEdges.end();
    97 B != E; ++B) {
    98 if ((*B)->ToolName() == ToolName) {
    99 llvm::IntrusiveRefCntPtr(Edg).swap(*B);
    100 return;
    101 }
    102 }
    103 OutEdges.push_back(llvm::IntrusiveRefCntPtr(Edg));
    104 }
    105
    106 CompilationGraph::CompilationGraph() {
    107 NodesMap["root"] = Node(this);
    108 }
    109
    110 Node* CompilationGraph::getNode(const std::string& ToolName) {
    111 nodes_map_type::iterator I = NodesMap.find(ToolName);
    112 if (I == NodesMap.end()) {
    113 PrintError("Node " + ToolName + " is not in the graph");
    114 return 0;
    115 }
    116 return &I->second;
    117 }
    118
    119 const Node* CompilationGraph::getNode(const std::string& ToolName) const {
    120 nodes_map_type::const_iterator I = NodesMap.find(ToolName);
    121 if (I == NodesMap.end()) {
    122 PrintError("Node " + ToolName + " is not in the graph!");
    123 return 0;
    124 }
    125 return &I->second;
    126 }
    127
    128 // Find the tools list corresponding to the given language name.
    129 const CompilationGraph::tools_vector_type*
    130 CompilationGraph::getToolsVector(const std::string& LangName) const
    131 {
    132 tools_map_type::const_iterator I = ToolsMap.find(LangName);
    133 if (I == ToolsMap.end()) {
    134 PrintError("No tool corresponding to the language " + LangName + " found");
    135 return 0;
    136 }
    137 return &I->second;
    138 }
    139
    140 void CompilationGraph::insertNode(Tool* V) {
    141 if (NodesMap.count(V->Name()) == 0)
    142 NodesMap[V->Name()] = Node(this, V);
    143 }
    144
    145 int CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
    146 Node* B = getNode(Edg->ToolName());
    147 if (B == 0)
    148 return 1;
    149
    150 if (A == "root") {
    151 const char** InLangs = B->ToolPtr->InputLanguages();
    152 for (;*InLangs; ++InLangs)
    153 ToolsMap[*InLangs].push_back(IntrusiveRefCntPtr(Edg));
    154 NodesMap["root"].AddEdge(Edg);
    155 }
    156 else {
    157 Node* N = getNode(A);
    158 if (N == 0)
    159 return 1;
    160
    161 N->AddEdge(Edg);
    162 }
    163 // Increase the inward edge counter.
    164 B->IncrInEdges();
    165
    166 return 0;
    167 }
    168
    169 // Pass input file through the chain until we bump into a Join node or
    170 // a node that says that it is the last.
    171 int CompilationGraph::PassThroughGraph (const sys::Path& InFile,
    172 const Node* StartNode,
    173 const InputLanguagesSet& InLangs,
    174 const sys::Path& TempDir,
    175 const LanguageMap& LangMap) const {
    176 sys::Path In = InFile;
    177 const Node* CurNode = StartNode;
    178
    179 while(true) {
    180 Tool* CurTool = CurNode->ToolPtr.getPtr();
    181
    182 if (CurTool->IsJoin()) {
    183 JoinTool& JT = static_cast(*CurTool);
    184 JT.AddToJoinList(In);
    185 break;
    186 }
    187
    188 Action CurAction;
    189 if (int ret = CurTool->GenerateAction(CurAction, In, CurNode->HasChildren(),
    190 TempDir, InLangs, LangMap)) {
    191 return ret;
    192 }
    193
    194 if (int ret = CurAction.Execute())
    195 return ret;
    196
    197 if (CurAction.StopCompilation())
    198 return 0;
    199
    200 const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name());
    201 if (Edg == 0)
    202 return 1;
    203
    204 CurNode = getNode(Edg->ToolName());
    205 if (CurNode == 0)
    206 return 1;
    207
    208 In = CurAction.OutFile();
    209 }
    210
    211 return 0;
    212 }
    213
    214 // Find the head of the toolchain corresponding to the given file.
    215 // Also, insert an input language into InLangs.
    216 const Node* CompilationGraph::
    217 FindToolChain(const sys::Path& In, const std::string* ForceLanguage,
    218 InputLanguagesSet& InLangs, const LanguageMap& LangMap) const {
    219
    220 // Determine the input language.
    221 const std::string* InLang = (ForceLanguage ? ForceLanguage
    222 : LangMap.GetLanguage(In));
    223 if (InLang == 0)
    224 return 0;
    225 const std::string& InLanguage = *InLang;
    226
    227 // Add the current input language to the input language set.
    228 InLangs.insert(InLanguage);
    229
    230 // Find the toolchain for the input language.
    231 const tools_vector_type* pTV = getToolsVector(InLanguage);
    232 if (pTV == 0)
    233 return 0;
    234
    235 const tools_vector_type& TV = *pTV;
    236 if (TV.empty()) {
    237 PrintError("No toolchain corresponding to language "
    238 + InLanguage + " found");
    239 return 0;
    240 }
    241
    242 const Edge* Edg = ChooseEdge(TV, InLangs);
    243 if (Edg == 0)
    244 return 0;
    245
    246 return getNode(Edg->ToolName());
    247 }
    248
    249 // Helper function used by Build().
    250 // Traverses initial portions of the toolchains (up to the first Join node).
    251 // This function is also responsible for handling the -x option.
    252 int CompilationGraph::BuildInitial (InputLanguagesSet& InLangs,
    253 const sys::Path& TempDir,
    254 const LanguageMap& LangMap) {
    255 // This is related to -x option handling.
    256 cl::list::const_iterator xIter = Languages.begin(),
    257 xBegin = xIter, xEnd = Languages.end();
    258 bool xEmpty = true;
    259 const std::string* xLanguage = 0;
    260 unsigned xPos = 0, xPosNext = 0, filePos = 0;
    261
    262 if (xIter != xEnd) {
    263 xEmpty = false;
    264 xPos = Languages.getPosition(xIter - xBegin);
    265 cl::list::const_iterator xNext = llvm::next(xIter);
    266 xPosNext = (xNext == xEnd) ? std::numeric_limits::max()
    267 : Languages.getPosition(xNext - xBegin);
    268 xLanguage = (*xIter == "none") ? 0 : &(*xIter);
    269 }
    270
    271 // For each input file:
    272 for (cl::list::const_iterator B = InputFilenames.begin(),
    273 CB = B, E = InputFilenames.end(); B != E; ++B) {
    274 sys::Path In = sys::Path(*B);
    275
    276 // Code for handling the -x option.
    277 // Output: std::string* xLanguage (can be NULL).
    278 if (!xEmpty) {
    279 filePos = InputFilenames.getPosition(B - CB);
    280
    281 if (xPos < filePos) {
    282 if (filePos < xPosNext) {
    283 xLanguage = (*xIter == "none") ? 0 : &(*xIter);
    284 }
    285 else { // filePos >= xPosNext
    286 // Skip xIters while filePos > xPosNext
    287 while (filePos > xPosNext) {
    288 ++xIter;
    289 xPos = xPosNext;
    290
    291 cl::list::const_iterator xNext = llvm::next(xIter);
    292 if (xNext == xEnd)
    293 xPosNext = std::numeric_limits::max();
    294 else
    295 xPosNext = Languages.getPosition(xNext - xBegin);
    296 xLanguage = (*xIter == "none") ? 0 : &(*xIter);
    297 }
    298 }
    299 }
    300 }
    301
    302 // Find the toolchain corresponding to this file.
    303 const Node* N = FindToolChain(In, xLanguage, InLangs, LangMap);
    304 if (N == 0)
    305 return 1;
    306 // Pass file through the chain starting at head.
    307 if (int ret = PassThroughGraph(In, N, InLangs, TempDir, LangMap))
    308 return ret;
    309 }
    310
    311 return 0;
    312 }
    313
    314 // Sort the nodes in topological order.
    315 int CompilationGraph::TopologicalSort(std::vector& Out) {
    316 std::queue Q;
    317
    318 Node* Root = getNode("root");
    319 if (Root == 0)
    320 return 1;
    321
    322 Q.push(Root);
    323
    324 while (!Q.empty()) {
    325 const Node* A = Q.front();
    326 Q.pop();
    327 Out.push_back(A);
    328 for (Node::const_iterator EB = A->EdgesBegin(), EE = A->EdgesEnd();
    329 EB != EE; ++EB) {
    330 Node* B = getNode((*EB)->ToolName());
    331 if (B == 0)
    332 return 1;
    333
    334 B->DecrInEdges();
    335 if (B->HasNoInEdges())
    336 Q.push(B);
    337 }
    338 }
    339
    340 return 0;
    341 }
    342
    343 namespace {
    344 bool NotJoinNode(const Node* N) {
    345 return N->ToolPtr ? !N->ToolPtr->IsJoin() : true;
    346 }
    347 }
    348
    349 // Call TopologicalSort and filter the resulting list to include
    350 // only Join nodes.
    351 int CompilationGraph::
    352 TopologicalSortFilterJoinNodes(std::vector& Out) {
    353 std::vector TopSorted;
    354 if (int ret = TopologicalSort(TopSorted))
    355 return ret;
    356 std::remove_copy_if(TopSorted.begin(), TopSorted.end(),
    357 std::back_inserter(Out), NotJoinNode);
    358
    359 return 0;
    360 }
    361
    362 int CompilationGraph::Build (const sys::Path& TempDir,
    363 const LanguageMap& LangMap) {
    364 InputLanguagesSet InLangs;
    365 bool WasSomeActionGenerated = !InputFilenames.empty();
    366
    367 // Traverse initial parts of the toolchains and fill in InLangs.
    368 if (int ret = BuildInitial(InLangs, TempDir, LangMap))
    369 return ret;
    370
    371 std::vector JTV;
    372 if (int ret = TopologicalSortFilterJoinNodes(JTV))
    373 return ret;
    374
    375 // For all join nodes in topological order:
    376 for (std::vector::iterator B = JTV.begin(), E = JTV.end();
    377 B != E; ++B) {
    378
    379 const Node* CurNode = *B;
    380 JoinTool* JT = &static_cast(*CurNode->ToolPtr.getPtr());
    381
    382 // Are there any files in the join list?
    383 if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty()))
    384 continue;
    385
    386 WasSomeActionGenerated = true;
    387 Action CurAction;
    388 if (int ret = JT->GenerateAction(CurAction, CurNode->HasChildren(),
    389 TempDir, InLangs, LangMap)) {
    390 return ret;
    391 }
    392
    393 if (int ret = CurAction.Execute())
    394 return ret;
    395
    396 if (CurAction.StopCompilation())
    397 return 0;
    398
    399 const Edge* Edg = ChooseEdge(CurNode->OutEdges, InLangs, CurNode->Name());
    400 if (Edg == 0)
    401 return 1;
    402
    403 const Node* NextNode = getNode(Edg->ToolName());
    404 if (NextNode == 0)
    405 return 1;
    406
    407 if (int ret = PassThroughGraph(sys::Path(CurAction.OutFile()), NextNode,
    408 InLangs, TempDir, LangMap)) {
    409 return ret;
    410 }
    411 }
    412
    413 if (!WasSomeActionGenerated) {
    414 PrintError("no input files");
    415 return 1;
    416 }
    417
    418 return 0;
    419 }
    420
    421 int CompilationGraph::CheckLanguageNames() const {
    422 int ret = 0;
    423
    424 // Check that names for output and input languages on all edges do match.
    425 for (const_nodes_iterator B = this->NodesMap.begin(),
    426 E = this->NodesMap.end(); B != E; ++B) {
    427
    428 const Node & N1 = B->second;
    429 if (N1.ToolPtr) {
    430 for (Node::const_iterator EB = N1.EdgesBegin(), EE = N1.EdgesEnd();
    431 EB != EE; ++EB) {
    432 const Node* N2 = this->getNode((*EB)->ToolName());
    433 if (N2 == 0)
    434 return 1;
    435
    436 if (!N2->ToolPtr) {
    437 ++ret;
    438 errs() << "Error: there is an edge from '" << N1.ToolPtr->Name()
    439 << "' back to the root!\n\n";
    440 continue;
    441 }
    442
    443 const char** OutLangs = N1.ToolPtr->OutputLanguages();
    444 const char** InLangs = N2->ToolPtr->InputLanguages();
    445 bool eq = false;
    446 const char* OutLang = 0;
    447 for (;*OutLangs; ++OutLangs) {
    448 OutLang = *OutLangs;
    449 for (;*InLangs; ++InLangs) {
    450 if (std::strcmp(OutLang, *InLangs) == 0) {
    451 eq = true;
    452 break;
    453 }
    454 }
    455 }
    456
    457 if (!eq) {
    458 ++ret;
    459 errs() << "Error: Output->input language mismatch in the edge '"
    460 << N1.ToolPtr->Name() << "' -> '" << N2->ToolPtr->Name()
    461 << "'!\n"
    462 << "Expected one of { ";
    463
    464 InLangs = N2->ToolPtr->InputLanguages();
    465 for (;*InLangs; ++InLangs) {
    466 errs() << '\'' << *InLangs << (*(InLangs+1) ? "', " : "'");
    467 }
    468
    469 errs() << " }, but got '" << OutLang << "'!\n\n";
    470 }
    471
    472 }
    473 }
    474 }
    475
    476 return ret;
    477 }
    478
    479 int CompilationGraph::CheckMultipleDefaultEdges() const {
    480 int ret = 0;
    481 InputLanguagesSet Dummy;
    482
    483 // For all nodes, just iterate over the outgoing edges and check if there is
    484 // more than one edge with maximum weight.
    485 for (const_nodes_iterator B = this->NodesMap.begin(),
    486 E = this->NodesMap.end(); B != E; ++B) {
    487 const Node& N = B->second;
    488 int MaxWeight = -1024;
    489
    490 // Ignore the root node.
    491 if (!N.ToolPtr)
    492 continue;
    493
    494 for (Node::const_iterator EB = N.EdgesBegin(), EE = N.EdgesEnd();
    495 EB != EE; ++EB) {
    496 int EdgeWeight = (*EB)->Weight(Dummy);
    497 if (EdgeWeight > MaxWeight) {
    498 MaxWeight = EdgeWeight;
    499 }
    500 else if (EdgeWeight == MaxWeight) {
    501 ++ret;
    502 errs() << "Error: there are multiple maximal edges stemming from the '"
    503 << N.ToolPtr->Name() << "' node!\n\n";
    504 break;
    505 }
    506 }
    507 }
    508
    509 return ret;
    510 }
    511
    512 int CompilationGraph::CheckCycles() {
    513 unsigned deleted = 0;
    514 std::queue Q;
    515
    516 Node* Root = getNode("root");
    517 if (Root == 0)
    518 return 1;
    519
    520 Q.push(Root);
    521
    522 // Try to delete all nodes that have no ingoing edges, starting from the
    523 // root. If there are any nodes left after this operation, then we have a
    524 // cycle. This relies on '--check-graph' not performing the topological sort.
    525 while (!Q.empty()) {
    526 Node* A = Q.front();
    527 Q.pop();
    528 ++deleted;
    529
    530 for (Node::iterator EB = A->EdgesBegin(), EE = A->EdgesEnd();
    531 EB != EE; ++EB) {
    532 Node* B = getNode((*EB)->ToolName());
    533 if (B == 0)
    534 return 1;
    535
    536 B->DecrInEdges();
    537 if (B->HasNoInEdges())
    538 Q.push(B);
    539 }
    540 }
    541
    542 if (deleted != NodesMap.size()) {
    543 errs() << "Error: there are cycles in the compilation graph!\n"
    544 << "Try inspecting the diagram produced by "
    545 << "'llvmc --view-graph'.\n\n";
    546 return 1;
    547 }
    548
    549 return 0;
    550 }
    551
    552 int CompilationGraph::Check () {
    553 // We try to catch as many errors as we can in one go.
    554 int errs = 0;
    555 int ret = 0;
    556
    557 // Check that output/input language names match.
    558 ret = this->CheckLanguageNames();
    559 if (ret < 0)
    560 return 1;
    561 errs += ret;
    562
    563 // Check for multiple default edges.
    564 ret = this->CheckMultipleDefaultEdges();
    565 if (ret < 0)
    566 return 1;
    567 errs += ret;
    568
    569 // Check for cycles.
    570 ret = this->CheckCycles();
    571 if (ret < 0)
    572 return 1;
    573 errs += ret;
    574
    575 return errs;
    576 }
    577
    578 // Code related to graph visualization.
    579
    580 namespace {
    581
    582 std::string SquashStrArray (const char** StrArr) {
    583 std::string ret;
    584
    585 for (; *StrArr; ++StrArr) {
    586 if (*(StrArr + 1)) {
    587 ret += *StrArr;
    588 ret += ", ";
    589 }
    590 else {
    591 ret += *StrArr;
    592 }
    593 }
    594
    595 return ret;
    596 }
    597
    598 } // End anonymous namespace.
    599
    600 namespace llvm {
    601 template <>
    602 struct DOTGraphTraits
    603 : public DefaultDOTGraphTraits
    604 {
    605 DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
    606
    607 template
    608 static std::string getNodeLabel(const Node* N, const GraphType&)
    609 {
    610 if (N->ToolPtr)
    611 if (N->ToolPtr->IsJoin())
    612 return N->Name() + "\n (join" +
    613 (N->HasChildren() ? ")"
    614 : std::string(": ") +
    615 SquashStrArray(N->ToolPtr->OutputLanguages()) + ')');
    616 else
    617 return N->Name();
    618 else
    619 return "root";
    620 }
    621
    622 template
    623 static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) {
    624 if (N->ToolPtr) {
    625 return SquashStrArray(N->ToolPtr->OutputLanguages());
    626 }
    627 else {
    628 return SquashStrArray(I->ToolPtr->InputLanguages());
    629 }
    630 }
    631 };
    632
    633 } // End namespace llvm
    634
    635 int CompilationGraph::writeGraph(const std::string& OutputFilename) {
    636 std::string ErrorInfo;
    637 raw_fd_ostream O(OutputFilename.c_str(), ErrorInfo);
    638
    639 if (ErrorInfo.empty()) {
    640 errs() << "Writing '"<< OutputFilename << "' file...";
    641 llvm::WriteGraph(O, this);
    642 errs() << "done.\n";
    643 }
    644 else {
    645 PrintError("Error opening file '" + OutputFilename + "' for writing!");
    646 return 1;
    647 }
    648
    649 return 0;
    650 }
    651
    652 void CompilationGraph::viewGraph() {
    653 llvm::ViewGraph(this, "compilation-graph");
    654 }
    +0
    -146
    lib/CompilerDriver/Main.cpp less more
    None //===--- Main.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // llvmc::Main function - driver entry point.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #include "llvm/CompilerDriver/AutoGenerated.h"
    14 #include "llvm/CompilerDriver/BuiltinOptions.h"
    15 #include "llvm/CompilerDriver/CompilationGraph.h"
    16 #include "llvm/CompilerDriver/Error.h"
    17
    18 #include "llvm/Support/FileSystem.h"
    19 #include "llvm/Support/raw_ostream.h"
    20 #include "llvm/Support/Path.h"
    21
    22 #include
    23 #include
    24
    25 namespace cl = llvm::cl;
    26 namespace sys = llvm::sys;
    27 using namespace llvmc;
    28
    29 namespace {
    30
    31 std::stringstream* GlobalTimeLog;
    32
    33 /// GetTempDir - Get the temporary directory location. Returns non-zero value
    34 /// on error.
    35 int GetTempDir(sys::Path& tempDir) {
    36 // The --temp-dir option.
    37 if (!TempDirname.empty()) {
    38 tempDir = TempDirname;
    39 }
    40 // GCC 4.5-style -save-temps handling.
    41 else if (SaveTemps == SaveTempsEnum::Unset) {
    42 tempDir = sys::Path::GetTemporaryDirectory();
    43 return 0;
    44 }
    45 else if (SaveTemps == SaveTempsEnum::Obj && !OutputFilename.empty()) {
    46 tempDir = sys::path::parent_path(OutputFilename);
    47 }
    48 else {
    49 // SaveTemps == Cwd --> use current dir (leave tempDir empty).
    50 return 0;
    51 }
    52
    53 bool Exists;
    54 if (llvm::sys::fs::exists(tempDir.str(), Exists) || !Exists) {
    55 std::string ErrMsg;
    56 if (tempDir.createDirectoryOnDisk(true, &ErrMsg)) {
    57 PrintError(ErrMsg);
    58 return 1;
    59 }
    60 }
    61
    62 return 0;
    63 }
    64
    65 /// BuildTargets - A small wrapper for CompilationGraph::Build. Returns
    66 /// non-zero value in case of error.
    67 int BuildTargets(CompilationGraph& graph, const LanguageMap& langMap) {
    68 int ret;
    69 sys::Path tempDir;
    70 bool toDelete = (SaveTemps == SaveTempsEnum::Unset);
    71
    72 if (int ret = GetTempDir(tempDir))
    73 return ret;
    74
    75 ret = graph.Build(tempDir, langMap);
    76
    77 if (toDelete)
    78 tempDir.eraseFromDisk(true);
    79
    80 return ret;
    81 }
    82 }
    83
    84 namespace llvmc {
    85
    86 // Used to implement -time option. External linkage is intentional.
    87 void AppendToGlobalTimeLog(const std::string& cmd, double time) {
    88 *GlobalTimeLog << "# " << cmd << ' ' << time << '\n';
    89 }
    90
    91 // Sometimes user code wants to access the argv[0] value.
    92 const char* ProgramName;
    93
    94 int Main(int argc, char** argv) {
    95 int ret = 0;
    96 LanguageMap langMap;
    97 CompilationGraph graph;
    98
    99 ProgramName = argv[0];
    100
    101 cl::ParseCommandLineOptions
    102 (argc, argv,
    103 /* Overview = */ "LLVM Compiler Driver (Work In Progress)",
    104 /* ReadResponseFiles = */ false);
    105
    106 if (int ret = autogenerated::RunInitialization(langMap, graph))
    107 return ret;
    108
    109 if (CheckGraph) {
    110 ret = graph.Check();
    111 if (!ret)
    112 llvm::errs() << "check-graph: no errors found.\n";
    113
    114 return ret;
    115 }
    116
    117 if (ViewGraph) {
    118 graph.viewGraph();
    119 if (!WriteGraph)
    120 return 0;
    121 }
    122
    123 if (WriteGraph) {
    124 const std::string& Out = (OutputFilename.empty()
    125 ? std::string("compilation-graph.dot")
    126 : OutputFilename);
    127 return graph.writeGraph(Out);
    128 }
    129
    130 if (Time) {
    131 GlobalTimeLog = new std::stringstream;
    132 GlobalTimeLog->precision(2);
    133 }
    134
    135 ret = BuildTargets(graph, langMap);
    136
    137 if (Time) {
    138 llvm::errs() << GlobalTimeLog->str();
    139 delete GlobalTimeLog;
    140 }
    141
    142 return ret;
    143 }
    144
    145 } // end namespace llvmc
    +0
    -20
    lib/CompilerDriver/Makefile less more
    None ##===- lib/CompilerDriver/Makefile -------------------------*- Makefile -*-===##
    1 #
    2 # The LLVM Compiler Infrastructure
    3 #
    4 # This file is distributed under the University of Illinois Open
    5 # Source License. See LICENSE.TXT for details.
    6 #
    7 ##===----------------------------------------------------------------------===##
    8
    9 LEVEL = ../..
    10
    11 # We don't want this library to appear in `llvm-config --libs` output, so its
    12 # name doesn't start with "LLVM" and NO_LLVM_CONFIG is set.
    13
    14 LIBRARYNAME = CompilerDriver
    15 LINK_COMPONENTS = support
    16 NO_LLVM_CONFIG = 1
    17
    18
    19 include $(LEVEL)/Makefile.common
    +0
    -95
    lib/CompilerDriver/Tool.cpp less more
    None //===--- Tool.cpp - The LLVM Compiler Driver --------------------*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // Tool base class - implementation details.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #include "llvm/CompilerDriver/BuiltinOptions.h"
    14 #include "llvm/CompilerDriver/Tool.h"
    15
    16 #include "llvm/ADT/StringExtras.h"
    17 #include "llvm/Support/Path.h"
    18
    19 #include
    20
    21 using namespace llvm;
    22 using namespace llvmc;
    23
    24 namespace {
    25 sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
    26 const std::string& Suffix) {
    27 sys::Path Out;
    28
    29 // Make sure we don't end up with path names like '/file.o' if the
    30 // TempDir is empty.
    31 if (TempDir.empty()) {
    32 Out.set(BaseName);
    33 }
    34 else {
    35 Out = TempDir;
    36 Out.appendComponent(BaseName);
    37 }
    38 Out.appendSuffix(Suffix);
    39 // NOTE: makeUnique always *creates* a unique temporary file,
    40 // which is good, since there will be no races. However, some
    41 // tools do not like it when the output file already exists, so
    42 // they need to be placated with -f or something like that.
    43 Out.makeUnique(true, NULL);
    44 return Out;
    45 }
    46 }
    47
    48 sys::Path Tool::OutFilename(const sys::Path& In,
    49 const sys::Path& TempDir,
    50 bool StopCompilation,
    51 const char* OutputSuffix) const {
    52 sys::Path Out;
    53
    54 if (StopCompilation) {
    55 if (!OutputFilename.empty()) {
    56 Out.set(OutputFilename);
    57 }
    58 else if (IsJoin()) {
    59 Out.set("a");
    60 Out.appendSuffix(OutputSuffix);
    61 }
    62 else {
    63 Out.set(sys::path::stem(In.str()));
    64 Out.appendSuffix(OutputSuffix);
    65 }
    66 }
    67 else {
    68 if (IsJoin())
    69 Out = MakeTempFile(TempDir, "tmp", OutputSuffix);
    70 else
    71 Out = MakeTempFile(TempDir, sys::path::stem(In.str()), OutputSuffix);
    72 }
    73 return Out;
    74 }
    75
    76 namespace {
    77 template
    78 bool CompareFirst (std::pair p1, std::pair p2) {
    79 return std::less()(p1.first, p2.first);
    80 }
    81 }
    82
    83 StrVector Tool::SortArgs(ArgsVector& Args) const {
    84 StrVector Out;
    85
    86 // HACK: this won't be needed when we'll migrate away from CommandLine.
    87 std::stable_sort(Args.begin(), Args.end(),
    88 &CompareFirst);
    89 for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B) {
    90 Out.push_back(B->second);
    91 }
    92
    93 return Out;
    94 }
    1010 include $(LEVEL)/Makefile.config
    1111
    1212 PARALLEL_DIRS := VMCore AsmParser Bitcode Archive Analysis Transforms CodeGen \
    13 Target ExecutionEngine Linker MC CompilerDriver Object DebugInfo
    13 Target ExecutionEngine Linker MC Object DebugInfo
    1414
    1515 include $(LEVEL)/Makefile.common
    1616
    3030 InstrEnumEmitter.cpp
    3131 InstrInfoEmitter.cpp
    3232 IntrinsicEmitter.cpp
    33 LLVMCConfigurationEmitter.cpp
    3433 NeonEmitter.cpp
    3534 OptParserEmitter.cpp
    3635 PseudoLoweringEmitter.cpp
    +0
    -3134
    utils/TableGen/LLVMCConfigurationEmitter.cpp less more
    None //===- LLVMCConfigurationEmitter.cpp - Generate LLVMC config ----*- C++ -*-===//
    1 //
    2 // The LLVM Compiler Infrastructure
    3 //
    4 // This file is distributed under the University of Illinois Open
    5 // Source License. See LICENSE.TXT for details.
    6 //
    7 //===----------------------------------------------------------------------===//
    8 //
    9 // This tablegen backend is responsible for emitting LLVMC configuration code.
    10 //
    11 //===----------------------------------------------------------------------===//
    12
    13 #include "LLVMCConfigurationEmitter.h"
    14 #include "Record.h"
    15
    16 #include "llvm/ADT/IntrusiveRefCntPtr.h"
    17 #include "llvm/ADT/StringMap.h"
    18 #include "llvm/ADT/StringSet.h"
    19
    20 #include
    21 #include
    22 #include
    23 #include
    24 #include
    25 #include
    26
    27
    28 using namespace llvm;
    29
    30 namespace {
    31
    32 //===----------------------------------------------------------------------===//
    33 /// Typedefs
    34
    35 typedef std::vector RecordVector;
    36 typedef std::vector DagVector;
    37 typedef std::vector StrVector;
    38
    39 //===----------------------------------------------------------------------===//
    40 /// Constants
    41
    42 // Indentation.
    43 const unsigned TabWidth = 4;
    44 const unsigned Indent1 = TabWidth*1;
    45 const unsigned Indent2 = TabWidth*2;
    46 const unsigned Indent3 = TabWidth*3;
    47 const unsigned Indent4 = TabWidth*4;
    48
    49 // Default help string.
    50 const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
    51
    52 // Name for the "sink" option.
    53 const char * const SinkOptionName = "SinkOption";
    54
    55 //===----------------------------------------------------------------------===//
    56 /// Helper functions
    57
    58 /// Id - An 'identity' function object.
    59 struct Id {
    60 template
    61 void operator()(const T0&) const {
    62 }
    63 template
    64 void operator()(const T0&, const T1&) const {
    65 }
    66 template
    67 void operator()(const T0&, const T1&, const T2&) const {
    68 }
    69 };
    70
    71 int InitPtrToInt(const Init* ptr) {
    72 const IntInit& val = dynamic_cast(*ptr);
    73 return val.getValue();
    74 }
    75
    76 bool InitPtrToBool(const Init* ptr) {
    77 bool ret = false;
    78 const DefInit& val = dynamic_cast(*ptr);
    79 const std::string& str = val.getAsString();
    80
    81 if (str == "true") {
    82 ret = true;
    83 }
    84 else if (str == "false") {
    85 ret = false;
    86 }
    87 else {
    88 throw "Incorrect boolean value: '" + str +
    89 "': must be either 'true' or 'false'";
    90 }
    91
    92 return ret;
    93 }
    94
    95 const std::string& InitPtrToString(const Init* ptr) {
    96 const StringInit& val = dynamic_cast(*ptr);
    97 return val.getValue();
    98 }
    99
    100 const ListInit& InitPtrToList(const Init* ptr) {
    101 const ListInit& val = dynamic_cast(*ptr);
    102 return val;
    103 }
    104
    105 const DagInit& InitPtrToDag(const Init* ptr) {
    106 const DagInit& val = dynamic_cast(*ptr);
    107 return val;
    108 }
    109
    110 const std::string GetOperatorName(const DagInit& D) {
    111 return D.getOperator()->getAsString();
    112 }
    113
    114 /// CheckBooleanConstant - Check that the provided value is a boolean constant.
    115 void CheckBooleanConstant(const Init* I) {
    116 InitPtrToBool(I);
    117 }
    118
    119 // CheckNumberOfArguments - Ensure that the number of args in d is
    120 // greater than or equal to min_arguments, otherwise throw an exception.
    121 void CheckNumberOfArguments (const DagInit& d, unsigned minArgs) {
    122 if (d.getNumArgs() < minArgs)
    123 throw GetOperatorName(d) + ": too few arguments!";
    124 }
    125
    126 // EscapeVariableName - Escape commas and other symbols not allowed
    127 // in the C++ variable names. Makes it possible to use options named
    128 // like "Wa," (useful for prefix options).
    129 std::string EscapeVariableName (const std::string& Var) {
    130 std::string ret;
    131 for (unsigned i = 0; i != Var.size(); ++i) {
    132 char cur_char = Var[i];
    133 if (cur_char == ',') {
    134 ret += "_comma_";
    135 }
    136 else if (cur_char == '+') {
    137 ret += "_plus_";
    138 }
    139 else if (cur_char == '-') {
    140 ret += "_dash_";
    141 }
    142 else {
    143 ret.push_back(cur_char);
    144 }
    145 }
    146 return ret;
    147 }
    148
    149 /// EscapeQuotes - Replace '"' with '\"'.
    150 std::string EscapeQuotes (const std::string& Var) {
    151 std::string ret;
    152 for (unsigned i = 0; i != Var.size(); ++i) {
    153 char cur_char = Var[i];
    154 if (cur_char == '"') {
    155 ret += "\\\"";
    156 }
    157 else {
    158 ret.push_back(cur_char);
    159 }
    160 }
    161 return ret;
    162 }
    163
    164 /// OneOf - Does the input string contain this character?
    165 bool OneOf(const char* lst, char c) {
    166 while (*lst) {
    167 if (*lst++ == c)
    168 return true;
    169 }
    170 return false;
    171 }
    172
    173 template
    174 void CheckedIncrement(I& P, I E, S ErrorString) {
    175 ++P;
    176 if (P == E)
    177 throw ErrorString;
    178 }
    179
    180 //===----------------------------------------------------------------------===//
    181 /// Back-end specific code
    182
    183
    184 /// OptionType - One of six different option types. See the
    185 /// documentation for detailed description of differences.
    186 namespace OptionType {
    187
    188 enum OptionType { Alias, Switch, SwitchList,
    189 Parameter, ParameterList, Prefix, PrefixList };
    190
    191 bool IsAlias(OptionType t) {
    192 return (t == Alias);
    193 }
    194
    195 bool IsList (OptionType t) {
    196 return (t == SwitchList || t == ParameterList || t == PrefixList);
    197 }
    198
    199 bool IsSwitch (OptionType t) {
    200 return (t == Switch);
    201 }
    202
    203 bool IsSwitchList (OptionType t) {
    204 return (t == SwitchList);
    205 }
    206
    207 bool IsParameter (OptionType t) {
    208 return (t == Parameter || t == Prefix);
    209 }
    210
    211 }
    212
    213 OptionType::OptionType stringToOptionType(const std::string& T) {
    214 if (T == "alias_option")
    215 return OptionType::Alias;
    216 else if (T == "switch_option")
    217 return OptionType::Switch;
    218 else if (T == "switch_list_option")
    219 return OptionType::SwitchList;
    220 else if (T == "parameter_option")
    221 return OptionType::Parameter;
    222 else if (T == "parameter_list_option")
    223 return OptionType::ParameterList;
    224 else if (T == "prefix_option")
    225 return OptionType::Prefix;
    226 else if (T == "prefix_list_option")
    227 return OptionType::PrefixList;
    228 else
    229 throw "Unknown option type: " + T + '!';
    230 }
    231
    232 namespace OptionDescriptionFlags {
    233 enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2,
    234 ReallyHidden = 0x4, OneOrMore = 0x8,
    235 Optional = 0x10, CommaSeparated = 0x20,
    236 ForwardNotSplit = 0x40, ZeroOrMore = 0x80 };
    237 }
    238
    239 /// OptionDescription - Represents data contained in a single
    240 /// OptionList entry.
    241 struct OptionDescription {
    242 OptionType::OptionType Type;
    243 std::string Name;
    244 unsigned Flags;
    245 std::string Help;
    246 unsigned MultiVal;
    247 Init* InitVal;
    248
    249 OptionDescription(OptionType::OptionType t = OptionType::Switch,
    250 const std::string& n = "",
    251 const std::string& h = DefaultHelpString)
    252 : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)
    253 {}
    254
    255 /// GenTypeDeclaration - Returns the C++ variable type of this
    256 /// option.
    257 const char* GenTypeDeclaration() const;
    258
    259 /// GenVariableName - Returns the variable name used in the
    260 /// generated C++ code.
    261 std::string GenVariableName() const
    262 { return "autogenerated::" + GenOptionType() + EscapeVariableName(Name); }
    263
    264 /// GenPlainVariableName - Returns the variable name without the namespace
    265 /// prefix.
    266 std::string GenPlainVariableName() const
    267 { return GenOptionType() + EscapeVariableName(Name); }
    268
    269 /// Merge - Merge two option descriptions.
    270 void Merge (const OptionDescription& other);
    271
    272 /// CheckConsistency - Check that the flags are consistent.
    273 void CheckConsistency() const;
    274
    275 // Misc convenient getters/setters.
    276
    277 bool isAlias() const;
    278
    279 bool isMultiVal() const;
    280
    281 bool isCommaSeparated() const;
    282 void setCommaSeparated();
    283
    284 bool isForwardNotSplit() const;
    285 void setForwardNotSplit();
    286
    287 bool isRequired() const;
    288 void setRequired();
    289
    290 bool isOneOrMore() const;
    291 void setOneOrMore();
    292
    293 bool isZeroOrMore() const;
    294 void setZeroOrMore();
    295
    296 bool isOptional() const;
    297 void setOptional();
    298
    299 bool isHidden() const;
    300 void setHidden();
    301
    302 bool isReallyHidden() const;
    303 void setReallyHidden();
    304
    305 bool isSwitch() const
    306 { return OptionType::IsSwitch(this->Type); }
    307
    308 bool isSwitchList() const
    309 { return OptionType::IsSwitchList(this->Type); }
    310
    311 bool isParameter() const
    312 { return OptionType::IsParameter(this->Type); }
    313
    314 bool isList() const
    315 { return OptionType::IsList(this->Type); }
    316
    317 bool isParameterList() const
    318 { return (OptionType::IsList(this->Type)
    319 && !OptionType::IsSwitchList(this->Type)); }
    320
    321 private:
    322
    323 // GenOptionType - Helper function used by GenVariableName().
    324 std::string GenOptionType() const;
    325 };
    326
    327 void OptionDescription::CheckConsistency() const {
    328 unsigned i = 0;
    329
    330 i += this->isRequired();
    331 i += this->isOptional();
    332 i += this->isOneOrMore();
    333 i += this->isZeroOrMore();
    334
    335 if (i > 1) {
    336 throw "Only one of (required), (optional), (one_or_more) or "
    337 "(zero_or_more) properties is allowed!";
    338 }
    339 }
    340
    341 void OptionDescription::Merge (const OptionDescription& other)
    342 {
    343 if (other.Type != Type)
    344 throw "Conflicting definitions for the option " + Name + "!";
    345
    346 if (Help == other.Help || Help == DefaultHelpString)
    347 Help = other.Help;
    348 else if (other.Help != DefaultHelpString) {
    349 llvm::errs() << "Warning: several different help strings"
    350 " defined for option " + Name + "\n";
    351 }
    352
    353 Flags |= other.Flags;
    354 }
    355
    356 bool OptionDescription::isAlias() const {
    357 return OptionType::IsAlias(this->Type);
    358 }
    359
    360 bool OptionDescription::isMultiVal() const {
    361 return MultiVal > 1;
    362 }
    363
    364 bool OptionDescription::isCommaSeparated() const {
    365 return Flags & OptionDescriptionFlags::CommaSeparated;
    366 }
    367 void OptionDescription::setCommaSeparated() {
    368 Flags |= OptionDescriptionFlags::CommaSeparated;
    369 }
    370
    371 bool OptionDescription::isForwardNotSplit() const {
    372 return Flags & OptionDescriptionFlags::ForwardNotSplit;
    373 }
    374 void OptionDescription::setForwardNotSplit() {
    375 Flags |= OptionDescriptionFlags::ForwardNotSplit;
    376 }
    377
    378 bool OptionDescription::isRequired() const {
    379 return Flags & OptionDescriptionFlags::Required;
    380 }
    381 void OptionDescription::setRequired() {
    382 Flags |= OptionDescriptionFlags::Required;
    383 }
    384
    385 bool OptionDescription::isOneOrMore() const {
    386 return Flags & OptionDescriptionFlags::OneOrMore;
    387 }
    388 void OptionDescription::setOneOrMore() {
    389 Flags |= OptionDescriptionFlags::OneOrMore;
    390 }
    391
    392 bool OptionDescription::isZeroOrMore() const {
    393 return Flags & OptionDescriptionFlags::ZeroOrMore;
    394 }
    395 void OptionDescription::setZeroOrMore() {
    396 Flags |= OptionDescriptionFlags::ZeroOrMore;
    397 }
    398
    399 bool OptionDescription::isOptional() const {
    400 return Flags & OptionDescriptionFlags::Optional;
    401 }
    402 void OptionDescription::setOptional() {
    403 Flags |= OptionDescriptionFlags::Optional;
    404 }
    405
    406 bool OptionDescription::isHidden() const {
    407 return Flags & OptionDescriptionFlags::Hidden;
    408 }
    409 void OptionDescription::setHidden() {
    410 Flags |= OptionDescriptionFlags::Hidden;
    411 }
    412
    413 bool OptionDescription::isReallyHidden() const {
    414 return Flags & OptionDescriptionFlags::ReallyHidden;
    415 }
    416 void OptionDescription::setReallyHidden() {
    417 Flags |= OptionDescriptionFlags::ReallyHidden;
    418 }
    419
    420 const char* OptionDescription::GenTypeDeclaration() const {
    421 switch (Type) {
    422 case OptionType::Alias:
    423 return "cl::alias";
    424 case OptionType::PrefixList:
    425 case OptionType::ParameterList:
    426 return "cl::list";
    427 case OptionType::Switch:
    428 return "cl::opt";
    429 case OptionType::SwitchList:
    430 return "cl::list";
    431 case OptionType::Parameter:
    432 case OptionType::Prefix:
    433 default:
    434 return "cl::opt";
    435 }
    436 }
    437
    438 std::string OptionDescription::GenOptionType() const {
    439 switch (Type) {
    440 case OptionType::Alias:
    441 return "Alias_";
    442 case OptionType::PrefixList:
    443 case OptionType::ParameterList:
    444 return "List_";
    445 case OptionType::Switch:
    446 return "Switch_";
    447 case OptionType::SwitchList:
    448 return "SwitchList_";
    449 case OptionType::Prefix:
    450 case OptionType::Parameter:
    451 default:
    452 return "Parameter_";
    453 }
    454 }
    455
    456 /// OptionDescriptions - An OptionDescription array plus some helper
    457 /// functions.
    458 class OptionDescriptions {
    459 typedef StringMap container_type;
    460
    461 /// Descriptions - A list of OptionDescriptions.
    462 container_type Descriptions;
    463
    464 public:
    465 /// FindOption - exception-throwing wrapper for find().
    466 const OptionDescription& FindOption(const std::string& OptName) const;
    467
    468 // Wrappers for FindOption that throw an exception in case the option has a
    469 // wrong type.
    470 const OptionDescription& FindSwitch(const std::string& OptName) const;
    471 const OptionDescription& FindParameter(const std::string& OptName) const;
    472 const OptionDescription& FindParameterList(const std::string& OptName) const;
    473 const OptionDescription&
    474 FindListOrParameter(const std::string& OptName) const;
    475 const OptionDescription&
    476 FindParameterListOrParameter(const std::string& OptName) const;
    477
    478 /// insertDescription - Insert new OptionDescription into
    479 /// OptionDescriptions list
    480 void InsertDescription (const OptionDescription& o);
    481
    482 // Support for STL-style iteration
    483 typedef container_type::const_iterator const_iterator;
    484 const_iterator begin() const { return Descriptions.begin(); }
    485 const_iterator end() const { return Descriptions.end(); }
    486 };
    487
    488 const OptionDescription&
    489 OptionDescriptions::FindOption(const std::string& OptName) const {
    490 const_iterator I = Descriptions.find(OptName);
    491 if (I != Descriptions.end())
    492 return I->second;
    493 else
    494 throw OptName + ": no such option!";
    495 }
    496
    497 const OptionDescription&
    498 OptionDescriptions::FindSwitch(const std::string& OptName) const {
    499 const OptionDescription& OptDesc = this->FindOption(OptName);
    500 if (!OptDesc.isSwitch())
    501 throw OptName + ": incorrect option type - should be a switch!";
    502 return OptDesc;
    503 }
    504
    505 const OptionDescription&
    506 OptionDescriptions::FindParameterList(const std::string& OptName) const {
    507 const OptionDescription& OptDesc = this->FindOption(OptName);
    508 if (!OptDesc.isList() || OptDesc.isSwitchList())
    509 throw OptName + ": incorrect option type - should be a parameter list!";
    510 return OptDesc;
    511 }
    512
    513 const OptionDescription&
    514 OptionDescriptions::FindParameter(const std::string& OptName) const {
    515 const OptionDescription& OptDesc = this->FindOption(OptName);
    516 if (!OptDesc.isParameter())
    517 throw OptName + ": incorrect option type - should be a parameter!";
    518 return OptDesc;
    519 }
    520
    521 const OptionDescription&
    522 OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
    523 const OptionDescription& OptDesc = this->FindOption(OptName);
    524 if (!OptDesc.isList() && !OptDesc.isParameter())
    525 throw OptName
    526 + ": incorrect option type - should be a list or parameter!";
    527 return OptDesc;
    528 }
    529
    530 const OptionDescription&
    531 OptionDescriptions::FindParameterListOrParameter
    532 (const std::string& OptName) const {
    533 const OptionDescription& OptDesc = this->FindOption(OptName);
    534 if ((!OptDesc.isList() && !OptDesc.isParameter()) || OptDesc.isSwitchList())
    535 throw OptName
    536 + ": incorrect option type - should be a parameter list or parameter!";
    537 return OptDesc;
    538 }
    539
    540 void OptionDescriptions::InsertDescription (const OptionDescription& o) {
    541 container_type::iterator I = Descriptions.find(o.Name);
    542 if (I != Descriptions.end()) {
    543 OptionDescription& D = I->second;
    544 D.Merge(o);
    545 }
    546 else {
    547 Descriptions[o.Name] = o;
    548 }
    549 }
    550
    551 /// HandlerTable - A base class for function objects implemented as
    552 /// 'tables of handlers'.
    553 template
    554 class HandlerTable {
    555 protected:
    556 // Implementation details.
    557
    558 /// HandlerMap - A map from property names to property handlers
    559 typedef StringMap HandlerMap;
    560
    561 static HandlerMap Handlers_;
    562 static bool staticMembersInitialized_;
    563
    564 public:
    565
    566 Handler GetHandler (const std::string& HandlerName) const {
    567 typename HandlerMap::iterator method = Handlers_.find(HandlerName);
    568
    569 if (method != Handlers_.end()) {
    570 Handler h = method->second;
    571 return h;
    572 }
    573 else {
    574 throw "No handler found for property " + HandlerName + "!";
    575 }
    576 }
    577
    578 void AddHandler(const char* Property, Handler H) {
    579 Handlers_[Property] = H;
    580 }
    581
    582 };
    583
    584 template
    585 Handler GetHandler(FunctionObject* Obj, const DagInit& Dag) {
    586 const std::string& HandlerName = GetOperatorName(Dag);
    587 return Obj->GetHandler(HandlerName);
    588 }
    589
    590 template
    591 void InvokeDagInitHandler(FunctionObject* Obj, Init* I) {
    592 typedef void (FunctionObject::*Handler) (const DagInit&);
    593
    594 const DagInit& Dag = InitPtrToDag(I);
    595 Handler h = GetHandler(Obj, Dag);
    596
    597 ((Obj)->*(h))(Dag);
    598 }
    599
    600 template
    601 void InvokeDagInitHandler(const FunctionObject* const Obj,
    602 const Init* I, unsigned IndentLevel, raw_ostream& O)
    603 {
    604 typedef void (FunctionObject::*Handler)
    605 (const DagInit&, unsigned IndentLevel, raw_ostream& O) const;
    606
    607 const DagInit& Dag = InitPtrToDag(I);
    608 Handler h = GetHandler(Obj, Dag);
    609
    610 ((Obj)->*(h))(Dag, IndentLevel, O);
    611 }
    612
    613 template
    614 typename HandlerTable::HandlerMap HandlerTable::Handlers_;
    615
    616 template
    617 bool HandlerTable::staticMembersInitialized_ = false;
    618
    619
    620 /// CollectOptionProperties - Function object for iterating over an
    621 /// option property list.
    622 class CollectOptionProperties;
    623 typedef void (CollectOptionProperties::* CollectOptionPropertiesHandler)
    624 (const DagInit&);
    625
    626 class CollectOptionProperties
    627 : public HandlerTable
    628 {
    629 private:
    630
    631 /// optDescs_ - OptionDescriptions table. This is where the
    632 /// information is stored.
    633 OptionDescription& optDesc_;
    634
    635 public:
    636
    637 explicit CollectOptionProperties(OptionDescription& OD)
    638 : optDesc_(OD)
    639 {
    640 if (!staticMembersInitialized_) {
    641 AddHandler("help", &CollectOptionProperties::onHelp);
    642 AddHandler("hidden", &CollectOptionProperties::onHidden);
    643 AddHandler("init", &CollectOptionProperties::onInit);
    644 AddHandler("multi_val", &CollectOptionProperties::onMultiVal);
    645 AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);
    646 AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore);
    647 AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden);
    648 AddHandler("required", &CollectOptionProperties::onRequired);
    649 AddHandler("optional", &CollectOptionProperties::onOptional);
    650 AddHandler("comma_separated", &CollectOptionProperties::onCommaSeparated);
    651 AddHandler("forward_not_split",
    652 &CollectOptionProperties::onForwardNotSplit);
    653
    654 staticMembersInitialized_ = true;
    655 }
    656 }
    657
    658 /// operator() - Just forwards to the corresponding property
    659 /// handler.
    660 void operator() (Init* I) {
    661 InvokeDagInitHandler(this, I);
    662 }
    663
    664 private:
    665
    666 /// Option property handlers --
    667 /// Methods that handle option properties such as (help) or (hidden).
    668
    669 void onHelp (const DagInit& d) {
    670 CheckNumberOfArguments(d, 1);
    671 optDesc_.Help = EscapeQuotes(InitPtrToString(d.getArg(0)));
    672 }
    673
    674 void onHidden (const DagInit& d) {
    675 CheckNumberOfArguments(d, 0);
    676 optDesc_.setHidden();
    677 }
    678
    679 void onReallyHidden (const DagInit& d) {
    680 CheckNumberOfArguments(d, 0);
    681 optDesc_.setReallyHidden();
    682 }
    683
    684 void onCommaSeparated (const DagInit& d) {
    685 CheckNumberOfArguments(d, 0);
    686 if (!optDesc_.isParameterList())
    687 throw "'comma_separated' is valid only on parameter list options!";
    688 optDesc_.setCommaSeparated();
    689 }
    690
    691 void onForwardNotSplit (const DagInit& d) {
    692 CheckNumberOfArguments(d, 0);
    693 if (!optDesc_.isParameter())
    694 throw "'forward_not_split' is valid only for parameter options!";
    695 optDesc_.setForwardNotSplit();
    696 }
    697