#include <cassert>
#include <list>
#include <string>
#include "llvm/Linker.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/PassManagerBuilder.h"
#include "llvm/Support/system_error.h"
#include "llvm/Target/TargetData.h"
static llvm::cl::list<std::string>
InputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore,
llvm::cl::desc("<input bitcode files>"));
static llvm::cl::list<std::string>
OutputFilenames("o", llvm::cl::desc("Override output filename"),
llvm::cl::value_desc("output bitcode file"));
static llvm::Module* getModuleFromFilename(std::string& Filename,
llvm::LLVMContext& Ctx,
std::string& ErrMsg) {
llvm::OwningPtr<llvm::MemoryBuffer> MB;
llvm::MemoryBuffer::getFile(Filename, MB);
llvm::Module* M = llvm::ParseBitcodeFile(MB.get(), Ctx, &ErrMsg);
assert(M && ErrMsg);
return M;
}
static void optimizeModule(llvm::Module* M) {
llvm::PassManager Passes;
const std::string &ModuleDataLayout = M->getDataLayout();
if (!ModuleDataLayout.empty())
if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
Passes.add(TD);
Passes.add(llvm::createInternalizePass(true/* AllButMain*/));
#if 0
FIXME REMOVE
createStandardLTOPasses(&Passes,
/* Internalize = */false,
/* RunInliner = */true,
/* VerifyEach = */false);
#endif
llvm::PassManagerBuilder PMBuilder;
PMBuilder.populateLTOPassManager(Passes, false, true);
Passes.run(*M);
}
static llvm::Module* linkFilesToModule(llvm::cl::list<std::string>& Inputs,
llvm::LLVMContext& Ctx) {
std::string ErrMsg;
llvm::Module* M = getModuleFromFilename(Inputs[0], Ctx, ErrMsg);
llvm::Linker Linker("llvm-ndk-link", M);
for (unsigned i=1; i<Inputs.size(); ++i) {
llvm::Module* M = getModuleFromFilename(Inputs[i], Ctx, ErrMsg);
if (!Linker.LinkInModule(M, &ErrMsg)) {
assert(false && ErrMsg);
}
optimizeModule(M);
}
M = Linker.releaseModule();
llvm::PassManager PM;
const std::string &ModuleDataLayout = M->getDataLayout();
if (!ModuleDataLayout.empty())
if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout))
PM.add(TD);
#if 0
FIXME REMOVE
llvm::createStandardFunctionPasses(&PM, 3 /* OptLevel*/);
llvm::createStandardModulePasses(&PM,
3, /* OptimizationLevel */
true, /* OptimizeSize */
true, /* UnitAtATime */
true, /* UnrollLoops */
true, /* SimplifyLibCalls */
false, /* HaveExceptions */
NULL /* InliningPass */);
#endif
llvm::PassManagerBuilder PMBuilder;
//PMBuilder.OptLevel = 3;
//PMBuilder.populateFunctionPassManager(PM);
PMBuilder.OptLevel = 3;
PMBuilder.SizeLevel = true;
PMBuilder.DisableUnitAtATime = false;
PMBuilder.DisableUnrollLoops = false;
PMBuilder.DisableSimplifyLibCalls = false;
PMBuilder.populateModulePassManager(PM);
PM.run(*M);
return M;
}
int main(int argc, char** argv) {
llvm::llvm_shutdown_obj _ShutdownObj;
llvm::cl::ParseCommandLineOptions(argc, argv, "P-NDK Link Tool");
llvm::LLVMContext& Ctx = llvm::getGlobalContext();
std::string ErrMsg;
llvm::raw_fd_ostream FOS(OutputFilenames[0].c_str(), ErrMsg);
assert(!FOS.has_error());
// No need to link (just one file).
// Output Directly.
if (InputFilenames.size() == 1) {
llvm::OwningPtr<llvm::Module> M(getModuleFromFilename(InputFilenames[0],
Ctx,
ErrMsg));
llvm::WriteBitcodeToFile(M.get(), FOS);
return 0;
}
llvm::OwningPtr<llvm::Module> M(linkFilesToModule(InputFilenames, Ctx));
llvm::WriteBitcodeToFile(M.get(), FOS);
assert(!FOS.has_error());
return 0;
}