blob: 6eb841745785d7afa100041fa0c3a0a767c735ce [file] [log] [blame]
Zonr Changa02010c2010-10-11 20:54:28 +08001#include <list>
zonr6315f762010-10-05 15:35:14 +08002#include <memory>
3#include <string>
4#include <vector>
5
Shih-wei Liao835a7b72010-08-06 02:29:11 -07006#include "llvm/Linker.h"
7#include "llvm/LLVMContext.h"
8#include "llvm/Metadata.h"
9#include "llvm/Module.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080010
Shih-wei Liao835a7b72010-08-06 02:29:11 -070011#include "llvm/Analysis/Verifier.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080012
Shih-wei Liao835a7b72010-08-06 02:29:11 -070013#include "llvm/Bitcode/ReaderWriter.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080014
Shih-wei Liao835a7b72010-08-06 02:29:11 -070015#include "llvm/Support/CommandLine.h"
16#include "llvm/Support/ManagedStatic.h"
17#include "llvm/Support/MemoryBuffer.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070018#include "llvm/Support/StandardPasses.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070019#include "llvm/Support/raw_ostream.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080020
Shih-wei Liao835a7b72010-08-06 02:29:11 -070021#include "llvm/System/Signals.h"
22#include "llvm/System/Path.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080023
Shih-wei Liao835a7b72010-08-06 02:29:11 -070024#include "llvm/Target/TargetData.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080025
26#include "slang_rs_metadata.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070027
28using namespace llvm;
29
30static cl::list<std::string>
31InputFilenames(cl::Positional, cl::OneOrMore,
32 cl::desc("<input bitcode files>"));
33
Zonr Changa02010c2010-10-11 20:54:28 +080034static cl::list<std::string>
35OutputFilenames("o", cl::desc("Override output filename"),
36 cl::value_desc("<output bitcode file>"));
37
38static cl::opt<bool>
39NoStdLib("nostdlib", cl::desc("Don't link RS default libraries"));
40
41static cl::list<std::string>
42 AdditionalLibs("l", cl::Prefix,
43 cl::desc("Specify additional libraries to link to"),
44 cl::value_desc("<library bitcode>"));
Shih-wei Liao835a7b72010-08-06 02:29:11 -070045
Zonr Chang7f2f3852010-10-07 19:12:23 +080046static bool GetExportSymbolNames(NamedMDNode *N,
47 unsigned NameOpIdx,
48 std::vector<const char *> &Names) {
49 if (N == NULL)
50 return true;
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -070051
Zonr Chang7f2f3852010-10-07 19:12:23 +080052 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
53 MDNode *V = N->getOperand(i);
54 if (V == NULL)
55 continue;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070056
Zonr Chang7f2f3852010-10-07 19:12:23 +080057 if (V->getNumOperands() < (NameOpIdx + 1)) {
58 errs() << "Invalid metadata spec of " << N->getName()
59 << " in RenderScript executable. (#op)\n";
60 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070061 }
62
Zonr Chang7f2f3852010-10-07 19:12:23 +080063 MDString *Name = dyn_cast<MDString>(V->getOperand(NameOpIdx));
64 if (Name == NULL) {
65 errs() << "Invalid metadata spec of " << N->getName()
66 << " in RenderScript executable. (#name)\n";
67 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070068 }
69
Zonr Chang7f2f3852010-10-07 19:12:23 +080070 Names.push_back(Name->getString().data());
Shih-wei Liao835a7b72010-08-06 02:29:11 -070071 }
Zonr Chang7f2f3852010-10-07 19:12:23 +080072 return true;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070073}
74
Zonr Chang7f2f3852010-10-07 19:12:23 +080075static bool GetExportSymbols(Module *M, std::vector<const char *> &Names) {
76 bool Result = true;
77 // Variables marked as export must be externally visible
78 if (NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN))
79 Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names);
80 // So are those exported functions
81 if (NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN))
82 Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names);
83 return Result;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070084}
85
Shih-wei Liao835a7b72010-08-06 02:29:11 -070086
Zonr Changa02010c2010-10-11 20:54:28 +080087static inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) {
Shih-wei Liao835a7b72010-08-06 02:29:11 -070088 std::string Err;
Zonr Changa02010c2010-10-11 20:54:28 +080089 MemoryBuffer *MB = MemoryBuffer::getFile(F, &Err);
Shih-wei Liao835a7b72010-08-06 02:29:11 -070090
Zonr Changa02010c2010-10-11 20:54:28 +080091 if (MB == NULL)
92 errs() << "Failed to load `" << F << "' (" << Err << ")\n";
Shih-wei Liao835a7b72010-08-06 02:29:11 -070093
Zonr Changa02010c2010-10-11 20:54:28 +080094 return MB;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070095}
96
Zonr Changa02010c2010-10-11 20:54:28 +080097static inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB,
98 LLVMContext& Context) {
99 std::string Err;
100 Module *M = ParseBitcodeFile(MB, Context, &Err);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700101
Zonr Changa02010c2010-10-11 20:54:28 +0800102 if (M == NULL)
103 errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier()
104 << "' (" << Err << ")\n";
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700105
Zonr Changa02010c2010-10-11 20:54:28 +0800106 return M;
107}
108
109// LoadBitcodeFile - Read the specified bitcode file in and return it.
110static inline Module *LoadBitcodeFile(const std::string &F,
111 LLVMContext& Context) {
112 MemoryBuffer *MB = LoadFileIntoMemory(F);
113 if (MB == NULL)
114 return NULL;
115
116 Module *M = ParseBitcodeFromMemoryBuffer(MB, Context);
117 if (M == NULL)
118 delete MB;
119
120 return M;
121}
122
123extern const char rslib_bc[];
124extern unsigned rslib_bc_size;
125
126static bool PreloadLibraries(bool NoStdLib,
127 const std::vector<std::string> &AdditionalLibs,
128 std::list<MemoryBuffer *> LibBitcode) {
129 MemoryBuffer *MB;
130
131 LibBitcode.clear();
132
133 if (!NoStdLib) {
134 // rslib.bc
135 MB = MemoryBuffer::getMemBufferCopy(StringRef(rslib_bc, rslib_bc_size),
136 "rslib.bc");
137 if (MB == NULL) {
138 errs() << "Failed to load (in-memory) `rslib.bc'!\n";
139 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700140 }
Zonr Changa02010c2010-10-11 20:54:28 +0800141
142 LibBitcode.push_back(MB);
143 }
144
145 // Load additional libraries
146 for (std::vector<std::string>::const_iterator
147 I = AdditionalLibs.begin(), E = AdditionalLibs.end();
148 I != E;
149 I++) {
150 MB = LoadFileIntoMemory(*I);
151 if (MB == NULL)
152 return false;
153 LibBitcode.push_back(MB);
154 }
155
156 return true;
157}
158
159static void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) {
160 for (std::list<MemoryBuffer *>::iterator
161 I = LibBitcode.begin(), E = LibBitcode.end();
162 I != E;
163 I++)
164 delete *I;
165 LibBitcode.clear();
166 return;
167}
168
169Module *PerformLinking(const std::string &InputFile,
170 const std::list<MemoryBuffer *> &LibBitcode,
171 LLVMContext &Context) {
172 std::string Err;
173 std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context));
174
175 if (Composite.get() == NULL)
176 return NULL;
177
178 for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(),
179 E = LibBitcode.end();
180 I != E;
181 I++) {
182 Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context);
183 if (Lib == NULL)
184 return NULL;
185
186 if (Linker::LinkModules(Composite.get(), Lib, &Err)) {
187 errs() << "Failed to link `" << InputFile << "' with library bitcode `"
188 << (*I)->getBufferIdentifier() << "' (" << Err << ")\n";
189 return NULL;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700190 }
191 }
192
Zonr Changa02010c2010-10-11 20:54:28 +0800193 return Composite.release();
194}
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700195
Zonr Changa02010c2010-10-11 20:54:28 +0800196bool OptimizeModule(Module *M) {
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700197 PassManager Passes;
198
Zonr Changa02010c2010-10-11 20:54:28 +0800199 const std::string &ModuleDataLayout = M->getDataLayout();
Zonr Chang7f2f3852010-10-07 19:12:23 +0800200 if (!ModuleDataLayout.empty())
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700201 if (TargetData *TD = new TargetData(ModuleDataLayout))
202 Passes.add(TD);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700203
Zonr Chang7f2f3852010-10-07 19:12:23 +0800204 // Some symbols must not be internalized
205 std::vector<const char *> ExportList;
206 ExportList.push_back("init");
207 ExportList.push_back("root");
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700208
Zonr Changa02010c2010-10-11 20:54:28 +0800209 if (!GetExportSymbols(M, ExportList)) {
210 return false;
211 }
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -0700212
Zonr Chang7f2f3852010-10-07 19:12:23 +0800213 Passes.add(createInternalizePass(ExportList));
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700214
Zonr Changa02010c2010-10-11 20:54:28 +0800215 // TODO(zonr): Do we need to run all LTO passes?
Zonr Chang7f2f3852010-10-07 19:12:23 +0800216 createStandardLTOPasses(&Passes,
217 /* Internalize = */false,
218 /* RunInliner = */true,
219 /* VerifyEach = */false);
Zonr Changa02010c2010-10-11 20:54:28 +0800220 Passes.run(*M);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700221
Zonr Changa02010c2010-10-11 20:54:28 +0800222 return true;
223}
Zonr Chang7f2f3852010-10-07 19:12:23 +0800224
Zonr Changa02010c2010-10-11 20:54:28 +0800225int main(int argc, char **argv) {
226 llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
227
228 cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
229
230 std::list<MemoryBuffer *> LibBitcode;
231
232 if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode))
233 return 1;
234
235 // No libraries specified to be linked
236 if (LibBitcode.size() == 0)
237 return 0;
238
239 LLVMContext &Context = getGlobalContext();
240 bool HasError = true;
241 std::string Err;
242
243 for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) {
244 std::auto_ptr<Module> Linked(
245 PerformLinking(InputFilenames[i], LibBitcode, Context));
246
247 // Failed to link with InputFilenames[i] with LibBitcode
248 if (Linked.get() == NULL)
249 break;
250
251 // Verify linked module
252 if (verifyModule(*Linked, ReturnStatusAction, &Err)) {
253 errs() << InputFilenames[i] << " linked, but does not verify as "
254 "correct! (" << Err << ")\n";
255 break;
256 }
257
258 if (!OptimizeModule(Linked.get()))
259 break;
260
261 // Write out the module
262 tool_output_file Out(InputFilenames[i].c_str(), Err,
263 raw_fd_ostream::F_Binary);
264
265 if (!Err.empty()) {
266 errs() << InputFilenames[i] << " linked, but failed to write out! "
267 "(" << Err << ")\n";
268 break;
269 }
270
271 WriteBitcodeToFile(Linked.get(), Out);
272
273 Out.keep();
274 Linked.reset();
275
276 if (i == (InputFilenames.size() - 1))
277 // This is the last file and no error occured.
278 HasError = false;
279 }
280
281 UnloadLibraries(LibBitcode);
282
283 return HasError;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700284}