blob: 32ea36de9cf9a264ac9d0658f25e43320345afe9 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Zonr Changa02010c2010-10-11 20:54:28 +080017#include <list>
zonr6315f762010-10-05 15:35:14 +080018#include <memory>
19#include <string>
20#include <vector>
21
Shih-wei Liao835a7b72010-08-06 02:29:11 -070022#include "llvm/Linker.h"
23#include "llvm/LLVMContext.h"
24#include "llvm/Metadata.h"
25#include "llvm/Module.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080026
Shih-wei Liao835a7b72010-08-06 02:29:11 -070027#include "llvm/Analysis/Verifier.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080028
Shih-wei Liao835a7b72010-08-06 02:29:11 -070029#include "llvm/Bitcode/ReaderWriter.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080030
Shih-wei Liao835a7b72010-08-06 02:29:11 -070031#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/ManagedStatic.h"
33#include "llvm/Support/MemoryBuffer.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070034#include "llvm/Support/StandardPasses.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070035#include "llvm/Support/raw_ostream.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080036
Shih-wei Liao835a7b72010-08-06 02:29:11 -070037#include "llvm/Target/TargetData.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080038
39#include "slang_rs_metadata.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070040
41using namespace llvm;
42
43static cl::list<std::string>
44InputFilenames(cl::Positional, cl::OneOrMore,
45 cl::desc("<input bitcode files>"));
46
Zonr Changa02010c2010-10-11 20:54:28 +080047static cl::list<std::string>
48OutputFilenames("o", cl::desc("Override output filename"),
49 cl::value_desc("<output bitcode file>"));
50
51static cl::opt<bool>
52NoStdLib("nostdlib", cl::desc("Don't link RS default libraries"));
53
54static cl::list<std::string>
55 AdditionalLibs("l", cl::Prefix,
56 cl::desc("Specify additional libraries to link to"),
57 cl::value_desc("<library bitcode>"));
Shih-wei Liao835a7b72010-08-06 02:29:11 -070058
Zonr Chang7f2f3852010-10-07 19:12:23 +080059static bool GetExportSymbolNames(NamedMDNode *N,
60 unsigned NameOpIdx,
61 std::vector<const char *> &Names) {
62 if (N == NULL)
63 return true;
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -070064
Zonr Chang7f2f3852010-10-07 19:12:23 +080065 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
66 MDNode *V = N->getOperand(i);
67 if (V == NULL)
68 continue;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070069
Zonr Chang7f2f3852010-10-07 19:12:23 +080070 if (V->getNumOperands() < (NameOpIdx + 1)) {
71 errs() << "Invalid metadata spec of " << N->getName()
72 << " in RenderScript executable. (#op)\n";
73 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070074 }
75
Zonr Chang7f2f3852010-10-07 19:12:23 +080076 MDString *Name = dyn_cast<MDString>(V->getOperand(NameOpIdx));
77 if (Name == NULL) {
78 errs() << "Invalid metadata spec of " << N->getName()
79 << " in RenderScript executable. (#name)\n";
80 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070081 }
82
Zonr Chang7f2f3852010-10-07 19:12:23 +080083 Names.push_back(Name->getString().data());
Shih-wei Liao835a7b72010-08-06 02:29:11 -070084 }
Zonr Chang7f2f3852010-10-07 19:12:23 +080085 return true;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070086}
87
Zonr Chang7f2f3852010-10-07 19:12:23 +080088static bool GetExportSymbols(Module *M, std::vector<const char *> &Names) {
89 bool Result = true;
90 // Variables marked as export must be externally visible
91 if (NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN))
92 Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names);
93 // So are those exported functions
94 if (NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN))
95 Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names);
96 return Result;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070097}
98
Shih-wei Liao835a7b72010-08-06 02:29:11 -070099
Zonr Changa02010c2010-10-11 20:54:28 +0800100static inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) {
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700101 std::string Err;
Zonr Changa02010c2010-10-11 20:54:28 +0800102 MemoryBuffer *MB = MemoryBuffer::getFile(F, &Err);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700103
Zonr Changa02010c2010-10-11 20:54:28 +0800104 if (MB == NULL)
105 errs() << "Failed to load `" << F << "' (" << Err << ")\n";
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700106
Zonr Changa02010c2010-10-11 20:54:28 +0800107 return MB;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700108}
109
Zonr Changa02010c2010-10-11 20:54:28 +0800110static inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB,
111 LLVMContext& Context) {
112 std::string Err;
113 Module *M = ParseBitcodeFile(MB, Context, &Err);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700114
Zonr Changa02010c2010-10-11 20:54:28 +0800115 if (M == NULL)
116 errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier()
117 << "' (" << Err << ")\n";
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700118
Zonr Changa02010c2010-10-11 20:54:28 +0800119 return M;
120}
121
122// LoadBitcodeFile - Read the specified bitcode file in and return it.
123static inline Module *LoadBitcodeFile(const std::string &F,
124 LLVMContext& Context) {
125 MemoryBuffer *MB = LoadFileIntoMemory(F);
126 if (MB == NULL)
127 return NULL;
128
129 Module *M = ParseBitcodeFromMemoryBuffer(MB, Context);
130 if (M == NULL)
131 delete MB;
132
133 return M;
134}
135
136extern const char rslib_bc[];
137extern unsigned rslib_bc_size;
138
139static bool PreloadLibraries(bool NoStdLib,
140 const std::vector<std::string> &AdditionalLibs,
141 std::list<MemoryBuffer *> LibBitcode) {
142 MemoryBuffer *MB;
143
144 LibBitcode.clear();
145
146 if (!NoStdLib) {
147 // rslib.bc
Zonr Changd124ee62010-10-22 18:26:25 +0800148 MB = MemoryBuffer::getMemBuffer(StringRef(rslib_bc, rslib_bc_size),
149 "rslib.bc");
Zonr Changa02010c2010-10-11 20:54:28 +0800150 if (MB == NULL) {
151 errs() << "Failed to load (in-memory) `rslib.bc'!\n";
152 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700153 }
Zonr Changa02010c2010-10-11 20:54:28 +0800154
155 LibBitcode.push_back(MB);
156 }
157
158 // Load additional libraries
159 for (std::vector<std::string>::const_iterator
160 I = AdditionalLibs.begin(), E = AdditionalLibs.end();
161 I != E;
162 I++) {
163 MB = LoadFileIntoMemory(*I);
164 if (MB == NULL)
165 return false;
166 LibBitcode.push_back(MB);
167 }
168
169 return true;
170}
171
172static void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) {
173 for (std::list<MemoryBuffer *>::iterator
174 I = LibBitcode.begin(), E = LibBitcode.end();
175 I != E;
176 I++)
177 delete *I;
178 LibBitcode.clear();
179 return;
180}
181
182Module *PerformLinking(const std::string &InputFile,
183 const std::list<MemoryBuffer *> &LibBitcode,
184 LLVMContext &Context) {
185 std::string Err;
186 std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context));
187
188 if (Composite.get() == NULL)
189 return NULL;
190
191 for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(),
192 E = LibBitcode.end();
193 I != E;
194 I++) {
195 Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context);
196 if (Lib == NULL)
197 return NULL;
198
199 if (Linker::LinkModules(Composite.get(), Lib, &Err)) {
200 errs() << "Failed to link `" << InputFile << "' with library bitcode `"
201 << (*I)->getBufferIdentifier() << "' (" << Err << ")\n";
202 return NULL;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700203 }
204 }
205
Zonr Changa02010c2010-10-11 20:54:28 +0800206 return Composite.release();
207}
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700208
Zonr Changa02010c2010-10-11 20:54:28 +0800209bool OptimizeModule(Module *M) {
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700210 PassManager Passes;
211
Zonr Changa02010c2010-10-11 20:54:28 +0800212 const std::string &ModuleDataLayout = M->getDataLayout();
Zonr Chang7f2f3852010-10-07 19:12:23 +0800213 if (!ModuleDataLayout.empty())
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700214 if (TargetData *TD = new TargetData(ModuleDataLayout))
215 Passes.add(TD);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700216
Zonr Chang7f2f3852010-10-07 19:12:23 +0800217 // Some symbols must not be internalized
218 std::vector<const char *> ExportList;
219 ExportList.push_back("init");
220 ExportList.push_back("root");
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700221
Zonr Changa02010c2010-10-11 20:54:28 +0800222 if (!GetExportSymbols(M, ExportList)) {
223 return false;
224 }
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -0700225
Zonr Chang7f2f3852010-10-07 19:12:23 +0800226 Passes.add(createInternalizePass(ExportList));
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700227
Zonr Changa02010c2010-10-11 20:54:28 +0800228 // TODO(zonr): Do we need to run all LTO passes?
Zonr Chang7f2f3852010-10-07 19:12:23 +0800229 createStandardLTOPasses(&Passes,
230 /* Internalize = */false,
231 /* RunInliner = */true,
232 /* VerifyEach = */false);
Zonr Changa02010c2010-10-11 20:54:28 +0800233 Passes.run(*M);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700234
Zonr Changa02010c2010-10-11 20:54:28 +0800235 return true;
236}
Zonr Chang7f2f3852010-10-07 19:12:23 +0800237
Zonr Changa02010c2010-10-11 20:54:28 +0800238int main(int argc, char **argv) {
239 llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
240
241 cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
242
243 std::list<MemoryBuffer *> LibBitcode;
244
245 if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode))
246 return 1;
247
248 // No libraries specified to be linked
249 if (LibBitcode.size() == 0)
250 return 0;
251
252 LLVMContext &Context = getGlobalContext();
253 bool HasError = true;
254 std::string Err;
255
256 for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) {
257 std::auto_ptr<Module> Linked(
258 PerformLinking(InputFilenames[i], LibBitcode, Context));
259
260 // Failed to link with InputFilenames[i] with LibBitcode
261 if (Linked.get() == NULL)
262 break;
263
264 // Verify linked module
265 if (verifyModule(*Linked, ReturnStatusAction, &Err)) {
266 errs() << InputFilenames[i] << " linked, but does not verify as "
267 "correct! (" << Err << ")\n";
268 break;
269 }
270
271 if (!OptimizeModule(Linked.get()))
272 break;
273
274 // Write out the module
275 tool_output_file Out(InputFilenames[i].c_str(), Err,
276 raw_fd_ostream::F_Binary);
277
278 if (!Err.empty()) {
279 errs() << InputFilenames[i] << " linked, but failed to write out! "
280 "(" << Err << ")\n";
281 break;
282 }
283
284 WriteBitcodeToFile(Linked.get(), Out);
285
286 Out.keep();
287 Linked.reset();
288
289 if (i == (InputFilenames.size() - 1))
290 // This is the last file and no error occured.
291 HasError = false;
292 }
293
294 UnloadLibraries(LibBitcode);
295
296 return HasError;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700297}