• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 static llvm::cl::list<std::string>
25 InputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
26                llvm::cl::desc("<input bitcode files>"));
27 
28 static llvm::cl::list<std::string>
29 OutputFilenames("o", llvm::cl::desc("Override output filename"),
30                 llvm::cl::value_desc("output bitcode file"));
31 
32 
getModuleFromFilename(std::string & Filename,llvm::LLVMContext & Ctx,std::string & ErrMsg)33 static 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 
optimizeModule(llvm::Module * M)43 static 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 
linkFilesToModule(llvm::cl::list<std::string> & Inputs,llvm::LLVMContext & Ctx)64 static 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 
main(int argc,char ** argv)113 int 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