int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext Context; Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); auto Composite = make_unique<Module>("llvm-link", Context); Linker L(*Composite); unsigned Flags = Linker::Flags::None; if (Internalize) Flags |= Linker::Flags::InternalizeLinkedSymbols; if (OnlyNeeded) Flags |= Linker::Flags::LinkOnlyNeeded; // First add all the regular input files if (!linkFiles(argv[0], Context, L, InputFilenames, Flags)) return 1; // Next the -override ones. if (!linkFiles(argv[0], Context, L, OverridingInputs, Flags | Linker::Flags::OverrideFromSrc)) return 1; // Import any functions requested via -import if (!importFunctions(argv[0], Context, L)) return 1; if (DumpAsm) errs() << "Here's the assembly:\n" << *Composite; std::error_code EC; tool_output_file Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (verifyModule(*Composite, &errs())) { errs() << argv[0] << ": error: linked module is broken!\n"; return 1; } if (Verbose) errs() << "Writing bitcode...\n"; if (OutputAssembly) { Composite->print(Out.os(), nullptr, PreserveAssemblyUseListOrder); } else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) WriteBitcodeToFile(Composite.get(), Out.os(), PreserveBitcodeUseListOrder); // Declare success. Out.keep(); return 0; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. Context.setDiagnosticHandler(diagnosticHandler, argv[0]); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); Expected<std::unique_ptr<Module>> MOrErr = openInputFile(Context); if (!MOrErr) { handleAllErrors(MOrErr.takeError(), [&](ErrorInfoBase &EIB) { errs() << argv[0] << ": "; EIB.log(errs()); errs() << '\n'; }); return 1; } std::unique_ptr<Module> M = std::move(*MOrErr); // Just use stdout. We won't actually print anything on it. if (DontPrint) OutputFilename = "-"; if (OutputFilename.empty()) { // Unspecified output, infer it. if (InputFilename == "-") { OutputFilename = "-"; } else { StringRef IFN = InputFilename; OutputFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str(); OutputFilename += ".ll"; } } std::error_code EC; std::unique_ptr<tool_output_file> Out( new tool_output_file(OutputFilename, EC, sys::fs::F_None)); if (EC) { errs() << EC.message() << '\n'; return 1; } std::unique_ptr<AssemblyAnnotationWriter> Annotator; if (ShowAnnotations) Annotator.reset(new CommentWriter()); // All that llvm-dis does is write the assembly to a file. if (!DontPrint) M->print(Out->os(), Annotator.get(), PreserveAssemblyUseListOrder); // Declare success. Out->keep(); return 0; }
// main - Entry point for the llc compiler. // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // Initialize codegen and IR passes used by llc so that the -print-after, // -print-before, and -stop-after options work. PassRegistry *Registry = PassRegistry::getPassRegistry(); initializeCore(*Registry); initializeCodeGen(*Registry); initializeLoopStrengthReducePass(*Registry); initializeLowerIntrinsicsPass(*Registry); initializeCountingFunctionInserterPass(*Registry); initializeUnreachableBlockElimLegacyPassPass(*Registry); initializeConstantHoistingLegacyPassPass(*Registry); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); Context.setDiscardValueNames(DiscardValueNames); // Set a diagnostic handler that doesn't exit on the first error bool HasError = false; Context.setDiagnosticHandler(DiagnosticHandler, &HasError); // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) if (int RetVal = compileModule(argv, Context)) return RetVal; return 0; }
/// Perform the ThinLTO backend on a single module, invoking the LTO and codegen /// pipelines. static void thinLTOBackendTask(claimed_file &F, const void *View, ld_plugin_input_file &File, raw_fd_ostream *ApiFile, const ModuleSummaryIndex &CombinedIndex, raw_fd_ostream *OS, unsigned TaskID) { // Need to use a separate context for each task LLVMContext Context; Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true); std::unique_ptr<llvm::Module> NewModule(new llvm::Module(File.name, Context)); IRMover L(*NewModule.get()); StringSet<> Dummy; if (linkInModule(Context, L, F, View, File, ApiFile, Dummy, Dummy)) message(LDPL_FATAL, "Failed to rename module for ThinLTO"); if (renameModuleForThinLTO(*NewModule, CombinedIndex)) message(LDPL_FATAL, "Failed to rename module for ThinLTO"); CodeGen codeGen(std::move(NewModule), OS, TaskID, &CombinedIndex, File.name); codeGen.runAll(); }
// main - Entry point for the llc compiler. // int main(int argc, char **argv) { sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); // Enable debug stream buffering. EnableDebugBuffering = true; LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // Initialize codegen and IR passes used by llc so that the -print-after, // -print-before, and -stop-after options work. PassRegistry *Registry = PassRegistry::getPassRegistry(); initializeCore(*Registry); initializeCodeGen(*Registry); initializeLoopStrengthReducePass(*Registry); initializeLowerIntrinsicsPass(*Registry); initializeCountingFunctionInserterPass(*Registry); initializeUnreachableBlockElimLegacyPassPass(*Registry); initializeConstantHoistingLegacyPassPass(*Registry); initializeScalarOpts(*Registry); initializeVectorization(*Registry); // Register the target printer for --version. cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n"); Context.setDiscardValueNames(DiscardValueNames); // Set a diagnostic handler that doesn't exit on the first error bool HasError = false; Context.setDiagnosticHandler(DiagnosticHandler, &HasError); Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError); if (PassRemarksWithHotness) Context.setDiagnosticHotnessRequested(true); std::unique_ptr<tool_output_file> YamlFile; if (RemarksFilename != "") { std::error_code EC; YamlFile = llvm::make_unique<tool_output_file>(RemarksFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } Context.setDiagnosticsOutputFile( llvm::make_unique<yaml::Output>(YamlFile->os())); } // Compile the module TimeCompilations times to give better compile time // metrics. for (unsigned I = TimeCompilations; I; --I) if (int RetVal = compileModule(argv, Context)) return RetVal; if (YamlFile) YamlFile->keep(); return 0; }
/// 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; Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); // If we are doing ThinLTO compilation, simply build the combined // function index/summary and emit it. We don't need to parse the modules // and link them in this case. if (options::thinlto) { std::unique_ptr<FunctionInfoIndex> CombinedIndex(new FunctionInfoIndex()); uint64_t NextModuleId = 0; for (claimed_file &F : Modules) { ld_plugin_input_file File; if (get_input_file(F.handle, &File) != LDPS_OK) message(LDPL_FATAL, "Failed to get file information"); std::unique_ptr<FunctionInfoIndex> Index = getFunctionIndexForFile(Context, F, File); CombinedIndex->mergeFrom(std::move(Index), ++NextModuleId); } std::error_code EC; raw_fd_ostream OS(output_name + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); if (EC) message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s", output_name.data(), EC.message().c_str()); WriteFunctionSummaryToFile(CombinedIndex.get(), OS); OS.close(); cleanup_hook(); exit(0); } 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) { ld_plugin_input_file File; if (get_input_file(F.handle, &File) != LDPS_OK) message(LDPL_FATAL, "Failed to get file information"); std::unique_ptr<Module> M = getModuleForFile(Context, F, File, ApiFile, Internalize, Maybe); if (!options::triple.empty()) M->setTargetTriple(options::triple.c_str()); else if (M->getTargetTriple().empty()) { M->setTargetTriple(DefaultTriple); } if (L.linkInModule(M.get())) message(LDPL_FATAL, "Failed to link module"); if (release_input_file(F.handle) != LDPS_OK) message(LDPL_FATAL, "Failed to release file information"); } for (const auto &Name : Internalize) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (GV) internalize(*GV); } for (const auto &Name : Maybe) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (!GV) continue; GV->setLinkage(GlobalValue::LinkOnceODRLinkage); if (canBeOmittedFromSymbolTable(GV)) internalize(*GV); } if (options::TheOutputType == options::OT_DISABLE) return LDPS_OK; if (options::TheOutputType != options::OT_NORMAL) { std::string path; if (options::TheOutputType == options::OT_BC_ONLY) path = output_name; else path = output_name + ".bc"; saveBCFile(path, *L.getModule()); if (options::TheOutputType == options::OT_BC_ONLY) return LDPS_OK; } codegen(std::move(Combined)); if (!options::extra_library_path.empty() && set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) message(LDPL_FATAL, "Unable to set the extra library path."); return LDPS_OK; }
/// Called by gold to see whether this file is one that our plugin can handle. /// We'll try to open it and register all the symbols with add_symbol if /// possible. static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, int *claimed) { LLVMContext Context; MemoryBufferRef BufferRef; std::unique_ptr<MemoryBuffer> Buffer; if (get_view) { const void *view; if (get_view(file->handle, &view) != LDPS_OK) { message(LDPL_ERROR, "Failed to get a view of %s", file->name); return LDPS_ERR; } BufferRef = MemoryBufferRef(StringRef((const char *)view, file->filesize), ""); } else { int64_t offset = 0; // Gold has found what might be IR part-way inside of a file, such as // an .a archive. if (file->offset) { offset = file->offset; } ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = MemoryBuffer::getOpenFileSlice(file->fd, file->name, file->filesize, offset); if (std::error_code EC = BufferOrErr.getError()) { message(LDPL_ERROR, EC.message().c_str()); return LDPS_ERR; } Buffer = std::move(BufferOrErr.get()); BufferRef = Buffer->getMemBufferRef(); } Context.setDiagnosticHandler(diagnosticHandler); ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr = object::IRObjectFile::create(BufferRef, Context); std::error_code EC = ObjOrErr.getError(); if (EC == object::object_error::invalid_file_type || EC == object::object_error::bitcode_section_not_found) return LDPS_OK; *claimed = 1; if (EC) { message(LDPL_ERROR, "LLVM gold plugin has failed to create LTO module: %s", EC.message().c_str()); return LDPS_ERR; } std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr); Modules.resize(Modules.size() + 1); claimed_file &cf = Modules.back(); cf.handle = file->handle; // If we are doing ThinLTO compilation, don't need to process the symbols. // Later we simply build a combined index file after all files are claimed. if (options::thinlto) return LDPS_OK; for (auto &Sym : Obj->symbols()) { uint32_t Symflags = Sym.getFlags(); if (shouldSkip(Symflags)) continue; cf.syms.push_back(ld_plugin_symbol()); ld_plugin_symbol &sym = cf.syms.back(); sym.version = nullptr; SmallString<64> Name; { raw_svector_ostream OS(Name); Sym.printName(OS); } sym.name = strdup(Name.c_str()); const GlobalValue *GV = Obj->getSymbolGV(Sym.getRawDataRefImpl()); sym.visibility = LDPV_DEFAULT; if (GV) { switch (GV->getVisibility()) { case GlobalValue::DefaultVisibility: sym.visibility = LDPV_DEFAULT; break; case GlobalValue::HiddenVisibility: sym.visibility = LDPV_HIDDEN; break; case GlobalValue::ProtectedVisibility: sym.visibility = LDPV_PROTECTED; break; } } if (Symflags & object::BasicSymbolRef::SF_Undefined) { sym.def = LDPK_UNDEF; if (GV && GV->hasExternalWeakLinkage()) sym.def = LDPK_WEAKUNDEF; } else { sym.def = LDPK_DEF; if (GV) { assert(!GV->hasExternalWeakLinkage() && !GV->hasAvailableExternallyLinkage() && "Not a declaration!"); if (GV->hasCommonLinkage()) sym.def = LDPK_COMMON; else if (GV->isWeakForLinker()) sym.def = LDPK_WEAKDEF; } } sym.size = 0; sym.comdat_key = nullptr; if (GV) { const GlobalObject *Base = getBaseObject(*GV); if (!Base) message(LDPL_FATAL, "Unable to determine comdat of alias!"); const Comdat *C = Base->getComdat(); if (C) sym.comdat_key = strdup(C->getName().str().c_str()); else if (Base->hasWeakLinkage() || Base->hasLinkOnceLinkage()) sym.comdat_key = strdup(sym.name); } sym.resolution = LDPR_UNKNOWN; } if (!cf.syms.empty()) { if (add_symbols(cf.handle, cf.syms.size(), cf.syms.data()) != LDPS_OK) { message(LDPL_ERROR, "Unable to add symbols!"); return LDPS_ERR; } } return LDPS_OK; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n"); if (OptLevel < '0' || OptLevel > '3') error("optimization level must be between 0 and 3"); // Initialize the configured targets. InitializeAllTargets(); InitializeAllTargetMCs(); InitializeAllAsmPrinters(); InitializeAllAsmParsers(); // set up the TargetOptions for the machine TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); if (ListSymbolsOnly) { listSymbols(Options); return 0; } if (ThinLTOMode.getNumOccurrences()) { if (ThinLTOMode.getNumOccurrences() > 1) report_fatal_error("You can't specify more than one -thinlto-action"); thinlto::ThinLTOProcessing ThinLTOProcessor(Options); ThinLTOProcessor.run(); return 0; } if (ThinLTO) { createCombinedFunctionIndex(); return 0; } unsigned BaseArg = 0; LLVMContext Context; Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true); LTOCodeGenerator CodeGen(Context); if (UseDiagnosticHandler) CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr); CodeGen.setCodePICModel(RelocModel); CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); CodeGen.setTargetOptions(Options); CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage); llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet; for (unsigned i = 0; i < DSOSymbols.size(); ++i) DSOSymbolsSet.insert(DSOSymbols[i]); std::vector<std::string> KeptDSOSyms; for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) { CurrentActivity = "loading file '" + InputFilenames[i] + "'"; ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr = LTOModule::createFromFile(Context, InputFilenames[i].c_str(), Options); std::unique_ptr<LTOModule> &Module = *ModuleOrErr; CurrentActivity = ""; unsigned NumSyms = Module->getSymbolCount(); for (unsigned I = 0; I < NumSyms; ++I) { StringRef Name = Module->getSymbolName(I); if (!DSOSymbolsSet.count(Name)) continue; lto_symbol_attributes Attrs = Module->getSymbolAttributes(I); unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK; if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN) KeptDSOSyms.push_back(Name); } // We use the first input module as the destination module when // SetMergedModule is true. if (SetMergedModule && i == BaseArg) { // Transfer ownership to the code generator. CodeGen.setModule(std::move(Module)); } else if (!CodeGen.addModule(Module.get())) { // Print a message here so that we know addModule() did not abort. errs() << argv[0] << ": error adding file '" << InputFilenames[i] << "'\n"; return 1; } } // Add all the exported symbols to the table of symbols to preserve. for (unsigned i = 0; i < ExportedSymbols.size(); ++i) CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str()); // Add all the dso symbols to the table of symbols to expose. for (unsigned i = 0; i < KeptDSOSyms.size(); ++i) CodeGen.addMustPreserveSymbol(KeptDSOSyms[i].c_str()); // Set cpu and attrs strings for the default target/subtarget. CodeGen.setCpu(MCPU.c_str()); CodeGen.setOptLevel(OptLevel - '0'); std::string attrs; for (unsigned i = 0; i < MAttrs.size(); ++i) { if (i > 0) attrs.append(","); attrs.append(MAttrs[i]); } if (!attrs.empty()) CodeGen.setAttr(attrs.c_str()); if (FileType.getNumOccurrences()) CodeGen.setFileType(FileType); if (!OutputFilename.empty()) { if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE, DisableLTOVectorization)) { // Diagnostic messages should have been printed by the handler. errs() << argv[0] << ": error optimizing the code\n"; return 1; } if (SaveModuleFile) { std::string ModuleFilename = OutputFilename; ModuleFilename += ".merged.bc"; std::string ErrMsg; if (!CodeGen.writeMergedModules(ModuleFilename.c_str())) { errs() << argv[0] << ": writing merged module failed.\n"; return 1; } } std::list<tool_output_file> OSs; std::vector<raw_pwrite_stream *> OSPtrs; for (unsigned I = 0; I != Parallelism; ++I) { std::string PartFilename = OutputFilename; if (Parallelism != 1) PartFilename += "." + utostr(I); std::error_code EC; OSs.emplace_back(PartFilename, EC, sys::fs::F_None); if (EC) { errs() << argv[0] << ": error opening the file '" << PartFilename << "': " << EC.message() << "\n"; return 1; } OSPtrs.push_back(&OSs.back().os()); } if (!CodeGen.compileOptimized(OSPtrs)) { // Diagnostic messages should have been printed by the handler. errs() << argv[0] << ": error compiling the code\n"; return 1; } for (tool_output_file &OS : OSs) OS.keep(); } else { if (Parallelism != 1) { errs() << argv[0] << ": -j must be specified together with -o\n"; return 1; } if (SaveModuleFile) { errs() << argv[0] << ": -save-merged-module must be specified with -o\n"; return 1; } const char *OutputName = nullptr; if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline, DisableGVNLoadPRE, DisableLTOVectorization)) { // Diagnostic messages should have been printed by the handler. errs() << argv[0] << ": error compiling the code\n"; return 1; } outs() << "Wrote native object file '" << OutputName << "'\n"; } return 0; }
/// 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; if (unsigned NumOpts = options::extra.size()) cl::ParseCommandLineOptions(NumOpts, &options::extra[0]); // If we are doing ThinLTO compilation, simply build the combined // module index/summary and emit it. We don't need to parse the modules // and link them in this case. if (options::thinlto) { ModuleSummaryIndex CombinedIndex; uint64_t NextModuleId = 0; for (claimed_file &F : Modules) { PluginInputFile InputFile(F.handle); std::unique_ptr<ModuleSummaryIndex> Index = getModuleSummaryIndexForFile(F, InputFile.file()); // Skip files without a module summary. if (Index) CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId); } std::error_code EC; raw_fd_ostream OS(output_name + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); if (EC) message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s", output_name.data(), EC.message().c_str()); WriteIndexToFile(CombinedIndex, OS); OS.close(); if (options::thinlto_index_only) { cleanup_hook(); exit(0); } thinLTOBackends(ApiFile, CombinedIndex); return LDPS_OK; } LLVMContext Context; Context.setDiscardValueNames(options::DiscardValueNames); Context.enableDebugTypeODRUniquing(); // Merge debug info types. Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true); std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context)); IRMover L(*Combined); StringSet<> Internalize; StringSet<> Maybe; for (claimed_file &F : Modules) { PluginInputFile InputFile(F.handle); const void *View = getSymbolsAndView(F); if (!View) continue; if (linkInModule(Context, L, F, View, InputFile.file(), ApiFile, Internalize, Maybe)) message(LDPL_FATAL, "Failed to link module"); } for (const auto &Name : Internalize) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (GV) internalize(*GV); } for (const auto &Name : Maybe) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (!GV) continue; GV->setLinkage(GlobalValue::LinkOnceODRLinkage); if (canBeOmittedFromSymbolTable(GV)) internalize(*GV); } if (options::TheOutputType == options::OT_DISABLE) return LDPS_OK; if (options::TheOutputType != options::OT_NORMAL) { std::string path; if (options::TheOutputType == options::OT_BC_ONLY) path = output_name; else path = output_name + ".bc"; saveBCFile(path, *Combined); if (options::TheOutputType == options::OT_BC_ONLY) return LDPS_OK; } CodeGen codeGen(std::move(Combined)); codeGen.runAll(); if (!options::extra_library_path.empty() && set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) message(LDPL_FATAL, "Unable to set the extra library path."); return LDPS_OK; }
/// 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; Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); 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) { ld_plugin_input_file File; if (get_input_file(F.handle, &File) != LDPS_OK) message(LDPL_FATAL, "Failed to get file information"); std::unique_ptr<Module> M = getModuleForFile(Context, F, File, ApiFile, Internalize, Maybe); if (!options::triple.empty()) M->setTargetTriple(options::triple.c_str()); else if (M->getTargetTriple().empty()) { M->setTargetTriple(DefaultTriple); } if (L.linkInModule(M.get())) message(LDPL_FATAL, "Failed to link module"); if (release_input_file(F.handle) != LDPS_OK) message(LDPL_FATAL, "Failed to release file information"); } for (const auto &Name : Internalize) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (GV) internalize(*GV); } for (const auto &Name : Maybe) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (!GV) continue; GV->setLinkage(GlobalValue::LinkOnceODRLinkage); if (canBeOmittedFromSymbolTable(GV)) internalize(*GV); } // @LOCALMOD-BEGIN // Perform symbol wrapping. unsigned num_wrapped; if ((*get_num_wrapped)(&num_wrapped) != LDPS_OK) { (*message)(LDPL_ERROR, "Unable to get the number of wrapped symbols."); return LDPS_ERR; } for (unsigned i = 0; i < num_wrapped; ++i) { const char *sym; if ((*get_wrapped)(i, &sym) != LDPS_OK) { (*message)(LDPL_ERROR, "Unable to wrap symbol %u/%u.", i, num_wrapped); return LDPS_ERR; } wrapSymbol(Combined.get(), sym); } // @LOCALMOD-END if (options::TheOutputType == options::OT_DISABLE) return LDPS_OK; if (options::TheOutputType != options::OT_NORMAL) { std::string path; if (options::TheOutputType == options::OT_BC_ONLY) path = output_name; else path = output_name + ".bc"; saveBCFile(path, *L.getModule()); if (options::TheOutputType == options::OT_BC_ONLY) return LDPS_OK; } codegen(*L.getModule()); if (!options::extra_library_path.empty() && set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) message(LDPL_FATAL, "Unable to set the extra library path."); return LDPS_OK; }