106f32e7eSjoerg //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization  ------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This is a gold plugin for LLVM. It provides an LLVM implementation of the
1006f32e7eSjoerg // interface described in http://gcc.gnu.org/wiki/whopr/driver .
1106f32e7eSjoerg //
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg 
1406f32e7eSjoerg #include "llvm/ADT/Statistic.h"
1506f32e7eSjoerg #include "llvm/Bitcode/BitcodeReader.h"
1606f32e7eSjoerg #include "llvm/Bitcode/BitcodeWriter.h"
17*da58b97aSjoerg #include "llvm/CodeGen/CommandFlags.h"
1806f32e7eSjoerg #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H
19*da58b97aSjoerg #include "llvm/Config/llvm-config.h"
2006f32e7eSjoerg #include "llvm/IR/Constants.h"
2106f32e7eSjoerg #include "llvm/IR/DiagnosticPrinter.h"
2206f32e7eSjoerg #include "llvm/LTO/Caching.h"
2306f32e7eSjoerg #include "llvm/LTO/LTO.h"
2406f32e7eSjoerg #include "llvm/Object/Error.h"
25*da58b97aSjoerg #include "llvm/Remarks/HotnessThresholdParser.h"
2606f32e7eSjoerg #include "llvm/Support/CachePruning.h"
2706f32e7eSjoerg #include "llvm/Support/CommandLine.h"
2806f32e7eSjoerg #include "llvm/Support/FileSystem.h"
29*da58b97aSjoerg #include "llvm/Support/Host.h"
3006f32e7eSjoerg #include "llvm/Support/ManagedStatic.h"
3106f32e7eSjoerg #include "llvm/Support/MemoryBuffer.h"
3206f32e7eSjoerg #include "llvm/Support/Path.h"
3306f32e7eSjoerg #include "llvm/Support/TargetSelect.h"
34*da58b97aSjoerg #include "llvm/Support/Threading.h"
3506f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
3606f32e7eSjoerg #include <list>
3706f32e7eSjoerg #include <map>
3806f32e7eSjoerg #include <plugin-api.h>
3906f32e7eSjoerg #include <string>
4006f32e7eSjoerg #include <system_error>
4106f32e7eSjoerg #include <utility>
4206f32e7eSjoerg #include <vector>
4306f32e7eSjoerg 
4406f32e7eSjoerg // FIXME: remove this declaration when we stop maintaining Ubuntu Quantal and
4506f32e7eSjoerg // Precise and Debian Wheezy (binutils 2.23 is required)
4606f32e7eSjoerg #define LDPO_PIE 3
4706f32e7eSjoerg 
4806f32e7eSjoerg #define LDPT_GET_SYMBOLS_V3 28
4906f32e7eSjoerg 
5006f32e7eSjoerg // FIXME: Remove when binutils 2.31 (containing gold 1.16) is the minimum
5106f32e7eSjoerg // required version.
5206f32e7eSjoerg #define LDPT_GET_WRAP_SYMBOLS 32
5306f32e7eSjoerg 
5406f32e7eSjoerg using namespace llvm;
5506f32e7eSjoerg using namespace lto;
5606f32e7eSjoerg 
57*da58b97aSjoerg static codegen::RegisterCodeGenFlags CodeGenFlags;
58*da58b97aSjoerg 
5906f32e7eSjoerg // FIXME: Remove when binutils 2.31 (containing gold 1.16) is the minimum
6006f32e7eSjoerg // required version.
6106f32e7eSjoerg typedef enum ld_plugin_status (*ld_plugin_get_wrap_symbols)(
6206f32e7eSjoerg     uint64_t *num_symbols, const char ***wrap_symbol_list);
6306f32e7eSjoerg 
6406f32e7eSjoerg static ld_plugin_status discard_message(int level, const char *format, ...) {
6506f32e7eSjoerg   // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
6606f32e7eSjoerg   // callback in the transfer vector. This should never be called.
6706f32e7eSjoerg   abort();
6806f32e7eSjoerg }
6906f32e7eSjoerg 
7006f32e7eSjoerg static ld_plugin_release_input_file release_input_file = nullptr;
7106f32e7eSjoerg static ld_plugin_get_input_file get_input_file = nullptr;
7206f32e7eSjoerg static ld_plugin_message message = discard_message;
7306f32e7eSjoerg static ld_plugin_get_wrap_symbols get_wrap_symbols = nullptr;
7406f32e7eSjoerg 
7506f32e7eSjoerg namespace {
7606f32e7eSjoerg struct claimed_file {
7706f32e7eSjoerg   void *handle;
7806f32e7eSjoerg   void *leader_handle;
7906f32e7eSjoerg   std::vector<ld_plugin_symbol> syms;
8006f32e7eSjoerg   off_t filesize;
8106f32e7eSjoerg   std::string name;
8206f32e7eSjoerg };
8306f32e7eSjoerg 
8406f32e7eSjoerg /// RAII wrapper to manage opening and releasing of a ld_plugin_input_file.
8506f32e7eSjoerg struct PluginInputFile {
8606f32e7eSjoerg   void *Handle;
8706f32e7eSjoerg   std::unique_ptr<ld_plugin_input_file> File;
8806f32e7eSjoerg 
PluginInputFile__anon7eeef7220111::PluginInputFile8906f32e7eSjoerg   PluginInputFile(void *Handle) : Handle(Handle) {
9006f32e7eSjoerg     File = std::make_unique<ld_plugin_input_file>();
9106f32e7eSjoerg     if (get_input_file(Handle, File.get()) != LDPS_OK)
9206f32e7eSjoerg       message(LDPL_FATAL, "Failed to get file information");
9306f32e7eSjoerg   }
~PluginInputFile__anon7eeef7220111::PluginInputFile9406f32e7eSjoerg   ~PluginInputFile() {
9506f32e7eSjoerg     // File would have been reset to nullptr if we moved this object
9606f32e7eSjoerg     // to a new owner.
9706f32e7eSjoerg     if (File)
9806f32e7eSjoerg       if (release_input_file(Handle) != LDPS_OK)
9906f32e7eSjoerg         message(LDPL_FATAL, "Failed to release file information");
10006f32e7eSjoerg   }
10106f32e7eSjoerg 
file__anon7eeef7220111::PluginInputFile10206f32e7eSjoerg   ld_plugin_input_file &file() { return *File; }
10306f32e7eSjoerg 
10406f32e7eSjoerg   PluginInputFile(PluginInputFile &&RHS) = default;
10506f32e7eSjoerg   PluginInputFile &operator=(PluginInputFile &&RHS) = default;
10606f32e7eSjoerg };
10706f32e7eSjoerg 
10806f32e7eSjoerg struct ResolutionInfo {
10906f32e7eSjoerg   bool CanOmitFromDynSym = true;
11006f32e7eSjoerg   bool DefaultVisibility = true;
11106f32e7eSjoerg   bool CanInline = true;
11206f32e7eSjoerg   bool IsUsedInRegularObj = false;
11306f32e7eSjoerg };
11406f32e7eSjoerg 
11506f32e7eSjoerg }
11606f32e7eSjoerg 
11706f32e7eSjoerg static ld_plugin_add_symbols add_symbols = nullptr;
11806f32e7eSjoerg static ld_plugin_get_symbols get_symbols = nullptr;
11906f32e7eSjoerg static ld_plugin_add_input_file add_input_file = nullptr;
12006f32e7eSjoerg static ld_plugin_set_extra_library_path set_extra_library_path = nullptr;
12106f32e7eSjoerg static ld_plugin_get_view get_view = nullptr;
12206f32e7eSjoerg static bool IsExecutable = false;
12306f32e7eSjoerg static bool SplitSections = true;
12406f32e7eSjoerg static Optional<Reloc::Model> RelocationModel = None;
12506f32e7eSjoerg static std::string output_name = "";
12606f32e7eSjoerg static std::list<claimed_file> Modules;
12706f32e7eSjoerg static DenseMap<int, void *> FDToLeaderHandle;
12806f32e7eSjoerg static StringMap<ResolutionInfo> ResInfo;
12906f32e7eSjoerg static std::vector<std::string> Cleanup;
13006f32e7eSjoerg 
13106f32e7eSjoerg namespace options {
13206f32e7eSjoerg   enum OutputType {
13306f32e7eSjoerg     OT_NORMAL,
13406f32e7eSjoerg     OT_DISABLE,
13506f32e7eSjoerg     OT_BC_ONLY,
13606f32e7eSjoerg     OT_ASM_ONLY,
13706f32e7eSjoerg     OT_SAVE_TEMPS
13806f32e7eSjoerg   };
13906f32e7eSjoerg   static OutputType TheOutputType = OT_NORMAL;
14006f32e7eSjoerg   static unsigned OptLevel = 2;
141*da58b97aSjoerg   // Currently only affects ThinLTO, where the default is the max cores in the
142*da58b97aSjoerg   // system. See llvm::get_threadpool_strategy() for acceptable values.
143*da58b97aSjoerg   static std::string Parallelism;
14406f32e7eSjoerg   // Default regular LTO codegen parallelism (number of partitions).
14506f32e7eSjoerg   static unsigned ParallelCodeGenParallelismLevel = 1;
14606f32e7eSjoerg #ifdef NDEBUG
14706f32e7eSjoerg   static bool DisableVerify = true;
14806f32e7eSjoerg #else
14906f32e7eSjoerg   static bool DisableVerify = false;
15006f32e7eSjoerg #endif
15106f32e7eSjoerg   static std::string obj_path;
15206f32e7eSjoerg   static std::string extra_library_path;
15306f32e7eSjoerg   static std::string triple;
15406f32e7eSjoerg   static std::string mcpu;
15506f32e7eSjoerg   // When the thinlto plugin option is specified, only read the function
15606f32e7eSjoerg   // the information from intermediate files and write a combined
15706f32e7eSjoerg   // global index for the ThinLTO backends.
15806f32e7eSjoerg   static bool thinlto = false;
15906f32e7eSjoerg   // If false, all ThinLTO backend compilations through code gen are performed
16006f32e7eSjoerg   // using multiple threads in the gold-plugin, before handing control back to
16106f32e7eSjoerg   // gold. If true, write individual backend index files which reflect
16206f32e7eSjoerg   // the import decisions, and exit afterwards. The assumption is
16306f32e7eSjoerg   // that the build system will launch the backend processes.
16406f32e7eSjoerg   static bool thinlto_index_only = false;
16506f32e7eSjoerg   // If non-empty, holds the name of a file in which to write the list of
16606f32e7eSjoerg   // oject files gold selected for inclusion in the link after symbol
16706f32e7eSjoerg   // resolution (i.e. they had selected symbols). This will only be non-empty
16806f32e7eSjoerg   // in the thinlto_index_only case. It is used to identify files, which may
16906f32e7eSjoerg   // have originally been within archive libraries specified via
17006f32e7eSjoerg   // --start-lib/--end-lib pairs, that should be included in the final
17106f32e7eSjoerg   // native link process (since intervening function importing and inlining
17206f32e7eSjoerg   // may change the symbol resolution detected in the final link and which
17306f32e7eSjoerg   // files to include out of --start-lib/--end-lib libraries as a result).
17406f32e7eSjoerg   static std::string thinlto_linked_objects_file;
17506f32e7eSjoerg   // If true, when generating individual index files for distributed backends,
17606f32e7eSjoerg   // also generate a "${bitcodefile}.imports" file at the same location for each
17706f32e7eSjoerg   // bitcode file, listing the files it imports from in plain text. This is to
17806f32e7eSjoerg   // support distributed build file staging.
17906f32e7eSjoerg   static bool thinlto_emit_imports_files = false;
18006f32e7eSjoerg   // Option to control where files for a distributed backend (the individual
18106f32e7eSjoerg   // index files and optional imports files) are created.
18206f32e7eSjoerg   // If specified, expects a string of the form "oldprefix:newprefix", and
18306f32e7eSjoerg   // instead of generating these files in the same directory path as the
18406f32e7eSjoerg   // corresponding bitcode file, will use a path formed by replacing the
18506f32e7eSjoerg   // bitcode file's path prefix matching oldprefix with newprefix.
18606f32e7eSjoerg   static std::string thinlto_prefix_replace;
18706f32e7eSjoerg   // Option to control the name of modules encoded in the individual index
18806f32e7eSjoerg   // files for a distributed backend. This enables the use of minimized
18906f32e7eSjoerg   // bitcode files for the thin link, assuming the name of the full bitcode
19006f32e7eSjoerg   // file used in the backend differs just in some part of the file suffix.
19106f32e7eSjoerg   // If specified, expects a string of the form "oldsuffix:newsuffix".
19206f32e7eSjoerg   static std::string thinlto_object_suffix_replace;
19306f32e7eSjoerg   // Optional path to a directory for caching ThinLTO objects.
19406f32e7eSjoerg   static std::string cache_dir;
19506f32e7eSjoerg   // Optional pruning policy for ThinLTO caches.
19606f32e7eSjoerg   static std::string cache_policy;
19706f32e7eSjoerg   // Additional options to pass into the code generator.
19806f32e7eSjoerg   // Note: This array will contain all plugin options which are not claimed
19906f32e7eSjoerg   // as plugin exclusive to pass to the code generator.
20006f32e7eSjoerg   static std::vector<const char *> extra;
20106f32e7eSjoerg   // Sample profile file path
20206f32e7eSjoerg   static std::string sample_profile;
20306f32e7eSjoerg   // New pass manager
204*da58b97aSjoerg   static bool new_pass_manager = LLVM_ENABLE_NEW_PASS_MANAGER;
20506f32e7eSjoerg   // Debug new pass manager
20606f32e7eSjoerg   static bool debug_pass_manager = false;
20706f32e7eSjoerg   // Directory to store the .dwo files.
20806f32e7eSjoerg   static std::string dwo_dir;
20906f32e7eSjoerg   /// Statistics output filename.
21006f32e7eSjoerg   static std::string stats_file;
211*da58b97aSjoerg   // Asserts that LTO link has whole program visibility
212*da58b97aSjoerg   static bool whole_program_visibility = false;
21306f32e7eSjoerg 
21406f32e7eSjoerg   // Optimization remarks filename, accepted passes and hotness options
21506f32e7eSjoerg   static std::string RemarksFilename;
21606f32e7eSjoerg   static std::string RemarksPasses;
21706f32e7eSjoerg   static bool RemarksWithHotness = false;
218*da58b97aSjoerg   static Optional<uint64_t> RemarksHotnessThreshold = 0;
21906f32e7eSjoerg   static std::string RemarksFormat;
22006f32e7eSjoerg 
22106f32e7eSjoerg   // Context sensitive PGO options.
22206f32e7eSjoerg   static std::string cs_profile_path;
22306f32e7eSjoerg   static bool cs_pgo_gen = false;
22406f32e7eSjoerg 
process_plugin_option(const char * opt_)22506f32e7eSjoerg   static void process_plugin_option(const char *opt_)
22606f32e7eSjoerg   {
22706f32e7eSjoerg     if (opt_ == nullptr)
22806f32e7eSjoerg       return;
22906f32e7eSjoerg     llvm::StringRef opt = opt_;
23006f32e7eSjoerg 
231*da58b97aSjoerg     if (opt.consume_front("mcpu=")) {
232*da58b97aSjoerg       mcpu = std::string(opt);
233*da58b97aSjoerg     } else if (opt.consume_front("extra-library-path=")) {
234*da58b97aSjoerg       extra_library_path = std::string(opt);
235*da58b97aSjoerg     } else if (opt.consume_front("mtriple=")) {
236*da58b97aSjoerg       triple = std::string(opt);
237*da58b97aSjoerg     } else if (opt.consume_front("obj-path=")) {
238*da58b97aSjoerg       obj_path = std::string(opt);
23906f32e7eSjoerg     } else if (opt == "emit-llvm") {
24006f32e7eSjoerg       TheOutputType = OT_BC_ONLY;
24106f32e7eSjoerg     } else if (opt == "save-temps") {
24206f32e7eSjoerg       TheOutputType = OT_SAVE_TEMPS;
24306f32e7eSjoerg     } else if (opt == "disable-output") {
24406f32e7eSjoerg       TheOutputType = OT_DISABLE;
24506f32e7eSjoerg     } else if (opt == "emit-asm") {
24606f32e7eSjoerg       TheOutputType = OT_ASM_ONLY;
24706f32e7eSjoerg     } else if (opt == "thinlto") {
24806f32e7eSjoerg       thinlto = true;
24906f32e7eSjoerg     } else if (opt == "thinlto-index-only") {
25006f32e7eSjoerg       thinlto_index_only = true;
251*da58b97aSjoerg     } else if (opt.consume_front("thinlto-index-only=")) {
25206f32e7eSjoerg       thinlto_index_only = true;
253*da58b97aSjoerg       thinlto_linked_objects_file = std::string(opt);
25406f32e7eSjoerg     } else if (opt == "thinlto-emit-imports-files") {
25506f32e7eSjoerg       thinlto_emit_imports_files = true;
256*da58b97aSjoerg     } else if (opt.consume_front("thinlto-prefix-replace=")) {
257*da58b97aSjoerg       thinlto_prefix_replace = std::string(opt);
25806f32e7eSjoerg       if (thinlto_prefix_replace.find(';') == std::string::npos)
25906f32e7eSjoerg         message(LDPL_FATAL, "thinlto-prefix-replace expects 'old;new' format");
260*da58b97aSjoerg     } else if (opt.consume_front("thinlto-object-suffix-replace=")) {
261*da58b97aSjoerg       thinlto_object_suffix_replace = std::string(opt);
26206f32e7eSjoerg       if (thinlto_object_suffix_replace.find(';') == std::string::npos)
26306f32e7eSjoerg         message(LDPL_FATAL,
26406f32e7eSjoerg                 "thinlto-object-suffix-replace expects 'old;new' format");
265*da58b97aSjoerg     } else if (opt.consume_front("cache-dir=")) {
266*da58b97aSjoerg       cache_dir = std::string(opt);
267*da58b97aSjoerg     } else if (opt.consume_front("cache-policy=")) {
268*da58b97aSjoerg       cache_policy = std::string(opt);
26906f32e7eSjoerg     } else if (opt.size() == 2 && opt[0] == 'O') {
27006f32e7eSjoerg       if (opt[1] < '0' || opt[1] > '3')
27106f32e7eSjoerg         message(LDPL_FATAL, "Optimization level must be between 0 and 3");
27206f32e7eSjoerg       OptLevel = opt[1] - '0';
273*da58b97aSjoerg     } else if (opt.consume_front("jobs=")) {
274*da58b97aSjoerg       Parallelism = std::string(opt);
275*da58b97aSjoerg       if (!get_threadpool_strategy(opt))
276*da58b97aSjoerg         message(LDPL_FATAL, "Invalid parallelism level: %s",
277*da58b97aSjoerg                 Parallelism.c_str());
278*da58b97aSjoerg     } else if (opt.consume_front("lto-partitions=")) {
279*da58b97aSjoerg       if (opt.getAsInteger(10, ParallelCodeGenParallelismLevel))
28006f32e7eSjoerg         message(LDPL_FATAL, "Invalid codegen partition level: %s", opt_ + 5);
28106f32e7eSjoerg     } else if (opt == "disable-verify") {
28206f32e7eSjoerg       DisableVerify = true;
283*da58b97aSjoerg     } else if (opt.consume_front("sample-profile=")) {
284*da58b97aSjoerg       sample_profile = std::string(opt);
28506f32e7eSjoerg     } else if (opt == "cs-profile-generate") {
28606f32e7eSjoerg       cs_pgo_gen = true;
287*da58b97aSjoerg     } else if (opt.consume_front("cs-profile-path=")) {
288*da58b97aSjoerg       cs_profile_path = std::string(opt);
28906f32e7eSjoerg     } else if (opt == "new-pass-manager") {
29006f32e7eSjoerg       new_pass_manager = true;
291*da58b97aSjoerg     } else if (opt == "legacy-pass-manager") {
292*da58b97aSjoerg       new_pass_manager = false;
29306f32e7eSjoerg     } else if (opt == "debug-pass-manager") {
29406f32e7eSjoerg       debug_pass_manager = true;
295*da58b97aSjoerg     } else if (opt == "whole-program-visibility") {
296*da58b97aSjoerg       whole_program_visibility = true;
297*da58b97aSjoerg     } else if (opt.consume_front("dwo_dir=")) {
298*da58b97aSjoerg       dwo_dir = std::string(opt);
299*da58b97aSjoerg     } else if (opt.consume_front("opt-remarks-filename=")) {
300*da58b97aSjoerg       RemarksFilename = std::string(opt);
301*da58b97aSjoerg     } else if (opt.consume_front("opt-remarks-passes=")) {
302*da58b97aSjoerg       RemarksPasses = std::string(opt);
30306f32e7eSjoerg     } else if (opt == "opt-remarks-with-hotness") {
30406f32e7eSjoerg       RemarksWithHotness = true;
305*da58b97aSjoerg     } else if (opt.consume_front("opt-remarks-hotness-threshold=")) {
306*da58b97aSjoerg       auto ResultOrErr = remarks::parseHotnessThresholdOption(opt);
307*da58b97aSjoerg       if (!ResultOrErr)
308*da58b97aSjoerg         message(LDPL_FATAL, "Invalid remarks hotness threshold: %s", opt);
309*da58b97aSjoerg       else
310*da58b97aSjoerg         RemarksHotnessThreshold = *ResultOrErr;
311*da58b97aSjoerg     } else if (opt.consume_front("opt-remarks-format=")) {
312*da58b97aSjoerg       RemarksFormat = std::string(opt);
313*da58b97aSjoerg     } else if (opt.consume_front("stats-file=")) {
314*da58b97aSjoerg       stats_file = std::string(opt);
31506f32e7eSjoerg     } else {
31606f32e7eSjoerg       // Save this option to pass to the code generator.
31706f32e7eSjoerg       // ParseCommandLineOptions() expects argv[0] to be program name. Lazily
31806f32e7eSjoerg       // add that.
31906f32e7eSjoerg       if (extra.empty())
32006f32e7eSjoerg         extra.push_back("LLVMgold");
32106f32e7eSjoerg 
32206f32e7eSjoerg       extra.push_back(opt_);
32306f32e7eSjoerg     }
32406f32e7eSjoerg   }
32506f32e7eSjoerg }
32606f32e7eSjoerg 
32706f32e7eSjoerg static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
32806f32e7eSjoerg                                         int *claimed);
32906f32e7eSjoerg static ld_plugin_status all_symbols_read_hook(void);
33006f32e7eSjoerg static ld_plugin_status cleanup_hook(void);
33106f32e7eSjoerg 
33206f32e7eSjoerg extern "C" ld_plugin_status onload(ld_plugin_tv *tv);
onload(ld_plugin_tv * tv)33306f32e7eSjoerg ld_plugin_status onload(ld_plugin_tv *tv) {
33406f32e7eSjoerg   InitializeAllTargetInfos();
33506f32e7eSjoerg   InitializeAllTargets();
33606f32e7eSjoerg   InitializeAllTargetMCs();
33706f32e7eSjoerg   InitializeAllAsmParsers();
33806f32e7eSjoerg   InitializeAllAsmPrinters();
33906f32e7eSjoerg 
34006f32e7eSjoerg   // We're given a pointer to the first transfer vector. We read through them
34106f32e7eSjoerg   // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values
34206f32e7eSjoerg   // contain pointers to functions that we need to call to register our own
34306f32e7eSjoerg   // hooks. The others are addresses of functions we can use to call into gold
34406f32e7eSjoerg   // for services.
34506f32e7eSjoerg 
34606f32e7eSjoerg   bool registeredClaimFile = false;
34706f32e7eSjoerg   bool RegisteredAllSymbolsRead = false;
34806f32e7eSjoerg 
34906f32e7eSjoerg   for (; tv->tv_tag != LDPT_NULL; ++tv) {
35006f32e7eSjoerg     // Cast tv_tag to int to allow values not in "enum ld_plugin_tag", like, for
35106f32e7eSjoerg     // example, LDPT_GET_SYMBOLS_V3 when building against an older plugin-api.h
35206f32e7eSjoerg     // header.
35306f32e7eSjoerg     switch (static_cast<int>(tv->tv_tag)) {
35406f32e7eSjoerg     case LDPT_OUTPUT_NAME:
35506f32e7eSjoerg       output_name = tv->tv_u.tv_string;
35606f32e7eSjoerg       break;
35706f32e7eSjoerg     case LDPT_LINKER_OUTPUT:
35806f32e7eSjoerg       switch (tv->tv_u.tv_val) {
35906f32e7eSjoerg       case LDPO_REL: // .o
36006f32e7eSjoerg         IsExecutable = false;
36106f32e7eSjoerg         SplitSections = false;
36206f32e7eSjoerg         break;
36306f32e7eSjoerg       case LDPO_DYN: // .so
36406f32e7eSjoerg         IsExecutable = false;
36506f32e7eSjoerg         RelocationModel = Reloc::PIC_;
36606f32e7eSjoerg         break;
36706f32e7eSjoerg       case LDPO_PIE: // position independent executable
36806f32e7eSjoerg         IsExecutable = true;
36906f32e7eSjoerg         RelocationModel = Reloc::PIC_;
37006f32e7eSjoerg         break;
37106f32e7eSjoerg       case LDPO_EXEC: // .exe
37206f32e7eSjoerg         IsExecutable = true;
37306f32e7eSjoerg         RelocationModel = Reloc::Static;
37406f32e7eSjoerg         break;
37506f32e7eSjoerg       default:
37606f32e7eSjoerg         message(LDPL_ERROR, "Unknown output file type %d", tv->tv_u.tv_val);
37706f32e7eSjoerg         return LDPS_ERR;
37806f32e7eSjoerg       }
37906f32e7eSjoerg       break;
38006f32e7eSjoerg     case LDPT_OPTION:
38106f32e7eSjoerg       options::process_plugin_option(tv->tv_u.tv_string);
38206f32e7eSjoerg       break;
38306f32e7eSjoerg     case LDPT_REGISTER_CLAIM_FILE_HOOK: {
38406f32e7eSjoerg       ld_plugin_register_claim_file callback;
38506f32e7eSjoerg       callback = tv->tv_u.tv_register_claim_file;
38606f32e7eSjoerg 
38706f32e7eSjoerg       if (callback(claim_file_hook) != LDPS_OK)
38806f32e7eSjoerg         return LDPS_ERR;
38906f32e7eSjoerg 
39006f32e7eSjoerg       registeredClaimFile = true;
39106f32e7eSjoerg     } break;
39206f32e7eSjoerg     case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: {
39306f32e7eSjoerg       ld_plugin_register_all_symbols_read callback;
39406f32e7eSjoerg       callback = tv->tv_u.tv_register_all_symbols_read;
39506f32e7eSjoerg 
39606f32e7eSjoerg       if (callback(all_symbols_read_hook) != LDPS_OK)
39706f32e7eSjoerg         return LDPS_ERR;
39806f32e7eSjoerg 
39906f32e7eSjoerg       RegisteredAllSymbolsRead = true;
40006f32e7eSjoerg     } break;
40106f32e7eSjoerg     case LDPT_REGISTER_CLEANUP_HOOK: {
40206f32e7eSjoerg       ld_plugin_register_cleanup callback;
40306f32e7eSjoerg       callback = tv->tv_u.tv_register_cleanup;
40406f32e7eSjoerg 
40506f32e7eSjoerg       if (callback(cleanup_hook) != LDPS_OK)
40606f32e7eSjoerg         return LDPS_ERR;
40706f32e7eSjoerg     } break;
40806f32e7eSjoerg     case LDPT_GET_INPUT_FILE:
40906f32e7eSjoerg       get_input_file = tv->tv_u.tv_get_input_file;
41006f32e7eSjoerg       break;
41106f32e7eSjoerg     case LDPT_RELEASE_INPUT_FILE:
41206f32e7eSjoerg       release_input_file = tv->tv_u.tv_release_input_file;
41306f32e7eSjoerg       break;
41406f32e7eSjoerg     case LDPT_ADD_SYMBOLS:
41506f32e7eSjoerg       add_symbols = tv->tv_u.tv_add_symbols;
41606f32e7eSjoerg       break;
41706f32e7eSjoerg     case LDPT_GET_SYMBOLS_V2:
41806f32e7eSjoerg       // Do not override get_symbols_v3 with get_symbols_v2.
41906f32e7eSjoerg       if (!get_symbols)
42006f32e7eSjoerg         get_symbols = tv->tv_u.tv_get_symbols;
42106f32e7eSjoerg       break;
42206f32e7eSjoerg     case LDPT_GET_SYMBOLS_V3:
42306f32e7eSjoerg       get_symbols = tv->tv_u.tv_get_symbols;
42406f32e7eSjoerg       break;
42506f32e7eSjoerg     case LDPT_ADD_INPUT_FILE:
42606f32e7eSjoerg       add_input_file = tv->tv_u.tv_add_input_file;
42706f32e7eSjoerg       break;
42806f32e7eSjoerg     case LDPT_SET_EXTRA_LIBRARY_PATH:
42906f32e7eSjoerg       set_extra_library_path = tv->tv_u.tv_set_extra_library_path;
43006f32e7eSjoerg       break;
43106f32e7eSjoerg     case LDPT_GET_VIEW:
43206f32e7eSjoerg       get_view = tv->tv_u.tv_get_view;
43306f32e7eSjoerg       break;
43406f32e7eSjoerg     case LDPT_MESSAGE:
43506f32e7eSjoerg       message = tv->tv_u.tv_message;
43606f32e7eSjoerg       break;
43706f32e7eSjoerg     case LDPT_GET_WRAP_SYMBOLS:
43806f32e7eSjoerg       // FIXME: When binutils 2.31 (containing gold 1.16) is the minimum
43906f32e7eSjoerg       // required version, this should be changed to:
44006f32e7eSjoerg       // get_wrap_symbols = tv->tv_u.tv_get_wrap_symbols;
44106f32e7eSjoerg       get_wrap_symbols =
44206f32e7eSjoerg           (ld_plugin_get_wrap_symbols)tv->tv_u.tv_message;
44306f32e7eSjoerg       break;
44406f32e7eSjoerg     default:
44506f32e7eSjoerg       break;
44606f32e7eSjoerg     }
44706f32e7eSjoerg   }
44806f32e7eSjoerg 
44906f32e7eSjoerg   if (!registeredClaimFile) {
45006f32e7eSjoerg     message(LDPL_ERROR, "register_claim_file not passed to LLVMgold.");
45106f32e7eSjoerg     return LDPS_ERR;
45206f32e7eSjoerg   }
45306f32e7eSjoerg   if (!add_symbols) {
45406f32e7eSjoerg     message(LDPL_ERROR, "add_symbols not passed to LLVMgold.");
45506f32e7eSjoerg     return LDPS_ERR;
45606f32e7eSjoerg   }
45706f32e7eSjoerg 
45806f32e7eSjoerg   if (!RegisteredAllSymbolsRead)
45906f32e7eSjoerg     return LDPS_OK;
46006f32e7eSjoerg 
46106f32e7eSjoerg   if (!get_input_file) {
46206f32e7eSjoerg     message(LDPL_ERROR, "get_input_file not passed to LLVMgold.");
46306f32e7eSjoerg     return LDPS_ERR;
46406f32e7eSjoerg   }
46506f32e7eSjoerg   if (!release_input_file) {
46606f32e7eSjoerg     message(LDPL_ERROR, "release_input_file not passed to LLVMgold.");
46706f32e7eSjoerg     return LDPS_ERR;
46806f32e7eSjoerg   }
46906f32e7eSjoerg 
47006f32e7eSjoerg   return LDPS_OK;
47106f32e7eSjoerg }
47206f32e7eSjoerg 
diagnosticHandler(const DiagnosticInfo & DI)47306f32e7eSjoerg static void diagnosticHandler(const DiagnosticInfo &DI) {
47406f32e7eSjoerg   std::string ErrStorage;
47506f32e7eSjoerg   {
47606f32e7eSjoerg     raw_string_ostream OS(ErrStorage);
47706f32e7eSjoerg     DiagnosticPrinterRawOStream DP(OS);
47806f32e7eSjoerg     DI.print(DP);
47906f32e7eSjoerg   }
48006f32e7eSjoerg   ld_plugin_level Level;
48106f32e7eSjoerg   switch (DI.getSeverity()) {
48206f32e7eSjoerg   case DS_Error:
48306f32e7eSjoerg     Level = LDPL_FATAL;
48406f32e7eSjoerg     break;
48506f32e7eSjoerg   case DS_Warning:
48606f32e7eSjoerg     Level = LDPL_WARNING;
48706f32e7eSjoerg     break;
48806f32e7eSjoerg   case DS_Note:
48906f32e7eSjoerg   case DS_Remark:
49006f32e7eSjoerg     Level = LDPL_INFO;
49106f32e7eSjoerg     break;
49206f32e7eSjoerg   }
49306f32e7eSjoerg   message(Level, "LLVM gold plugin: %s",  ErrStorage.c_str());
49406f32e7eSjoerg }
49506f32e7eSjoerg 
check(Error E,std::string Msg="LLVM gold plugin")49606f32e7eSjoerg static void check(Error E, std::string Msg = "LLVM gold plugin") {
49706f32e7eSjoerg   handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) -> Error {
49806f32e7eSjoerg     message(LDPL_FATAL, "%s: %s", Msg.c_str(), EIB.message().c_str());
49906f32e7eSjoerg     return Error::success();
50006f32e7eSjoerg   });
50106f32e7eSjoerg }
50206f32e7eSjoerg 
check(Expected<T> E)50306f32e7eSjoerg template <typename T> static T check(Expected<T> E) {
50406f32e7eSjoerg   if (E)
50506f32e7eSjoerg     return std::move(*E);
50606f32e7eSjoerg   check(E.takeError());
50706f32e7eSjoerg   return T();
50806f32e7eSjoerg }
50906f32e7eSjoerg 
51006f32e7eSjoerg /// Called by gold to see whether this file is one that our plugin can handle.
51106f32e7eSjoerg /// We'll try to open it and register all the symbols with add_symbol if
51206f32e7eSjoerg /// possible.
claim_file_hook(const ld_plugin_input_file * file,int * claimed)51306f32e7eSjoerg static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
51406f32e7eSjoerg                                         int *claimed) {
51506f32e7eSjoerg   MemoryBufferRef BufferRef;
51606f32e7eSjoerg   std::unique_ptr<MemoryBuffer> Buffer;
51706f32e7eSjoerg   if (get_view) {
51806f32e7eSjoerg     const void *view;
51906f32e7eSjoerg     if (get_view(file->handle, &view) != LDPS_OK) {
52006f32e7eSjoerg       message(LDPL_ERROR, "Failed to get a view of %s", file->name);
52106f32e7eSjoerg       return LDPS_ERR;
52206f32e7eSjoerg     }
52306f32e7eSjoerg     BufferRef =
52406f32e7eSjoerg         MemoryBufferRef(StringRef((const char *)view, file->filesize), "");
52506f32e7eSjoerg   } else {
52606f32e7eSjoerg     int64_t offset = 0;
52706f32e7eSjoerg     // Gold has found what might be IR part-way inside of a file, such as
52806f32e7eSjoerg     // an .a archive.
52906f32e7eSjoerg     if (file->offset) {
53006f32e7eSjoerg       offset = file->offset;
53106f32e7eSjoerg     }
53206f32e7eSjoerg     ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
53306f32e7eSjoerg         MemoryBuffer::getOpenFileSlice(sys::fs::convertFDToNativeFile(file->fd),
53406f32e7eSjoerg                                        file->name, file->filesize, offset);
53506f32e7eSjoerg     if (std::error_code EC = BufferOrErr.getError()) {
53606f32e7eSjoerg       message(LDPL_ERROR, EC.message().c_str());
53706f32e7eSjoerg       return LDPS_ERR;
53806f32e7eSjoerg     }
53906f32e7eSjoerg     Buffer = std::move(BufferOrErr.get());
54006f32e7eSjoerg     BufferRef = Buffer->getMemBufferRef();
54106f32e7eSjoerg   }
54206f32e7eSjoerg 
54306f32e7eSjoerg   *claimed = 1;
54406f32e7eSjoerg 
54506f32e7eSjoerg   Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef);
54606f32e7eSjoerg   if (!ObjOrErr) {
54706f32e7eSjoerg     handleAllErrors(ObjOrErr.takeError(), [&](const ErrorInfoBase &EI) {
54806f32e7eSjoerg       std::error_code EC = EI.convertToErrorCode();
54906f32e7eSjoerg       if (EC == object::object_error::invalid_file_type ||
55006f32e7eSjoerg           EC == object::object_error::bitcode_section_not_found)
55106f32e7eSjoerg         *claimed = 0;
55206f32e7eSjoerg       else
55306f32e7eSjoerg         message(LDPL_FATAL,
55406f32e7eSjoerg                 "LLVM gold plugin has failed to create LTO module: %s",
55506f32e7eSjoerg                 EI.message().c_str());
55606f32e7eSjoerg     });
55706f32e7eSjoerg 
55806f32e7eSjoerg     return *claimed ? LDPS_ERR : LDPS_OK;
55906f32e7eSjoerg   }
56006f32e7eSjoerg 
56106f32e7eSjoerg   std::unique_ptr<InputFile> Obj = std::move(*ObjOrErr);
56206f32e7eSjoerg 
56306f32e7eSjoerg   Modules.emplace_back();
56406f32e7eSjoerg   claimed_file &cf = Modules.back();
56506f32e7eSjoerg 
56606f32e7eSjoerg   cf.handle = file->handle;
56706f32e7eSjoerg   // Keep track of the first handle for each file descriptor, since there are
56806f32e7eSjoerg   // multiple in the case of an archive. This is used later in the case of
56906f32e7eSjoerg   // ThinLTO parallel backends to ensure that each file is only opened and
57006f32e7eSjoerg   // released once.
57106f32e7eSjoerg   auto LeaderHandle =
57206f32e7eSjoerg       FDToLeaderHandle.insert(std::make_pair(file->fd, file->handle)).first;
57306f32e7eSjoerg   cf.leader_handle = LeaderHandle->second;
57406f32e7eSjoerg   // Save the filesize since for parallel ThinLTO backends we can only
57506f32e7eSjoerg   // invoke get_input_file once per archive (only for the leader handle).
57606f32e7eSjoerg   cf.filesize = file->filesize;
57706f32e7eSjoerg   // In the case of an archive library, all but the first member must have a
57806f32e7eSjoerg   // non-zero offset, which we can append to the file name to obtain a
57906f32e7eSjoerg   // unique name.
58006f32e7eSjoerg   cf.name = file->name;
58106f32e7eSjoerg   if (file->offset)
58206f32e7eSjoerg     cf.name += ".llvm." + std::to_string(file->offset) + "." +
58306f32e7eSjoerg                sys::path::filename(Obj->getSourceFileName()).str();
58406f32e7eSjoerg 
58506f32e7eSjoerg   for (auto &Sym : Obj->symbols()) {
58606f32e7eSjoerg     cf.syms.push_back(ld_plugin_symbol());
58706f32e7eSjoerg     ld_plugin_symbol &sym = cf.syms.back();
58806f32e7eSjoerg     sym.version = nullptr;
58906f32e7eSjoerg     StringRef Name = Sym.getName();
59006f32e7eSjoerg     sym.name = strdup(Name.str().c_str());
59106f32e7eSjoerg 
59206f32e7eSjoerg     ResolutionInfo &Res = ResInfo[Name];
59306f32e7eSjoerg 
59406f32e7eSjoerg     Res.CanOmitFromDynSym &= Sym.canBeOmittedFromSymbolTable();
59506f32e7eSjoerg 
59606f32e7eSjoerg     sym.visibility = LDPV_DEFAULT;
59706f32e7eSjoerg     GlobalValue::VisibilityTypes Vis = Sym.getVisibility();
59806f32e7eSjoerg     if (Vis != GlobalValue::DefaultVisibility)
59906f32e7eSjoerg       Res.DefaultVisibility = false;
60006f32e7eSjoerg     switch (Vis) {
60106f32e7eSjoerg     case GlobalValue::DefaultVisibility:
60206f32e7eSjoerg       break;
60306f32e7eSjoerg     case GlobalValue::HiddenVisibility:
60406f32e7eSjoerg       sym.visibility = LDPV_HIDDEN;
60506f32e7eSjoerg       break;
60606f32e7eSjoerg     case GlobalValue::ProtectedVisibility:
60706f32e7eSjoerg       sym.visibility = LDPV_PROTECTED;
60806f32e7eSjoerg       break;
60906f32e7eSjoerg     }
61006f32e7eSjoerg 
61106f32e7eSjoerg     if (Sym.isUndefined()) {
61206f32e7eSjoerg       sym.def = LDPK_UNDEF;
61306f32e7eSjoerg       if (Sym.isWeak())
61406f32e7eSjoerg         sym.def = LDPK_WEAKUNDEF;
61506f32e7eSjoerg     } else if (Sym.isCommon())
61606f32e7eSjoerg       sym.def = LDPK_COMMON;
61706f32e7eSjoerg     else if (Sym.isWeak())
61806f32e7eSjoerg       sym.def = LDPK_WEAKDEF;
61906f32e7eSjoerg     else
62006f32e7eSjoerg       sym.def = LDPK_DEF;
62106f32e7eSjoerg 
62206f32e7eSjoerg     sym.size = 0;
62306f32e7eSjoerg     sym.comdat_key = nullptr;
62406f32e7eSjoerg     int CI = Sym.getComdatIndex();
62506f32e7eSjoerg     if (CI != -1) {
62606f32e7eSjoerg       StringRef C = Obj->getComdatTable()[CI];
62706f32e7eSjoerg       sym.comdat_key = strdup(C.str().c_str());
62806f32e7eSjoerg     }
62906f32e7eSjoerg 
63006f32e7eSjoerg     sym.resolution = LDPR_UNKNOWN;
63106f32e7eSjoerg   }
63206f32e7eSjoerg 
63306f32e7eSjoerg   if (!cf.syms.empty()) {
63406f32e7eSjoerg     if (add_symbols(cf.handle, cf.syms.size(), cf.syms.data()) != LDPS_OK) {
63506f32e7eSjoerg       message(LDPL_ERROR, "Unable to add symbols!");
63606f32e7eSjoerg       return LDPS_ERR;
63706f32e7eSjoerg     }
63806f32e7eSjoerg   }
63906f32e7eSjoerg 
64006f32e7eSjoerg   // Handle any --wrap options passed to gold, which are than passed
64106f32e7eSjoerg   // along to the plugin.
64206f32e7eSjoerg   if (get_wrap_symbols) {
64306f32e7eSjoerg     const char **wrap_symbols;
64406f32e7eSjoerg     uint64_t count = 0;
64506f32e7eSjoerg     if (get_wrap_symbols(&count, &wrap_symbols) != LDPS_OK) {
64606f32e7eSjoerg       message(LDPL_ERROR, "Unable to get wrap symbols!");
64706f32e7eSjoerg       return LDPS_ERR;
64806f32e7eSjoerg     }
64906f32e7eSjoerg     for (uint64_t i = 0; i < count; i++) {
65006f32e7eSjoerg       StringRef Name = wrap_symbols[i];
65106f32e7eSjoerg       ResolutionInfo &Res = ResInfo[Name];
65206f32e7eSjoerg       ResolutionInfo &WrapRes = ResInfo["__wrap_" + Name.str()];
65306f32e7eSjoerg       ResolutionInfo &RealRes = ResInfo["__real_" + Name.str()];
65406f32e7eSjoerg       // Tell LTO not to inline symbols that will be overwritten.
65506f32e7eSjoerg       Res.CanInline = false;
65606f32e7eSjoerg       RealRes.CanInline = false;
65706f32e7eSjoerg       // Tell LTO not to eliminate symbols that will be used after renaming.
65806f32e7eSjoerg       Res.IsUsedInRegularObj = true;
65906f32e7eSjoerg       WrapRes.IsUsedInRegularObj = true;
66006f32e7eSjoerg     }
66106f32e7eSjoerg   }
66206f32e7eSjoerg 
66306f32e7eSjoerg   return LDPS_OK;
66406f32e7eSjoerg }
66506f32e7eSjoerg 
freeSymName(ld_plugin_symbol & Sym)66606f32e7eSjoerg static void freeSymName(ld_plugin_symbol &Sym) {
66706f32e7eSjoerg   free(Sym.name);
66806f32e7eSjoerg   free(Sym.comdat_key);
66906f32e7eSjoerg   Sym.name = nullptr;
67006f32e7eSjoerg   Sym.comdat_key = nullptr;
67106f32e7eSjoerg }
67206f32e7eSjoerg 
67306f32e7eSjoerg /// Helper to get a file's symbols and a view into it via gold callbacks.
getSymbolsAndView(claimed_file & F)67406f32e7eSjoerg static const void *getSymbolsAndView(claimed_file &F) {
67506f32e7eSjoerg   ld_plugin_status status = get_symbols(F.handle, F.syms.size(), F.syms.data());
67606f32e7eSjoerg   if (status == LDPS_NO_SYMS)
67706f32e7eSjoerg     return nullptr;
67806f32e7eSjoerg 
67906f32e7eSjoerg   if (status != LDPS_OK)
68006f32e7eSjoerg     message(LDPL_FATAL, "Failed to get symbol information");
68106f32e7eSjoerg 
68206f32e7eSjoerg   const void *View;
68306f32e7eSjoerg   if (get_view(F.handle, &View) != LDPS_OK)
68406f32e7eSjoerg     message(LDPL_FATAL, "Failed to get a view of file");
68506f32e7eSjoerg 
68606f32e7eSjoerg   return View;
68706f32e7eSjoerg }
68806f32e7eSjoerg 
68906f32e7eSjoerg /// Parse the thinlto-object-suffix-replace option into the \p OldSuffix and
69006f32e7eSjoerg /// \p NewSuffix strings, if it was specified.
getThinLTOOldAndNewSuffix(std::string & OldSuffix,std::string & NewSuffix)69106f32e7eSjoerg static void getThinLTOOldAndNewSuffix(std::string &OldSuffix,
69206f32e7eSjoerg                                       std::string &NewSuffix) {
69306f32e7eSjoerg   assert(options::thinlto_object_suffix_replace.empty() ||
694*da58b97aSjoerg          options::thinlto_object_suffix_replace.find(';') != StringRef::npos);
69506f32e7eSjoerg   StringRef SuffixReplace = options::thinlto_object_suffix_replace;
696*da58b97aSjoerg   auto Split = SuffixReplace.split(';');
697*da58b97aSjoerg   OldSuffix = std::string(Split.first);
698*da58b97aSjoerg   NewSuffix = std::string(Split.second);
69906f32e7eSjoerg }
70006f32e7eSjoerg 
70106f32e7eSjoerg /// Given the original \p Path to an output file, replace any filename
70206f32e7eSjoerg /// suffix matching \p OldSuffix with \p NewSuffix.
getThinLTOObjectFileName(StringRef Path,StringRef OldSuffix,StringRef NewSuffix)70306f32e7eSjoerg static std::string getThinLTOObjectFileName(StringRef Path, StringRef OldSuffix,
70406f32e7eSjoerg                                             StringRef NewSuffix) {
70506f32e7eSjoerg   if (Path.consume_back(OldSuffix))
70606f32e7eSjoerg     return (Path + NewSuffix).str();
707*da58b97aSjoerg   return std::string(Path);
70806f32e7eSjoerg }
70906f32e7eSjoerg 
71006f32e7eSjoerg // Returns true if S is valid as a C language identifier.
isValidCIdentifier(StringRef S)71106f32e7eSjoerg static bool isValidCIdentifier(StringRef S) {
71206f32e7eSjoerg   return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&
71306f32e7eSjoerg          std::all_of(S.begin() + 1, S.end(),
71406f32e7eSjoerg                      [](char C) { return C == '_' || isAlnum(C); });
71506f32e7eSjoerg }
71606f32e7eSjoerg 
isUndefined(ld_plugin_symbol & Sym)71706f32e7eSjoerg static bool isUndefined(ld_plugin_symbol &Sym) {
71806f32e7eSjoerg   return Sym.def == LDPK_UNDEF || Sym.def == LDPK_WEAKUNDEF;
71906f32e7eSjoerg }
72006f32e7eSjoerg 
addModule(LTO & Lto,claimed_file & F,const void * View,StringRef Filename)72106f32e7eSjoerg static void addModule(LTO &Lto, claimed_file &F, const void *View,
72206f32e7eSjoerg                       StringRef Filename) {
72306f32e7eSjoerg   MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize),
72406f32e7eSjoerg                             Filename);
72506f32e7eSjoerg   Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef);
72606f32e7eSjoerg 
72706f32e7eSjoerg   if (!ObjOrErr)
72806f32e7eSjoerg     message(LDPL_FATAL, "Could not read bitcode from file : %s",
72906f32e7eSjoerg             toString(ObjOrErr.takeError()).c_str());
73006f32e7eSjoerg 
73106f32e7eSjoerg   unsigned SymNum = 0;
73206f32e7eSjoerg   std::unique_ptr<InputFile> Input = std::move(ObjOrErr.get());
73306f32e7eSjoerg   auto InputFileSyms = Input->symbols();
73406f32e7eSjoerg   assert(InputFileSyms.size() == F.syms.size());
73506f32e7eSjoerg   std::vector<SymbolResolution> Resols(F.syms.size());
73606f32e7eSjoerg   for (ld_plugin_symbol &Sym : F.syms) {
73706f32e7eSjoerg     const InputFile::Symbol &InpSym = InputFileSyms[SymNum];
73806f32e7eSjoerg     SymbolResolution &R = Resols[SymNum++];
73906f32e7eSjoerg 
74006f32e7eSjoerg     ld_plugin_symbol_resolution Resolution =
74106f32e7eSjoerg         (ld_plugin_symbol_resolution)Sym.resolution;
74206f32e7eSjoerg 
74306f32e7eSjoerg     ResolutionInfo &Res = ResInfo[Sym.name];
74406f32e7eSjoerg 
74506f32e7eSjoerg     switch (Resolution) {
74606f32e7eSjoerg     case LDPR_UNKNOWN:
74706f32e7eSjoerg       llvm_unreachable("Unexpected resolution");
74806f32e7eSjoerg 
74906f32e7eSjoerg     case LDPR_RESOLVED_IR:
75006f32e7eSjoerg     case LDPR_RESOLVED_EXEC:
75106f32e7eSjoerg     case LDPR_PREEMPTED_IR:
75206f32e7eSjoerg     case LDPR_PREEMPTED_REG:
75306f32e7eSjoerg     case LDPR_UNDEF:
75406f32e7eSjoerg       break;
75506f32e7eSjoerg 
756*da58b97aSjoerg     case LDPR_RESOLVED_DYN:
757*da58b97aSjoerg       R.ExportDynamic = true;
758*da58b97aSjoerg       break;
759*da58b97aSjoerg 
76006f32e7eSjoerg     case LDPR_PREVAILING_DEF_IRONLY:
76106f32e7eSjoerg       R.Prevailing = !isUndefined(Sym);
76206f32e7eSjoerg       break;
76306f32e7eSjoerg 
76406f32e7eSjoerg     case LDPR_PREVAILING_DEF:
76506f32e7eSjoerg       R.Prevailing = !isUndefined(Sym);
76606f32e7eSjoerg       R.VisibleToRegularObj = true;
76706f32e7eSjoerg       break;
76806f32e7eSjoerg 
76906f32e7eSjoerg     case LDPR_PREVAILING_DEF_IRONLY_EXP:
77006f32e7eSjoerg       R.Prevailing = !isUndefined(Sym);
771*da58b97aSjoerg       // Identify symbols exported dynamically, and that therefore could be
772*da58b97aSjoerg       // referenced by a shared library not visible to the linker.
773*da58b97aSjoerg       R.ExportDynamic = true;
77406f32e7eSjoerg       if (!Res.CanOmitFromDynSym)
77506f32e7eSjoerg         R.VisibleToRegularObj = true;
77606f32e7eSjoerg       break;
77706f32e7eSjoerg     }
77806f32e7eSjoerg 
77906f32e7eSjoerg     // If the symbol has a C identifier section name, we need to mark
78006f32e7eSjoerg     // it as visible to a regular object so that LTO will keep it around
78106f32e7eSjoerg     // to ensure the linker generates special __start_<secname> and
78206f32e7eSjoerg     // __stop_<secname> symbols which may be used elsewhere.
78306f32e7eSjoerg     if (isValidCIdentifier(InpSym.getSectionName()))
78406f32e7eSjoerg       R.VisibleToRegularObj = true;
78506f32e7eSjoerg 
78606f32e7eSjoerg     if (Resolution != LDPR_RESOLVED_DYN && Resolution != LDPR_UNDEF &&
78706f32e7eSjoerg         (IsExecutable || !Res.DefaultVisibility))
78806f32e7eSjoerg       R.FinalDefinitionInLinkageUnit = true;
78906f32e7eSjoerg 
79006f32e7eSjoerg     if (!Res.CanInline)
79106f32e7eSjoerg       R.LinkerRedefined = true;
79206f32e7eSjoerg 
79306f32e7eSjoerg     if (Res.IsUsedInRegularObj)
79406f32e7eSjoerg       R.VisibleToRegularObj = true;
79506f32e7eSjoerg 
79606f32e7eSjoerg     freeSymName(Sym);
79706f32e7eSjoerg   }
79806f32e7eSjoerg 
79906f32e7eSjoerg   check(Lto.add(std::move(Input), Resols),
80006f32e7eSjoerg         std::string("Failed to link module ") + F.name);
80106f32e7eSjoerg }
80206f32e7eSjoerg 
recordFile(const std::string & Filename,bool TempOutFile)80306f32e7eSjoerg static void recordFile(const std::string &Filename, bool TempOutFile) {
80406f32e7eSjoerg   if (add_input_file(Filename.c_str()) != LDPS_OK)
80506f32e7eSjoerg     message(LDPL_FATAL,
80606f32e7eSjoerg             "Unable to add .o file to the link. File left behind in: %s",
80706f32e7eSjoerg             Filename.c_str());
80806f32e7eSjoerg   if (TempOutFile)
80906f32e7eSjoerg     Cleanup.push_back(Filename);
81006f32e7eSjoerg }
81106f32e7eSjoerg 
81206f32e7eSjoerg /// Return the desired output filename given a base input name, a flag
81306f32e7eSjoerg /// indicating whether a temp file should be generated, and an optional task id.
81406f32e7eSjoerg /// The new filename generated is returned in \p NewFilename.
getOutputFileName(StringRef InFilename,bool TempOutFile,SmallString<128> & NewFilename,int TaskID)81506f32e7eSjoerg static int getOutputFileName(StringRef InFilename, bool TempOutFile,
81606f32e7eSjoerg                              SmallString<128> &NewFilename, int TaskID) {
81706f32e7eSjoerg   int FD = -1;
81806f32e7eSjoerg   if (TempOutFile) {
81906f32e7eSjoerg     std::error_code EC =
82006f32e7eSjoerg         sys::fs::createTemporaryFile("lto-llvm", "o", FD, NewFilename);
82106f32e7eSjoerg     if (EC)
82206f32e7eSjoerg       message(LDPL_FATAL, "Could not create temporary file: %s",
82306f32e7eSjoerg               EC.message().c_str());
82406f32e7eSjoerg   } else {
82506f32e7eSjoerg     NewFilename = InFilename;
82606f32e7eSjoerg     if (TaskID > 0)
82706f32e7eSjoerg       NewFilename += utostr(TaskID);
82806f32e7eSjoerg     std::error_code EC =
82906f32e7eSjoerg         sys::fs::openFileForWrite(NewFilename, FD, sys::fs::CD_CreateAlways);
83006f32e7eSjoerg     if (EC)
83106f32e7eSjoerg       message(LDPL_FATAL, "Could not open file %s: %s", NewFilename.c_str(),
83206f32e7eSjoerg               EC.message().c_str());
83306f32e7eSjoerg   }
83406f32e7eSjoerg   return FD;
83506f32e7eSjoerg }
83606f32e7eSjoerg 
getCGOptLevel()83706f32e7eSjoerg static CodeGenOpt::Level getCGOptLevel() {
83806f32e7eSjoerg   switch (options::OptLevel) {
83906f32e7eSjoerg   case 0:
84006f32e7eSjoerg     return CodeGenOpt::None;
84106f32e7eSjoerg   case 1:
84206f32e7eSjoerg     return CodeGenOpt::Less;
84306f32e7eSjoerg   case 2:
84406f32e7eSjoerg     return CodeGenOpt::Default;
84506f32e7eSjoerg   case 3:
84606f32e7eSjoerg     return CodeGenOpt::Aggressive;
84706f32e7eSjoerg   }
84806f32e7eSjoerg   llvm_unreachable("Invalid optimization level");
84906f32e7eSjoerg }
85006f32e7eSjoerg 
85106f32e7eSjoerg /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
85206f32e7eSjoerg /// \p NewPrefix strings, if it was specified.
getThinLTOOldAndNewPrefix(std::string & OldPrefix,std::string & NewPrefix)85306f32e7eSjoerg static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
85406f32e7eSjoerg                                       std::string &NewPrefix) {
85506f32e7eSjoerg   StringRef PrefixReplace = options::thinlto_prefix_replace;
856*da58b97aSjoerg   assert(PrefixReplace.empty() || PrefixReplace.find(';') != StringRef::npos);
857*da58b97aSjoerg   auto Split = PrefixReplace.split(';');
858*da58b97aSjoerg   OldPrefix = std::string(Split.first);
859*da58b97aSjoerg   NewPrefix = std::string(Split.second);
86006f32e7eSjoerg }
86106f32e7eSjoerg 
86206f32e7eSjoerg /// Creates instance of LTO.
86306f32e7eSjoerg /// OnIndexWrite is callback to let caller know when LTO writes index files.
86406f32e7eSjoerg /// LinkedObjectsFile is an output stream to write the list of object files for
86506f32e7eSjoerg /// the final ThinLTO linking. Can be nullptr.
createLTO(IndexWriteCallback OnIndexWrite,raw_fd_ostream * LinkedObjectsFile)86606f32e7eSjoerg static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
86706f32e7eSjoerg                                       raw_fd_ostream *LinkedObjectsFile) {
86806f32e7eSjoerg   Config Conf;
86906f32e7eSjoerg   ThinBackend Backend;
87006f32e7eSjoerg 
87106f32e7eSjoerg   Conf.CPU = options::mcpu;
872*da58b97aSjoerg   Conf.Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
87306f32e7eSjoerg 
87406f32e7eSjoerg   // Disable the new X86 relax relocations since gold might not support them.
87506f32e7eSjoerg   // FIXME: Check the gold version or add a new option to enable them.
87606f32e7eSjoerg   Conf.Options.RelaxELFRelocations = false;
87706f32e7eSjoerg 
87806f32e7eSjoerg   // Toggle function/data sections.
879*da58b97aSjoerg   if (!codegen::getExplicitFunctionSections())
88006f32e7eSjoerg     Conf.Options.FunctionSections = SplitSections;
881*da58b97aSjoerg   if (!codegen::getExplicitDataSections())
88206f32e7eSjoerg     Conf.Options.DataSections = SplitSections;
88306f32e7eSjoerg 
884*da58b97aSjoerg   Conf.MAttrs = codegen::getMAttrs();
88506f32e7eSjoerg   Conf.RelocModel = RelocationModel;
886*da58b97aSjoerg   Conf.CodeModel = codegen::getExplicitCodeModel();
88706f32e7eSjoerg   Conf.CGOptLevel = getCGOptLevel();
88806f32e7eSjoerg   Conf.DisableVerify = options::DisableVerify;
88906f32e7eSjoerg   Conf.OptLevel = options::OptLevel;
890*da58b97aSjoerg   Conf.PTO.LoopVectorization = options::OptLevel > 1;
891*da58b97aSjoerg   Conf.PTO.SLPVectorization = options::OptLevel > 1;
892*da58b97aSjoerg   Conf.AlwaysEmitRegularLTOObj = !options::obj_path.empty();
893*da58b97aSjoerg 
89406f32e7eSjoerg   if (options::thinlto_index_only) {
89506f32e7eSjoerg     std::string OldPrefix, NewPrefix;
89606f32e7eSjoerg     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
89706f32e7eSjoerg     Backend = createWriteIndexesThinBackend(OldPrefix, NewPrefix,
89806f32e7eSjoerg                                             options::thinlto_emit_imports_files,
89906f32e7eSjoerg                                             LinkedObjectsFile, OnIndexWrite);
900*da58b97aSjoerg   } else {
901*da58b97aSjoerg     Backend = createInProcessThinBackend(
902*da58b97aSjoerg         llvm::heavyweight_hardware_concurrency(options::Parallelism));
90306f32e7eSjoerg   }
90406f32e7eSjoerg 
90506f32e7eSjoerg   Conf.OverrideTriple = options::triple;
90606f32e7eSjoerg   Conf.DefaultTriple = sys::getDefaultTargetTriple();
90706f32e7eSjoerg 
90806f32e7eSjoerg   Conf.DiagHandler = diagnosticHandler;
90906f32e7eSjoerg 
91006f32e7eSjoerg   switch (options::TheOutputType) {
91106f32e7eSjoerg   case options::OT_NORMAL:
91206f32e7eSjoerg     break;
91306f32e7eSjoerg 
91406f32e7eSjoerg   case options::OT_DISABLE:
91506f32e7eSjoerg     Conf.PreOptModuleHook = [](size_t Task, const Module &M) { return false; };
91606f32e7eSjoerg     break;
91706f32e7eSjoerg 
91806f32e7eSjoerg   case options::OT_BC_ONLY:
91906f32e7eSjoerg     Conf.PostInternalizeModuleHook = [](size_t Task, const Module &M) {
92006f32e7eSjoerg       std::error_code EC;
921*da58b97aSjoerg       SmallString<128> TaskFilename;
922*da58b97aSjoerg       getOutputFileName(output_name, /* TempOutFile */ false, TaskFilename,
923*da58b97aSjoerg                         Task);
924*da58b97aSjoerg       raw_fd_ostream OS(TaskFilename, EC, sys::fs::OpenFlags::OF_None);
92506f32e7eSjoerg       if (EC)
92606f32e7eSjoerg         message(LDPL_FATAL, "Failed to write the output file.");
92706f32e7eSjoerg       WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ false);
92806f32e7eSjoerg       return false;
92906f32e7eSjoerg     };
93006f32e7eSjoerg     break;
93106f32e7eSjoerg 
93206f32e7eSjoerg   case options::OT_SAVE_TEMPS:
93306f32e7eSjoerg     check(Conf.addSaveTemps(output_name + ".",
93406f32e7eSjoerg                             /* UseInputModulePath */ true));
93506f32e7eSjoerg     break;
93606f32e7eSjoerg   case options::OT_ASM_ONLY:
937*da58b97aSjoerg     Conf.CGFileType = CGFT_AssemblyFile;
93806f32e7eSjoerg     break;
93906f32e7eSjoerg   }
94006f32e7eSjoerg 
94106f32e7eSjoerg   if (!options::sample_profile.empty())
94206f32e7eSjoerg     Conf.SampleProfile = options::sample_profile;
94306f32e7eSjoerg 
94406f32e7eSjoerg   if (!options::cs_profile_path.empty())
94506f32e7eSjoerg     Conf.CSIRProfile = options::cs_profile_path;
94606f32e7eSjoerg   Conf.RunCSIRInstr = options::cs_pgo_gen;
94706f32e7eSjoerg 
94806f32e7eSjoerg   Conf.DwoDir = options::dwo_dir;
94906f32e7eSjoerg 
95006f32e7eSjoerg   // Set up optimization remarks handling.
95106f32e7eSjoerg   Conf.RemarksFilename = options::RemarksFilename;
95206f32e7eSjoerg   Conf.RemarksPasses = options::RemarksPasses;
95306f32e7eSjoerg   Conf.RemarksWithHotness = options::RemarksWithHotness;
954*da58b97aSjoerg   Conf.RemarksHotnessThreshold = options::RemarksHotnessThreshold;
95506f32e7eSjoerg   Conf.RemarksFormat = options::RemarksFormat;
95606f32e7eSjoerg 
95706f32e7eSjoerg   // Use new pass manager if set in driver
95806f32e7eSjoerg   Conf.UseNewPM = options::new_pass_manager;
95906f32e7eSjoerg   // Debug new pass manager if requested
96006f32e7eSjoerg   Conf.DebugPassManager = options::debug_pass_manager;
96106f32e7eSjoerg 
962*da58b97aSjoerg   Conf.HasWholeProgramVisibility = options::whole_program_visibility;
963*da58b97aSjoerg 
96406f32e7eSjoerg   Conf.StatsFile = options::stats_file;
96506f32e7eSjoerg   return std::make_unique<LTO>(std::move(Conf), Backend,
96606f32e7eSjoerg                                 options::ParallelCodeGenParallelismLevel);
96706f32e7eSjoerg }
96806f32e7eSjoerg 
96906f32e7eSjoerg // Write empty files that may be expected by a distributed build
97006f32e7eSjoerg // system when invoked with thinlto_index_only. This is invoked when
97106f32e7eSjoerg // the linker has decided not to include the given module in the
97206f32e7eSjoerg // final link. Frequently the distributed build system will want to
97306f32e7eSjoerg // confirm that all expected outputs are created based on all of the
97406f32e7eSjoerg // modules provided to the linker.
97506f32e7eSjoerg // If SkipModule is true then .thinlto.bc should contain just
97606f32e7eSjoerg // SkipModuleByDistributedBackend flag which requests distributed backend
97706f32e7eSjoerg // to skip the compilation of the corresponding module and produce an empty
97806f32e7eSjoerg // object file.
writeEmptyDistributedBuildOutputs(const std::string & ModulePath,const std::string & OldPrefix,const std::string & NewPrefix,bool SkipModule)97906f32e7eSjoerg static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath,
98006f32e7eSjoerg                                               const std::string &OldPrefix,
98106f32e7eSjoerg                                               const std::string &NewPrefix,
98206f32e7eSjoerg                                               bool SkipModule) {
98306f32e7eSjoerg   std::string NewModulePath =
98406f32e7eSjoerg       getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
98506f32e7eSjoerg   std::error_code EC;
98606f32e7eSjoerg   {
98706f32e7eSjoerg     raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
98806f32e7eSjoerg                       sys::fs::OpenFlags::OF_None);
98906f32e7eSjoerg     if (EC)
99006f32e7eSjoerg       message(LDPL_FATAL, "Failed to write '%s': %s",
99106f32e7eSjoerg               (NewModulePath + ".thinlto.bc").c_str(), EC.message().c_str());
99206f32e7eSjoerg 
99306f32e7eSjoerg     if (SkipModule) {
99406f32e7eSjoerg       ModuleSummaryIndex Index(/*HaveGVs*/ false);
99506f32e7eSjoerg       Index.setSkipModuleByDistributedBackend();
99606f32e7eSjoerg       WriteIndexToFile(Index, OS, nullptr);
99706f32e7eSjoerg     }
99806f32e7eSjoerg   }
99906f32e7eSjoerg   if (options::thinlto_emit_imports_files) {
100006f32e7eSjoerg     raw_fd_ostream OS(NewModulePath + ".imports", EC,
100106f32e7eSjoerg                       sys::fs::OpenFlags::OF_None);
100206f32e7eSjoerg     if (EC)
100306f32e7eSjoerg       message(LDPL_FATAL, "Failed to write '%s': %s",
100406f32e7eSjoerg               (NewModulePath + ".imports").c_str(), EC.message().c_str());
100506f32e7eSjoerg   }
100606f32e7eSjoerg }
100706f32e7eSjoerg 
100806f32e7eSjoerg // Creates and returns output stream with a list of object files for final
100906f32e7eSjoerg // linking of distributed ThinLTO.
CreateLinkedObjectsFile()101006f32e7eSjoerg static std::unique_ptr<raw_fd_ostream> CreateLinkedObjectsFile() {
101106f32e7eSjoerg   if (options::thinlto_linked_objects_file.empty())
101206f32e7eSjoerg     return nullptr;
101306f32e7eSjoerg   assert(options::thinlto_index_only);
101406f32e7eSjoerg   std::error_code EC;
101506f32e7eSjoerg   auto LinkedObjectsFile = std::make_unique<raw_fd_ostream>(
101606f32e7eSjoerg       options::thinlto_linked_objects_file, EC, sys::fs::OpenFlags::OF_None);
101706f32e7eSjoerg   if (EC)
101806f32e7eSjoerg     message(LDPL_FATAL, "Failed to create '%s': %s",
101906f32e7eSjoerg             options::thinlto_linked_objects_file.c_str(), EC.message().c_str());
102006f32e7eSjoerg   return LinkedObjectsFile;
102106f32e7eSjoerg }
102206f32e7eSjoerg 
102306f32e7eSjoerg /// Runs LTO and return a list of pairs <FileName, IsTemporary>.
runLTO()102406f32e7eSjoerg static std::vector<std::pair<SmallString<128>, bool>> runLTO() {
102506f32e7eSjoerg   // Map to own RAII objects that manage the file opening and releasing
102606f32e7eSjoerg   // interfaces with gold. This is needed only for ThinLTO mode, since
102706f32e7eSjoerg   // unlike regular LTO, where addModule will result in the opened file
102806f32e7eSjoerg   // being merged into a new combined module, we need to keep these files open
102906f32e7eSjoerg   // through Lto->run().
103006f32e7eSjoerg   DenseMap<void *, std::unique_ptr<PluginInputFile>> HandleToInputFile;
103106f32e7eSjoerg 
103206f32e7eSjoerg   // Owns string objects and tells if index file was already created.
103306f32e7eSjoerg   StringMap<bool> ObjectToIndexFileState;
103406f32e7eSjoerg 
103506f32e7eSjoerg   std::unique_ptr<raw_fd_ostream> LinkedObjects = CreateLinkedObjectsFile();
103606f32e7eSjoerg   std::unique_ptr<LTO> Lto = createLTO(
103706f32e7eSjoerg       [&ObjectToIndexFileState](const std::string &Identifier) {
103806f32e7eSjoerg         ObjectToIndexFileState[Identifier] = true;
103906f32e7eSjoerg       },
104006f32e7eSjoerg       LinkedObjects.get());
104106f32e7eSjoerg 
104206f32e7eSjoerg   std::string OldPrefix, NewPrefix;
104306f32e7eSjoerg   if (options::thinlto_index_only)
104406f32e7eSjoerg     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
104506f32e7eSjoerg 
104606f32e7eSjoerg   std::string OldSuffix, NewSuffix;
104706f32e7eSjoerg   getThinLTOOldAndNewSuffix(OldSuffix, NewSuffix);
104806f32e7eSjoerg 
104906f32e7eSjoerg   for (claimed_file &F : Modules) {
105006f32e7eSjoerg     if (options::thinlto && !HandleToInputFile.count(F.leader_handle))
105106f32e7eSjoerg       HandleToInputFile.insert(std::make_pair(
105206f32e7eSjoerg           F.leader_handle, std::make_unique<PluginInputFile>(F.handle)));
105306f32e7eSjoerg     // In case we are thin linking with a minimized bitcode file, ensure
105406f32e7eSjoerg     // the module paths encoded in the index reflect where the backends
105506f32e7eSjoerg     // will locate the full bitcode files for compiling/importing.
105606f32e7eSjoerg     std::string Identifier =
105706f32e7eSjoerg         getThinLTOObjectFileName(F.name, OldSuffix, NewSuffix);
105806f32e7eSjoerg     auto ObjFilename = ObjectToIndexFileState.insert({Identifier, false});
105906f32e7eSjoerg     assert(ObjFilename.second);
106006f32e7eSjoerg     if (const void *View = getSymbolsAndView(F))
106106f32e7eSjoerg       addModule(*Lto, F, View, ObjFilename.first->first());
106206f32e7eSjoerg     else if (options::thinlto_index_only) {
106306f32e7eSjoerg       ObjFilename.first->second = true;
106406f32e7eSjoerg       writeEmptyDistributedBuildOutputs(Identifier, OldPrefix, NewPrefix,
106506f32e7eSjoerg                                         /* SkipModule */ true);
106606f32e7eSjoerg     }
106706f32e7eSjoerg   }
106806f32e7eSjoerg 
106906f32e7eSjoerg   SmallString<128> Filename;
107006f32e7eSjoerg   // Note that getOutputFileName will append a unique ID for each task
107106f32e7eSjoerg   if (!options::obj_path.empty())
107206f32e7eSjoerg     Filename = options::obj_path;
107306f32e7eSjoerg   else if (options::TheOutputType == options::OT_SAVE_TEMPS)
1074*da58b97aSjoerg     Filename = output_name + ".lto.o";
107506f32e7eSjoerg   else if (options::TheOutputType == options::OT_ASM_ONLY)
107606f32e7eSjoerg     Filename = output_name;
107706f32e7eSjoerg   bool SaveTemps = !Filename.empty();
107806f32e7eSjoerg 
107906f32e7eSjoerg   size_t MaxTasks = Lto->getMaxTasks();
108006f32e7eSjoerg   std::vector<std::pair<SmallString<128>, bool>> Files(MaxTasks);
108106f32e7eSjoerg 
108206f32e7eSjoerg   auto AddStream =
108306f32e7eSjoerg       [&](size_t Task) -> std::unique_ptr<lto::NativeObjectStream> {
108406f32e7eSjoerg     Files[Task].second = !SaveTemps;
108506f32e7eSjoerg     int FD = getOutputFileName(Filename, /* TempOutFile */ !SaveTemps,
108606f32e7eSjoerg                                Files[Task].first, Task);
108706f32e7eSjoerg     return std::make_unique<lto::NativeObjectStream>(
108806f32e7eSjoerg         std::make_unique<llvm::raw_fd_ostream>(FD, true));
108906f32e7eSjoerg   };
109006f32e7eSjoerg 
109106f32e7eSjoerg   auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
109206f32e7eSjoerg     *AddStream(Task)->OS << MB->getBuffer();
109306f32e7eSjoerg   };
109406f32e7eSjoerg 
109506f32e7eSjoerg   NativeObjectCache Cache;
109606f32e7eSjoerg   if (!options::cache_dir.empty())
109706f32e7eSjoerg     Cache = check(localCache(options::cache_dir, AddBuffer));
109806f32e7eSjoerg 
109906f32e7eSjoerg   check(Lto->run(AddStream, Cache));
110006f32e7eSjoerg 
110106f32e7eSjoerg   // Write empty output files that may be expected by the distributed build
110206f32e7eSjoerg   // system.
110306f32e7eSjoerg   if (options::thinlto_index_only)
110406f32e7eSjoerg     for (auto &Identifier : ObjectToIndexFileState)
110506f32e7eSjoerg       if (!Identifier.getValue())
1106*da58b97aSjoerg         writeEmptyDistributedBuildOutputs(std::string(Identifier.getKey()),
1107*da58b97aSjoerg                                           OldPrefix, NewPrefix,
1108*da58b97aSjoerg                                           /* SkipModule */ false);
110906f32e7eSjoerg 
111006f32e7eSjoerg   return Files;
111106f32e7eSjoerg }
111206f32e7eSjoerg 
111306f32e7eSjoerg /// gold informs us that all symbols have been read. At this point, we use
111406f32e7eSjoerg /// get_symbols to see if any of our definitions have been overridden by a
111506f32e7eSjoerg /// native object file. Then, perform optimization and codegen.
allSymbolsReadHook()111606f32e7eSjoerg static ld_plugin_status allSymbolsReadHook() {
111706f32e7eSjoerg   if (Modules.empty())
111806f32e7eSjoerg     return LDPS_OK;
111906f32e7eSjoerg 
112006f32e7eSjoerg   if (unsigned NumOpts = options::extra.size())
112106f32e7eSjoerg     cl::ParseCommandLineOptions(NumOpts, &options::extra[0]);
112206f32e7eSjoerg 
112306f32e7eSjoerg   std::vector<std::pair<SmallString<128>, bool>> Files = runLTO();
112406f32e7eSjoerg 
112506f32e7eSjoerg   if (options::TheOutputType == options::OT_DISABLE ||
112606f32e7eSjoerg       options::TheOutputType == options::OT_BC_ONLY ||
112706f32e7eSjoerg       options::TheOutputType == options::OT_ASM_ONLY)
112806f32e7eSjoerg     return LDPS_OK;
112906f32e7eSjoerg 
113006f32e7eSjoerg   if (options::thinlto_index_only) {
113106f32e7eSjoerg     llvm_shutdown();
113206f32e7eSjoerg     cleanup_hook();
113306f32e7eSjoerg     exit(0);
113406f32e7eSjoerg   }
113506f32e7eSjoerg 
113606f32e7eSjoerg   for (const auto &F : Files)
113706f32e7eSjoerg     if (!F.first.empty())
1138*da58b97aSjoerg       recordFile(std::string(F.first.str()), F.second);
113906f32e7eSjoerg 
114006f32e7eSjoerg   if (!options::extra_library_path.empty() &&
114106f32e7eSjoerg       set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK)
114206f32e7eSjoerg     message(LDPL_FATAL, "Unable to set the extra library path.");
114306f32e7eSjoerg 
114406f32e7eSjoerg   return LDPS_OK;
114506f32e7eSjoerg }
114606f32e7eSjoerg 
all_symbols_read_hook(void)114706f32e7eSjoerg static ld_plugin_status all_symbols_read_hook(void) {
114806f32e7eSjoerg   ld_plugin_status Ret = allSymbolsReadHook();
114906f32e7eSjoerg   llvm_shutdown();
115006f32e7eSjoerg 
115106f32e7eSjoerg   if (options::TheOutputType == options::OT_BC_ONLY ||
115206f32e7eSjoerg       options::TheOutputType == options::OT_ASM_ONLY ||
115306f32e7eSjoerg       options::TheOutputType == options::OT_DISABLE) {
115406f32e7eSjoerg     if (options::TheOutputType == options::OT_DISABLE) {
115506f32e7eSjoerg       // Remove the output file here since ld.bfd creates the output file
115606f32e7eSjoerg       // early.
115706f32e7eSjoerg       std::error_code EC = sys::fs::remove(output_name);
115806f32e7eSjoerg       if (EC)
115906f32e7eSjoerg         message(LDPL_ERROR, "Failed to delete '%s': %s", output_name.c_str(),
116006f32e7eSjoerg                 EC.message().c_str());
116106f32e7eSjoerg     }
116206f32e7eSjoerg     exit(0);
116306f32e7eSjoerg   }
116406f32e7eSjoerg 
116506f32e7eSjoerg   return Ret;
116606f32e7eSjoerg }
116706f32e7eSjoerg 
cleanup_hook(void)116806f32e7eSjoerg static ld_plugin_status cleanup_hook(void) {
116906f32e7eSjoerg   for (std::string &Name : Cleanup) {
117006f32e7eSjoerg     std::error_code EC = sys::fs::remove(Name);
117106f32e7eSjoerg     if (EC)
117206f32e7eSjoerg       message(LDPL_ERROR, "Failed to delete '%s': %s", Name.c_str(),
117306f32e7eSjoerg               EC.message().c_str());
117406f32e7eSjoerg   }
117506f32e7eSjoerg 
117606f32e7eSjoerg   // Prune cache
117706f32e7eSjoerg   if (!options::cache_dir.empty()) {
117806f32e7eSjoerg     CachePruningPolicy policy = check(parseCachePruningPolicy(options::cache_policy));
117906f32e7eSjoerg     pruneCache(options::cache_dir, policy);
118006f32e7eSjoerg   }
118106f32e7eSjoerg 
118206f32e7eSjoerg   return LDPS_OK;
118306f32e7eSjoerg }
1184