llvm.org GIT mirror llvm / ac67b7e
Add first proof-of-concept universal compiler driver framework based on ideas mentioned in PR686. Written by Mikhail Glushenkov and contributed by Codedgers, Inc. Old llvmc will be removed soon after new one will have all its properties. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48699 91177308-0d34-0410-b5e6-96231b3b80d8 Anton Korobeynikov 11 years ago
19 changed file(s) with 2019 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
221221
222222 } // end namespace llvm
223223
224 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR
224 #endif // LLVM_ADT_INTRUSIVE_REF_CNT_PTR
1515 llc llvm-ranlib llvm-ar llvm-nm \
1616 llvm-ld llvmc llvm-prof llvm-link \
1717 lli gccas gccld llvm-extract llvm-db llvm2cpp \
18 bugpoint llvm-bcanalyzer llvm-stub
18 bugpoint llvm-bcanalyzer llvm-stub llvmc2
1919
2020
2121 include $(LEVEL)/Makefile.config
0 //===- Tools.td - Common definitions for LLVMCC -----------*- 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 llvmcc 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 cmd_line;
23 def join;
24 def sink;
25
26 // Possible option types
27
28 def switch_option;
29 def parameter_option;
30 def parameter_list_option;
31 def prefix_option;
32 def prefix_list_option;
33
34 // Possible option properties
35
36 def append_cmd;
37 def forward;
38 def stop_compilation;
39 def unpack_values;
40 def help;
41 def required;
42
43 // Map from suffixes to language names
44
45 class LangToSuffixes lst> {
46 string lang = str;
47 list suffixes = lst;
48 }
49
50 class LanguageMap lst> {
51 list map = lst;
52 }
53
54 // Toolchain classes
55
56 class ToolChain lst> {
57 list tools = lst;
58 }
59
60 class ToolChains lst> {
61 list chains = lst;
62 }
0 //===--- Core.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 // Core driver abstractions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Core.h"
14 #include "Utility.h"
15
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/CommandLine.h"
19
20 #include
21 #include
22 #include
23
24 using namespace llvm;
25 using namespace llvmcc;
26
27 extern cl::list InputFilenames;
28 extern cl::opt OutputFilename;
29 extern cl::opt VerboseMode;
30
31 namespace {
32 void print_string (const std::string& str) {
33 std::cerr << str << ' ';
34 }
35 }
36
37 int llvmcc::Action::Execute() {
38 if (VerboseMode) {
39 std::cerr << Command_ << " ";
40 std::for_each(Args_.begin(), Args_.end(), print_string);
41 std::cerr << '\n';
42 }
43 return ExecuteProgram(Command_, Args_);
44 }
45
46 int llvmcc::CompilationGraph::Build (const sys::Path& tempDir) const {
47 sys::Path In(InputFilenames.at(0)), Out;
48
49 // Find out which language corresponds to the suffix of the first input file
50 LanguageMap::const_iterator Lang = ExtsToLangs.find(In.getSuffix());
51 if (Lang == ExtsToLangs.end())
52 throw std::runtime_error("Unknown suffix!");
53
54 // Find the toolchain corresponding to this language
55 ToolChainMap::const_iterator ToolsIt = ToolChains.find(Lang->second);
56 if (ToolsIt == ToolChains.end())
57 throw std::runtime_error("Unknown language!");
58 ToolChain Tools = ToolsIt->second;
59
60 PathVector JoinList;
61
62 for (cl::list::const_iterator B = InputFilenames.begin(),
63 E = InputFilenames.end(); B != E; ++B) {
64 In = sys::Path(*B);
65
66 // Pass input file through the toolchain
67 for (ToolChain::const_iterator B = Tools.begin(), E = Tools.end();
68 B != E; ++B) {
69
70 const Tool* CurTool = B->getPtr();
71
72 // Is this the last step in the chain?
73 if (llvm::next(B) == E || CurTool->IsLast()) {
74 JoinList.push_back(In);
75 break;
76 }
77 else {
78 Out = tempDir;
79 Out.appendComponent(In.getBasename());
80 Out.appendSuffix(CurTool->OutputSuffix());
81 Out.makeUnique(true, NULL);
82 Out.eraseFromDisk();
83 }
84
85 if (CurTool->GenerateAction(In, Out).Execute() != 0)
86 throw std::runtime_error("Tool returned error code!");
87
88 In = Out; Out.clear();
89 }
90 }
91
92 // Pass .o files to linker
93 const Tool* JoinNode = (--Tools.end())->getPtr();
94
95 // If the final output name is empty, set it to "a.out"
96 if (!OutputFilename.empty()) {
97 Out = sys::Path(OutputFilename);
98 }
99 else {
100 Out = sys::Path("a");
101 Out.appendSuffix(JoinNode->OutputSuffix());
102 }
103
104 if (JoinNode->GenerateAction(JoinList, Out).Execute() != 0)
105 throw std::runtime_error("Tool returned error code!");
106
107 return 0;
108 }
109
110 void llvmcc::Tool::UnpackValues (const std::string& from,
111 std::vector& to) const {
112 SplitString(from, to, ",");
113 }
114
0 //===--- Core.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 // Core driver abstractions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TOOLS_LLVMCC_CORE_H
14 #define LLVM_TOOLS_LLVMCC_CORE_H
15
16 #include "Utility.h"
17
18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/System/Path.h"
21
22 #include
23 #include
24 #include
25
26 // Core functionality
27
28 namespace llvmcc {
29
30 typedef std::vector PathVector;
31 typedef llvm::StringMap LanguageMap;
32
33 class Action {
34 std::string Command_;
35 std::vector Args_;
36 public:
37 Action (std::string const& C,
38 std::vector const& A)
39 : Command_(C), Args_(A)
40 {}
41
42 int Execute();
43 };
44
45 class Tool : public llvm::RefCountedBaseVPTR {
46 public:
47 virtual Action GenerateAction (PathVector const& inFiles,
48 llvm::sys::Path const& outFile) const = 0;
49
50 virtual Action GenerateAction (llvm::sys::Path const& inFile,
51 llvm::sys::Path const& outFile) const = 0;
52
53 virtual std::string Name() const = 0;
54 virtual std::string InputLanguage() const = 0;
55 virtual std::string OutputLanguage() const = 0;
56 virtual std::string OutputSuffix() const = 0;
57
58 virtual bool IsLast() const = 0;
59 virtual bool IsJoin() const = 0;
60
61 // Helper function that is called by the auto-generated code
62 // Splits strings of the form ",-foo,-bar,-baz"
63 // TOFIX: find a better name
64 void UnpackValues (std::string const& from,
65 std::vector& to) const;
66
67 virtual ~Tool()
68 {}
69 };
70
71 typedef std::vector > ToolChain;
72 typedef llvm::StringMap ToolChainMap;
73
74 struct CompilationGraph {
75 ToolChainMap ToolChains;
76 LanguageMap ExtsToLangs;
77
78 int Build(llvm::sys::Path const& tempDir) const;
79 };
80 }
81
82 #endif // LLVM_TOOLS_LLVMCC_CORE_H
0 //===- Example.td - LLVMCC toolchain descriptions ---------*- 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 toolchain descriptions used by llvmcc.
10 //
11 //===----------------------------------------------------------------------===//
12
13 include "Common.td"
14 include "Tools.td"
15
16 // Toolchains
17
18 def ToolChains : ToolChains<[
19 ToolChain<[llvm_gcc_c, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
20 ToolChain<[llvm_gcc_cpp, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
21 ToolChain<[llvm_as, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
22 ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
23 ]>;
0 //===- ExampleWithOpt.td - LLVMCC toolchain descriptions --*- 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 toolchain descriptions used by llvmcc.
10 //
11 //===----------------------------------------------------------------------===//
12
13 include "Common.td"
14 include "Tools.td"
15
16 // Toolchains
17
18 def ToolChains : ToolChains<[
19 ToolChain<[llvm_gcc_c, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
20 ToolChain<[llvm_gcc_cpp, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
21 ToolChain<[llvm_as, opt, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
22 ToolChain<[llvm_gcc_assembler, llvm_gcc_linker]>
23 ]>;
0 ##===- tools/llvmcc/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 LEVEL = ../..
9 TOOLNAME = llvmc2
10 BUILT_SOURCES = Tools.inc
11 LINK_COMPONENTS = support system
12 REQUIRES_EH := 1
13
14 include $(LEVEL)/Makefile.common
15
16 TOOLS_TARGET=default
17 ifeq ($(TOOLS_TARGET), default)
18 TOOLS_SOURCE=Example.td
19 else
20 TOOLS_SOURCE=ExampleWithOpt.td
21 endif
22
23 # TOFIX: integrate this part into Makefile.rules?
24 # The degree of horrorshowness in that file is too much for me atm.
25 $(ObjDir)/Tools.inc.tmp: $(TOOLS_SOURCE) $(ObjDir)/.dir
26 $(Echo) "Building LLVMCC configuration library with tblgen"
27 $(Verb) $(TableGen) -gen-llvmcc -o $@ $<
28
29 Tools.inc : $(ObjDir)/Tools.inc.tmp
30 $(Verb) $(CMP) -s $@ $< || $(CP) $< $@
31
0 //===--- Tools.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 // Auto-generated tool descriptions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Tools.h"
14 #include "Core.h"
15
16 #include "llvm/ADT/IntrusiveRefCntPtr.h"
17 #include "llvm/Support/CommandLine.h"
18
19 #include
20 #include
21 #include
22
23 using namespace llvm;
24 using namespace llvmcc;
25
26 // Include the auto-generated file
27 #include "Tools.inc"
0 //===--- Tools.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 // Auto-generated tool descriptions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TOOLS_LLVMCC_TOOLS_H
14 #define LLVM_TOOLS_LLVMCC_TOOLS_H
15
16 #include "Core.h"
17
18 namespace llvmcc {
19
20 void PopulateLanguageMap(LanguageMap& language_map);
21 void PopulateCompilationGraph(CompilationGraph& tools);
22
23 }
24
25 #endif //LLVM_TOOLS_LLVMCC_TOOLS_H
0 //===- Tools.td - Tools description for the LLVMCC --------*- 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 descriptions of the various build tools run by llvmcc.
10 //
11 //===----------------------------------------------------------------------===//
12
13 // Open issue: should we use DAG lists in Tool specifications
14 // or change to something like
15 // def LLVMGccC : < Tool<
16 // [ InLanguage<"c">,
17 // PrefixListOption<"Wl", [UnpackValues, PropertyName, ...]>
18 // ...] ?
19 // DAG lists look more aesthetically pleasing to me.
20
21 def llvm_gcc_c : Tool<
22 [(in_language "c"),
23 (out_language "llvm-assembler"),
24 (output_suffix "bc"),
25 (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE -emit-llvm"),
26 (sink)
27 ]>;
28
29 def llvm_gcc_cpp : Tool<
30 [(in_language "c++"),
31 (out_language "llvm-assembler"),
32 (output_suffix "bc"),
33 (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
34 (sink)
35 ]>;
36
37 def opt : Tool<
38 [(in_language "llvm-bitcode"),
39 (out_language "llvm-bitcode"),
40 (output_suffix "bc"),
41 (cmd_line "opt $INFILE -o $OUTFILE")
42 ]>;
43
44 def llvm_as : Tool<
45 [(in_language "llvm-assembler"),
46 (out_language "llvm-bitcode"),
47 (output_suffix "bc"),
48 (cmd_line "llvm-as $INFILE -o $OUTFILE")
49 ]>;
50
51 def llc : Tool<
52 [(in_language "llvm-bitcode"),
53 (out_language "assembler"),
54 (output_suffix "s"),
55 (cmd_line "llc $INFILE -o $OUTFILE")
56 ]>;
57
58 def llvm_gcc_assembler : Tool<
59 [(in_language "assembler"),
60 (out_language "object-code"),
61 (output_suffix "o"),
62 (cmd_line "llvm-gcc -c $INFILE -o $OUTFILE"),
63 (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
64 ]>;
65
66 def llvm_gcc_linker : Tool<
67 [(in_language "object-code"),
68 (out_language "executable"),
69 (output_suffix "out"),
70 (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
71 (join),
72 (prefix_list_option "L", (forward), (help "add a directory to link path")),
73 (prefix_list_option "l", (forward), (help "search a library when linking")),
74 (prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
75 ]>;
76
77 // Language map
78
79 def LanguageMap : LanguageMap<
80 [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
81 LangToSuffixes<"c", ["c"]>,
82 LangToSuffixes<"assembler", ["s"]>,
83 LangToSuffixes<"llvm-assembler", ["ll"]>,
84 LangToSuffixes<"llvm-bitcode", ["bc"]>,
85 LangToSuffixes<"object-code", ["o"]>,
86 LangToSuffixes<"executable", ["out"]>]>;
0 //===--- Utility.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 // Various helper and utility functions - implementation.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "Utility.h"
14
15 #include "llvm/System/Program.h"
16
17 #include
18
19 using namespace llvm;
20
21 int llvmcc::ExecuteProgram(const std::string& name,
22 const std::vector& args) {
23 sys::Path prog = sys::Program::FindProgramByName(name);
24
25 if (prog.isEmpty())
26 throw std::runtime_error("Can't find program '" + name + "'");
27 if (!prog.canExecute())
28 throw std::runtime_error("Program '" + name + "' is not executable.");
29
30 // Invoke the program
31 std::vector argv((args.size()+2));
32 argv[0] = name.c_str();
33 for (unsigned i = 1; i <= args.size(); ++i)
34 argv[i] = args[i-1].c_str();
35 argv[args.size()+1] = 0; // null terminate list.
36
37 return sys::Program::ExecuteAndWait(prog, &argv[0]);
38 }
0 //===--- Utility.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 // Various helper and utility functions.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TOOLS_LLVMCC_UTILITY_H
14 #define LLVM_TOOLS_LLVMCC_UTILITY_H
15
16 #include
17 #include
18
19 namespace llvmcc {
20
21 int ExecuteProgram (const std::string& name,
22 const std::vector& arguments);
23
24 }
25
26 #endif // LLVM_TOOLS_LLVMCC_UTILITY_H
0 Introduction
1 ============
2
3 A complete rewrite of the LLVMC compiler driver is proposed, aimed at
4 making it more configurable and useful.
5
6 Motivation
7 ==========
8
9 As it stands, current version of LLVMC does not meet its stated goals
10 of configurability and extensibility and is therefore not used
11 much. The need for enhancements in LLVMC is also reflected in [1]_. The
12 proposed rewrite will fix the aforementioned deficiences and provide
13 an extensible, future-proof solution.
14
15 Design
16 ======
17
18 A compiler driver's job is essentially to find a way how to transform
19 a set of input files into a set of targets, depending on the
20 user-provided options. Since several ways of transformation can exist
21 potentially, it's natural to use a directed graph to represent all of
22 them. In this graph, nodes are tools (for example, ``gcc -S`` is a tool
23 that generates assembly from C language files) and edges between them
24 mean that the output of one tool can be given as input to another (as
25 in ``gcc -S -o - file.c | as``). We'll call this graph the compilation
26 graph.
27
28 The proposed design revolves around the compilation graph and the
29 following core abstractions:
30
31 - Target - An (intermediate) compilation target.
32
33 - Action - A shell command template that represents basic compilation
34 transformation(example: ``gcc -S $INPUT_FILE -o $OUTPUT_FILE``).
35
36 - Tool - Encapsulates information about a concrete tool used in the
37 compilation process, produces Actions. Operation depends on
38 command-line options provided by the user.
39
40 - GraphBuilder - Constructs the compilation graph, operation depends
41 on command-line options.
42
43 - GraphTraverser - Traverses the compilation graph and constructs a
44 sequence of Actions needed to build the target file, operation
45 depends on command-line options.
46
47 A high-level view of the compilation process:
48
49 1. Configuration libraries (see below) are loaded in and the
50 compilation graph is constructed from the tool descriptions.
51
52 2. Information about possible options is gathered from (the nodes of)
53 the compilation graph.
54
55 3. Options are parsed based on data gathered in step 2.
56
57 4. A sequence of Actions needed to build the target is constructed
58 using the compilation graph and provided options.
59
60 5. The resulting action sequence is executed.
61
62 Extensibility
63 ==============
64
65 To make this design extensible, TableGen [2]_ will be used for
66 automatic generation of the Tool classes. Users wanting to customize
67 LLVMC will need to write a configuration library consisting of a set
68 of TableGen descriptions of compilation tools plus a number of hooks
69 that influence compilation graph construction and traversal. LLVMC
70 will have the ability to load user configuration libraries at runtime;
71 in fact, its own basic functionality will be implemented as a
72 configuration library.
73
74 TableGen specification example
75 ------------------------------
76
77 This small example specifies a Tool that converts C source to object
78 files. Note that it is only a mock-up of inteded functionality, not a
79 final specification::
80
81 def GCC : Tool<
82 GCCProperties, // Properties of this tool
83 GCCOptions // Options description for this tool
84 >;
85
86 def GCCProperties : ToolProperties<[
87 ToolName<"GCC">,
88 InputLanguageName<"C">,
89 OutputLanguageName<"Object-Code">
90 InputFileExtension<"c">,
91 OutputFileExtension<"o">,
92 CommandFormat<"gcc -c $OPTIONS $FILES">
93 ]>;
94
95 def GCCOptions : ToolOptions<[
96 Option<
97 "-Wall", // Option name
98 [None], // Allowed values
99 [AddOption<"-Wall">]>, // Action
100
101 Option<
102 "-Wextra", // Option name
103 [None], // Allowed values
104 [AddOption<"-Wextra">]>, // Action
105
106 Option<
107 "-W", // Option name
108 [None], // Allowed values
109 [AddOption<"-W">]>, // Action
110
111 Option<
112 "-D", // Option name
113 [AnyString], // Allowed values
114
115 [AddOptionWithArgument<"-D",GetOptionArgument<"-D">>]
116 // Action:
117 // If the driver was given option "-D", add
118 // option "-D" with the same argument to the invocation string of
119 // this tool.
120 >
121
122 ]>;
123
124 Example of generated code
125 -------------------------
126
127 The specification above compiles to the following code (again, it's a
128 mock-up)::
129
130 class GCC : public Tool {
131
132 public:
133
134 GCC() { //... }
135
136 // Properties
137
138 static const char* ToolName = "GCC";
139 static const char* InputLanguageName = "C";
140 static const char* OutputLanguageName = "Object-Code";
141 static const char* InputFileExtension = "c";
142 static const char* OutputFileExtension = "o";
143 static const char* CommandFormat = "gcc -c $OPTIONS $FILES";
144
145 // Options
146
147 OptionsDescription SupportedOptions() {
148 OptionsDescription supportedOptions;
149
150 supportedOptions.Add(Option("-Wall"));
151 supportedOptions.Add(Option("-Wextra"));
152 supportedOptions.Add(Option("-W"));
153 supportedOptions.Add(Option("-D", AllowedArgs::ANY_STRING));
154
155 return supportedOptions;
156 }
157
158 Action GenerateAction(Options providedOptions) {
159 Action generatedAction(CommandFormat); Option curOpt;
160
161 curOpt = providedOptions.Get("-D");
162 if (curOpt) {
163 assert(curOpt.HasArgument());
164 generatedAction.AddOption(Option("-D", curOpt.GetArgument()));
165 }
166
167 curOpt = providedOptions.Get("-Wall");
168 if (curOpt)
169 generatedAction.AddOption(Option("-Wall"));
170
171 curOpt = providedOptions.Get("-Wextra");
172 if (curOpt)
173 generatedAction.AddOption(Option("-Wall"));
174
175 curOpt = providedOptions.Get("-W");
176 if (curOpt)
177 generatedAction.AddOption(Option("-Wall")); }
178
179 return generatedAction;
180 }
181
182 };
183
184 // defined somewhere...
185
186 class Action { public: void AddOption(const Option& opt) {...}
187 int Run(const Filenames& fnms) {...}
188
189 }
190
191 Option handling
192 ===============
193
194 Since one of the main tasks of the compiler driver is to correctly
195 handle user-provided options, it is important to define this process
196 in exact way. The intent of the proposed scheme is to function as a
197 drop-in replacement for GCC.
198
199 Option syntax
200 -------------
201
202 Option syntax is specified by the following formal grammar::
203
204 ::=
205
206 ::= -[-][]
207 ::= ',' | '=' | ' '
208 ::=
209 ::=
210 ::=
211
212 This roughly corresponds to the GCC option syntax. Note that grouping
213 of short options(as in ``ls -la``) is forbidden.
214
215 Example::
216
217 llvmc -O3 -Wa,-foo,-bar -pedantic -std=c++0x a.c b.c c.c
218
219 Option arguments can also have special forms: for example, an argument
220 can be a comma-separated list (like in -Wa,-foo,-bar). In such cases,
221 it's up to the option handler to parse the argument.
222
223 Option semantics
224 ----------------
225
226 According to their meaning, options are classified into following
227 categories:
228
229 - Global options - Options that influence compilation graph
230 construction/traversal. Example: -E (stop after preprocessing).
231
232 - Local options - Options that influence one or several Actions in
233 the generated action sequence. Example: -O3 (turn on optimization).
234
235 - Prefix options - Options that influence meaning of the following
236 command-line arguments. Example: -x language (specify language for
237 the input files explicitly). Prefix options can be local or global.
238
239 - Built-in options - Options that are hard-coded into
240 driver. Examples: --help, -o file/-pipe (redirect output). Can be
241 local or global.
242
243 Naming
244 ======
245
246 Since the compiler driver, as a single point of access to the LLVM
247 tool set, is a very often used tool, it would be desirable to make its name
248 as short and easy to type as possible. Some possible names are 'llcc' or
249 'lcc', by analogy with gcc.
250
251
252 Issues
253 ======
254
255 1. Should global-options-influencing hooks be written by hand or
256 auto-generated from TableGen specifications?
257
258 2. More?
259
260 References
261 ==========
262
263 .. [1] LLVM Bug#686
264
265 http://llvm.org/bugs/show_bug.cgi?id=686
266
267 .. [2] TableGen Fundamentals
268
269 http://llvm.org/docs/TableGenFundamentals.html
0 Tutorial - Writing LLVMCC Configuration files
1 =============================================
2
3 LLVMCC is a generic compiler driver(just like ``gcc``), designed to be
4 customizable and extensible. Its job is essentially to transform a set
5 of input files into a set of targets, depending on configuration rules
6 and user options. This tutorial describes how one can write
7 configuration files for ``llvmcc``.
8
9 Since LLVMCC uses TableGen [1]_ as the language of its configuration
10 files, you need to be familiar with it.
11
12 Describing a toolchain
13 ----------------------
14
15 The main concept that ``llvmcc`` operates with is a *toolchain*, which
16 is just a list of tools that process input files in a pipeline-like
17 fashion. Toolchain definitions look like this::
18
19 def ToolChains : ToolChains<[
20 ToolChain<[llvm_gcc_c, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
21 ToolChain<[llvm_gcc_cpp, llc, llvm_gcc_assembler, llvm_gcc_linker]>,
22 ...
23 ]>;
24
25 Every configuration file should have a single toolchains list called
26 ``ToolChains``.
27
28 At the time of writing, ``llvmcc`` does not support mixing various
29 toolchains together - in other words, all input files should be in the
30 same language.
31
32 Another temporary limitation is that every toolchain should end with a
33 "join" node - a linker-like program that combines its inputs into a
34 single output file.
35
36 Describing a tool
37 -----------------
38
39 A single element of a toolchain is a tool. A tool definition looks
40 like this (taken from the Tools.td file)::
41
42 def llvm_gcc_cpp : Tool<[
43 (in_language "c++"),
44 (out_language "llvm-assembler"),
45 (output_suffix "bc"),
46 (cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"),
47 (sink)
48 ]>;
49
50 This defines a new tool called ``llvm_gcc_cpp``, which is an alias for
51 ``llvm-g++``. As you can see, a tool definition is just a list of
52 properties; most of them should be self-evident. The ``sink`` property
53 means that this tool should be passed all command-line options that
54 aren't handled by the other tools.
55
56 The complete list of the currently implemented tool properties follows:
57
58 * Possible tool properties:
59 - in_language - input language name.
60
61 - out_language - output language name.
62
63 - output_suffix - output file suffix.
64
65 - cmd_line - the actual command used to run the tool. You can use
66 ``$INFILE`` and ``$OUTFILE`` variables.
67
68 - join - this tool is a "join node" in the graph, i.e. it gets a
69 list of input files and joins them together. Used for linkers.
70
71 - sink - all command-line options that are not handled by other
72 tools are passed to this tool.
73
74 The next tool definition is slightly more complex::
75
76 def llvm_gcc_linker : Tool<[
77 (in_language "object-code"),
78 (out_language "executable"),
79 (output_suffix "out"),
80 (cmd_line "llvm-gcc $INFILE -o $OUTFILE"),
81 (join),
82 (prefix_list_option "L", (forward), (help "add a directory to link path")),
83 (prefix_list_option "l", (forward), (help "search a library when linking")),
84 (prefix_list_option "Wl", (unpack_values), (help "pass options to linker"))
85 ]>;
86
87 This tool has a "join" property, which means that it behaves like a
88 linker (because of that this tool should be the last in the
89 toolchain). This tool also defines several command-line options: ``-l``,
90 ``-L`` and ``-Wl`` which have their usual meaning. An option has two
91 attributes: a name and a (possibly empty) list of properties. All
92 currently implemented option types and properties are described below:
93
94 * Possible option types:
95 - switch_option - a simple boolean switch, for example ``-time``.
96
97 - parameter_option - option that takes an argument, for example ``-std=c99``;
98
99 - parameter_list_option - same as the above, but more than one
100 occurence of the option is allowed.
101
102 - prefix_option - same as the parameter_option, but the option name
103 and parameter value are not separated.
104
105 - prefix_list_option - same as the above, but more than one
106 occurence of the option is allowed; example: ``-lm -lpthread``.
107
108 * Possible option properties:
109 - append_cmd - append a string to the tool invocation command.
110
111 - forward - forward this option unchanged.
112
113 - stop_compilation - stop compilation after this phase.
114
115 - unpack_values - used for for splitting and forwarding
116 comma-separated lists of options, e.g. ``-Wa,-foo=bar,-baz`` is
117 converted to ``-foo=bar -baz`` and appended to the tool invocation
118 command.
119
120 - help - help string associated with this option.
121
122 - required - this option is obligatory.
123
124 Language map
125 ------------
126
127 One last bit that you probably should change is the language map,
128 which defines mappings between language names and file extensions. It
129 is used internally to choose the proper toolchain based on the names
130 of the input files. Language map definition is located in the file
131 ``Tools.td`` and looks like this::
132
133 def LanguageMap : LanguageMap<
134 [LangToSuffixes<"c++", ["cc", "cp", "cxx", "cpp", "CPP", "c++", "C"]>,
135 LangToSuffixes<"c", ["c"]>,
136 ...
137 ]>;
138
139
140 Putting it all together
141 -----------------------
142
143 Since at the time of writing LLVMCC does not support on-the-fly
144 reloading of the configuration, the only way to test your changes is
145 to recompile the program. To do this, ``cd`` to the source code
146 directory and run ``make``.
147
148 References
149 ==========
150
151 .. [1] TableGen Fundamentals
152 http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html
0 //===--- llvmcc.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 // This tool provides a single point of access to the LLVM
10 // compilation tools. It has many options. To discover the options
11 // supported please refer to the tools' manual page or run the tool
12 // with the --help option.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "Core.h"
17 #include "Utility.h"
18 #include "Tools.h"
19
20 #include "llvm/System/Path.h"
21 #include "llvm/Support/CommandLine.h"
22
23 #include
24 #include
25 #include
26
27 using namespace llvm;
28 using namespace llvmcc;
29
30 // These variables are also used in Core.cpp,
31 // so they should have external linkage.
32 cl::list InputFilenames(cl::Positional,
33 cl::desc(""), cl::OneOrMore);
34 cl::opt OutputFilename("o", cl::desc("Output file name"),
35 cl::value_desc("file"));
36 cl::opt VerboseMode("v", cl::desc("Enable verbose mode"));
37
38
39 namespace {
40 int BuildTargets(const CompilationGraph& graph) {
41 int ret;
42 sys::Path tempDir(sys::Path::GetTemporaryDirectory());
43
44 try {
45 ret = graph.Build(tempDir);
46 }
47 catch(...) {
48 tempDir.eraseFromDisk(true);
49 throw;
50 }
51
52 tempDir.eraseFromDisk(true);
53 return ret;
54 }
55 }
56
57 int main(int argc, char** argv) {
58 try {
59 CompilationGraph graph;
60
61 cl::ParseCommandLineOptions(argc, argv,
62 "LLVM Compiler Driver(Work In Progress)");
63 PopulateCompilationGraph(graph);
64 return BuildTargets(graph);
65 }
66 catch(const std::exception& ex) {
67 std::cerr << ex.what() << '\n';
68 }
69 catch(...) {
70 std::cerr << "Unknown error!\n";
71 }
72 }
0 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
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 LLVMCC configuration code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "LLVMCCConfigurationEmitter.h"
14 #include "Record.h"
15
16 #include "llvm/ADT/IntrusiveRefCntPtr.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/Support/Streams.h"
21
22 #include
23 #include
24 #include
25 #include
26
27 using namespace llvm;
28
29 namespace {
30
31 //===----------------------------------------------------------------------===//
32 /// Typedefs
33
34 typedef std::vector RecordVector;
35 typedef std::vector StrVector;
36
37 //===----------------------------------------------------------------------===//
38 /// Constants
39
40 // Indentation strings
41 const char * Indent1 = " ";
42 const char * Indent2 = " ";
43 const char * Indent3 = " ";
44 const char * Indent4 = " ";
45
46 // Default help string
47 const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED";
48
49 // Name for the "sink" option
50 const char * SinkOptionName = "AutoGeneratedSinkOption";
51
52 //===----------------------------------------------------------------------===//
53 /// Helper functions
54
55 std::string InitPtrToString(Init* ptr) {
56 StringInit& val = dynamic_cast(*ptr);
57 return val.getValue();
58 }
59
60 //===----------------------------------------------------------------------===//
61 /// Back-end specific code
62
63 // A command-line option can have one of the following types:
64 //
65 // Switch - a simple switch w/o arguments, e.g. -O2
66 //
67 // Parameter - an option that takes one(and only one) argument, e.g. -o file,
68 // --output=file
69 //
70 // ParameterList - same as Parameter, but more than one occurence
71 // of the option is allowed, e.g. -lm -lpthread
72 //
73 // Prefix - argument is everything after the prefix,
74 // e.g. -Wa,-foo,-bar, -DNAME=VALUE
75 //
76 // PrefixList - same as Prefix, but more than one option occurence is
77 // allowed
78
79 namespace OptionType {
80 enum OptionType { Switch, Parameter, ParameterList, Prefix, PrefixList};
81 }
82
83 bool IsListOptionType (OptionType::OptionType t) {
84 return (t == OptionType::ParameterList || t == OptionType::PrefixList);
85 }
86
87 // Code duplication here is necessary because one option can affect
88 // several tools and those tools may have different actions associated
89 // with this option. GlobalOptionDescriptions are used to generate
90 // the option registration code, while ToolOptionDescriptions are used
91 // to generate tool-specific code.
92
93 // Base class for option descriptions
94
95 struct OptionDescription {
96 OptionType::OptionType Type;
97 std::string Name;
98
99 OptionDescription(OptionType::OptionType t = OptionType::Switch,
100 const std::string& n = "")
101 : Type(t), Name(n)
102 {}
103
104 const char* GenTypeDeclaration() const {
105 switch (Type) {
106 case OptionType::PrefixList:
107 case OptionType::ParameterList:
108 return "cl::list";
109 case OptionType::Switch:
110 return "cl::opt";
111 case OptionType::Parameter:
112 case OptionType::Prefix:
113 default:
114 return "cl::opt";
115 }
116 }
117
118 std::string GenVariableName() const {
119 switch (Type) {
120 case OptionType::Switch:
121 return "AutoGeneratedSwitch" + Name;
122 case OptionType::Prefix:
123 return "AutoGeneratedPrefix" + Name;
124 case OptionType::PrefixList:
125 return "AutoGeneratedPrefixList" + Name;
126 case OptionType::Parameter:
127 return "AutoGeneratedParameter" + Name;
128 case OptionType::ParameterList:
129 default:
130 return "AutoGeneratedParameterList" + Name;
131 }
132 }
133
134 };
135
136 // Global option description
137
138 namespace GlobalOptionDescriptionFlags {
139 enum GlobalOptionDescriptionFlags { Required = 0x1 };
140 }
141
142 struct GlobalOptionDescription : public OptionDescription {
143 std::string Help;
144 unsigned Flags;
145
146 // StringMap can only store DefaultConstructible objects
147 GlobalOptionDescription() : OptionDescription(), Flags(0)
148 {}
149
150 GlobalOptionDescription (OptionType::OptionType t, const std::string& n)
151 : OptionDescription(t, n), Help(DefaultHelpString), Flags(0)
152 {}
153
154 bool isRequired() const {
155 return Flags & GlobalOptionDescriptionFlags::Required;
156 }
157 void setRequired() {
158 Flags |= GlobalOptionDescriptionFlags::Required;
159 }
160
161 // Merge two option descriptions
162 void Merge (const GlobalOptionDescription& other)
163 {
164 if (other.Type != Type)
165 throw "Conflicting definitions for the option " + Name + "!";
166
167 if (Help.empty() && !other.Help.empty())
168 Help = other.Help;
169 else if (!Help.empty() && !other.Help.empty())
170 cerr << "Warning: more than one help string defined for option "
171 + Name + "\n";
172
173 Flags |= other.Flags;
174 }
175 };
176
177 // A GlobalOptionDescription array
178 // + some flags affecting generation of option declarations
179 struct GlobalOptionDescriptions {
180 typedef StringMap container_type;
181 typedef container_type::const_iterator const_iterator;
182
183 // A list of GlobalOptionDescriptions
184 container_type Descriptions;
185 // Should the emitter generate a "cl::sink" option?
186 bool HasSink;
187
188 // Support for STL-style iteration
189 const_iterator begin() const { return Descriptions.begin(); }
190 const_iterator end() const { return Descriptions.end(); }
191 };
192
193
194 // Tool-local option description
195
196 // Properties without arguments are implemented as flags
197 namespace ToolOptionDescriptionFlags {
198 enum ToolOptionDescriptionFlags { StopCompilation = 0x1,
199 Forward = 0x2, UnpackValues = 0x4};
200 }
201 namespace OptionPropertyType {
202 enum OptionPropertyType { AppendCmd };
203 }
204
205 typedef std::pair
206 OptionProperty;
207 typedef SmallVector OptionPropertyList;
208
209 struct ToolOptionDescription : public OptionDescription {
210 unsigned Flags;
211 OptionPropertyList Props;
212
213 // StringMap can only store DefaultConstructible objects
214 ToolOptionDescription() : OptionDescription() {}
215
216 ToolOptionDescription (OptionType::OptionType t, const std::string& n)
217 : OptionDescription(t, n)
218 {}
219
220 // Various boolean properties
221 bool isStopCompilation() const {
222 return Flags & ToolOptionDescriptionFlags::StopCompilation;
223 }
224 void setStopCompilation() {
225 Flags |= ToolOptionDescriptionFlags::StopCompilation;
226 }
227
228 bool isForward() const {
229 return Flags & ToolOptionDescriptionFlags::Forward;
230 }
231 void setForward() {
232 Flags |= ToolOptionDescriptionFlags::Forward;
233 }
234
235 bool isUnpackValues() const {
236 return Flags & ToolOptionDescriptionFlags::UnpackValues;
237 }
238 void setUnpackValues() {
239 Flags |= ToolOptionDescriptionFlags::UnpackValues;
240 }
241
242 void AddProperty (OptionPropertyType::OptionPropertyType t,
243 const std::string& val)
244 {
245 Props.push_back(std::make_pair(t, val));
246 }
247 };
248
249 typedef StringMap ToolOptionDescriptions;
250
251 // Tool information record
252
253 namespace ToolFlags {
254 enum ToolFlags { Join = 0x1, Sink = 0x2 };
255 }
256
257 struct ToolProperties : public RefCountedBase {
258 std::string Name;
259 StrVector CmdLine;
260 std::string InLanguage;
261 std::string OutLanguage;
262 std::string OutputSuffix;
263 unsigned Flags;
264 ToolOptionDescriptions OptDescs;
265
266 // Various boolean properties
267 void setSink() { Flags |= ToolFlags::Sink; }
268 bool isSink() const { return Flags & ToolFlags::Sink; }
269 void setJoin() { Flags |= ToolFlags::Join; }
270 bool isJoin() const { return Flags & ToolFlags::Join; }
271
272 // Default ctor here is needed because StringMap can only store
273 // DefaultConstructible objects
274 ToolProperties() {}
275 ToolProperties (const std::string& n) : Name(n) {}
276 };
277
278
279 // A list of Tool information records
280 // IntrusiveRefCntPtrs are used because StringMap has no copy constructor
281 // (and we want to avoid copying ToolProperties anyway)
282 typedef std::vector > ToolPropertiesList;
283
284
285 // Function object for iterating over a list of tool property records
286 class CollectProperties {
287 private:
288
289 /// Implementation details
290
291 // "Property handler" - a function that extracts information
292 // about a given tool property from its DAG representation
293 typedef void (CollectProperties::*PropertyHandler)(DagInit*);
294
295 // Map from property names -> property handlers
296 typedef StringMap PropertyHandlerMap;
297
298 // "Option property handler" - a function that extracts information
299 // about a given option property from its DAG representation
300 typedef void (CollectProperties::*
301 OptionPropertyHandler)(DagInit*, GlobalOptionDescription &);
302
303 // Map from option property names -> option property handlers
304 typedef StringMap OptionPropertyHandlerMap;
305
306 // Static maps from strings to CollectProperties methods("handlers")
307 static PropertyHandlerMap propertyHandlers_;
308 static OptionPropertyHandlerMap optionPropertyHandlers_;
309 static bool staticMembersInitialized_;
310
311
312 /// This is where the information is stored
313
314 // Current Tool properties
315 ToolProperties& toolProps_;
316 // OptionDescriptions table(used to register options globally)
317 GlobalOptionDescriptions& optDescs_;
318
319 public:
320
321 explicit CollectProperties (ToolProperties& p, GlobalOptionDescriptions& d)
322 : toolProps_(p), optDescs_(d)
323 {
324 if (!staticMembersInitialized_) {
325 // Init tool property handlers
326 propertyHandlers_["cmd_line"] = &CollectProperties::onCmdLine;
327 propertyHandlers_["in_language"] = &CollectProperties::onInLanguage;
328 propertyHandlers_["join"] = &CollectProperties::onJoin;
329 propertyHandlers_["out_language"] = &CollectProperties::onOutLanguage;
330 propertyHandlers_["output_suffix"] = &CollectProperties::onOutputSuffix;
331 propertyHandlers_["parameter_option"]
332 = &CollectProperties::onParameter;
333 propertyHandlers_["parameter_list_option"] =
334 &CollectProperties::onParameterList;
335 propertyHandlers_["prefix_option"] = &CollectProperties::onPrefix;
336 propertyHandlers_["prefix_list_option"] =
337 &CollectProperties::onPrefixList;
338 propertyHandlers_["sink"] = &CollectProperties::onSink;
339 propertyHandlers_["switch_option"] = &CollectProperties::onSwitch;
340
341 // Init option property handlers
342 optionPropertyHandlers_["append_cmd"] = &CollectProperties::onAppendCmd;
343 optionPropertyHandlers_["forward"] = &CollectProperties::onForward;
344 optionPropertyHandlers_["help"] = &CollectProperties::onHelp;
345 optionPropertyHandlers_["required"] = &CollectProperties::onRequired;
346 optionPropertyHandlers_["stop_compilation"] =
347 &CollectProperties::onStopCompilation;
348 optionPropertyHandlers_["unpack_values"] =
349 &CollectProperties::onUnpackValues;
350
351 staticMembersInitialized_ = true;
352 }
353 }
354
355 // Gets called for every tool property;
356 // Just forwards to the corresponding property handler.
357 void operator() (Init* i) {
358 DagInit& d = dynamic_cast(*i);
359 std::string property_name = d.getOperator()->getAsString();
360 PropertyHandlerMap::iterator method
361 = propertyHandlers_.find(property_name);
362
363 if (method != propertyHandlers_.end()) {
364 PropertyHandler h = method->second;
365 (this->*h)(&d);
366 }
367 else {
368 throw "Unknown tool property: " + property_name + "!";
369 }
370 }
371
372 private:
373
374 /// Property handlers --
375 /// Functions that extract information about tool properties from
376 /// DAG representation.
377
378 void onCmdLine (DagInit* d) {
379 checkNumberOfArguments(d, 1);
380 SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
381 if (toolProps_.CmdLine.empty())
382 throw std::string("Tool " + toolProps_.Name + " has empty command line!");
383 }
384
385 void onInLanguage (DagInit* d) {
386 checkNumberOfArguments(d, 1);
387 toolProps_.InLanguage = InitPtrToString(d->getArg(0));
388 }
389
390 void onJoin (DagInit* d) {
391 checkNumberOfArguments(d, 0);
392 toolProps_.setJoin();
393 }
394
395 void onOutLanguage (DagInit* d) {
396 checkNumberOfArguments(d, 1);
397 toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
398 }
399
400 void onOutputSuffix (DagInit* d) {
401 checkNumberOfArguments(d, 1);
402 toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
403 }
404
405 void onSink (DagInit* d) {
406 checkNumberOfArguments(d, 0);
407 optDescs_.HasSink = true;
408 toolProps_.setSink();
409 }
410
411 void onSwitch (DagInit* d) { addOption(d, OptionType::Switch); }
412 void onParameter (DagInit* d) { addOption(d, OptionType::Parameter); }
413 void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); }
414 void onPrefix (DagInit* d) { addOption(d, OptionType::Prefix); }
415 void onPrefixList (DagInit* d) { addOption(d, OptionType::PrefixList); }
416
417 /// Option property handlers --
418 /// Methods that handle properties that are common for all types of
419 /// options (like append_cmd, stop_compilation)
420
421 void onAppendCmd (DagInit* d, GlobalOptionDescription& o) {
422 checkNumberOfArguments(d, 1);
423 std::string const& cmd = InitPtrToString(d->getArg(0));
424
425 toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
426 }
427
428 void onForward (DagInit* d, GlobalOptionDescription& o) {
429 checkNumberOfArguments(d, 0);
430 toolProps_.OptDescs[o.Name].setForward();
431 }
432
433 void onHelp (DagInit* d, GlobalOptionDescription& o) {
434 checkNumberOfArguments(d, 1);
435 const std::string& help_message = InitPtrToString(d->getArg(0));
436
437 o.Help = help_message;
438 }
439
440 void onRequired (DagInit* d, GlobalOptionDescription& o) {
441 checkNumberOfArguments(d, 0);
442 o.setRequired();
443 }
444
445 void onStopCompilation (DagInit* d, GlobalOptionDescription& o) {
446 checkNumberOfArguments(d, 0);
447 if (o.Type != OptionType::Switch)
448 throw std::string("Only options of type Switch can stop compilation!");
449 toolProps_.OptDescs[o.Name].setStopCompilation();
450 }
451
452 void onUnpackValues (DagInit* d, GlobalOptionDescription& o) {
453 checkNumberOfArguments(d, 0);
454 toolProps_.OptDescs[o.Name].setUnpackValues();
455 }
456
457 /// Helper functions
458
459 // Add an option of type t
460 void addOption (DagInit* d, OptionType::OptionType t) {
461 checkNumberOfArguments(d, 2);
462 const std::string& name = InitPtrToString(d->getArg(0));
463
464 GlobalOptionDescription o(t, name);
465 toolProps_.OptDescs[name].Type = t;
466 toolProps_.OptDescs[name].Name = name;
467 processOptionProperties(d, o);
468 insertDescription(o);
469 }
470
471 // Ensure that the number of args in d is <= min_arguments,
472 // throw exception otherwise
473 void checkNumberOfArguments (DagInit* d, unsigned min_arguments) {
474 if (d->getNumArgs() < min_arguments)
475 throw "Property " + d->getOperator()->getAsString()
476 + " has too few arguments!";
477 }
478
479 // Insert new GlobalOptionDescription into GlobalOptionDescriptions list
480 void insertDescription (const GlobalOptionDescription& o)
481 {
482 if (optDescs_.Descriptions.count(o.Name)) {
483 GlobalOptionDescription& D = optDescs_.Descriptions[o.Name];
484 D.Merge(o);
485 }
486 else {
487 optDescs_.Descriptions[o.Name] = o;
488 }
489 }
490
491 // Go through the list of option properties and call a corresponding
492 // handler for each.
493 //
494 // Parameters:
495 // name - option name
496 // d - option property list
497 void processOptionProperties (DagInit* d, GlobalOptionDescription& o) {
498 // First argument is option name
499 checkNumberOfArguments(d, 2);
500
501 for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
502 DagInit& option_property
503 = dynamic_cast(*d->getArg(B));
504 const std::string& option_property_name
505 = option_property.getOperator()->getAsString();
506 OptionPropertyHandlerMap::iterator method
507 = optionPropertyHandlers_.find(option_property_name);
508
509 if (method != optionPropertyHandlers_.end()) {
510 OptionPropertyHandler h = method->second;
511 (this->*h)(&option_property, o);
512 }
513 else {
514 throw "Unknown option property: " + option_property_name + "!";
515 }
516 }
517 }
518 };
519
520 // Static members of CollectProperties
521 CollectProperties::PropertyHandlerMap
522 CollectProperties::propertyHandlers_;
523
524 CollectProperties::OptionPropertyHandlerMap
525 CollectProperties::optionPropertyHandlers_;
526
527 bool CollectProperties::staticMembersInitialized_ = false;
528
529
530 // Gather information from the parsed TableGen data
531 // (Basically a wrapper for CollectProperties)
532 void CollectToolProperties (RecordVector::const_iterator B,
533 RecordVector::const_iterator E,
534 ToolPropertiesList& TPList,
535 GlobalOptionDescriptions& OptDescs)
536 {
537 // Iterate over a properties list of every Tool definition
538 for (;B!=E;++B) {
539 RecordVector::value_type T = *B;
540 ListInit* PropList = T->getValueAsListInit("properties");
541 if (!PropList)
542 throw std::string("Tool has no property list!");
543
544 IntrusiveRefCntPtr
545 ToolProps(new ToolProperties(T->getName()));
546
547 std::for_each(PropList->begin(), PropList->end(),
548 CollectProperties(*ToolProps, OptDescs));
549 TPList.push_back(ToolProps);
550 }
551 }
552
553 // Used by EmitGenerateActionMethod
554 void EmitOptionPropertyHandlingCode (const ToolProperties& P,
555 const ToolOptionDescription& D,
556 std::ostream& O)
557 {
558 // if clause
559 O << Indent2 << "if (";
560 if (D.Type == OptionType::Switch)
561 O << D.GenVariableName();
562 else
563 O << '!' << D.GenVariableName() << ".empty()";
564
565 O <<") {\n";
566
567 // Handle option properties that take an argument
568 for (OptionPropertyList::const_iterator B = D.Props.begin(),
569 E = D.Props.end(); B!=E; ++B) {
570 const OptionProperty& val = *B;
571
572 switch (val.first) {
573 // (append_cmd cmd) property
574 case OptionPropertyType::AppendCmd:
575 O << Indent3 << "vec.push_back(\"" << val.second << "\");\n";
576 break;
577 // Other properties with argument
578 default:
579 break;
580 }
581 }
582
583 // Handle flags
584
585 // (forward) property
586 if (D.isForward()) {
587 switch (D.Type) {
588 case OptionType::Switch:
589 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
590 break;
591 case OptionType::Parameter:
592 O << Indent3 << "vec.push_back(\"-" << D.Name << "\");\n";
593 O << Indent3 << "vec.push_back(" << D.GenVariableName() << ");\n";
594 break;
595 case OptionType::Prefix:
596 O << Indent3 << "vec.push_back(\"-" << D.Name << "\" + "
597 << D.GenVariableName() << ");\n";
598 break;
599 case OptionType::PrefixList:
600 O << Indent3 << "for (" << D.GenTypeDeclaration()
601 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
602 << Indent3 << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"
603 << Indent4 << "vec.push_back(\"-" << D.Name << "\" + "
604 << "*B);\n";
605 break;
606 case OptionType::ParameterList:
607 O << Indent3 << "for (" << D.GenTypeDeclaration()
608 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
609 << Indent3 << "E = " << D.GenVariableName()
610 << ".end() ; B != E; ++B) {\n"
611 << Indent4 << "vec.push_back(\"-" << D.Name << "\");\n"
612 << Indent4 << "vec.push_back(*B);\n"
613 << Indent3 << "}\n";
614 break;
615 }
616 }
617
618 // (unpack_values) property
619 if (D.isUnpackValues()) {
620 if (IsListOptionType(D.Type)) {
621 O << Indent3 << "for (" << D.GenTypeDeclaration()
622 << "::iterator B = " << D.GenVariableName() << ".begin(),\n"
623 << Indent3 << "E = " << D.GenVariableName()
624 << ".end(); B != E; ++B)\n"
625 << Indent4 << "UnpackValues(*B, vec);\n";
626 }
627 else if (D.Type == OptionType::Prefix || D.Type == OptionType::Parameter){
628 O << Indent3 << "UnpackValues("
629 << D.GenVariableName() << ", vec);\n";
630 }
631 else {
632 // TOFIX: move this to the type-checking phase
633 throw std::string("Switches can't have unpack_values property!");
634 }
635 }
636
637 // close if clause
638 O << Indent2 << "}\n";
639 }
640
641 // Emite one of two versions of GenerateAction method
642 void EmitGenerateActionMethod (const ToolProperties& P, int V, std::ostream& O)
643 {
644 assert(V==1 || V==2);
645 if (V==1)
646 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n";
647 else
648 O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n";
649
650 O << Indent2 << "const sys::Path& outFile) const\n"
651 << Indent1 << "{\n"
652 << Indent2 << "std::vector vec;\n";
653
654 // Parse CmdLine tool property
655 StrVector::const_iterator I = P.CmdLine.begin();
656 ++I;
657 for (StrVector::const_iterator E = P.CmdLine.end(); I != E; ++I) {
658 const std::string& cmd = *I;
659 O << Indent2;
660 if (cmd == "$INFILE") {
661 if (V==1)
662 O << "for (PathVector::const_iterator B = inFiles.begin()"
663 << ", E = inFiles.end();\n"
664 << Indent2 << "B != E; ++B)\n"
665 << Indent3 << "vec.push_back(B->toString());\n";
666 else
667 O << "vec.push_back(inFile.toString());\n";
668 }
669 else if (cmd == "$OUTFILE") {
670 O << "vec.push_back(outFile.toString());\n";
671 }
672 else {
673 O << "vec.push_back(\"" << cmd << "\");\n";
674 }
675 }
676
677 // For every understood option, emit handling code
678 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
679 E = P.OptDescs.end(); B != E; ++B) {
680 const ToolOptionDescription& val = B->second;
681 EmitOptionPropertyHandlingCode(P, val, O);
682 }
683
684 // Handle Sink property
685 if (P.isSink()) {
686 O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n"
687 << Indent3 << "vec.insert(vec.end(), "
688 << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n"
689 << Indent2 << "}\n";
690 }
691
692 O << Indent2 << "return Action(\"" << P.CmdLine.at(0) << "\", vec);\n"
693 << Indent1 << "}\n\n";
694 }
695
696 // Emit GenerateAction methods for Tool classes
697 void EmitGenerateActionMethods (const ToolProperties& P, std::ostream& O) {
698
699 if (!P.isJoin())
700 O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"
701 << Indent2 << "const llvm::sys::Path& outFile) const\n"
702 << Indent1 << "{\n"
703 << Indent2 << "throw std::runtime_error(\"" << P.Name
704 << " is not a Join tool!\");\n"
705 << Indent1 << "}\n\n";
706 else
707 EmitGenerateActionMethod(P, 1, O);
708
709 EmitGenerateActionMethod(P, 2, O);
710 }
711
712 // Emit IsLast() method for Tool classes
713 void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
714 O << Indent1 << "bool IsLast() const {\n"
715 << Indent2 << "bool last = false;\n";
716
717 for (ToolOptionDescriptions::const_iterator B = P.OptDescs.begin(),
718 E = P.OptDescs.end(); B != E; ++B) {
719 const ToolOptionDescription& val = B->second;
720
721 if (val.isStopCompilation())
722 O << Indent2
723 << "if (" << val.GenVariableName()
724 << ")\n" << Indent3 << "last = true;\n";
725 }
726
727 O << Indent2 << "return last;\n"
728 << Indent1 << "}\n\n";
729 }
730
731 // Emit static [Input,Output]Language() methods for Tool classes
732 void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
733 O << Indent1 << "std::string InputLanguage() const {\n"
734 << Indent2 << "return \"" << P.InLanguage << "\";\n"
735 << Indent1 << "}\n\n";
736
737 O << Indent1 << "std::string OutputLanguage() const {\n"
738 << Indent2 << "return \"" << P.OutLanguage << "\";\n"
739 << Indent1 << "}\n\n";
740 }
741
742 // Emit static [Input,Output]Language() methods for Tool classes
743 void EmitOutputSuffixMethod (const ToolProperties& P, std::ostream& O) {
744 O << Indent1 << "std::string OutputSuffix() const {\n"
745 << Indent2 << "return \"" << P.OutputSuffix << "\";\n"
746 << Indent1 << "}\n\n";
747 }
748
749 // Emit static Name() method for Tool classes
750 void EmitNameMethod (const ToolProperties& P, std::ostream& O) {
751 O << Indent1 << "std::string Name() const {\n"
752 << Indent2 << "return \"" << P.Name << "\";\n"
753 << Indent1 << "}\n\n";
754 }
755
756 // Emit static Name() method for Tool classes
757 void EmitIsJoinMethod (const ToolProperties& P, std::ostream& O) {
758 O << Indent1 << "bool IsJoin() const {\n";
759 if (P.isJoin())
760 O << Indent2 << "return true;\n";
761 else
762 O << Indent2 << "return false;\n";
763 O << Indent1 << "}\n\n";
764 }
765
766 // Emit a Tool class definition
767 void EmitToolClassDefinition (const ToolProperties& P, std::ostream& O) {
768 // Header
769 O << "class " << P.Name << " : public Tool {\n"
770 << "public:\n";
771
772 EmitNameMethod(P, O);
773 EmitInOutLanguageMethods(P, O);
774 EmitOutputSuffixMethod(P, O);
775 EmitIsJoinMethod(P, O);
776 EmitGenerateActionMethods(P, O);
777 EmitIsLastMethod(P, O);
778
779 // Close class definition
780 O << "};\n\n";
781 }
782
783 // Iterate over a list of option descriptions and emit registration code
784 void EmitOptionDescriptions (const GlobalOptionDescriptions& descs,
785 std::ostream& O)
786 {
787 // Emit static cl::Option variables
788 for (GlobalOptionDescriptions::const_iterator B = descs.begin(),
789 E = descs.end(); B!=E; ++B) {
790 const GlobalOptionDescription& val = B->second;
791
792 O << val.GenTypeDeclaration() << ' '
793 << val.GenVariableName()
794 << "(\"" << val.Name << '\"';
795
796 if (val.Type == OptionType::Prefix || val.Type == OptionType::PrefixList)
797 O << ", cl::Prefix";
798
799 if (val.isRequired()) {
800 switch (val.Type) {
801 case OptionType::PrefixList:
802 case OptionType::ParameterList:
803 O << ", cl::OneOrMore";
804 break;
805 default:
806 O << ", cl::Required";
807 }
808 }
809
810 O << ", cl::desc(\"" << val.Help << "\"));\n";
811 }
812
813 if (descs.HasSink)
814 O << "cl::list " << SinkOptionName << "(cl::Sink);\n";
815
816 O << '\n';
817 }
818
819 void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
820 {
821 // Get the relevant field out of RecordKeeper
822 Record* LangMapRecord = Records.getDef("LanguageMap");
823 if (!LangMapRecord)
824 throw std::string("Language map definition not found!");
825
826 ListInit* LangsToSuffixesList = LangMapRecord->getValueAsListInit("map");
827 if (!LangsToSuffixesList)
828 throw std::string("Error in the language map definition!");
829
830 // Generate code
831 O << "void llvmcc::PopulateLanguageMap(LanguageMap& language_map) {\n";
832
833 for (unsigned i = 0; i < LangsToSuffixesList->size(); ++i) {
834 Record* LangToSuffixes = LangsToSuffixesList->getElementAsRecord(i);
835
836 const std::string& Lang = LangToSuffixes->getValueAsString("lang");
837 const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");
838
839 for (unsigned i = 0; i < Suffixes->size(); ++i)
840 O << Indent1 << "language_map[\""
841 << InitPtrToString(Suffixes->getElement(i))
842 << "\"] = \"" << Lang << "\";\n";
843 }
844
845 O << "}\n\n";
846 }
847
848 void EmitPopulateCompilationGraph (const RecordKeeper& Records,
849 StringMap& ToolToLang,
850 std::ostream& O)
851 {
852 // Get the relevant field out of RecordKeeper
853 Record* ToolChains = Records.getDef("ToolChains");
854 if (!ToolChains)
855 throw std::string("No ToolChains specification found!");
856 ListInit* chains = ToolChains->getValueAsListInit("chains");
857 if (!chains)
858 throw std::string("Error in toolchain list definition!");
859
860 // Generate code
861 O << "void llvmcc::PopulateCompilationGraph(CompilationGraph& G) {\n"
862 << Indent1 << "PopulateLanguageMap(G.ExtsToLangs);\n"
863 << Indent1 << "std::vector > vec;\n\n";
864
865 for (unsigned i = 0; i < chains->size(); ++i) {
866 Record* ToolChain = chains->getElementAsRecord(i);
867 ListInit* Tools = ToolChain->getValueAsListInit("tools");
868
869 // Get name of the first tool in the list
870 const std::string& firstTool =
871 dynamic_cast(**Tools->begin()).getDef()->getName();
872
873 for (ListInit::iterator B = Tools->begin(),
874 E = Tools->end(); B != E; ++B) {
875 Record* val = dynamic_cast(**B).getDef();
876 O << Indent1 << "vec.push_back(IntrusiveRefCntPtr(new "
877 << val->getName() << "()));\n";
878 }
879 O << Indent1 << "G.ToolChains[\"" << ToolToLang[firstTool]
880 << "\"] = vec;\n";
881 O << Indent1 << "vec.clear();\n\n";
882 }
883
884 O << "}\n\n";
885 }
886
887 void FillInToolToLang (const ToolPropertiesList& T,
888 StringMap& M) {
889 for (ToolPropertiesList::const_iterator B = T.begin(), E = T.end();
890 B != E; ++B) {
891 const ToolProperties& P = *(*B);
892 M[P.Name] = P.InLanguage;
893 }
894 }
895
896 // End of anonymous namespace
897 }
898
899 // Back-end entry point
900 void LLVMCCConfigurationEmitter::run (std::ostream &O) {
901 // Emit file header
902 EmitSourceFileHeader("LLVMCC Configuration Library", O);
903
904 // Get a list of all defined Tools
905 RecordVector Tools = Records.getAllDerivedDefinitions("Tool");
906 if (Tools.empty())
907 throw std::string("No tool definitions found!");
908
909 // Gather information from the Tool descriptions
910 ToolPropertiesList tool_props;
911 GlobalOptionDescriptions opt_descs;
912 CollectToolProperties(Tools.begin(), Tools.end(), tool_props, opt_descs);
913
914 // Emit global option registration code
915 EmitOptionDescriptions(opt_descs, O);
916
917 // Emit PopulateLanguageMap function
918 // (a language map maps from file extensions to language names)
919 EmitPopulateLanguageMap(Records, O);
920
921 // Emit Tool classes
922 for (ToolPropertiesList::const_iterator B = tool_props.begin(),
923 E = tool_props.end(); B!=E; ++B)
924 EmitToolClassDefinition(*(*B), O);
925
926 // Fill in table that maps tool names to languages
927 StringMap ToolToLang;
928 FillInToolToLang(tool_props, ToolToLang);
929
930 // Emit PopulateCompilationGraph function
931 EmitPopulateCompilationGraph(Records, ToolToLang, O);
932
933 // EOF
934 }
0 //===- LLVMCConfigurationEmitter.cpp - Generate LLVMCC config -------------===//
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 LLVMCC configuration code.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVMCCCONF_EMITTER_H
14 #define LLVMCCCONF_EMITTER_H
15
16 #include "TableGenBackend.h"
17
18 namespace llvm {
19 class LLVMCCConfigurationEmitter : public TableGenBackend {
20 RecordKeeper &Records;
21 public:
22 explicit LLVMCCConfigurationEmitter(RecordKeeper &R) : Records(R) {}
23
24 // run - Output the asmwriter, returning true on failure.
25 void run(std::ostream &o);
26 };
27 }
28
29 #endif //LLVMCCCONF_EMITTER_H
3030 #include "DAGISelEmitter.h"
3131 #include "SubtargetEmitter.h"
3232 #include "IntrinsicEmitter.h"
33 #include "LLVMCCConfigurationEmitter.h"
3334 #include
3435 #include
3536 #include
4041 PrintRecords,
4142 GenEmitter,
4243 GenRegisterEnums, GenRegister, GenRegisterHeader,
43 GenInstrEnums, GenInstrs, GenAsmWriter,
44 GenInstrEnums, GenInstrs, GenAsmWriter,
4445 GenCallingConv,
4546 GenDAGISel,
4647 GenSubtarget,
4748 GenIntrinsic,
49 GenLLVMCCConf,
4850 PrintEnums
4951 };
5052
7577 "Generate subtarget enumerations"),
7678 clEnumValN(GenIntrinsic, "gen-intrinsic",
7779 "Generate intrinsic information"),
80 clEnumValN(GenLLVMCCConf, "gen-llvmcc",
81 "Generate LLVMCC configuration library"),
7882 clEnumValN(PrintEnums, "print-enums",
7983 "Print enum values for a class"),
8084 clEnumValEnd));
179183 case GenIntrinsic:
180184 IntrinsicEmitter(Records).run(*Out);
181185 break;
186 case GenLLVMCCConf:
187 LLVMCCConfigurationEmitter(Records).run(*Out);
188 break;
182189 case PrintEnums:
183190 {
184191 std::vector Recs = Records.getAllDerivedDefinitions(Class);