1c383a500aa59423264811be3874461bf8adbfea0Zonr Chang/*
2c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Copyright 2010, The Android Open Source Project
3c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
4c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * you may not use this file except in compliance with the License.
6c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * You may obtain a copy of the License at
7c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
8c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9c383a500aa59423264811be3874461bf8adbfea0Zonr Chang *
10c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * Unless required by applicable law or agreed to in writing, software
11c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * See the License for the specific language governing permissions and
14c383a500aa59423264811be3874461bf8adbfea0Zonr Chang * limitations under the License.
15c383a500aa59423264811be3874461bf8adbfea0Zonr Chang */
16c383a500aa59423264811be3874461bf8adbfea0Zonr Chang
17a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang#include <list>
186315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include <memory>
196315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include <string>
206315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr#include <vector>
216315f76e3cc6ff2d012d1183a0b030d4ff0dc808zonr
22e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Analysis/Verifier.h"
23e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
24e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include "llvm/Bitcode/ReaderWriter.h"
25e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
26835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Linker.h"
27835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/LLVMContext.h"
28835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Metadata.h"
29835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Module.h"
307f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang
31835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Support/CommandLine.h"
32835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Support/ManagedStatic.h"
33835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Support/MemoryBuffer.h"
34835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Support/raw_ostream.h"
35df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao#include "llvm/Support/ToolOutputFile.h"
36be27482cdeaf08576bc39b72a15d35d13014a636Logan#include "llvm/Support/system_error.h"
377f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang
389207a2e495c8363606861e4f034504ec5c153dabLogan Chien#include "llvm/PassManager.h"
399207a2e495c8363606861e4f034504ec5c153dabLogan Chien#include "llvm/Transforms/IPO.h"
409207a2e495c8363606861e4f034504ec5c153dabLogan Chien#include "llvm/Transforms/IPO/PassManagerBuilder.h"
419207a2e495c8363606861e4f034504ec5c153dabLogan Chien
42835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao#include "llvm/Target/TargetData.h"
437f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang
447f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang#include "slang_rs_metadata.h"
45835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
46e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesusing llvm::errs;
47e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesusing llvm::LLVMContext;
48e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesusing llvm::MemoryBuffer;
49e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesusing llvm::Module;
50835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
51e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesstatic llvm::cl::list<std::string>
52e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen HinesInputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
53e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines               llvm::cl::desc("<input bitcode files>"));
54835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
55e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesstatic llvm::cl::list<std::string>
56e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen HinesOutputFilenames("o", llvm::cl::desc("Override output filename"),
57e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                llvm::cl::value_desc("<output bitcode file>"));
58a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
59e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesstatic llvm::cl::opt<bool>
60e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen HinesNoStdLib("nostdlib", llvm::cl::desc("Don't link RS default libraries"));
61a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
62e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesstatic llvm::cl::list<std::string>
63e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    AdditionalLibs("l", llvm::cl::Prefix,
64e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                   llvm::cl::desc("Specify additional libraries to link to"),
65e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                   llvm::cl::value_desc("<library bitcode>"));
66835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
67e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesstatic bool GetExportSymbolNames(llvm::NamedMDNode *N,
687f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang                                 unsigned NameOpIdx,
697f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang                                 std::vector<const char *> &Names) {
707f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  if (N == NULL)
717f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    return true;
727f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang
737f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
74e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    llvm::MDNode *V = N->getOperand(i);
757f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    if (V == NULL)
767f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang      continue;
777f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang
787f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    if (V->getNumOperands() < (NameOpIdx + 1)) {
797f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang      errs() << "Invalid metadata spec of " << N->getName()
80b7d1269f983f28d9fe625a96439fa88b39dc96f6Stephen Hines             << " in Renderscript executable. (#op)\n";
817f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang      return false;
82835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao    }
83835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
84e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    llvm::MDString *Name =
85e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines        llvm::dyn_cast<llvm::MDString>(V->getOperand(NameOpIdx));
867f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    if (Name == NULL) {
877f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang      errs() << "Invalid metadata spec of " << N->getName()
88b7d1269f983f28d9fe625a96439fa88b39dc96f6Stephen Hines             << " in Renderscript executable. (#name)\n";
897f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang      return false;
90835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao    }
91835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
927f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    Names.push_back(Name->getString().data());
93835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao  }
947f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  return true;
95835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao}
96835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
977f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Changstatic bool GetExportSymbols(Module *M, std::vector<const char *> &Names) {
987f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  bool Result = true;
997f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  // Variables marked as export must be externally visible
100e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (llvm::NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN))
1017f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names);
1027f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  // So are those exported functions
103e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  if (llvm::NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN))
1047f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang    Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names);
1057f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  return Result;
106835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao}
107835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
108a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changstatic inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) {
109be27482cdeaf08576bc39b72a15d35d13014a636Logan  llvm::OwningPtr<MemoryBuffer> MB;
110835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
111be27482cdeaf08576bc39b72a15d35d13014a636Logan  if (llvm::error_code EC = MemoryBuffer::getFile(F, MB)) {
112be27482cdeaf08576bc39b72a15d35d13014a636Logan    errs() << "Failed to load `" << F << "' (" + EC.message() + ")\n";
113be27482cdeaf08576bc39b72a15d35d13014a636Logan  }
114835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
115be27482cdeaf08576bc39b72a15d35d13014a636Logan  return MB.take();
116835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao}
117835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
118a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changstatic inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB,
119a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                                                   LLVMContext& Context) {
120a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  std::string Err;
121a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  Module *M = ParseBitcodeFile(MB, Context, &Err);
122835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
123a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (M == NULL)
124a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier()
125a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang           <<  "' (" << Err << ")\n";
126835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
127a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return M;
128a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang}
129a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
130a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang// LoadBitcodeFile - Read the specified bitcode file in and return it.
131a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changstatic inline Module *LoadBitcodeFile(const std::string &F,
132a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                                      LLVMContext& Context) {
133a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  MemoryBuffer *MB = LoadFileIntoMemory(F);
134a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (MB == NULL)
135a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    return NULL;
136a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
137a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  Module *M = ParseBitcodeFromMemoryBuffer(MB, Context);
138a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (M == NULL)
139a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    delete MB;
140a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
141a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return M;
142a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang}
143a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
144a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changextern const char rslib_bc[];
145a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changextern unsigned rslib_bc_size;
146a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
147a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changstatic bool PreloadLibraries(bool NoStdLib,
148a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                             const std::vector<std::string> &AdditionalLibs,
149552b581ecc3070b2344a00da9e6f247648167b4dShih-wei Liao                             std::list<MemoryBuffer *> &LibBitcode) {
150a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  MemoryBuffer *MB;
151a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
152a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  LibBitcode.clear();
153a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
154a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (!NoStdLib) {
155a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    // rslib.bc
156e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    MB = MemoryBuffer::getMemBuffer(llvm::StringRef(rslib_bc, rslib_bc_size),
157d124ee6cfcb90229e7121fe81742d23a05375ce8Zonr Chang                                    "rslib.bc");
158a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (MB == NULL) {
159a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      errs() << "Failed to load (in-memory) `rslib.bc'!\n";
160a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      return false;
161835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao    }
162a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
163a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    LibBitcode.push_back(MB);
164835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao  }
165835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
166a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  // Load additional libraries
167a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  for (std::vector<std::string>::const_iterator
168a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang          I = AdditionalLibs.begin(), E = AdditionalLibs.end();
169a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang       I != E;
170a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang       I++) {
171a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    MB = LoadFileIntoMemory(*I);
172a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (MB == NULL)
173a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      return false;
174a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    LibBitcode.push_back(MB);
175835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao  }
176835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
177a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return true;
178a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang}
179a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
180a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changstatic void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) {
181a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  for (std::list<MemoryBuffer *>::iterator
182a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang          I = LibBitcode.begin(), E = LibBitcode.end();
183a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang       I != E;
184a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang       I++)
185a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    delete *I;
186a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  LibBitcode.clear();
187a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return;
188a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang}
189a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
190a02010cd90184a9c1be7b451fe32e114ffb1810fZonr ChangModule *PerformLinking(const std::string &InputFile,
191a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                       const std::list<MemoryBuffer *> &LibBitcode,
192a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                       LLVMContext &Context) {
193a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  std::string Err;
194a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context));
195a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
196a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (Composite.get() == NULL)
197a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    return NULL;
198a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
199a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(),
200a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang          E = LibBitcode.end();
201a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang       I != E;
202a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang       I++) {
203a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context);
204a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (Lib == NULL)
205a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      return NULL;
206a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
2079207a2e495c8363606861e4f034504ec5c153dabLogan Chien    if (llvm::Linker::LinkModules(Composite.get(), Lib,
2089207a2e495c8363606861e4f034504ec5c153dabLogan Chien                                  llvm::Linker::DestroySource, &Err)) {
209a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      errs() << "Failed to link `" << InputFile << "' with library bitcode `"
210a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang             << (*I)->getBufferIdentifier() << "' (" << Err << ")\n";
211a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      return NULL;
212a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    }
213835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao  }
214835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
215a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return Composite.release();
216a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang}
217a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
218a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changbool OptimizeModule(Module *M) {
219e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  llvm::PassManager Passes;
220835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
221a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  const std::string &ModuleDataLayout = M->getDataLayout();
2227f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  if (!ModuleDataLayout.empty())
223e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
224835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao      Passes.add(TD);
225835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
2267f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  // Some symbols must not be internalized
2277f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  std::vector<const char *> ExportList;
2287f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  ExportList.push_back("init");
2297f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang  ExportList.push_back("root");
230688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  ExportList.push_back(".rs.dtor");
2319c9bbc87c525e4f3c5f529dadea3f3cd8bd69010Shih-wei Liao
232a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (!GetExportSymbols(M, ExportList)) {
233a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    return false;
234a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  }
235835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
236e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  Passes.add(llvm::createInternalizePass(ExportList));
237835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
238fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao  // TODO(sliao): Do we need to run all LTO passes?
239fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao  llvm::PassManagerBuilder PMBuilder;
240fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao  PMBuilder.populateLTOPassManager(Passes,
241fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao                                   /* Internalize = */false,
242fcc654a1f4034978f7534479f9c5c33a92ca8546Shih-wei Liao                                   /* RunInliner = */true);
243a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  Passes.run(*M);
244a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
245a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return true;
246a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang}
247a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
248a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Changint main(int argc, char **argv) {
249e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  llvm::llvm_shutdown_obj X;  // Call llvm_shutdown() on exit.
250a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
251e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  llvm::cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
252a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
253a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  std::list<MemoryBuffer *> LibBitcode;
254a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
255a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode))
256a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    return 1;
257a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
258a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  // No libraries specified to be linked
259a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  if (LibBitcode.size() == 0)
260a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    return 0;
261a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
262e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  LLVMContext &Context = llvm::getGlobalContext();
263a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  bool HasError = true;
264a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  std::string Err;
265a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
266a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) {
267a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    std::auto_ptr<Module> Linked(
268a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang        PerformLinking(InputFilenames[i], LibBitcode, Context));
269a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
270a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    // Failed to link with InputFilenames[i] with LibBitcode
271a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (Linked.get() == NULL)
272a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      break;
273a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
274a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    // Verify linked module
275e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    if (verifyModule(*Linked, llvm::ReturnStatusAction, &Err)) {
276a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      errs() << InputFilenames[i] << " linked, but does not verify as "
277a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                                     "correct! (" << Err << ")\n";
278a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      break;
279a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    }
280a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
281a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (!OptimizeModule(Linked.get()))
282a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      break;
283a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
284a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    // Write out the module
285e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    llvm::tool_output_file Out(InputFilenames[i].c_str(), Err,
286e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                               llvm::raw_fd_ostream::F_Binary);
287a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
288a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (!Err.empty()) {
289a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      errs() << InputFilenames[i] << " linked, but failed to write out! "
290a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang                                     "(" << Err << ")\n";
291a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      break;
292a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    }
293a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
294df5bcce1582d839eead432a5e24435236c90fb05Shih-wei Liao    WriteBitcodeToFile(Linked.get(), Out.os());
295a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
296a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    Out.keep();
297a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    Linked.reset();
298a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang
299a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang    if (i == (InputFilenames.size() - 1))
300a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      // This is the last file and no error occured.
301a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang      HasError = false;
302a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  }
303835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao
304a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  UnloadLibraries(LibBitcode);
3057f2f385d3129ba4de82ef56adb9cb4385fd33001Zonr Chang
306a02010cd90184a9c1be7b451fe32e114ffb1810fZonr Chang  return HasError;
307835a7b773631261b9ea2fb448a4c8a7a8cacfaabShih-wei Liao}
308