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