blob: b9f7f3b8e155feef4f44680b8ac020ec7adc9ccb [file] [log] [blame]
John Criswelldc0de4f2003-09-18 16:22:26 +00001//===- genexec.cpp - Functions for generating executable files ------------===//
2//
3// This file contains functions for generating executable files once linking
4// has finished. This includes generating a shell script to run the JIT or
5// a native executable derived from the bytecode.
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Transforms/Utils/Linker.h"
10#include "llvm/Transforms/IPO.h"
11#include "llvm/Transforms/Scalar.h"
12#include "llvm/Target/TargetData.h"
13#include "llvm/Module.h"
14#include "llvm/PassManager.h"
15#include "llvm/Bytecode/WriteBytecodePass.h"
16#include "Support/SystemUtils.h"
17#include "util.h"
18
19#include <fstream>
20#include <string>
21#include <vector>
22
23//
24// Function: GenerateBytecode ()
25//
26// Description:
27// This function generates a bytecode file from the specified module.
28//
29// Inputs:
30// M - The module for which bytecode should be generated.
31// Strip - Flags whether symbols should be stripped from the output.
32// Internalize - Flags whether all symbols should be marked internal.
33// Out - Pointer to file stream to which to write the output.
34//
35// Outputs:
36// None.
37//
38// Return value:
39// 0 - No error.
40// 1 - Error.
41//
42int
43GenerateBytecode (Module * M,
44 bool Strip,
45 bool Internalize,
46 std::ofstream * Out)
47{
48 // In addition to just linking the input from GCC, we also want to spiff it up
49 // a little bit. Do this now.
50 PassManager Passes;
51
52 // Add an appropriate TargetData instance for this module...
53 Passes.add(new TargetData("gccld", M));
54
55 // Linking modules together can lead to duplicated global constants, only keep
56 // one copy of each constant...
57 //
58 Passes.add(createConstantMergePass());
59
60 // If the -s command line option was specified, strip the symbols out of the
61 // resulting program to make it smaller. -s is a GCC option that we are
62 // supporting.
63 //
64 if (Strip)
65 Passes.add(createSymbolStrippingPass());
66
67 // Often if the programmer does not specify proper prototypes for the
68 // functions they are calling, they end up calling a vararg version of the
69 // function that does not get a body filled in (the real function has typed
70 // arguments). This pass merges the two functions.
71 //
72 Passes.add(createFunctionResolvingPass());
73
74 if (Internalize) {
75 // Now that composite has been compiled, scan through the module, looking
76 // for a main function. If main is defined, mark all other functions
77 // internal.
78 //
79 Passes.add(createInternalizePass());
80 }
81
82 // Remove unused arguments from functions...
83 //
84 Passes.add(createDeadArgEliminationPass());
85
86 // The FuncResolve pass may leave cruft around if functions were prototyped
87 // differently than they were defined. Remove this cruft.
88 //
89 Passes.add(createInstructionCombiningPass());
90
91 // Delete basic blocks, which optimization passes may have killed...
92 //
93 Passes.add(createCFGSimplificationPass());
94
95 // Now that we have optimized the program, discard unreachable functions...
96 //
97 Passes.add(createGlobalDCEPass());
98
99 // Add the pass that writes bytecode to the output file...
100 Passes.add(new WriteBytecodePass(Out));
101
102 // Run our queue of passes all at once now, efficiently.
103 Passes.run(*M);
104
105 return 0;
106}
107
108//
109// Function: generate_assembly ()
110//
111// Description:
112// This function generates a native assembly language source file from the
113// specified bytecode file.
114//
115// Inputs:
116// InputFilename - The name of the output bytecode file.
117// OutputFilename - The name of the file to generate.
118// llc - The pathname to use for LLC.
119// envp - The environment to use when running LLC.
120//
121// Outputs:
122// None.
123//
124// Return value:
125// 0 - Success
126// 1 - Failure
127//
128int
129generate_assembly (std::string OutputFilename,
130 std::string InputFilename,
131 std::string llc,
132 char ** const envp)
133{
134 //
135 // Run LLC to convert the bytecode file into assembly code.
136 //
137 const char * cmd[8];
138
139 cmd[0] = llc.c_str();
140 cmd[1] = "-f";
141 cmd[2] = "-o";
142 cmd[3] = OutputFilename.c_str();
143 cmd[4] = InputFilename.c_str();
144 cmd[5] = NULL;
145 if ((ExecWait (cmd, envp)) == -1)
146 {
147 return 1;
148 }
149
150 return 0;
151}
152
153//
154// Function: generate_native ()
155//
156// Description:
157// This function generates a native assembly language source file from the
158// specified assembly source file.
159//
160// Inputs:
161// InputFilename - The name of the output bytecode file.
162// OutputFilename - The name of the file to generate.
163// Libraries - The list of libraries with which to link.
164// gcc - The pathname to use for GGC.
165// envp - A copy of the process's current environment.
166//
167// Outputs:
168// None.
169//
170// Return value:
171// 0 - Success
172// 1 - Failure
173//
174int
175generate_native (std::string OutputFilename,
176 std::string InputFilename,
177 std::vector<std::string> Libraries,
178 std::string gcc,
179 char ** const envp)
180{
181 //
182 // Remove these environment variables from the environment of the
183 // programs that we will execute. It appears that GCC sets these
184 // environment variables so that the programs it uses can configure
185 // themselves identically.
186 //
187 // However, when we invoke GCC below, we want it to use its normal
188 // configuration. Hence, we must sanitize it's environment.
189 //
190 char ** clean_env = copy_env (envp);
191 if (clean_env == NULL)
192 {
193 return 1;
194 }
195 remove_env ("LIBRARY_PATH", clean_env);
196 remove_env ("COLLECT_GCC_OPTIONS", clean_env);
197 remove_env ("GCC_EXEC_PREFIX", clean_env);
198 remove_env ("COMPILER_PATH", clean_env);
199 remove_env ("COLLECT_GCC", clean_env);
200
201 const char * cmd[8 + Libraries.size()];
202
203 //
204 // Run GCC to assemble and link the program into native code.
205 //
206 // Note:
207 // We can't just assemble and link the file with the system assembler
208 // and linker because we don't know where to put the _start symbol.
209 // GCC mysteriously knows how to do it.
210 //
211 unsigned int index=0;
212 cmd[index++] = gcc.c_str();
213 cmd[index++] = "-o";
214 cmd[index++] = OutputFilename.c_str();
215 cmd[index++] = InputFilename.c_str();
216 for (; (index - 4) < Libraries.size(); index++)
217 {
218 Libraries[index - 4] = "-l" + Libraries[index - 4];
219 cmd[index] = Libraries[index-4].c_str();
220 }
221 cmd[index++] = NULL;
222 if ((ExecWait (cmd, clean_env)) == -1)
223 {
224 return 1;
225 }
226
227 return 0;
228}