Added the use of the const keyword.
[oota-llvm.git] / tools / gccld / gccld.cpp
1 //===- gccld.cpp - LLVM 'ld' compatible linker ----------------------------===//
2 //
3 // This utility is intended to be compatible with GCC, and follows standard
4 // system 'ld' conventions.  As such, the default output file is ./a.out.
5 // 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,
12 // I'm not too worried about this.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "llvm/Transforms/Utils/Linker.h"
17 #include "llvm/Module.h"
18 #include "llvm/PassManager.h"
19 #include "llvm/Bytecode/Reader.h"
20 #include "llvm/Bytecode/WriteBytecodePass.h"
21 #include "llvm/Target/TargetData.h"
22 #include "llvm/Transforms/IPO.h"
23 #include "llvm/Transforms/Scalar.h"
24 #include "Support/FileUtilities.h"
25 #include "Support/SystemUtils.h"
26 #include "Support/CommandLine.h"
27 #include "Support/Signals.h"
28 #include "Config/unistd.h"
29 #include <fstream>
30 #include <memory>
31 #include <set>
32 #include <algorithm>
33
34 namespace {
35   cl::list<std::string> 
36   InputFilenames(cl::Positional, cl::desc("<input bytecode files>"),
37                  cl::OneOrMore);
38
39   cl::opt<std::string> 
40   OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"),
41                  cl::value_desc("filename"));
42
43   cl::opt<bool>    
44   Verbose("v", cl::desc("Print information about actions taken"));
45   
46   cl::list<std::string> 
47   LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix,
48            cl::value_desc("directory"));
49
50   cl::list<std::string> 
51   Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix,
52             cl::value_desc("library prefix"));
53
54   cl::opt<bool>
55   Strip("s", cl::desc("Strip symbol info from executable"));
56
57   cl::opt<bool>
58   NoInternalize("disable-internalize",
59                 cl::desc("Do not mark all symbols as internal"));
60   static cl::alias
61   ExportDynamic("export-dynamic", cl::desc("Alias for -disable-internalize"),
62                 cl::aliasopt(NoInternalize));
63
64   cl::opt<bool>
65   LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a"
66                                             " library, not an executable"));
67
68   cl::opt<bool>    
69   Native("native", cl::desc("Generate a native binary instead of a shell script"));
70   
71   // Compatibility options that are ignored, but support by LD
72   cl::opt<std::string>
73   CO3("soname", cl::Hidden, cl::desc("Compatibility option: ignored"));
74   cl::opt<std::string>
75   CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored"));
76   cl::opt<bool>
77   CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored"));
78   cl::opt<bool>
79   CO6("r", cl::Hidden, cl::desc("Compatibility option: ignored"));
80 }
81
82 // FileExists - Return true if the specified string is an openable file...
83 static inline bool FileExists(const std::string &FN) {
84   return access(FN.c_str(), F_OK) != -1;
85 }
86
87
88 // LoadObject - Read the specified "object file", which should not search the
89 // library path to find it.
90 static inline std::auto_ptr<Module> LoadObject(std::string FN,
91                                                std::string &OutErrorMessage) {
92   if (Verbose) std::cerr << "Loading '" << FN << "'\n";
93   if (!FileExists(FN)) {
94     // Attempt to load from the LLVM_LIB_SEARCH_PATH directory... if we would
95     // otherwise fail.  This is used to locate objects like crtend.o.
96     //
97     char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");
98     if (SearchPath && FileExists(std::string(SearchPath)+"/"+FN))
99       FN = std::string(SearchPath)+"/"+FN;
100     else {
101       OutErrorMessage = "could not find input file '" + FN + "'!";
102       return std::auto_ptr<Module>();
103     }
104   }
105
106   std::string ErrorMessage;
107   Module *Result = ParseBytecodeFile(FN, &ErrorMessage);
108   if (Result) return std::auto_ptr<Module>(Result);
109
110   OutErrorMessage = "Bytecode file '" + FN + "' corrupt!";
111   if (ErrorMessage.size()) OutErrorMessage += ": " + ErrorMessage;
112   return std::auto_ptr<Module>();
113 }
114
115
116 static Module *LoadSingleLibraryObject(const std::string &Filename) {
117   std::string ErrorMessage;
118   std::auto_ptr<Module> M = LoadObject(Filename, ErrorMessage);
119   if (M.get() == 0 && Verbose) {
120     std::cerr << "Error loading '" + Filename + "'";
121     if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage;
122     std::cerr << "\n";
123   }
124   
125   return M.release();
126 }
127
128 // IsArchive -  Returns true iff FILENAME appears to be the name of an ar
129 // archive file. It determines this by checking the magic string at the
130 // beginning of the file.
131 static bool IsArchive(const std::string &filename) {
132   std::string ArchiveMagic("!<arch>\012");
133   char buf[1 + ArchiveMagic.size()];
134   std::ifstream f(filename.c_str());
135   f.read(buf, ArchiveMagic.size());
136   buf[ArchiveMagic.size()] = '\0';
137   return ArchiveMagic == buf;
138 }
139
140 // LoadLibraryExactName - This looks for a file with a known name and tries to
141 // load it, similarly to LoadLibraryFromDirectory(). 
142 static inline bool LoadLibraryExactName(const std::string &FileName,
143     std::vector<Module*> &Objects, bool &isArchive) {
144   if (Verbose) std::cerr << "  Considering '" << FileName << "'\n";
145   if (FileExists(FileName)) {
146         if (IsArchive(FileName)) {
147       std::string ErrorMessage;
148       if (Verbose) std::cerr << "  Loading '" << FileName << "'\n";
149       if (!ReadArchiveFile(FileName, Objects, &ErrorMessage)) {
150         isArchive = true;
151         return false;           // Success!
152       }
153       if (Verbose) {
154         std::cerr << "  Error loading archive '" + FileName + "'";
155         if (!ErrorMessage.empty()) std::cerr << ": " << ErrorMessage;
156         std::cerr << "\n";
157       }
158     } else {
159       if (Module *M = LoadSingleLibraryObject(FileName)) {
160         isArchive = false;
161         Objects.push_back(M);
162         return false;
163       }
164     }
165   }
166   return true;
167 }
168
169 // LoadLibrary - Try to load a library named LIBNAME that contains
170 // LLVM bytecode. If SEARCH is true, then search for a file named
171 // libLIBNAME.{a,so,bc} in the current library search path.  Otherwise,
172 // assume LIBNAME is the real name of the library file.  This method puts
173 // the loaded modules into the Objects list, and sets isArchive to true if
174 // a .a file was loaded. It returns true if no library is found or if an
175 // error occurs; otherwise it returns false.
176 //
177 static inline bool LoadLibrary(const std::string &LibName,
178                                std::vector<Module*> &Objects, bool &isArchive,
179                                bool search, std::string &ErrorMessage) {
180   if (search) {
181     // First, try the current directory. Then, iterate over the
182     // directories in LibPaths, looking for a suitable match for LibName
183     // in each one.
184     for (unsigned NextLibPathIdx = 0; NextLibPathIdx != LibPaths.size();
185          ++NextLibPathIdx) {
186       std::string Directory = LibPaths[NextLibPathIdx] + "/";
187       if (!LoadLibraryExactName(Directory + "lib" + LibName + ".a",
188         Objects, isArchive))
189           return false;
190       if (!LoadLibraryExactName(Directory + "lib" + LibName + ".so",
191         Objects, isArchive))
192           return false;
193       if (!LoadLibraryExactName(Directory + "lib" + LibName + ".bc",
194         Objects, isArchive))
195           return false;
196     }
197   } else {
198     // If they said no searching, then assume LibName is the real name.
199     if (!LoadLibraryExactName(LibName, Objects, isArchive))
200       return false;
201   }
202   ErrorMessage = "error linking library '-l" + LibName+ "': library not found!";
203   return true;
204 }
205
206 static void GetAllDefinedSymbols(Module *M, 
207                                  std::set<std::string> &DefinedSymbols) {
208   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
209     if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
210       DefinedSymbols.insert(I->getName());
211   for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
212     if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
213       DefinedSymbols.insert(I->getName());
214 }
215
216 // GetAllUndefinedSymbols - This calculates the set of undefined symbols that
217 // still exist in an LLVM module.  This is a bit tricky because there may be two
218 // symbols with the same name, but different LLVM types that will be resolved to
219 // each other, but aren't currently (thus we need to treat it as resolved).
220 //
221 static void GetAllUndefinedSymbols(Module *M, 
222                                    std::set<std::string> &UndefinedSymbols) {
223   std::set<std::string> DefinedSymbols;
224   UndefinedSymbols.clear();   // Start out empty
225   
226   for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
227     if (I->hasName()) {
228       if (I->isExternal())
229         UndefinedSymbols.insert(I->getName());
230       else if (!I->hasInternalLinkage())
231         DefinedSymbols.insert(I->getName());
232     }
233   for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
234     if (I->hasName()) {
235       if (I->isExternal())
236         UndefinedSymbols.insert(I->getName());
237       else if (!I->hasInternalLinkage())
238         DefinedSymbols.insert(I->getName());
239     }
240   
241   // Prune out any defined symbols from the undefined symbols set...
242   for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
243        I != UndefinedSymbols.end(); )
244     if (DefinedSymbols.count(*I))
245       UndefinedSymbols.erase(I++);  // This symbol really is defined!
246     else
247       ++I; // Keep this symbol in the undefined symbols list
248 }
249
250
251 static bool LinkLibrary(Module *M, const std::string &LibName,
252                         bool search, std::string &ErrorMessage) {
253   std::set<std::string> UndefinedSymbols;
254   GetAllUndefinedSymbols(M, UndefinedSymbols);
255   if (UndefinedSymbols.empty()) {
256     if (Verbose) std::cerr << "  No symbols undefined, don't link library!\n";
257     return false;  // No need to link anything in!
258   }
259
260   std::vector<Module*> Objects;
261   bool isArchive;
262   if (LoadLibrary(LibName, Objects, isArchive, search, ErrorMessage))
263     return true;
264
265   // Figure out which symbols are defined by all of the modules in the .a file
266   std::vector<std::set<std::string> > DefinedSymbols;
267   DefinedSymbols.resize(Objects.size());
268   for (unsigned i = 0; i != Objects.size(); ++i)
269     GetAllDefinedSymbols(Objects[i], DefinedSymbols[i]);
270
271   bool Linked = true;
272   while (Linked) {     // While we are linking in object files, loop.
273     Linked = false;
274
275     for (unsigned i = 0; i != Objects.size(); ++i) {
276       // Consider whether we need to link in this module...  we only need to
277       // link it in if it defines some symbol which is so far undefined.
278       //
279       const std::set<std::string> &DefSymbols = DefinedSymbols[i];
280
281       bool ObjectRequired = false;
282       for (std::set<std::string>::iterator I = UndefinedSymbols.begin(),
283              E = UndefinedSymbols.end(); I != E; ++I)
284         if (DefSymbols.count(*I)) {
285           if (Verbose)
286             std::cerr << "  Found object providing symbol '" << *I << "'...\n";
287           ObjectRequired = true;
288           break;
289         }
290       
291       // We DO need to link this object into the program...
292       if (ObjectRequired) {
293         if (LinkModules(M, Objects[i], &ErrorMessage))
294           return true;   // Couldn't link in the right object file...        
295         
296         // Since we have linked in this object, delete it from the list of
297         // objects to consider in this archive file.
298         std::swap(Objects[i], Objects.back());
299         std::swap(DefinedSymbols[i], DefinedSymbols.back());
300         Objects.pop_back();
301         DefinedSymbols.pop_back();
302         --i;   // Do not skip an entry
303         
304         // The undefined symbols set should have shrunk.
305         GetAllUndefinedSymbols(M, UndefinedSymbols);
306         Linked = true;  // We have linked something in!
307       }
308     }
309   }
310   
311   return false;
312 }
313
314 static int PrintAndReturn(const char *progname, const std::string &Message,
315                           const std::string &Extra = "") {
316   std::cerr << progname << Extra << ": " << Message << "\n";
317   return 1;
318 }
319
320 //
321 //
322 // Function: copy_env()
323 //
324 // Description:
325 //      This function takes an array of environment variables and makes a
326 //      copy of it.  This copy can then be manipulated any way the caller likes
327 //  without affecting the process's real environment.
328 //
329 // Inputs:
330 //  envp - An array of C strings containing an environment.
331 //
332 // Outputs:
333 //  None.
334 //
335 // Return value:
336 //  NULL - An error occurred.
337 //  Otherwise, a pointer to a new array of C strings is returned.  Every string
338 //  in the array is a duplicate of the one in the original array (i.e. we do
339 //  not copy the char *'s from one array to another).
340 //
341 static char **
342 copy_env (char ** const envp)
343 {
344   // The new environment list
345   char ** newenv;
346
347   // The number of entries in the old environment list
348   int entries;
349
350   //
351   // Count the number of entries in the old list;
352   //
353   for (entries = 0; envp[entries] != NULL; entries++)
354   {
355     ;
356   }
357
358   //
359   // Add one more entry for the NULL pointer that ends the list.
360   //
361   ++entries;
362
363   //
364   // If there are no entries at all, just return NULL.
365   //
366   if (entries == 0)
367   {
368     return NULL;
369   }
370
371   //
372   // Allocate a new environment list.
373   //
374   if ((newenv = new (char *) [entries]) == NULL)
375   {
376     return NULL;
377   }
378
379   //
380   // Make a copy of the list.  Don't forget the NULL that ends the list.
381   //
382   entries = 0;
383   while (envp[entries] != NULL)
384   {
385     newenv[entries] = strdup (envp[entries]);
386     ++entries;
387   }
388   newenv[entries] = NULL;
389
390   return newenv;
391 }
392
393
394 //
395 // Function: remove_env()
396 //
397 // Description:
398 //      Remove the specified environment variable from the environment array.
399 //
400 // Inputs:
401 //      name - The name of the variable to remove.  It cannot be NULL.
402 //      envp - The array of environment variables.  It cannot be NULL.
403 //
404 // Outputs:
405 //      envp - The pointer to the specified variable name is removed.
406 //
407 // Return value:
408 //      None.
409 //
410 // Notes:
411 //  This is mainly done because functions to remove items from the environment
412 //  are not available across all platforms.  In particular, Solaris does not
413 //  seem to have an unsetenv() function or a setenv() function (or they are
414 //  undocumented if they do exist).
415 //
416 static void
417 remove_env (const char * name, char ** const envp)
418 {
419   // Pointer for scanning arrays
420   register char * p;
421
422   // Index for selecting elements of the environment array
423   register int index;
424
425   for (index=0; envp[index] != NULL; index++)
426   {
427     //
428     // Find the first equals sign in the array and make it an EOS character.
429     //
430     p = strchr (envp[index], '=');
431     if (p == NULL)
432     {
433       continue;
434     }
435     else
436     {
437       *p = '\0';
438     }
439
440     //
441     // Compare the two strings.  If they are equal, zap this string.
442     // Otherwise, restore it.
443     //
444     if (!strcmp (name, envp[index]))
445     {
446       *envp[index] = '\0';
447     }
448     else
449     {
450       *p = '=';
451     }
452   }
453
454   return;
455 }
456
457
458 int main(int argc, char **argv, char ** envp) {
459   cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n");
460
461   std::string ErrorMessage;
462   std::auto_ptr<Module> Composite(LoadObject(InputFilenames[0], ErrorMessage));
463   if (Composite.get() == 0)
464     return PrintAndReturn(argv[0], ErrorMessage);
465
466   // We always look first in the current directory when searching for libraries.
467   LibPaths.insert(LibPaths.begin(), ".");
468
469   // If the user specied an extra search path in their environment, respect it.
470   if (char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH"))
471     LibPaths.push_back(SearchPath);
472
473   for (unsigned i = 1; i < InputFilenames.size(); ++i) {
474     // A user may specify an ar archive without -l, perhaps because it
475     // is not installed as a library. Detect that and link the library.
476     if (IsArchive(InputFilenames[i])) {
477       if (Verbose) std::cerr << "Linking archive '" << InputFilenames[i]
478                              << "'\n";
479       if (LinkLibrary(Composite.get(), InputFilenames[i], false, ErrorMessage))
480         return PrintAndReturn(argv[0], ErrorMessage,
481                               ": error linking in '" + InputFilenames[i] + "'");
482       continue;
483     }
484
485     std::auto_ptr<Module> M(LoadObject(InputFilenames[i], ErrorMessage));
486     if (M.get() == 0)
487       return PrintAndReturn(argv[0], ErrorMessage);
488
489     if (Verbose) std::cerr << "Linking in '" << InputFilenames[i] << "'\n";
490
491     if (LinkModules(Composite.get(), M.get(), &ErrorMessage))
492       return PrintAndReturn(argv[0], ErrorMessage,
493                             ": error linking in '" + InputFilenames[i] + "'");
494   }
495
496   // Remove any consecutive duplicates of the same library...
497   Libraries.erase(std::unique(Libraries.begin(), Libraries.end()),
498                   Libraries.end());
499
500   // Link in all of the libraries next...
501   for (unsigned i = 0; i != Libraries.size(); ++i) {
502     if (Verbose) std::cerr << "Linking in library: -l" << Libraries[i] << "\n";
503     if (LinkLibrary(Composite.get(), Libraries[i], true, ErrorMessage))
504       return PrintAndReturn(argv[0], ErrorMessage);
505   }
506
507   // In addition to just linking the input from GCC, we also want to spiff it up
508   // a little bit.  Do this now.
509   //
510   PassManager Passes;
511
512   // Add an appropriate TargetData instance for this module...
513   Passes.add(new TargetData("gccld", Composite.get()));
514
515   // Linking modules together can lead to duplicated global constants, only keep
516   // one copy of each constant...
517   //
518   Passes.add(createConstantMergePass());
519
520   // If the -s command line option was specified, strip the symbols out of the
521   // resulting program to make it smaller.  -s is a GCC option that we are
522   // supporting.
523   //
524   if (Strip)
525     Passes.add(createSymbolStrippingPass());
526
527   // Often if the programmer does not specify proper prototypes for the
528   // functions they are calling, they end up calling a vararg version of the
529   // function that does not get a body filled in (the real function has typed
530   // arguments).  This pass merges the two functions.
531   //
532   Passes.add(createFunctionResolvingPass());
533
534   if (!NoInternalize) {
535     // Now that composite has been compiled, scan through the module, looking
536     // for a main function.  If main is defined, mark all other functions
537     // internal.
538     //
539     Passes.add(createInternalizePass());
540   }
541
542   // Remove unused arguments from functions...
543   //
544   Passes.add(createDeadArgEliminationPass());
545
546   // The FuncResolve pass may leave cruft around if functions were prototyped
547   // differently than they were defined.  Remove this cruft.
548   //
549   Passes.add(createInstructionCombiningPass());
550
551   // Delete basic blocks, which optimization passes may have killed...
552   //
553   Passes.add(createCFGSimplificationPass());
554
555   // Now that we have optimized the program, discard unreachable functions...
556   //
557   Passes.add(createGlobalDCEPass());
558
559   // Add the pass that writes bytecode to the output file...
560   std::string RealBytecodeOutput = OutputFilename;
561   if (!LinkAsLibrary) RealBytecodeOutput += ".bc";
562   std::ofstream Out(RealBytecodeOutput.c_str());
563   if (!Out.good())
564     return PrintAndReturn(argv[0], "error opening '" + RealBytecodeOutput +
565                                    "' for writing!");
566   Passes.add(new WriteBytecodePass(&Out));        // Write bytecode to file...
567
568   // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
569   RemoveFileOnSignal(RealBytecodeOutput);
570
571   // Run our queue of passes all at once now, efficiently.
572   Passes.run(*Composite.get());
573   Out.close();
574
575   if (!LinkAsLibrary) {
576     //
577     // If the user wants to generate a native executable, compile it from the
578     // bytecode file.
579     //
580     // Otherwise, create a script that will run the bytecode through the JIT.
581     //
582     if (Native)
583     {
584       //
585       // Remove these environment variables from the environment of the
586       // programs that we will execute.  It appears that GCC sets these
587       // environment variables so that the programs it uses can configure
588       // themselves identically.
589       //
590       // However, when we invoke GCC below, we want it to use its  normal
591       // configuration.  Hence, we must sanitize it's environment.
592       //
593       char ** clean_env = copy_env (envp);
594       if (clean_env == NULL)
595       {
596         return PrintAndReturn (argv[0], "Failed to duplicate environment");
597       }
598       remove_env ("LIBRARY_PATH", clean_env);
599       remove_env ("COLLECT_GCC_OPTIONS", clean_env);
600       remove_env ("GCC_EXEC_PREFIX", clean_env);
601       remove_env ("COMPILER_PATH", clean_env);
602       remove_env ("COLLECT_GCC", clean_env);
603
604       //
605       // Determine the locations of the llc and gcc programs.
606       //
607       std::string llc=FindExecutable ("llc", argv[0]);
608       std::string gcc=FindExecutable ("gcc", argv[0]);
609       if (llc.empty())
610       {
611         return PrintAndReturn (argv[0], "Failed to find llc");
612       }
613
614       if (gcc.empty())
615       {
616         return PrintAndReturn (argv[0], "Failed to find gcc");
617       }
618
619       //
620       // Run LLC to convert the bytecode file into assembly code.
621       //
622       const char * cmd[8];
623       std::string AssemblyFile = OutputFilename + ".s";
624
625       cmd[0] =  llc.c_str();
626       cmd[1] =  "-f";
627       cmd[2] =  "-o";
628       cmd[3] =  AssemblyFile.c_str();
629       cmd[4] =  RealBytecodeOutput.c_str();
630       cmd[5] =  NULL;
631       if ((ExecWait (cmd, clean_env)) == -1)
632       {
633         return PrintAndReturn (argv[0], "Failed to compile bytecode");
634       }
635
636       //
637       // Run GCC to assemble and link the program into native code.
638       //
639       // Note:
640       //  We can't just assemble and link the file with the system assembler
641       //  and linker because we don't know where to put the _start symbol.
642       //  GCC mysteriously knows how to do it.
643       //
644       cmd[0] =  gcc.c_str();
645       cmd[1] =  "-o";
646       cmd[2] =  OutputFilename.c_str();
647       cmd[3] =  AssemblyFile.c_str();
648       cmd[4] =  NULL;
649       if ((ExecWait (cmd, clean_env)) == -1)
650       {
651         return PrintAndReturn (argv[0], "Failed to link native code file");
652       }
653
654       //
655       // The assembly file is no longer needed.  Remove it, but do not exit
656       // if we fail to unlink it.
657       //
658       if (((access (AssemblyFile.c_str(), F_OK)) != -1) &&
659           ((unlink (AssemblyFile.c_str())) == -1))
660       {
661         std::cerr << "Warning: Failed to unlink " << AssemblyFile << "\n";
662       }
663     }
664     else
665     {
666       // Output the script to start the program...
667       std::ofstream Out2(OutputFilename.c_str());
668       if (!Out2.good())
669         return PrintAndReturn(argv[0], "error opening '" + OutputFilename +
670                                        "' for writing!");
671       Out2 << "#!/bin/sh\nlli -q $0.bc $*\n";
672       Out2.close();
673     }
674   
675     // Make the script executable...
676     MakeFileExecutable (OutputFilename);
677
678     // Make the bytecode file readable and directly executable in LLEE as well
679     MakeFileExecutable (RealBytecodeOutput);
680     MakeFileReadable   (RealBytecodeOutput);
681   }
682
683   return 0;
684 }