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