blob: 8dec206ba1ebe80049e0d21192342066a8dfbc80 [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
Stephen Hinese639eb52010-11-08 19:27:20 -080022#include "llvm/Analysis/Verifier.h"
23
24#include "llvm/Bitcode/ReaderWriter.h"
25
Shih-wei Liao835a7b72010-08-06 02:29:11 -070026#include "llvm/Linker.h"
27#include "llvm/LLVMContext.h"
28#include "llvm/Metadata.h"
29#include "llvm/Module.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/raw_ostream.h"
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -080035#include "llvm/Support/ToolOutputFile.h"
Loganbe274822011-02-16 22:02:54 +080036#include "llvm/Support/system_error.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080037
Logan Chien9207a2e2011-10-21 15:39:28 +080038#include "llvm/PassManager.h"
39#include "llvm/Transforms/IPO.h"
40#include "llvm/Transforms/IPO/PassManagerBuilder.h"
41
Shih-wei Liao835a7b72010-08-06 02:29:11 -070042#include "llvm/Target/TargetData.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080043
44#include "slang_rs_metadata.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070045
Stephen Hinese639eb52010-11-08 19:27:20 -080046using llvm::errs;
47using llvm::LLVMContext;
48using llvm::MemoryBuffer;
49using llvm::Module;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070050
Stephen Hinese639eb52010-11-08 19:27:20 -080051static llvm::cl::list<std::string>
52InputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
53 llvm::cl::desc("<input bitcode files>"));
Shih-wei Liao835a7b72010-08-06 02:29:11 -070054
Stephen Hinese639eb52010-11-08 19:27:20 -080055static llvm::cl::list<std::string>
56OutputFilenames("o", llvm::cl::desc("Override output filename"),
57 llvm::cl::value_desc("<output bitcode file>"));
Zonr Changa02010c2010-10-11 20:54:28 +080058
Stephen Hinese639eb52010-11-08 19:27:20 -080059static llvm::cl::opt<bool>
60NoStdLib("nostdlib", llvm::cl::desc("Don't link RS default libraries"));
Zonr Changa02010c2010-10-11 20:54:28 +080061
Stephen Hinese639eb52010-11-08 19:27:20 -080062static llvm::cl::list<std::string>
63 AdditionalLibs("l", llvm::cl::Prefix,
64 llvm::cl::desc("Specify additional libraries to link to"),
65 llvm::cl::value_desc("<library bitcode>"));
Shih-wei Liao835a7b72010-08-06 02:29:11 -070066
Stephen Hinese639eb52010-11-08 19:27:20 -080067static bool GetExportSymbolNames(llvm::NamedMDNode *N,
Zonr Chang7f2f3852010-10-07 19:12:23 +080068 unsigned NameOpIdx,
69 std::vector<const char *> &Names) {
70 if (N == NULL)
71 return true;
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -070072
Zonr Chang7f2f3852010-10-07 19:12:23 +080073 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
Stephen Hinese639eb52010-11-08 19:27:20 -080074 llvm::MDNode *V = N->getOperand(i);
Zonr Chang7f2f3852010-10-07 19:12:23 +080075 if (V == NULL)
76 continue;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070077
Zonr Chang7f2f3852010-10-07 19:12:23 +080078 if (V->getNumOperands() < (NameOpIdx + 1)) {
79 errs() << "Invalid metadata spec of " << N->getName()
Stephen Hinesb7d12692011-09-02 18:16:19 -070080 << " in Renderscript executable. (#op)\n";
Zonr Chang7f2f3852010-10-07 19:12:23 +080081 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070082 }
83
Stephen Hinese639eb52010-11-08 19:27:20 -080084 llvm::MDString *Name =
85 llvm::dyn_cast<llvm::MDString>(V->getOperand(NameOpIdx));
Zonr Chang7f2f3852010-10-07 19:12:23 +080086 if (Name == NULL) {
87 errs() << "Invalid metadata spec of " << N->getName()
Stephen Hinesb7d12692011-09-02 18:16:19 -070088 << " in Renderscript executable. (#name)\n";
Zonr Chang7f2f3852010-10-07 19:12:23 +080089 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070090 }
91
Zonr Chang7f2f3852010-10-07 19:12:23 +080092 Names.push_back(Name->getString().data());
Shih-wei Liao835a7b72010-08-06 02:29:11 -070093 }
Zonr Chang7f2f3852010-10-07 19:12:23 +080094 return true;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070095}
96
Zonr Chang7f2f3852010-10-07 19:12:23 +080097static bool GetExportSymbols(Module *M, std::vector<const char *> &Names) {
98 bool Result = true;
99 // Variables marked as export must be externally visible
Stephen Hinese639eb52010-11-08 19:27:20 -0800100 if (llvm::NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN))
Zonr Chang7f2f3852010-10-07 19:12:23 +0800101 Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names);
102 // So are those exported functions
Stephen Hinese639eb52010-11-08 19:27:20 -0800103 if (llvm::NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN))
Zonr Chang7f2f3852010-10-07 19:12:23 +0800104 Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names);
105 return Result;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700106}
107
Zonr Changa02010c2010-10-11 20:54:28 +0800108static inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) {
Loganbe274822011-02-16 22:02:54 +0800109 llvm::OwningPtr<MemoryBuffer> MB;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700110
Loganbe274822011-02-16 22:02:54 +0800111 if (llvm::error_code EC = MemoryBuffer::getFile(F, MB)) {
112 errs() << "Failed to load `" << F << "' (" + EC.message() + ")\n";
113 }
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700114
Loganbe274822011-02-16 22:02:54 +0800115 return MB.take();
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700116}
117
Zonr Changa02010c2010-10-11 20:54:28 +0800118static inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB,
119 LLVMContext& Context) {
120 std::string Err;
121 Module *M = ParseBitcodeFile(MB, Context, &Err);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700122
Zonr Changa02010c2010-10-11 20:54:28 +0800123 if (M == NULL)
124 errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier()
125 << "' (" << Err << ")\n";
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700126
Zonr Changa02010c2010-10-11 20:54:28 +0800127 return M;
128}
129
130// LoadBitcodeFile - Read the specified bitcode file in and return it.
131static inline Module *LoadBitcodeFile(const std::string &F,
132 LLVMContext& Context) {
133 MemoryBuffer *MB = LoadFileIntoMemory(F);
134 if (MB == NULL)
135 return NULL;
136
137 Module *M = ParseBitcodeFromMemoryBuffer(MB, Context);
138 if (M == NULL)
139 delete MB;
140
141 return M;
142}
143
144extern const char rslib_bc[];
145extern unsigned rslib_bc_size;
146
147static bool PreloadLibraries(bool NoStdLib,
148 const std::vector<std::string> &AdditionalLibs,
Shih-wei Liao552b5812010-11-16 05:51:19 -0800149 std::list<MemoryBuffer *> &LibBitcode) {
Zonr Changa02010c2010-10-11 20:54:28 +0800150 MemoryBuffer *MB;
151
152 LibBitcode.clear();
153
154 if (!NoStdLib) {
155 // rslib.bc
Stephen Hinese639eb52010-11-08 19:27:20 -0800156 MB = MemoryBuffer::getMemBuffer(llvm::StringRef(rslib_bc, rslib_bc_size),
Zonr Changd124ee62010-10-22 18:26:25 +0800157 "rslib.bc");
Zonr Changa02010c2010-10-11 20:54:28 +0800158 if (MB == NULL) {
159 errs() << "Failed to load (in-memory) `rslib.bc'!\n";
160 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700161 }
Zonr Changa02010c2010-10-11 20:54:28 +0800162
163 LibBitcode.push_back(MB);
164 }
165
166 // Load additional libraries
167 for (std::vector<std::string>::const_iterator
168 I = AdditionalLibs.begin(), E = AdditionalLibs.end();
169 I != E;
170 I++) {
171 MB = LoadFileIntoMemory(*I);
172 if (MB == NULL)
173 return false;
174 LibBitcode.push_back(MB);
175 }
176
177 return true;
178}
179
180static void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) {
181 for (std::list<MemoryBuffer *>::iterator
182 I = LibBitcode.begin(), E = LibBitcode.end();
183 I != E;
184 I++)
185 delete *I;
186 LibBitcode.clear();
187 return;
188}
189
190Module *PerformLinking(const std::string &InputFile,
191 const std::list<MemoryBuffer *> &LibBitcode,
192 LLVMContext &Context) {
193 std::string Err;
194 std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context));
195
196 if (Composite.get() == NULL)
197 return NULL;
198
199 for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(),
200 E = LibBitcode.end();
201 I != E;
202 I++) {
203 Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context);
204 if (Lib == NULL)
205 return NULL;
206
Logan Chien9207a2e2011-10-21 15:39:28 +0800207 if (llvm::Linker::LinkModules(Composite.get(), Lib,
208 llvm::Linker::DestroySource, &Err)) {
Zonr Changa02010c2010-10-11 20:54:28 +0800209 errs() << "Failed to link `" << InputFile << "' with library bitcode `"
210 << (*I)->getBufferIdentifier() << "' (" << Err << ")\n";
211 return NULL;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700212 }
213 }
214
Zonr Changa02010c2010-10-11 20:54:28 +0800215 return Composite.release();
216}
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700217
Zonr Changa02010c2010-10-11 20:54:28 +0800218bool OptimizeModule(Module *M) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800219 llvm::PassManager Passes;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700220
Zonr Changa02010c2010-10-11 20:54:28 +0800221 const std::string &ModuleDataLayout = M->getDataLayout();
Zonr Chang7f2f3852010-10-07 19:12:23 +0800222 if (!ModuleDataLayout.empty())
Stephen Hinese639eb52010-11-08 19:27:20 -0800223 if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700224 Passes.add(TD);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700225
Zonr Chang7f2f3852010-10-07 19:12:23 +0800226 // Some symbols must not be internalized
227 std::vector<const char *> ExportList;
228 ExportList.push_back("init");
229 ExportList.push_back("root");
Stephen Hines688e64b2011-08-23 16:01:25 -0700230 ExportList.push_back(".rs.dtor");
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700231
Zonr Changa02010c2010-10-11 20:54:28 +0800232 if (!GetExportSymbols(M, ExportList)) {
233 return false;
234 }
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -0700235
Stephen Hinese639eb52010-11-08 19:27:20 -0800236 Passes.add(llvm::createInternalizePass(ExportList));
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700237
Shih-wei Liaofcc654a2011-06-22 04:47:33 -0700238 // TODO(sliao): Do we need to run all LTO passes?
239 llvm::PassManagerBuilder PMBuilder;
240 PMBuilder.populateLTOPassManager(Passes,
241 /* Internalize = */false,
242 /* RunInliner = */true);
Zonr Changa02010c2010-10-11 20:54:28 +0800243 Passes.run(*M);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700244
Zonr Changa02010c2010-10-11 20:54:28 +0800245 return true;
246}
Zonr Chang7f2f3852010-10-07 19:12:23 +0800247
Zonr Changa02010c2010-10-11 20:54:28 +0800248int main(int argc, char **argv) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800249 llvm::llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
Zonr Changa02010c2010-10-11 20:54:28 +0800250
Stephen Hinese639eb52010-11-08 19:27:20 -0800251 llvm::cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
Zonr Changa02010c2010-10-11 20:54:28 +0800252
253 std::list<MemoryBuffer *> LibBitcode;
254
255 if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode))
256 return 1;
257
258 // No libraries specified to be linked
259 if (LibBitcode.size() == 0)
260 return 0;
261
Stephen Hinese639eb52010-11-08 19:27:20 -0800262 LLVMContext &Context = llvm::getGlobalContext();
Zonr Changa02010c2010-10-11 20:54:28 +0800263 bool HasError = true;
264 std::string Err;
265
266 for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) {
267 std::auto_ptr<Module> Linked(
268 PerformLinking(InputFilenames[i], LibBitcode, Context));
269
270 // Failed to link with InputFilenames[i] with LibBitcode
271 if (Linked.get() == NULL)
272 break;
273
274 // Verify linked module
Stephen Hinese639eb52010-11-08 19:27:20 -0800275 if (verifyModule(*Linked, llvm::ReturnStatusAction, &Err)) {
Zonr Changa02010c2010-10-11 20:54:28 +0800276 errs() << InputFilenames[i] << " linked, but does not verify as "
277 "correct! (" << Err << ")\n";
278 break;
279 }
280
281 if (!OptimizeModule(Linked.get()))
282 break;
283
284 // Write out the module
Stephen Hinese639eb52010-11-08 19:27:20 -0800285 llvm::tool_output_file Out(InputFilenames[i].c_str(), Err,
286 llvm::raw_fd_ostream::F_Binary);
Zonr Changa02010c2010-10-11 20:54:28 +0800287
288 if (!Err.empty()) {
289 errs() << InputFilenames[i] << " linked, but failed to write out! "
290 "(" << Err << ")\n";
291 break;
292 }
293
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800294 WriteBitcodeToFile(Linked.get(), Out.os());
Zonr Changa02010c2010-10-11 20:54:28 +0800295
296 Out.keep();
297 Linked.reset();
298
299 if (i == (InputFilenames.size() - 1))
300 // This is the last file and no error occured.
301 HasError = false;
302 }
303
304 UnloadLibraries(LibBitcode);
305
306 return HasError;
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700307}