blob: 3fb22456028973327e4095a3b35ae4c388c751e2 [file] [log] [blame]
Chris Lattner1d496172003-04-19 22:44:38 +00001//===- gccld.cpp - LLVM 'ld' compatible linker ----------------------------===//
Chris Lattner5ff2e052002-01-24 19:12:12 +00002//
3// This utility is intended to be compatible with GCC, and follows standard
Chris Lattner1d496172003-04-19 22:44:38 +00004// system 'ld' conventions. As such, the default output file is ./a.out.
Chris Lattner5ff2e052002-01-24 19:12:12 +00005// Additionally, this program outputs a shell script that is used to invoke LLI
6// to execute the program. In this manner, the generated executable (a.out for
7// example), is directly executable, whereas the bytecode file actually lives in
8// the a.out.bc file generated by this program. Also, Force is on by default.
9//
10// Note that if someone (or a script) deletes the executable program generated,
11// the .bc file will be left around. Considering that this is a temporary hack,
Brian Gaeke5bfa37f2003-05-23 20:27:07 +000012// I'm not too worried about this.
Chris Lattner5ff2e052002-01-24 19:12:12 +000013//
14//===----------------------------------------------------------------------===//
15
Chris Lattner7608a462002-05-07 18:36:35 +000016#include "llvm/Transforms/Utils/Linker.h"
Chris Lattner5ff2e052002-01-24 19:12:12 +000017#include "llvm/Module.h"
Chris Lattner3b08c2f2002-04-08 00:14:58 +000018#include "llvm/PassManager.h"
19#include "llvm/Bytecode/Reader.h"
20#include "llvm/Bytecode/WriteBytecodePass.h"
Chris Lattnerd571e2a2003-04-24 19:13:02 +000021#include "llvm/Target/TargetData.h"
Chris Lattner35c45412002-07-23 22:04:43 +000022#include "llvm/Transforms/IPO.h"
Chris Lattner35c45412002-07-23 22:04:43 +000023#include "llvm/Transforms/Scalar.h"
John Criswell06327da2003-09-02 20:17:20 +000024#include "Support/FileUtilities.h"
John Criswellf22d8452003-09-17 15:20:51 +000025#include "Support/SystemUtils.h"
Chris Lattner5ff2e052002-01-24 19:12:12 +000026#include "Support/CommandLine.h"
Chris Lattnerc065ad82002-04-18 19:55:25 +000027#include "Support/Signals.h"
John Criswella3ce8b42003-09-02 21:11:22 +000028#include "Config/unistd.h"
John Criswell8ecc3022003-09-18 16:22:26 +000029#include "util.h"
30
Chris Lattner5ff2e052002-01-24 19:12:12 +000031#include <fstream>
32#include <memory>
Chris Lattner1d496172003-04-19 22:44:38 +000033#include <set>
Chris Lattner6f0d4532002-03-11 17:49:53 +000034#include <algorithm>
Chris Lattner5ff2e052002-01-24 19:12:12 +000035
John Criswell8ecc3022003-09-18 16:22:26 +000036//
37// External function prototypes
38//
39extern int
40GenerateBytecode (Module * M,
41 bool Strip,
42 bool Internalize,
43 std::ofstream * Out);
44
45extern int
46generate_assembly (std::string OutputFilename,
47 std::string InputFilename,
48 std::string llc,
49 char ** const envp);
50extern int
51generate_native (std::string OutputFilename,
52 std::string InputFilename,
53 std::vector<std::string> Libraries,
54 std::string gcc,
55 char ** const envp);
56
Chris Lattner2b3a5db2003-04-18 23:01:25 +000057namespace {
58 cl::list<std::string>
59 InputFilenames(cl::Positional, cl::desc("<input bytecode files>"),
60 cl::OneOrMore);
Chris Lattnerf5cad152002-07-22 02:10:13 +000061
Chris Lattner2b3a5db2003-04-18 23:01:25 +000062 cl::opt<std::string>
63 OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"),
64 cl::value_desc("filename"));
Chris Lattnerf5cad152002-07-22 02:10:13 +000065
Chris Lattner2b3a5db2003-04-18 23:01:25 +000066 cl::opt<bool>
67 Verbose("v", cl::desc("Print information about actions taken"));
68
69 cl::list<std::string>
70 LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix,
71 cl::value_desc("directory"));
Chris Lattnerf5cad152002-07-22 02:10:13 +000072
Chris Lattner2b3a5db2003-04-18 23:01:25 +000073 cl::list<std::string>
74 Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix,
75 cl::value_desc("library prefix"));
Chris Lattnerf5cad152002-07-22 02:10:13 +000076
Chris Lattner2b3a5db2003-04-18 23:01:25 +000077 cl::opt<bool>
78 Strip("s", cl::desc("Strip symbol info from executable"));
Chris Lattnerf5cad152002-07-22 02:10:13 +000079
Chris Lattner2b3a5db2003-04-18 23:01:25 +000080 cl::opt<bool>
81 NoInternalize("disable-internalize",
82 cl::desc("Do not mark all symbols as internal"));
Chris Lattnerb4d99212003-08-22 19:18:45 +000083 static cl::alias
84 ExportDynamic("export-dynamic", cl::desc("Alias for -disable-internalize"),
85 cl::aliasopt(NoInternalize));
Chris Lattner602d2092003-04-18 23:38:22 +000086
Chris Lattner1d496172003-04-19 22:44:38 +000087 cl::opt<bool>
88 LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a"
89 " library, not an executable"));
90
John Criswell1997a342003-09-16 21:27:35 +000091 cl::opt<bool>
92 Native("native", cl::desc("Generate a native binary instead of a shell script"));
93
John Criswell8ecc3022003-09-18 16:22:26 +000094 // Compatibility options that are ignored but supported by LD
Chris Lattner602d2092003-04-18 23:38:22 +000095 cl::opt<std::string>
96 CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored"));
97 cl::opt<std::string>
98 CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored"));
99 cl::opt<bool>
100 CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored"));
Chris Lattnere320c922003-05-27 19:15:11 +0000101 cl::opt<bool>
102 CO6("r", cl::Hidden, cl::desc("Compatibility option: ignored"));
Chris Lattner2b3a5db2003-04-18 23:01:25 +0000103}
Chris Lattner5ff2e052002-01-24 19:12:12 +0000104
105// FileExists - Return true if the specified string is an openable file...
106static inline bool FileExists(const std::string &FN) {
John Criswella3ce8b42003-09-02 21:11:22 +0000107 return access(FN.c_str(), F_OK) != -1;
Chris Lattner5ff2e052002-01-24 19:12:12 +0000108}
109
Chris Lattner5ff2e052002-01-24 19:12:12 +0000110
Chris Lattner1d496172003-04-19 22:44:38 +0000111// LoadObject - Read the specified "object file", which should not search the
112// library path to find it.
Chris Lattnera2d35042003-05-13 22:14:13 +0000113static inline std::auto_ptr<Module> LoadObject(std::string FN,
Chris Lattner1d496172003-04-19 22:44:38 +0000114 std::string &OutErrorMessage) {
115 if (Verbose) std::cerr << "Loading '" << FN << "'\n";
116 if (!FileExists(FN)) {
Chris Lattnera2d35042003-05-13 22:14:13 +0000117 // Attempt to load from the LLVM_LIB_SEARCH_PATH directory... if we would
118 // otherwise fail. This is used to locate objects like crtend.o.
119 //
120 char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");
121 if (SearchPath && FileExists(std::string(SearchPath)+"/"+FN))
122 FN = std::string(SearchPath)+"/"+FN;
123 else {
124 OutErrorMessage = "could not find input file '" + FN + "'!";
125 return std::auto_ptr<Module>();
126 }
Chris Lattner5ff2e052002-01-24 19:12:12 +0000127 }
128
Chris Lattner1d496172003-04-19 22:44:38 +0000129 std::string ErrorMessage;
130 Module *Result = ParseBytecodeFile(FN, &ErrorMessage);
131 if (Result) return std::auto_ptr<Module>(Result);
132
133 OutErrorMessage = "Bytecode file '" + FN + "' corrupt!";
134 if (ErrorMessage.size()) OutErrorMessage += ": " + ErrorMessage;
Chris Lattner5ff2e052002-01-24 19:12:12 +0000135 return std::auto_ptr<Module>();
136}
137
138
Chris Lattner1d496172003-04-19 22:44:38 +0000139static Module *LoadSingleLibraryObject(const std::string &Filename) {
140 std::string ErrorMessage;
141 std::auto_ptr<Module> M = LoadObject(Filename, ErrorMessage);
142 if (M.get() == 0 && Verbose) {
143 std::cerr << "Error loading '" + Filename + "'";
144 if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage;
145 std::cerr << "\n";
146 }
147
148 return M.release();
149}
150
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000151// LoadLibraryExactName - This looks for a file with a known name and tries to
152// load it, similarly to LoadLibraryFromDirectory().
Chris Lattner4c46c952003-05-29 15:13:15 +0000153static inline bool LoadLibraryExactName(const std::string &FileName,
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000154 std::vector<Module*> &Objects, bool &isArchive) {
155 if (Verbose) std::cerr << " Considering '" << FileName << "'\n";
156 if (FileExists(FileName)) {
Chris Lattner4c46c952003-05-29 15:13:15 +0000157 if (IsArchive(FileName)) {
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000158 std::string ErrorMessage;
159 if (Verbose) std::cerr << " Loading '" << FileName << "'\n";
160 if (!ReadArchiveFile(FileName, Objects, &ErrorMessage)) {
161 isArchive = true;
162 return false; // Success!
163 }
164 if (Verbose) {
165 std::cerr << " Error loading archive '" + FileName + "'";
166 if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage;
167 std::cerr << "\n";
168 }
169 } else {
170 if (Module *M = LoadSingleLibraryObject(FileName)) {
171 isArchive = false;
172 Objects.push_back(M);
173 return false;
174 }
Chris Lattner1d496172003-04-19 22:44:38 +0000175 }
176 }
Chris Lattner1d496172003-04-19 22:44:38 +0000177 return true;
178}
179
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000180// LoadLibrary - Try to load a library named LIBNAME that contains
181// LLVM bytecode. If SEARCH is true, then search for a file named
182// libLIBNAME.{a,so,bc} in the current library search path. Otherwise,
183// assume LIBNAME is the real name of the library file. This method puts
184// the loaded modules into the Objects list, and sets isArchive to true if
185// a .a file was loaded. It returns true if no library is found or if an
186// error occurs; otherwise it returns false.
Chris Lattner1d496172003-04-19 22:44:38 +0000187//
188static inline bool LoadLibrary(const std::string &LibName,
189 std::vector<Module*> &Objects, bool &isArchive,
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000190 bool search, std::string &ErrorMessage) {
191 if (search) {
192 // First, try the current directory. Then, iterate over the
193 // directories in LibPaths, looking for a suitable match for LibName
194 // in each one.
195 for (unsigned NextLibPathIdx = 0; NextLibPathIdx != LibPaths.size();
Chris Lattner4c46c952003-05-29 15:13:15 +0000196 ++NextLibPathIdx) {
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000197 std::string Directory = LibPaths[NextLibPathIdx] + "/";
198 if (!LoadLibraryExactName(Directory + "lib" + LibName + ".a",
199 Objects, isArchive))
200 return false;
201 if (!LoadLibraryExactName(Directory + "lib" + LibName + ".so",
202 Objects, isArchive))
203 return false;
204 if (!LoadLibraryExactName(Directory + "lib" + LibName + ".bc",
205 Objects, isArchive))
206 return false;
207 }
208 } else {
209 // If they said no searching, then assume LibName is the real name.
210 if (!LoadLibraryExactName(LibName, Objects, isArchive))
Chris Lattner1d496172003-04-19 22:44:38 +0000211 return false;
Chris Lattner1d496172003-04-19 22:44:38 +0000212 }
Chris Lattner1d496172003-04-19 22:44:38 +0000213 ErrorMessage = "error linking library '-l" + LibName+ "': library not found!";
214 return true;
215}
216
Chris Lattner1d496172003-04-19 22:44:38 +0000217
218static bool LinkLibrary(Module *M, const std::string &LibName,
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000219 bool search, std::string &ErrorMessage) {
Chris Lattnera2d35042003-05-13 22:14:13 +0000220 std::set<std::string> UndefinedSymbols;
221 GetAllUndefinedSymbols(M, UndefinedSymbols);
222 if (UndefinedSymbols.empty()) {
223 if (Verbose) std::cerr << " No symbols undefined, don't link library!\n";
224 return false; // No need to link anything in!
225 }
226
Chris Lattner1d496172003-04-19 22:44:38 +0000227 std::vector<Module*> Objects;
228 bool isArchive;
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000229 if (LoadLibrary(LibName, Objects, isArchive, search, ErrorMessage))
230 return true;
Chris Lattner1d496172003-04-19 22:44:38 +0000231
232 // Figure out which symbols are defined by all of the modules in the .a file
233 std::vector<std::set<std::string> > DefinedSymbols;
234 DefinedSymbols.resize(Objects.size());
235 for (unsigned i = 0; i != Objects.size(); ++i)
236 GetAllDefinedSymbols(Objects[i], DefinedSymbols[i]);
237
Chris Lattner1d496172003-04-19 22:44:38 +0000238 bool Linked = true;
239 while (Linked) { // While we are linking in object files, loop.
240 Linked = false;
241
242 for (unsigned i = 0; i != Objects.size(); ++i) {
243 // Consider whether we need to link in this module... we only need to
244 // link it in if it defines some symbol which is so far undefined.
245 //
246 const std::set<std::string> &DefSymbols = DefinedSymbols[i];
247
248 bool ObjectRequired = false;
249 for (std::set<std::string>::iterator I = UndefinedSymbols.begin(),
250 E = UndefinedSymbols.end(); I != E; ++I)
251 if (DefSymbols.count(*I)) {
252 if (Verbose)
253 std::cerr << " Found object providing symbol '" << *I << "'...\n";
254 ObjectRequired = true;
255 break;
256 }
257
258 // We DO need to link this object into the program...
259 if (ObjectRequired) {
260 if (LinkModules(M, Objects[i], &ErrorMessage))
261 return true; // Couldn't link in the right object file...
262
263 // Since we have linked in this object, delete it from the list of
264 // objects to consider in this archive file.
265 std::swap(Objects[i], Objects.back());
266 std::swap(DefinedSymbols[i], DefinedSymbols.back());
267 Objects.pop_back();
268 DefinedSymbols.pop_back();
269 --i; // Do not skip an entry
270
271 // The undefined symbols set should have shrunk.
272 GetAllUndefinedSymbols(M, UndefinedSymbols);
273 Linked = true; // We have linked something in!
274 }
275 }
276 }
277
278 return false;
279}
280
Chris Lattner1d496172003-04-19 22:44:38 +0000281
John Criswell8ecc3022003-09-18 16:22:26 +0000282int
283main(int argc, char **argv, char ** envp)
John Criswellf22d8452003-09-17 15:20:51 +0000284{
Chris Lattnerf5cad152002-07-22 02:10:13 +0000285 cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n");
Chris Lattner5ff2e052002-01-24 19:12:12 +0000286
Chris Lattner5ff2e052002-01-24 19:12:12 +0000287 std::string ErrorMessage;
Chris Lattner1d496172003-04-19 22:44:38 +0000288 std::auto_ptr<Module> Composite(LoadObject(InputFilenames[0], ErrorMessage));
289 if (Composite.get() == 0)
290 return PrintAndReturn(argv[0], ErrorMessage);
Chris Lattner5ff2e052002-01-24 19:12:12 +0000291
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000292 // We always look first in the current directory when searching for libraries.
293 LibPaths.insert(LibPaths.begin(), ".");
294
Chris Lattnerda3bc212003-04-21 19:53:24 +0000295 // If the user specied an extra search path in their environment, respect it.
296 if (char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH"))
297 LibPaths.push_back(SearchPath);
298
Chris Lattner1d496172003-04-19 22:44:38 +0000299 for (unsigned i = 1; i < InputFilenames.size(); ++i) {
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000300 // A user may specify an ar archive without -l, perhaps because it
301 // is not installed as a library. Detect that and link the library.
Chris Lattner4c46c952003-05-29 15:13:15 +0000302 if (IsArchive(InputFilenames[i])) {
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000303 if (Verbose) std::cerr << "Linking archive '" << InputFilenames[i]
304 << "'\n";
Chris Lattner4c46c952003-05-29 15:13:15 +0000305 if (LinkLibrary(Composite.get(), InputFilenames[i], false, ErrorMessage))
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000306 return PrintAndReturn(argv[0], ErrorMessage,
307 ": error linking in '" + InputFilenames[i] + "'");
308 continue;
309 }
310
Chris Lattner1d496172003-04-19 22:44:38 +0000311 std::auto_ptr<Module> M(LoadObject(InputFilenames[i], ErrorMessage));
312 if (M.get() == 0)
313 return PrintAndReturn(argv[0], ErrorMessage);
Chris Lattner5ff2e052002-01-24 19:12:12 +0000314
Chris Lattner2b3a5db2003-04-18 23:01:25 +0000315 if (Verbose) std::cerr << "Linking in '" << InputFilenames[i] << "'\n";
Chris Lattner5ff2e052002-01-24 19:12:12 +0000316
Chris Lattner1d496172003-04-19 22:44:38 +0000317 if (LinkModules(Composite.get(), M.get(), &ErrorMessage))
318 return PrintAndReturn(argv[0], ErrorMessage,
319 ": error linking in '" + InputFilenames[i] + "'");
320 }
321
Chris Lattner4b462c02003-04-19 23:07:33 +0000322 // Remove any consecutive duplicates of the same library...
323 Libraries.erase(std::unique(Libraries.begin(), Libraries.end()),
324 Libraries.end());
325
Chris Lattner1d496172003-04-19 22:44:38 +0000326 // Link in all of the libraries next...
327 for (unsigned i = 0; i != Libraries.size(); ++i) {
328 if (Verbose) std::cerr << "Linking in library: -l" << Libraries[i] << "\n";
Brian Gaeke5bfa37f2003-05-23 20:27:07 +0000329 if (LinkLibrary(Composite.get(), Libraries[i], true, ErrorMessage))
John Criswell8ecc3022003-09-18 16:22:26 +0000330 if (!Native)
331 return PrintAndReturn(argv[0], ErrorMessage);
Chris Lattner5ff2e052002-01-24 19:12:12 +0000332 }
333
Chris Lattner3b08c2f2002-04-08 00:14:58 +0000334 //
John Criswell8ecc3022003-09-18 16:22:26 +0000335 // Create the output file.
Chris Lattner3b08c2f2002-04-08 00:14:58 +0000336 //
Chris Lattner1d496172003-04-19 22:44:38 +0000337 std::string RealBytecodeOutput = OutputFilename;
338 if (!LinkAsLibrary) RealBytecodeOutput += ".bc";
339 std::ofstream Out(RealBytecodeOutput.c_str());
340 if (!Out.good())
341 return PrintAndReturn(argv[0], "error opening '" + RealBytecodeOutput +
342 "' for writing!");
Chris Lattner5ff2e052002-01-24 19:12:12 +0000343
John Criswell8ecc3022003-09-18 16:22:26 +0000344 //
345 // Ensure that the bytecode file gets removed from the disk if we get a
346 // SIGINT signal.
347 //
Chris Lattner1d496172003-04-19 22:44:38 +0000348 RemoveFileOnSignal(RealBytecodeOutput);
Chris Lattnerc065ad82002-04-18 19:55:25 +0000349
John Criswell8ecc3022003-09-18 16:22:26 +0000350 //
351 // Generate the bytecode file.
352 //
353 if (GenerateBytecode (Composite.get(), Strip, !NoInternalize, &Out))
354 {
355 Out.close();
356 return PrintAndReturn(argv[0], "error generating bytcode");
357 }
358
359 //
360 // Close the bytecode file.
361 //
Chris Lattner5ff2e052002-01-24 19:12:12 +0000362 Out.close();
363
John Criswell8ecc3022003-09-18 16:22:26 +0000364 //
365 // If we are not linking a library, generate either a native executable
366 // or a JIT shell script, depending upon what the user wants.
367 //
Chris Lattner1d496172003-04-19 22:44:38 +0000368 if (!LinkAsLibrary) {
John Criswell1997a342003-09-16 21:27:35 +0000369 //
370 // If the user wants to generate a native executable, compile it from the
371 // bytecode file.
372 //
373 // Otherwise, create a script that will run the bytecode through the JIT.
374 //
375 if (Native)
376 {
John Criswell8ecc3022003-09-18 16:22:26 +0000377 // Name of the Assembly Language output file
378 std::string AssemblyFile = OutputFilename + ".s";
379
John Criswell1997a342003-09-16 21:27:35 +0000380 //
John Criswell8ecc3022003-09-18 16:22:26 +0000381 // Mark the output files for removal if we get an interrupt.
John Criswell1997a342003-09-16 21:27:35 +0000382 //
John Criswell8ecc3022003-09-18 16:22:26 +0000383 RemoveFileOnSignal (AssemblyFile);
384 RemoveFileOnSignal (OutputFilename);
John Criswell1997a342003-09-16 21:27:35 +0000385
386 //
John Criswell0217b1b2003-09-17 19:04:22 +0000387 // Determine the locations of the llc and gcc programs.
388 //
389 std::string llc=FindExecutable ("llc", argv[0]);
390 std::string gcc=FindExecutable ("gcc", argv[0]);
391 if (llc.empty())
392 {
393 return PrintAndReturn (argv[0], "Failed to find llc");
394 }
395
396 if (gcc.empty())
397 {
398 return PrintAndReturn (argv[0], "Failed to find gcc");
399 }
400
401 //
John Criswell8ecc3022003-09-18 16:22:26 +0000402 // Generate an assembly language file for the bytecode.
John Criswell1997a342003-09-16 21:27:35 +0000403 //
John Criswell8ecc3022003-09-18 16:22:26 +0000404 generate_assembly (AssemblyFile, RealBytecodeOutput, llc, envp);
405 generate_native (OutputFilename, AssemblyFile, Libraries, gcc, envp);
John Criswell1997a342003-09-16 21:27:35 +0000406
407 //
John Criswell8ecc3022003-09-18 16:22:26 +0000408 // Remove the assembly language file.
John Criswell1997a342003-09-16 21:27:35 +0000409 //
John Criswell8ecc3022003-09-18 16:22:26 +0000410 removeFile (AssemblyFile);
John Criswell1997a342003-09-16 21:27:35 +0000411 }
412 else
413 {
414 // Output the script to start the program...
415 std::ofstream Out2(OutputFilename.c_str());
416 if (!Out2.good())
417 return PrintAndReturn(argv[0], "error opening '" + OutputFilename +
418 "' for writing!");
419 Out2 << "#!/bin/sh\nlli -q $0.bc $*\n";
420 Out2.close();
421 }
Chris Lattner5ff2e052002-01-24 19:12:12 +0000422
Chris Lattner1d496172003-04-19 22:44:38 +0000423 // Make the script executable...
John Criswell06327da2003-09-02 20:17:20 +0000424 MakeFileExecutable (OutputFilename);
Misha Brukman90869942003-08-20 20:38:15 +0000425
John Criswella3ce8b42003-09-02 21:11:22 +0000426 // Make the bytecode file readable and directly executable in LLEE as well
John Criswell06327da2003-09-02 20:17:20 +0000427 MakeFileExecutable (RealBytecodeOutput);
John Criswella3ce8b42003-09-02 21:11:22 +0000428 MakeFileReadable (RealBytecodeOutput);
Chris Lattner1d496172003-04-19 22:44:38 +0000429 }
Chris Lattner5ff2e052002-01-24 19:12:12 +0000430
431 return 0;
432}