*** empty log message ***
[oota-llvm.git] / tools / llvm-link / llvm-link.cpp
1 //===----------------------------------------------------------------------===//
2 // LLVM 'LINK' UTILITY 
3 //
4 // This utility may be invoked in the following manner:
5 //  link a.bc b.bc c.bc -o x.bc
6 //
7 // Alternatively, this can be used as an 'ar' tool as well.  If invoked as
8 // either 'ar' or 'llvm-ar', it accepts a 'rc' parameter as well.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/Transforms/Utils/Linker.h"
13 #include "llvm/Bytecode/Reader.h"
14 #include "llvm/Bytecode/Writer.h"
15 #include "llvm/Module.h"
16 #include "Support/CommandLine.h"
17 #include "Support/Signals.h"
18 #include <fstream>
19 #include <memory>
20 #include <sys/types.h>     // For FileExists
21 #include <sys/stat.h>
22
23 using std::cerr;
24
25 static cl::list<std::string>
26 InputFilenames(cl::Positional, cl::OneOrMore,
27                cl::desc("Load <arg> files, linking them together"));
28
29 static cl::opt<std::string>
30 OutputFilename("o", cl::desc("Override output filename"), cl::init("-"),
31                cl::value_desc("filename"));
32
33 static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
34
35 static cl::opt<bool>
36 Verbose("v", cl::desc("Print information about actions taken"));
37
38 static cl::opt<bool>
39 DumpAsm("d", cl::desc("Print assembly as linked"), cl::Hidden);
40
41 static cl::list<std::string>
42 LibPaths("L", cl::desc("Specify a library search path"), cl::ZeroOrMore,
43          cl::value_desc("directory"), cl::Prefix);
44
45 // FileExists - Return true if the specified string is an openable file...
46 static inline bool FileExists(const std::string &FN) {
47   struct stat StatBuf;
48   return stat(FN.c_str(), &StatBuf) != -1;
49 }
50
51 // LoadFile - Read the specified bytecode file in and return it.  This routine
52 // searches the link path for the specified file to try to find it...
53 //
54 static inline std::auto_ptr<Module> LoadFile(const std::string &FN) {
55   std::string Filename = FN;
56   std::string ErrorMessage;
57
58   unsigned NextLibPathIdx = 0;
59   bool FoundAFile = false;
60
61   while (1) {
62     if (Verbose) cerr << "Loading '" << Filename << "'\n";
63     if (FileExists(Filename)) FoundAFile = true;
64     Module *Result = ParseBytecodeFile(Filename, &ErrorMessage);
65     if (Result) return std::auto_ptr<Module>(Result);   // Load successful!
66
67     if (Verbose) {
68       cerr << "Error opening bytecode file: '" << Filename << "'";
69       if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
70       cerr << "\n";
71     }
72     
73     if (NextLibPathIdx == LibPaths.size()) break;
74     Filename = LibPaths[NextLibPathIdx++] + "/" + FN;
75   }
76
77   if (FoundAFile)
78     cerr << "Bytecode file '" << FN << "' corrupt!  "
79          << "Use 'link -v ...' for more info.\n";
80   else
81     cerr << "Could not locate bytecode file: '" << FN << "'\n";
82   return std::auto_ptr<Module>();
83 }
84
85
86
87
88 int main(int argc, char **argv) {
89   cl::ParseCommandLineOptions(argc, argv, " llvm linker\n");
90   assert(InputFilenames.size() > 0 && "OneOrMore is not working");
91
92   unsigned BaseArg = 0;
93   std::string ErrorMessage;
94
95   // TODO: TEST argv[0] for llvm-ar forms... for now, this is a huge hack.
96   if (InputFilenames.size() >= 3 && InputFilenames[0] == "rc" &&
97       OutputFilename == "-") {
98     BaseArg = 2;
99     OutputFilename = InputFilenames[1];
100   }
101
102   std::auto_ptr<Module> Composite(LoadFile(InputFilenames[BaseArg]));
103   if (Composite.get() == 0) return 1;
104
105   for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) {
106     std::auto_ptr<Module> M(LoadFile(InputFilenames[i]));
107     if (M.get() == 0) return 1;
108
109     if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
110
111     if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
112       cerr << "Error linking in '" << InputFilenames[i] << "': "
113            << ErrorMessage << "\n";
114       return 1;
115     }
116   }
117
118   if (DumpAsm) cerr << "Here's the assembly:\n" << Composite.get();
119
120   std::ostream *Out = &std::cout;  // Default to printing to stdout...
121   if (OutputFilename != "-") {
122     if (!Force && std::ifstream(OutputFilename.c_str())) {
123       // If force is not specified, make sure not to overwrite a file!
124       cerr << "Error opening '" << OutputFilename << "': File exists!\n"
125            << "Use -f command line argument to force output\n";
126       return 1;
127     }
128     Out = new std::ofstream(OutputFilename.c_str());
129     if (!Out->good()) {
130       cerr << "Error opening '" << OutputFilename << "'!\n";
131       return 1;
132     }
133
134     // Make sure that the Out file gets unlink'd from the disk if we get a
135     // SIGINT
136     RemoveFileOnSignal(OutputFilename);
137   }
138
139   if (Verbose) cerr << "Writing bytecode...\n";
140   WriteBytecodeToFile(Composite.get(), *Out);
141
142   if (Out != &std::cout) delete Out;
143   return 0;
144 }