1#include <cassert>
2#include <list>
3#include <string>
4
5#include "llvm/Linker.h"
6#include "llvm/LLVMContext.h"
7#include "llvm/Module.h"
8#include "llvm/PassManager.h"
9
10#include "llvm/ADT/OwningPtr.h"
11
12#include "llvm/Bitcode/ReaderWriter.h"
13
14#include "llvm/Support/CommandLine.h"
15#include "llvm/Support/ManagedStatic.h"
16#include "llvm/Support/MemoryBuffer.h"
17#include "llvm/Support/raw_ostream.h"
18#include "llvm/Transforms/IPO.h"
19#include "llvm/Transforms/IPO/PassManagerBuilder.h"
20#include "llvm/Support/system_error.h"
21
22#include "llvm/Target/TargetData.h"
23
24static llvm::cl::list<std::string>
25InputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
26               llvm::cl::desc("<input bitcode files>"));
27
28static llvm::cl::list<std::string>
29OutputFilenames("o", llvm::cl::desc("Override output filename"),
30                llvm::cl::value_desc("output bitcode file"));
31
32
33static llvm::Module* getModuleFromFilename(std::string& Filename,
34                                           llvm::LLVMContext& Ctx,
35                                           std::string& ErrMsg) {
36  llvm::OwningPtr<llvm::MemoryBuffer> MB;
37  llvm::MemoryBuffer::getFile(Filename, MB);
38  llvm::Module* M = llvm::ParseBitcodeFile(MB.get(), Ctx, &ErrMsg);
39  assert(M && ErrMsg);
40  return M;
41}
42
43static void optimizeModule(llvm::Module* M) {
44  llvm::PassManager Passes;
45
46  const std::string &ModuleDataLayout = M->getDataLayout();
47  if (!ModuleDataLayout.empty())
48    if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
49      Passes.add(TD);
50
51  Passes.add(llvm::createInternalizePass(true/* AllButMain*/));
52#if 0
53  FIXME REMOVE
54  createStandardLTOPasses(&Passes,
55                          /* Internalize = */false,
56                          /* RunInliner = */true,
57                          /* VerifyEach = */false);
58#endif
59  llvm::PassManagerBuilder PMBuilder;
60  PMBuilder.populateLTOPassManager(Passes, false, true);
61  Passes.run(*M);
62}
63
64static llvm::Module* linkFilesToModule(llvm::cl::list<std::string>& Inputs,
65                                       llvm::LLVMContext& Ctx) {
66  std::string ErrMsg;
67  llvm::Module* M = getModuleFromFilename(Inputs[0], Ctx, ErrMsg);
68  llvm::Linker Linker("llvm-ndk-link", M);
69
70  for (unsigned i=1; i<Inputs.size(); ++i) {
71    llvm::Module* M = getModuleFromFilename(Inputs[i], Ctx, ErrMsg);
72    if (!Linker.LinkInModule(M, &ErrMsg)) {
73      assert(false && ErrMsg);
74    }
75    optimizeModule(M);
76  }
77  M = Linker.releaseModule();
78
79  llvm::PassManager PM;
80  const std::string &ModuleDataLayout = M->getDataLayout();
81  if (!ModuleDataLayout.empty())
82    if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
83      PM.add(TD);
84
85#if 0
86  FIXME REMOVE
87  llvm::createStandardFunctionPasses(&PM, 3 /* OptLevel*/);
88  llvm::createStandardModulePasses(&PM,
89                                   3, /* OptimizationLevel */
90                                   true, /* OptimizeSize */
91                                   true, /* UnitAtATime */
92                                   true, /* UnrollLoops */
93                                   true, /* SimplifyLibCalls */
94                                   false, /* HaveExceptions */
95                                   NULL /* InliningPass */);
96#endif
97
98  llvm::PassManagerBuilder PMBuilder;
99  //PMBuilder.OptLevel = 3;
100  //PMBuilder.populateFunctionPassManager(PM);
101
102  PMBuilder.OptLevel = 3;
103  PMBuilder.SizeLevel = true;
104  PMBuilder.DisableUnitAtATime = false;
105  PMBuilder.DisableUnrollLoops = false;
106  PMBuilder.DisableSimplifyLibCalls = false;
107  PMBuilder.populateModulePassManager(PM);
108
109  PM.run(*M);
110  return M;
111}
112
113int main(int argc, char** argv) {
114  llvm::llvm_shutdown_obj _ShutdownObj;
115  llvm::cl::ParseCommandLineOptions(argc, argv, "P-NDK Link Tool");
116
117  llvm::LLVMContext& Ctx = llvm::getGlobalContext();
118  std::string ErrMsg;
119  llvm::raw_fd_ostream FOS(OutputFilenames[0].c_str(), ErrMsg);
120  assert(!FOS.has_error());
121
122  // No need to link (just one file).
123  // Output Directly.
124  if (InputFilenames.size() == 1) {
125    llvm::OwningPtr<llvm::Module> M(getModuleFromFilename(InputFilenames[0],
126                                                           Ctx,
127                                                           ErrMsg));
128    llvm::WriteBitcodeToFile(M.get(), FOS);
129    return 0;
130  }
131
132  llvm::OwningPtr<llvm::Module> M(linkFilesToModule(InputFilenames, Ctx));
133  llvm::WriteBitcodeToFile(M.get(), FOS);
134  assert(!FOS.has_error());
135  return 0;
136}
137