llvm-rs-link.cpp revision df5bcce1582d839eead432a5e24435236c90fb05
1/*
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
17#include <list>
18#include <memory>
19#include <string>
20#include <vector>
21
22#include "llvm/Analysis/Verifier.h"
23
24#include "llvm/Bitcode/ReaderWriter.h"
25
26#include "llvm/Linker.h"
27#include "llvm/LLVMContext.h"
28#include "llvm/Metadata.h"
29#include "llvm/Module.h"
30
31#include "llvm/Support/CommandLine.h"
32#include "llvm/Support/ManagedStatic.h"
33#include "llvm/Support/MemoryBuffer.h"
34#include "llvm/Support/StandardPasses.h"
35#include "llvm/Support/raw_ostream.h"
36#include "llvm/Support/ToolOutputFile.h"
37
38#include "llvm/Target/TargetData.h"
39
40#include "slang_rs_metadata.h"
41
42using llvm::errs;
43using llvm::LLVMContext;
44using llvm::MemoryBuffer;
45using llvm::Module;
46
47static llvm::cl::list<std::string>
48InputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
49               llvm::cl::desc("<input bitcode files>"));
50
51static llvm::cl::list<std::string>
52OutputFilenames("o", llvm::cl::desc("Override output filename"),
53                llvm::cl::value_desc("<output bitcode file>"));
54
55static llvm::cl::opt<bool>
56NoStdLib("nostdlib", llvm::cl::desc("Don't link RS default libraries"));
57
58static llvm::cl::list<std::string>
59    AdditionalLibs("l", llvm::cl::Prefix,
60                   llvm::cl::desc("Specify additional libraries to link to"),
61                   llvm::cl::value_desc("<library bitcode>"));
62
63static bool GetExportSymbolNames(llvm::NamedMDNode *N,
64                                 unsigned NameOpIdx,
65                                 std::vector<const char *> &Names) {
66  if (N == NULL)
67    return true;
68
69  for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
70    llvm::MDNode *V = N->getOperand(i);
71    if (V == NULL)
72      continue;
73
74    if (V->getNumOperands() < (NameOpIdx + 1)) {
75      errs() << "Invalid metadata spec of " << N->getName()
76             << " in RenderScript executable. (#op)\n";
77      return false;
78    }
79
80    llvm::MDString *Name =
81        llvm::dyn_cast<llvm::MDString>(V->getOperand(NameOpIdx));
82    if (Name == NULL) {
83      errs() << "Invalid metadata spec of " << N->getName()
84             << " in RenderScript executable. (#name)\n";
85      return false;
86    }
87
88    Names.push_back(Name->getString().data());
89  }
90  return true;
91}
92
93static bool GetExportSymbols(Module *M, std::vector<const char *> &Names) {
94  bool Result = true;
95  // Variables marked as export must be externally visible
96  if (llvm::NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN))
97    Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names);
98  // So are those exported functions
99  if (llvm::NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN))
100    Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names);
101  return Result;
102}
103
104static inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) {
105  std::string Err;
106  MemoryBuffer *MB = MemoryBuffer::getFile(F, &Err);
107
108  if (MB == NULL)
109    errs() << "Failed to load `" << F << "' (" << Err << ")\n";
110
111  return MB;
112}
113
114static inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB,
115                                                   LLVMContext& Context) {
116  std::string Err;
117  Module *M = ParseBitcodeFile(MB, Context, &Err);
118
119  if (M == NULL)
120    errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier()
121           <<  "' (" << Err << ")\n";
122
123  return M;
124}
125
126// LoadBitcodeFile - Read the specified bitcode file in and return it.
127static inline Module *LoadBitcodeFile(const std::string &F,
128                                      LLVMContext& Context) {
129  MemoryBuffer *MB = LoadFileIntoMemory(F);
130  if (MB == NULL)
131    return NULL;
132
133  Module *M = ParseBitcodeFromMemoryBuffer(MB, Context);
134  if (M == NULL)
135    delete MB;
136
137  return M;
138}
139
140extern const char rslib_bc[];
141extern unsigned rslib_bc_size;
142
143static bool PreloadLibraries(bool NoStdLib,
144                             const std::vector<std::string> &AdditionalLibs,
145                             std::list<MemoryBuffer *> &LibBitcode) {
146  MemoryBuffer *MB;
147
148  LibBitcode.clear();
149
150  if (!NoStdLib) {
151    // rslib.bc
152    MB = MemoryBuffer::getMemBuffer(llvm::StringRef(rslib_bc, rslib_bc_size),
153                                    "rslib.bc");
154    if (MB == NULL) {
155      errs() << "Failed to load (in-memory) `rslib.bc'!\n";
156      return false;
157    }
158
159    LibBitcode.push_back(MB);
160  }
161
162  // Load additional libraries
163  for (std::vector<std::string>::const_iterator
164          I = AdditionalLibs.begin(), E = AdditionalLibs.end();
165       I != E;
166       I++) {
167    MB = LoadFileIntoMemory(*I);
168    if (MB == NULL)
169      return false;
170    LibBitcode.push_back(MB);
171  }
172
173  return true;
174}
175
176static void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) {
177  for (std::list<MemoryBuffer *>::iterator
178          I = LibBitcode.begin(), E = LibBitcode.end();
179       I != E;
180       I++)
181    delete *I;
182  LibBitcode.clear();
183  return;
184}
185
186Module *PerformLinking(const std::string &InputFile,
187                       const std::list<MemoryBuffer *> &LibBitcode,
188                       LLVMContext &Context) {
189  std::string Err;
190  std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context));
191
192  if (Composite.get() == NULL)
193    return NULL;
194
195  for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(),
196          E = LibBitcode.end();
197       I != E;
198       I++) {
199    Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context);
200    if (Lib == NULL)
201      return NULL;
202
203    if (llvm::Linker::LinkModules(Composite.get(), Lib, &Err)) {
204      errs() << "Failed to link `" << InputFile << "' with library bitcode `"
205             << (*I)->getBufferIdentifier() << "' (" << Err << ")\n";
206      return NULL;
207    }
208  }
209
210  return Composite.release();
211}
212
213bool OptimizeModule(Module *M) {
214  llvm::PassManager Passes;
215
216  const std::string &ModuleDataLayout = M->getDataLayout();
217  if (!ModuleDataLayout.empty())
218    if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
219      Passes.add(TD);
220
221  // Some symbols must not be internalized
222  std::vector<const char *> ExportList;
223  ExportList.push_back("init");
224  ExportList.push_back("root");
225
226  if (!GetExportSymbols(M, ExportList)) {
227    return false;
228  }
229
230  Passes.add(llvm::createInternalizePass(ExportList));
231
232  // TODO(zonr): Do we need to run all LTO passes?
233  createStandardLTOPasses(&Passes,
234                          /* Internalize = */false,
235                          /* RunInliner = */true,
236                          /* VerifyEach = */false);
237  Passes.run(*M);
238
239  return true;
240}
241
242int main(int argc, char **argv) {
243  llvm::llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
244
245  llvm::cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
246
247  std::list<MemoryBuffer *> LibBitcode;
248
249  if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode))
250    return 1;
251
252  // No libraries specified to be linked
253  if (LibBitcode.size() == 0)
254    return 0;
255
256  LLVMContext &Context = llvm::getGlobalContext();
257  bool HasError = true;
258  std::string Err;
259
260  for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) {
261    std::auto_ptr<Module> Linked(
262        PerformLinking(InputFilenames[i], LibBitcode, Context));
263
264    // Failed to link with InputFilenames[i] with LibBitcode
265    if (Linked.get() == NULL)
266      break;
267
268    // Verify linked module
269    if (verifyModule(*Linked, llvm::ReturnStatusAction, &Err)) {
270      errs() << InputFilenames[i] << " linked, but does not verify as "
271                                     "correct! (" << Err << ")\n";
272      break;
273    }
274
275    if (!OptimizeModule(Linked.get()))
276      break;
277
278    // Write out the module
279    llvm::tool_output_file Out(InputFilenames[i].c_str(), Err,
280                               llvm::raw_fd_ostream::F_Binary);
281
282    if (!Err.empty()) {
283      errs() << InputFilenames[i] << " linked, but failed to write out! "
284                                     "(" << Err << ")\n";
285      break;
286    }
287
288    WriteBitcodeToFile(Linked.get(), Out.os());
289
290    Out.keep();
291    Linked.reset();
292
293    if (i == (InputFilenames.size() - 1))
294      // This is the last file and no error occured.
295      HasError = false;
296  }
297
298  UnloadLibraries(LibBitcode);
299
300  return HasError;
301}
302