+ return M;
+}
+
+static void runLTOPasses(Module &M, TargetMachine &TM) {
+ PassManager passes;
+ PassManagerBuilder PMB;
+ PMB.LibraryInfo = new TargetLibraryInfo(Triple(TM.getTargetTriple()));
+ PMB.Inliner = createFunctionInliningPass();
+ PMB.VerifyInput = true;
+ PMB.VerifyOutput = true;
+ PMB.populateLTOPassManager(passes, &TM);
+ passes.run(M);
+}
+
+static void codegen(Module &M) {
+ const std::string &TripleStr = M.getTargetTriple();
+ Triple TheTriple(TripleStr);
+
+ std::string ErrMsg;
+ const Target *TheTarget = TargetRegistry::lookupTarget(TripleStr, ErrMsg);
+ if (!TheTarget)
+ message(LDPL_FATAL, "Target not found: %s", ErrMsg.c_str());
+
+ if (unsigned NumOpts = options::extra.size())
+ cl::ParseCommandLineOptions(NumOpts, &options::extra[0]);
+
+ SubtargetFeatures Features;
+ Features.getDefaultSubtargetFeatures(TheTriple);
+ for (const std::string &A : MAttrs)
+ Features.AddFeature(A);
+
+ TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
+ std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine(
+ TripleStr, options::mcpu, Features.getString(), Options, RelocationModel,
+ CodeModel::Default, CodeGenOpt::Aggressive));
+
+ runLTOPasses(M, *TM);
+
+ PassManager CodeGenPasses;
+ CodeGenPasses.add(new DataLayoutPass());
+
+ SmallString<128> Filename;
+ int FD;
+ if (options::obj_path.empty()) {
+ std::error_code EC =
+ sys::fs::createTemporaryFile("lto-llvm", "o", FD, Filename);
+ if (EC)
+ message(LDPL_FATAL, "Could not create temorary file: %s",
+ EC.message().c_str());
+ } else {
+ Filename = options::obj_path;
+ std::error_code EC =
+ sys::fs::openFileForWrite(Filename.c_str(), FD, sys::fs::F_None);
+ if (EC)
+ message(LDPL_FATAL, "Could not open file: %s", EC.message().c_str());
+ }
+
+ {
+ raw_fd_ostream OS(FD, true);
+ formatted_raw_ostream FOS(OS);
+
+ if (TM->addPassesToEmitFile(CodeGenPasses, FOS,
+ TargetMachine::CGFT_ObjectFile))
+ message(LDPL_FATAL, "Failed to setup codegen");
+ CodeGenPasses.run(M);
+ }
+
+ if (add_input_file(Filename.c_str()) != LDPS_OK)
+ message(LDPL_FATAL,
+ "Unable to add .o file to the link. File left behind in: %s",
+ Filename.c_str());
+
+ if (options::obj_path.empty())
+ Cleanup.push_back(Filename.c_str());
+}
+
+/// gold informs us that all symbols have been read. At this point, we use
+/// get_symbols to see if any of our definitions have been overridden by a
+/// native object file. Then, perform optimization and codegen.
+static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) {
+ if (Modules.empty())
+ return LDPS_OK;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context));
+ Linker L(Combined.get());
+
+ std::string DefaultTriple = sys::getDefaultTargetTriple();
+
+ StringSet<> Internalize;
+ StringSet<> Maybe;
+ for (claimed_file &F : Modules) {
+ std::unique_ptr<Module> M =
+ getModuleForFile(Context, F, ApiFile, Internalize, Maybe);
+ if (!options::triple.empty())
+ M->setTargetTriple(options::triple.c_str());
+ else if (M->getTargetTriple().empty()) {
+ M->setTargetTriple(DefaultTriple);