1//===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is a gold plugin for LLVM. It provides an LLVM implementation of the
10// interface described in http://gcc.gnu.org/wiki/whopr/driver .
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ADT/Statistic.h"
15#include "llvm/Bitcode/BitcodeReader.h"
16#include "llvm/Bitcode/BitcodeWriter.h"
17#include "llvm/CodeGen/CommandFlags.h"
18#include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H
19#include "llvm/Config/llvm-config.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/IR/DiagnosticPrinter.h"
22#include "llvm/LTO/LTO.h"
23#include "llvm/Object/Error.h"
24#include "llvm/Remarks/HotnessThresholdParser.h"
25#include "llvm/Support/CachePruning.h"
26#include "llvm/Support/Caching.h"
27#include "llvm/Support/CommandLine.h"
28#include "llvm/Support/FileSystem.h"
29#include "llvm/Support/ManagedStatic.h"
30#include "llvm/Support/MemoryBuffer.h"
31#include "llvm/Support/Path.h"
32#include "llvm/Support/TargetSelect.h"
33#include "llvm/Support/Threading.h"
34#include "llvm/Support/raw_ostream.h"
35#include "llvm/TargetParser/Host.h"
36#include <list>
37#include <map>
38#include <plugin-api.h>
39#include <string>
40#include <system_error>
41#include <utility>
42#include <vector>
43
44// FIXME: remove this declaration when we stop maintaining Ubuntu Quantal and
45// Precise and Debian Wheezy (binutils 2.23 is required)
46#define LDPO_PIE 3
47
48#define LDPT_GET_SYMBOLS_V3 28
49
50// FIXME: Remove when binutils 2.31 (containing gold 1.16) is the minimum
51// required version.
52#define LDPT_GET_WRAP_SYMBOLS 32
53
54using namespace llvm;
55using namespace lto;
56
57static codegen::RegisterCodeGenFlags CodeGenFlags;
58
59// FIXME: Remove when binutils 2.31 (containing gold 1.16) is the minimum
60// required version.
61typedef enum ld_plugin_status (*ld_plugin_get_wrap_symbols)(
62 uint64_t *num_symbols, const char ***wrap_symbol_list);
63
64static ld_plugin_status discard_message(int level, const char *format, ...) {
65 // Die loudly. Recent versions of Gold pass ld_plugin_message as the first
66 // callback in the transfer vector. This should never be called.
67 abort();
68}
69
70static ld_plugin_release_input_file release_input_file = nullptr;
71static ld_plugin_get_input_file get_input_file = nullptr;
72static ld_plugin_message message = discard_message;
73static ld_plugin_get_wrap_symbols get_wrap_symbols = nullptr;
74
75namespace {
76struct claimed_file {
77 void *handle;
78 void *leader_handle;
79 std::vector<ld_plugin_symbol> syms;
80 off_t filesize;
81 std::string name;
82};
83
84/// RAII wrapper to manage opening and releasing of a ld_plugin_input_file.
85struct PluginInputFile {
86 void *Handle;
87 std::unique_ptr<ld_plugin_input_file> File;
88
89 PluginInputFile(void *Handle) : Handle(Handle) {
90 File = std::make_unique<ld_plugin_input_file>();
91 if (get_input_file(Handle, File.get()) != LDPS_OK)
92 message(LDPL_FATAL, "Failed to get file information");
93 }
94 ~PluginInputFile() {
95 // File would have been reset to nullptr if we moved this object
96 // to a new owner.
97 if (File)
98 if (release_input_file(Handle) != LDPS_OK)
99 message(LDPL_FATAL, "Failed to release file information");
100 }
101
102 ld_plugin_input_file &file() { return *File; }
103
104 PluginInputFile(PluginInputFile &&RHS) = default;
105 PluginInputFile &operator=(PluginInputFile &&RHS) = default;
106};
107
108struct ResolutionInfo {
109 bool CanOmitFromDynSym = true;
110 bool DefaultVisibility = true;
111 bool CanInline = true;
112 bool IsUsedInRegularObj = false;
113};
114
115}
116
117static ld_plugin_add_symbols add_symbols = nullptr;
118static ld_plugin_get_symbols get_symbols = nullptr;
119static ld_plugin_add_input_file add_input_file = nullptr;
120static ld_plugin_set_extra_library_path set_extra_library_path = nullptr;
121static ld_plugin_get_view get_view = nullptr;
122static bool IsExecutable = false;
123static bool SplitSections = true;
124static std::optional<Reloc::Model> RelocationModel;
125static std::string output_name = "";
126static std::list<claimed_file> Modules;
127static DenseMap<int, void *> FDToLeaderHandle;
128static StringMap<ResolutionInfo> ResInfo;
129static std::vector<std::string> Cleanup;
130
131namespace options {
132 enum OutputType {
133 OT_NORMAL,
134 OT_DISABLE,
135 OT_BC_ONLY,
136 OT_ASM_ONLY,
137 OT_SAVE_TEMPS
138 };
139 static OutputType TheOutputType = OT_NORMAL;
140 static unsigned OptLevel = 2;
141 // Currently only affects ThinLTO, where the default is the max cores in the
142 // system. See llvm::get_threadpool_strategy() for acceptable values.
143 static std::string Parallelism;
144 // Default regular LTO codegen parallelism (number of partitions).
145 static unsigned ParallelCodeGenParallelismLevel = 1;
146#ifdef NDEBUG
147 static bool DisableVerify = true;
148#else
149 static bool DisableVerify = false;
150#endif
151 static std::string obj_path;
152 static std::string extra_library_path;
153 static std::string triple;
154 static std::string mcpu;
155 // When the thinlto plugin option is specified, only read the function
156 // the information from intermediate files and write a combined
157 // global index for the ThinLTO backends.
158 static bool thinlto = false;
159 // If false, all ThinLTO backend compilations through code gen are performed
160 // using multiple threads in the gold-plugin, before handing control back to
161 // gold. If true, write individual backend index files which reflect
162 // the import decisions, and exit afterwards. The assumption is
163 // that the build system will launch the backend processes.
164 static bool thinlto_index_only = false;
165 // If non-empty, holds the name of a file in which to write the list of
166 // oject files gold selected for inclusion in the link after symbol
167 // resolution (i.e. they had selected symbols). This will only be non-empty
168 // in the thinlto_index_only case. It is used to identify files, which may
169 // have originally been within archive libraries specified via
170 // --start-lib/--end-lib pairs, that should be included in the final
171 // native link process (since intervening function importing and inlining
172 // may change the symbol resolution detected in the final link and which
173 // files to include out of --start-lib/--end-lib libraries as a result).
174 static std::string thinlto_linked_objects_file;
175 // If true, when generating individual index files for distributed backends,
176 // also generate a "${bitcodefile}.imports" file at the same location for each
177 // bitcode file, listing the files it imports from in plain text. This is to
178 // support distributed build file staging.
179 static bool thinlto_emit_imports_files = false;
180 // Option to control where files for a distributed backend (the individual
181 // index files and optional imports files) are created.
182 // If specified, expects a string of the form "oldprefix:newprefix", and
183 // instead of generating these files in the same directory path as the
184 // corresponding bitcode file, will use a path formed by replacing the
185 // bitcode file's path prefix matching oldprefix with newprefix.
186 static std::string thinlto_prefix_replace;
187 // Option to control the name of modules encoded in the individual index
188 // files for a distributed backend. This enables the use of minimized
189 // bitcode files for the thin link, assuming the name of the full bitcode
190 // file used in the backend differs just in some part of the file suffix.
191 // If specified, expects a string of the form "oldsuffix:newsuffix".
192 static std::string thinlto_object_suffix_replace;
193 // Optional path to a directory for caching ThinLTO objects.
194 static std::string cache_dir;
195 // Optional pruning policy for ThinLTO caches.
196 static std::string cache_policy;
197 // Additional options to pass into the code generator.
198 // Note: This array will contain all plugin options which are not claimed
199 // as plugin exclusive to pass to the code generator.
200 static std::vector<const char *> extra;
201 // Sample profile file path
202 static std::string sample_profile;
203 // Debug new pass manager
204 static bool debug_pass_manager = false;
205 // Directory to store the .dwo files.
206 static std::string dwo_dir;
207 /// Statistics output filename.
208 static std::string stats_file;
209 // Asserts that LTO link has whole program visibility
210 static bool whole_program_visibility = false;
211
212 // Optimization remarks filename, accepted passes and hotness options
213 static std::string RemarksFilename;
214 static std::string RemarksPasses;
215 static bool RemarksWithHotness = false;
216 static std::optional<uint64_t> RemarksHotnessThreshold = 0;
217 static std::string RemarksFormat;
218
219 // Context sensitive PGO options.
220 static std::string cs_profile_path;
221 static bool cs_pgo_gen = false;
222
223 static void process_plugin_option(const char *opt_)
224 {
225 if (opt_ == nullptr)
226 return;
227 llvm::StringRef opt = opt_;
228
229 if (opt.consume_front(Prefix: "mcpu=")) {
230 mcpu = std::string(opt);
231 } else if (opt.consume_front(Prefix: "extra-library-path=")) {
232 extra_library_path = std::string(opt);
233 } else if (opt.consume_front(Prefix: "mtriple=")) {
234 triple = std::string(opt);
235 } else if (opt.consume_front(Prefix: "obj-path=")) {
236 obj_path = std::string(opt);
237 } else if (opt == "emit-llvm") {
238 TheOutputType = OT_BC_ONLY;
239 } else if (opt == "save-temps") {
240 TheOutputType = OT_SAVE_TEMPS;
241 } else if (opt == "disable-output") {
242 TheOutputType = OT_DISABLE;
243 } else if (opt == "emit-asm") {
244 TheOutputType = OT_ASM_ONLY;
245 } else if (opt == "thinlto") {
246 thinlto = true;
247 } else if (opt == "thinlto-index-only") {
248 thinlto_index_only = true;
249 } else if (opt.consume_front(Prefix: "thinlto-index-only=")) {
250 thinlto_index_only = true;
251 thinlto_linked_objects_file = std::string(opt);
252 } else if (opt == "thinlto-emit-imports-files") {
253 thinlto_emit_imports_files = true;
254 } else if (opt.consume_front(Prefix: "thinlto-prefix-replace=")) {
255 thinlto_prefix_replace = std::string(opt);
256 if (thinlto_prefix_replace.find(c: ';') == std::string::npos)
257 message(LDPL_FATAL, "thinlto-prefix-replace expects 'old;new' format");
258 } else if (opt.consume_front(Prefix: "thinlto-object-suffix-replace=")) {
259 thinlto_object_suffix_replace = std::string(opt);
260 if (thinlto_object_suffix_replace.find(c: ';') == std::string::npos)
261 message(LDPL_FATAL,
262 "thinlto-object-suffix-replace expects 'old;new' format");
263 } else if (opt.consume_front(Prefix: "cache-dir=")) {
264 cache_dir = std::string(opt);
265 } else if (opt.consume_front(Prefix: "cache-policy=")) {
266 cache_policy = std::string(opt);
267 } else if (opt.size() == 2 && opt[0] == 'O') {
268 if (opt[1] < '0' || opt[1] > '3')
269 message(LDPL_FATAL, "Optimization level must be between 0 and 3");
270 OptLevel = opt[1] - '0';
271 } else if (opt.consume_front(Prefix: "jobs=")) {
272 Parallelism = std::string(opt);
273 if (!get_threadpool_strategy(Num: opt))
274 message(LDPL_FATAL, "Invalid parallelism level: %s",
275 Parallelism.c_str());
276 } else if (opt.consume_front(Prefix: "lto-partitions=")) {
277 if (opt.getAsInteger(Radix: 10, Result&: ParallelCodeGenParallelismLevel))
278 message(LDPL_FATAL, "Invalid codegen partition level: %s", opt_ + 5);
279 } else if (opt == "disable-verify") {
280 DisableVerify = true;
281 } else if (opt.consume_front(Prefix: "sample-profile=")) {
282 sample_profile = std::string(opt);
283 } else if (opt == "cs-profile-generate") {
284 cs_pgo_gen = true;
285 } else if (opt.consume_front(Prefix: "cs-profile-path=")) {
286 cs_profile_path = std::string(opt);
287 } else if (opt == "new-pass-manager") {
288 // We always use the new pass manager.
289 } else if (opt == "debug-pass-manager") {
290 debug_pass_manager = true;
291 } else if (opt == "whole-program-visibility") {
292 whole_program_visibility = true;
293 } else if (opt.consume_front(Prefix: "dwo_dir=")) {
294 dwo_dir = std::string(opt);
295 } else if (opt.consume_front(Prefix: "opt-remarks-filename=")) {
296 RemarksFilename = std::string(opt);
297 } else if (opt.consume_front(Prefix: "opt-remarks-passes=")) {
298 RemarksPasses = std::string(opt);
299 } else if (opt == "opt-remarks-with-hotness") {
300 RemarksWithHotness = true;
301 } else if (opt.consume_front(Prefix: "opt-remarks-hotness-threshold=")) {
302 auto ResultOrErr = remarks::parseHotnessThresholdOption(Arg: opt);
303 if (!ResultOrErr)
304 message(LDPL_FATAL, "Invalid remarks hotness threshold: %s", opt);
305 else
306 RemarksHotnessThreshold = *ResultOrErr;
307 } else if (opt.consume_front(Prefix: "opt-remarks-format=")) {
308 RemarksFormat = std::string(opt);
309 } else if (opt.consume_front(Prefix: "stats-file=")) {
310 stats_file = std::string(opt);
311 } else {
312 // Save this option to pass to the code generator.
313 // ParseCommandLineOptions() expects argv[0] to be program name. Lazily
314 // add that.
315 if (extra.empty())
316 extra.push_back(x: "LLVMgold");
317
318 extra.push_back(x: opt_);
319 }
320 }
321}
322
323static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
324 int *claimed);
325static ld_plugin_status all_symbols_read_hook(void);
326static ld_plugin_status cleanup_hook(void);
327
328extern "C" ld_plugin_status onload(ld_plugin_tv *tv);
329ld_plugin_status onload(ld_plugin_tv *tv) {
330 InitializeAllTargetInfos();
331 InitializeAllTargets();
332 InitializeAllTargetMCs();
333 InitializeAllAsmParsers();
334 InitializeAllAsmPrinters();
335
336 // We're given a pointer to the first transfer vector. We read through them
337 // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values
338 // contain pointers to functions that we need to call to register our own
339 // hooks. The others are addresses of functions we can use to call into gold
340 // for services.
341
342 bool registeredClaimFile = false;
343 bool RegisteredAllSymbolsRead = false;
344
345 for (; tv->tv_tag != LDPT_NULL; ++tv) {
346 // Cast tv_tag to int to allow values not in "enum ld_plugin_tag", like, for
347 // example, LDPT_GET_SYMBOLS_V3 when building against an older plugin-api.h
348 // header.
349 switch (static_cast<int>(tv->tv_tag)) {
350 case LDPT_OUTPUT_NAME:
351 output_name = tv->tv_u.tv_string;
352 break;
353 case LDPT_LINKER_OUTPUT:
354 switch (tv->tv_u.tv_val) {
355 case LDPO_REL: // .o
356 IsExecutable = false;
357 SplitSections = false;
358 break;
359 case LDPO_DYN: // .so
360 IsExecutable = false;
361 RelocationModel = Reloc::PIC_;
362 break;
363 case LDPO_PIE: // position independent executable
364 IsExecutable = true;
365 RelocationModel = Reloc::PIC_;
366 break;
367 case LDPO_EXEC: // .exe
368 IsExecutable = true;
369 RelocationModel = Reloc::Static;
370 break;
371 default:
372 message(LDPL_ERROR, "Unknown output file type %d", tv->tv_u.tv_val);
373 return LDPS_ERR;
374 }
375 break;
376 case LDPT_OPTION:
377 options::process_plugin_option(opt_: tv->tv_u.tv_string);
378 break;
379 case LDPT_REGISTER_CLAIM_FILE_HOOK: {
380 ld_plugin_register_claim_file callback;
381 callback = tv->tv_u.tv_register_claim_file;
382
383 if (callback(claim_file_hook) != LDPS_OK)
384 return LDPS_ERR;
385
386 registeredClaimFile = true;
387 } break;
388 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: {
389 ld_plugin_register_all_symbols_read callback;
390 callback = tv->tv_u.tv_register_all_symbols_read;
391
392 if (callback(all_symbols_read_hook) != LDPS_OK)
393 return LDPS_ERR;
394
395 RegisteredAllSymbolsRead = true;
396 } break;
397 case LDPT_REGISTER_CLEANUP_HOOK: {
398 ld_plugin_register_cleanup callback;
399 callback = tv->tv_u.tv_register_cleanup;
400
401 if (callback(cleanup_hook) != LDPS_OK)
402 return LDPS_ERR;
403 } break;
404 case LDPT_GET_INPUT_FILE:
405 get_input_file = tv->tv_u.tv_get_input_file;
406 break;
407 case LDPT_RELEASE_INPUT_FILE:
408 release_input_file = tv->tv_u.tv_release_input_file;
409 break;
410 case LDPT_ADD_SYMBOLS:
411 add_symbols = tv->tv_u.tv_add_symbols;
412 break;
413 case LDPT_GET_SYMBOLS_V2:
414 // Do not override get_symbols_v3 with get_symbols_v2.
415 if (!get_symbols)
416 get_symbols = tv->tv_u.tv_get_symbols;
417 break;
418 case LDPT_GET_SYMBOLS_V3:
419 get_symbols = tv->tv_u.tv_get_symbols;
420 break;
421 case LDPT_ADD_INPUT_FILE:
422 add_input_file = tv->tv_u.tv_add_input_file;
423 break;
424 case LDPT_SET_EXTRA_LIBRARY_PATH:
425 set_extra_library_path = tv->tv_u.tv_set_extra_library_path;
426 break;
427 case LDPT_GET_VIEW:
428 get_view = tv->tv_u.tv_get_view;
429 break;
430 case LDPT_MESSAGE:
431 message = tv->tv_u.tv_message;
432 break;
433 case LDPT_GET_WRAP_SYMBOLS:
434 // FIXME: When binutils 2.31 (containing gold 1.16) is the minimum
435 // required version, this should be changed to:
436 // get_wrap_symbols = tv->tv_u.tv_get_wrap_symbols;
437 get_wrap_symbols =
438 (ld_plugin_get_wrap_symbols)tv->tv_u.tv_message;
439 break;
440 default:
441 break;
442 }
443 }
444
445 if (!registeredClaimFile) {
446 message(LDPL_ERROR, "register_claim_file not passed to LLVMgold.");
447 return LDPS_ERR;
448 }
449 if (!add_symbols) {
450 message(LDPL_ERROR, "add_symbols not passed to LLVMgold.");
451 return LDPS_ERR;
452 }
453
454 if (!RegisteredAllSymbolsRead)
455 return LDPS_OK;
456
457 if (!get_input_file) {
458 message(LDPL_ERROR, "get_input_file not passed to LLVMgold.");
459 return LDPS_ERR;
460 }
461 if (!release_input_file) {
462 message(LDPL_ERROR, "release_input_file not passed to LLVMgold.");
463 return LDPS_ERR;
464 }
465
466 return LDPS_OK;
467}
468
469static void diagnosticHandler(const DiagnosticInfo &DI) {
470 std::string ErrStorage;
471 {
472 raw_string_ostream OS(ErrStorage);
473 DiagnosticPrinterRawOStream DP(OS);
474 DI.print(DP);
475 }
476 ld_plugin_level Level;
477 switch (DI.getSeverity()) {
478 case DS_Error:
479 Level = LDPL_FATAL;
480 break;
481 case DS_Warning:
482 Level = LDPL_WARNING;
483 break;
484 case DS_Note:
485 case DS_Remark:
486 Level = LDPL_INFO;
487 break;
488 }
489 message(Level, "LLVM gold plugin: %s", ErrStorage.c_str());
490}
491
492static void check(Error E, std::string Msg = "LLVM gold plugin") {
493 handleAllErrors(E: std::move(E), Handlers: [&](ErrorInfoBase &EIB) -> Error {
494 message(LDPL_FATAL, "%s: %s", Msg.c_str(), EIB.message().c_str());
495 return Error::success();
496 });
497}
498
499template <typename T> static T check(Expected<T> E) {
500 if (E)
501 return std::move(*E);
502 check(E.takeError());
503 return T();
504}
505
506/// Called by gold to see whether this file is one that our plugin can handle.
507/// We'll try to open it and register all the symbols with add_symbol if
508/// possible.
509static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file,
510 int *claimed) {
511 MemoryBufferRef BufferRef;
512 std::unique_ptr<MemoryBuffer> Buffer;
513 if (get_view) {
514 const void *view;
515 if (get_view(file->handle, &view) != LDPS_OK) {
516 message(LDPL_ERROR, "Failed to get a view of %s", file->name);
517 return LDPS_ERR;
518 }
519 BufferRef =
520 MemoryBufferRef(StringRef((const char *)view, file->filesize), "");
521 } else {
522 int64_t offset = 0;
523 // Gold has found what might be IR part-way inside of a file, such as
524 // an .a archive.
525 if (file->offset) {
526 offset = file->offset;
527 }
528 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
529 MemoryBuffer::getOpenFileSlice(FD: sys::fs::convertFDToNativeFile(FD: file->fd),
530 Filename: file->name, MapSize: file->filesize, Offset: offset);
531 if (std::error_code EC = BufferOrErr.getError()) {
532 message(LDPL_ERROR, EC.message().c_str());
533 return LDPS_ERR;
534 }
535 Buffer = std::move(BufferOrErr.get());
536 BufferRef = Buffer->getMemBufferRef();
537 }
538
539 *claimed = 1;
540
541 Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(Object: BufferRef);
542 if (!ObjOrErr) {
543 handleAllErrors(E: ObjOrErr.takeError(), Handlers: [&](const ErrorInfoBase &EI) {
544 std::error_code EC = EI.convertToErrorCode();
545 if (EC == object::object_error::invalid_file_type ||
546 EC == object::object_error::bitcode_section_not_found)
547 *claimed = 0;
548 else
549 message(LDPL_FATAL,
550 "LLVM gold plugin has failed to create LTO module: %s",
551 EI.message().c_str());
552 });
553
554 return *claimed ? LDPS_ERR : LDPS_OK;
555 }
556
557 std::unique_ptr<InputFile> Obj = std::move(*ObjOrErr);
558
559 Modules.emplace_back();
560 claimed_file &cf = Modules.back();
561
562 cf.handle = file->handle;
563 // Keep track of the first handle for each file descriptor, since there are
564 // multiple in the case of an archive. This is used later in the case of
565 // ThinLTO parallel backends to ensure that each file is only opened and
566 // released once.
567 auto LeaderHandle =
568 FDToLeaderHandle.insert(std::make_pair(file->fd, file->handle)).first;
569 cf.leader_handle = LeaderHandle->second;
570 // Save the filesize since for parallel ThinLTO backends we can only
571 // invoke get_input_file once per archive (only for the leader handle).
572 cf.filesize = file->filesize;
573 // In the case of an archive library, all but the first member must have a
574 // non-zero offset, which we can append to the file name to obtain a
575 // unique name.
576 cf.name = file->name;
577 if (file->offset)
578 cf.name += ".llvm." + std::to_string(file->offset) + "." +
579 sys::path::filename(path: Obj->getSourceFileName()).str();
580
581 for (auto &Sym : Obj->symbols()) {
582 cf.syms.push_back(ld_plugin_symbol());
583 ld_plugin_symbol &sym = cf.syms.back();
584 sym.version = nullptr;
585 StringRef Name = Sym.getName();
586 sym.name = strdup(s: Name.str().c_str());
587
588 ResolutionInfo &Res = ResInfo[Name];
589
590 Res.CanOmitFromDynSym &= Sym.canBeOmittedFromSymbolTable();
591
592 sym.visibility = LDPV_DEFAULT;
593 GlobalValue::VisibilityTypes Vis = Sym.getVisibility();
594 if (Vis != GlobalValue::DefaultVisibility)
595 Res.DefaultVisibility = false;
596 switch (Vis) {
597 case GlobalValue::DefaultVisibility:
598 break;
599 case GlobalValue::HiddenVisibility:
600 sym.visibility = LDPV_HIDDEN;
601 break;
602 case GlobalValue::ProtectedVisibility:
603 sym.visibility = LDPV_PROTECTED;
604 break;
605 }
606
607 if (Sym.isUndefined()) {
608 sym.def = LDPK_UNDEF;
609 if (Sym.isWeak())
610 sym.def = LDPK_WEAKUNDEF;
611 } else if (Sym.isCommon())
612 sym.def = LDPK_COMMON;
613 else if (Sym.isWeak())
614 sym.def = LDPK_WEAKDEF;
615 else
616 sym.def = LDPK_DEF;
617
618 sym.size = 0;
619 sym.comdat_key = nullptr;
620 int CI = Sym.getComdatIndex();
621 if (CI != -1) {
622 // Not setting comdat_key for nodeduplicate ensuress we don't deduplicate.
623 std::pair<StringRef, Comdat::SelectionKind> C = Obj->getComdatTable()[CI];
624 if (C.second != Comdat::NoDeduplicate)
625 sym.comdat_key = strdup(s: C.first.str().c_str());
626 }
627
628 sym.resolution = LDPR_UNKNOWN;
629 }
630
631 if (!cf.syms.empty()) {
632 if (add_symbols(cf.handle, cf.syms.size(), cf.syms.data()) != LDPS_OK) {
633 message(LDPL_ERROR, "Unable to add symbols!");
634 return LDPS_ERR;
635 }
636 }
637
638 // Handle any --wrap options passed to gold, which are than passed
639 // along to the plugin.
640 if (get_wrap_symbols) {
641 const char **wrap_symbols;
642 uint64_t count = 0;
643 if (get_wrap_symbols(&count, &wrap_symbols) != LDPS_OK) {
644 message(LDPL_ERROR, "Unable to get wrap symbols!");
645 return LDPS_ERR;
646 }
647 for (uint64_t i = 0; i < count; i++) {
648 StringRef Name = wrap_symbols[i];
649 ResolutionInfo &Res = ResInfo[Name];
650 ResolutionInfo &WrapRes = ResInfo["__wrap_" + Name.str()];
651 ResolutionInfo &RealRes = ResInfo["__real_" + Name.str()];
652 // Tell LTO not to inline symbols that will be overwritten.
653 Res.CanInline = false;
654 RealRes.CanInline = false;
655 // Tell LTO not to eliminate symbols that will be used after renaming.
656 Res.IsUsedInRegularObj = true;
657 WrapRes.IsUsedInRegularObj = true;
658 }
659 }
660
661 return LDPS_OK;
662}
663
664static void freeSymName(ld_plugin_symbol &Sym) {
665 free(Sym.name);
666 free(Sym.comdat_key);
667 Sym.name = nullptr;
668 Sym.comdat_key = nullptr;
669}
670
671/// Helper to get a file's symbols and a view into it via gold callbacks.
672static const void *getSymbolsAndView(claimed_file &F) {
673 ld_plugin_status status = get_symbols(F.handle, F.syms.size(), F.syms.data());
674 if (status == LDPS_NO_SYMS)
675 return nullptr;
676
677 if (status != LDPS_OK)
678 message(LDPL_FATAL, "Failed to get symbol information");
679
680 const void *View;
681 if (get_view(F.handle, &View) != LDPS_OK)
682 message(LDPL_FATAL, "Failed to get a view of file");
683
684 return View;
685}
686
687/// Parse the thinlto-object-suffix-replace option into the \p OldSuffix and
688/// \p NewSuffix strings, if it was specified.
689static void getThinLTOOldAndNewSuffix(std::string &OldSuffix,
690 std::string &NewSuffix) {
691 assert(options::thinlto_object_suffix_replace.empty() ||
692 options::thinlto_object_suffix_replace.find(';') != StringRef::npos);
693 StringRef SuffixReplace = options::thinlto_object_suffix_replace;
694 auto Split = SuffixReplace.split(Separator: ';');
695 OldSuffix = std::string(Split.first);
696 NewSuffix = std::string(Split.second);
697}
698
699/// Given the original \p Path to an output file, replace any filename
700/// suffix matching \p OldSuffix with \p NewSuffix.
701static std::string getThinLTOObjectFileName(StringRef Path, StringRef OldSuffix,
702 StringRef NewSuffix) {
703 if (Path.consume_back(Suffix: OldSuffix))
704 return (Path + NewSuffix).str();
705 return std::string(Path);
706}
707
708// Returns true if S is valid as a C language identifier.
709static bool isValidCIdentifier(StringRef S) {
710 return !S.empty() && (isAlpha(C: S[0]) || S[0] == '_') &&
711 llvm::all_of(Range: llvm::drop_begin(RangeOrContainer&: S),
712 P: [](char C) { return C == '_' || isAlnum(C); });
713}
714
715static bool isUndefined(ld_plugin_symbol &Sym) {
716 return Sym.def == LDPK_UNDEF || Sym.def == LDPK_WEAKUNDEF;
717}
718
719static void addModule(LTO &Lto, claimed_file &F, const void *View,
720 StringRef Filename) {
721 MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize),
722 Filename);
723 Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(Object: BufferRef);
724
725 if (!ObjOrErr)
726 message(LDPL_FATAL, "Could not read bitcode from file : %s",
727 toString(ObjOrErr.takeError()).c_str());
728
729 unsigned SymNum = 0;
730 std::unique_ptr<InputFile> Input = std::move(ObjOrErr.get());
731 auto InputFileSyms = Input->symbols();
732 assert(InputFileSyms.size() == F.syms.size());
733 std::vector<SymbolResolution> Resols(F.syms.size());
734 for (ld_plugin_symbol &Sym : F.syms) {
735 const InputFile::Symbol &InpSym = InputFileSyms[SymNum];
736 SymbolResolution &R = Resols[SymNum++];
737
738 ld_plugin_symbol_resolution Resolution =
739 (ld_plugin_symbol_resolution)Sym.resolution;
740
741 ResolutionInfo &Res = ResInfo[Sym.name];
742
743 switch (Resolution) {
744 case LDPR_UNKNOWN:
745 llvm_unreachable("Unexpected resolution");
746
747 case LDPR_RESOLVED_IR:
748 case LDPR_RESOLVED_EXEC:
749 case LDPR_PREEMPTED_IR:
750 case LDPR_PREEMPTED_REG:
751 case LDPR_UNDEF:
752 break;
753
754 case LDPR_RESOLVED_DYN:
755 R.ExportDynamic = true;
756 break;
757
758 case LDPR_PREVAILING_DEF_IRONLY:
759 R.Prevailing = !isUndefined(Sym);
760 break;
761
762 case LDPR_PREVAILING_DEF:
763 R.Prevailing = !isUndefined(Sym);
764 R.VisibleToRegularObj = true;
765 break;
766
767 case LDPR_PREVAILING_DEF_IRONLY_EXP:
768 R.Prevailing = !isUndefined(Sym);
769 // Identify symbols exported dynamically, and that therefore could be
770 // referenced by a shared library not visible to the linker.
771 R.ExportDynamic = true;
772 if (!Res.CanOmitFromDynSym)
773 R.VisibleToRegularObj = true;
774 break;
775 }
776
777 // If the symbol has a C identifier section name, we need to mark
778 // it as visible to a regular object so that LTO will keep it around
779 // to ensure the linker generates special __start_<secname> and
780 // __stop_<secname> symbols which may be used elsewhere.
781 if (isValidCIdentifier(InpSym.getSectionName()))
782 R.VisibleToRegularObj = true;
783
784 if (Resolution != LDPR_RESOLVED_DYN && Resolution != LDPR_UNDEF &&
785 (IsExecutable || !Res.DefaultVisibility))
786 R.FinalDefinitionInLinkageUnit = true;
787
788 if (!Res.CanInline)
789 R.LinkerRedefined = true;
790
791 if (Res.IsUsedInRegularObj)
792 R.VisibleToRegularObj = true;
793
794 freeSymName(Sym);
795 }
796
797 check(E: Lto.add(Obj: std::move(Input), Res: Resols),
798 Msg: std::string("Failed to link module ") + F.name);
799}
800
801static void recordFile(const std::string &Filename, bool TempOutFile) {
802 if (add_input_file(Filename.c_str()) != LDPS_OK)
803 message(LDPL_FATAL,
804 "Unable to add .o file to the link. File left behind in: %s",
805 Filename.c_str());
806 if (TempOutFile)
807 Cleanup.push_back(x: Filename);
808}
809
810/// Return the desired output filename given a base input name, a flag
811/// indicating whether a temp file should be generated, and an optional task id.
812/// The new filename generated is returned in \p NewFilename.
813static int getOutputFileName(StringRef InFilename, bool TempOutFile,
814 SmallString<128> &NewFilename, int TaskID) {
815 int FD = -1;
816 if (TempOutFile) {
817 std::error_code EC =
818 sys::fs::createTemporaryFile(Prefix: "lto-llvm", Suffix: "o", ResultFD&: FD, ResultPath&: NewFilename);
819 if (EC)
820 message(LDPL_FATAL, "Could not create temporary file: %s",
821 EC.message().c_str());
822 } else {
823 NewFilename = InFilename;
824 if (TaskID > 0)
825 NewFilename += utostr(X: TaskID);
826 std::error_code EC =
827 sys::fs::openFileForWrite(Name: NewFilename, ResultFD&: FD, Disp: sys::fs::CD_CreateAlways);
828 if (EC)
829 message(LDPL_FATAL, "Could not open file %s: %s", NewFilename.c_str(),
830 EC.message().c_str());
831 }
832 return FD;
833}
834
835/// Parse the thinlto_prefix_replace option into the \p OldPrefix and
836/// \p NewPrefix strings, if it was specified.
837static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
838 std::string &NewPrefix) {
839 StringRef PrefixReplace = options::thinlto_prefix_replace;
840 assert(PrefixReplace.empty() || PrefixReplace.find(';') != StringRef::npos);
841 auto Split = PrefixReplace.split(Separator: ';');
842 OldPrefix = std::string(Split.first);
843 NewPrefix = std::string(Split.second);
844}
845
846/// Creates instance of LTO.
847/// OnIndexWrite is callback to let caller know when LTO writes index files.
848/// LinkedObjectsFile is an output stream to write the list of object files for
849/// the final ThinLTO linking. Can be nullptr.
850static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
851 raw_fd_ostream *LinkedObjectsFile) {
852 Config Conf;
853 ThinBackend Backend;
854
855 Conf.CPU = options::mcpu;
856 Conf.Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple: Triple());
857
858 // Disable the new X86 relax relocations since gold might not support them.
859 // FIXME: Check the gold version or add a new option to enable them.
860 Conf.Options.MCOptions.X86RelaxRelocations = false;
861
862 // Toggle function/data sections.
863 if (!codegen::getExplicitFunctionSections())
864 Conf.Options.FunctionSections = SplitSections;
865 if (!codegen::getExplicitDataSections())
866 Conf.Options.DataSections = SplitSections;
867
868 Conf.MAttrs = codegen::getMAttrs();
869 Conf.RelocModel = RelocationModel;
870 Conf.CodeModel = codegen::getExplicitCodeModel();
871 std::optional<CodeGenOptLevel> CGOptLevelOrNone =
872 CodeGenOpt::getLevel(OL: options::OptLevel);
873 assert(CGOptLevelOrNone && "Invalid optimization level");
874 Conf.CGOptLevel = *CGOptLevelOrNone;
875 Conf.DisableVerify = options::DisableVerify;
876 Conf.OptLevel = options::OptLevel;
877 Conf.PTO.LoopVectorization = options::OptLevel > 1;
878 Conf.PTO.SLPVectorization = options::OptLevel > 1;
879 Conf.AlwaysEmitRegularLTOObj = !options::obj_path.empty();
880
881 if (options::thinlto_index_only) {
882 std::string OldPrefix, NewPrefix;
883 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
884 Backend = createWriteIndexesThinBackend(
885 OldPrefix, NewPrefix,
886 // TODO: Add support for optional native object path in
887 // thinlto_prefix_replace option to match lld.
888 /*NativeObjectPrefix=*/"", ShouldEmitImportsFiles: options::thinlto_emit_imports_files,
889 LinkedObjectsFile, OnWrite: OnIndexWrite);
890 } else {
891 Backend = createInProcessThinBackend(
892 Parallelism: llvm::heavyweight_hardware_concurrency(Num: options::Parallelism));
893 }
894
895 Conf.OverrideTriple = options::triple;
896 Conf.DefaultTriple = sys::getDefaultTargetTriple();
897
898 Conf.DiagHandler = diagnosticHandler;
899
900 switch (options::TheOutputType) {
901 case options::OT_NORMAL:
902 break;
903
904 case options::OT_DISABLE:
905 Conf.PreOptModuleHook = [](size_t Task, const Module &M) { return false; };
906 break;
907
908 case options::OT_BC_ONLY:
909 Conf.PostInternalizeModuleHook = [](size_t Task, const Module &M) {
910 std::error_code EC;
911 SmallString<128> TaskFilename;
912 getOutputFileName(InFilename: output_name, /* TempOutFile */ false, NewFilename&: TaskFilename,
913 TaskID: Task);
914 raw_fd_ostream OS(TaskFilename, EC, sys::fs::OpenFlags::OF_None);
915 if (EC)
916 message(LDPL_FATAL, "Failed to write the output file.");
917 WriteBitcodeToFile(M, Out&: OS, /* ShouldPreserveUseListOrder */ false);
918 return false;
919 };
920 break;
921
922 case options::OT_SAVE_TEMPS:
923 check(E: Conf.addSaveTemps(OutputFileName: output_name + ".",
924 /* UseInputModulePath */ true));
925 break;
926 case options::OT_ASM_ONLY:
927 Conf.CGFileType = CodeGenFileType::AssemblyFile;
928 Conf.Options.MCOptions.AsmVerbose = true;
929 break;
930 }
931
932 if (!options::sample_profile.empty())
933 Conf.SampleProfile = options::sample_profile;
934
935 if (!options::cs_profile_path.empty())
936 Conf.CSIRProfile = options::cs_profile_path;
937 Conf.RunCSIRInstr = options::cs_pgo_gen;
938
939 Conf.DwoDir = options::dwo_dir;
940
941 // Set up optimization remarks handling.
942 Conf.RemarksFilename = options::RemarksFilename;
943 Conf.RemarksPasses = options::RemarksPasses;
944 Conf.RemarksWithHotness = options::RemarksWithHotness;
945 Conf.RemarksHotnessThreshold = options::RemarksHotnessThreshold;
946 Conf.RemarksFormat = options::RemarksFormat;
947
948 // Debug new pass manager if requested
949 Conf.DebugPassManager = options::debug_pass_manager;
950
951 Conf.HasWholeProgramVisibility = options::whole_program_visibility;
952
953 Conf.StatsFile = options::stats_file;
954 return std::make_unique<LTO>(args: std::move(Conf), args&: Backend,
955 args&: options::ParallelCodeGenParallelismLevel);
956}
957
958// Write empty files that may be expected by a distributed build
959// system when invoked with thinlto_index_only. This is invoked when
960// the linker has decided not to include the given module in the
961// final link. Frequently the distributed build system will want to
962// confirm that all expected outputs are created based on all of the
963// modules provided to the linker.
964// If SkipModule is true then .thinlto.bc should contain just
965// SkipModuleByDistributedBackend flag which requests distributed backend
966// to skip the compilation of the corresponding module and produce an empty
967// object file.
968static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath,
969 const std::string &OldPrefix,
970 const std::string &NewPrefix,
971 bool SkipModule) {
972 std::string NewModulePath =
973 getThinLTOOutputFile(Path: ModulePath, OldPrefix, NewPrefix);
974 std::error_code EC;
975 {
976 raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
977 sys::fs::OpenFlags::OF_None);
978 if (EC)
979 message(LDPL_FATAL, "Failed to write '%s': %s",
980 (NewModulePath + ".thinlto.bc").c_str(), EC.message().c_str());
981
982 if (SkipModule) {
983 ModuleSummaryIndex Index(/*HaveGVs*/ false);
984 Index.setSkipModuleByDistributedBackend();
985 writeIndexToFile(Index, Out&: OS, ModuleToSummariesForIndex: nullptr);
986 }
987 }
988 if (options::thinlto_emit_imports_files) {
989 raw_fd_ostream OS(NewModulePath + ".imports", EC,
990 sys::fs::OpenFlags::OF_None);
991 if (EC)
992 message(LDPL_FATAL, "Failed to write '%s': %s",
993 (NewModulePath + ".imports").c_str(), EC.message().c_str());
994 }
995}
996
997// Creates and returns output stream with a list of object files for final
998// linking of distributed ThinLTO.
999static std::unique_ptr<raw_fd_ostream> CreateLinkedObjectsFile() {
1000 if (options::thinlto_linked_objects_file.empty())
1001 return nullptr;
1002 assert(options::thinlto_index_only);
1003 std::error_code EC;
1004 auto LinkedObjectsFile = std::make_unique<raw_fd_ostream>(
1005 args&: options::thinlto_linked_objects_file, args&: EC, args: sys::fs::OpenFlags::OF_None);
1006 if (EC)
1007 message(LDPL_FATAL, "Failed to create '%s': %s",
1008 options::thinlto_linked_objects_file.c_str(), EC.message().c_str());
1009 return LinkedObjectsFile;
1010}
1011
1012/// Runs LTO and return a list of pairs <FileName, IsTemporary>.
1013static std::vector<std::pair<SmallString<128>, bool>> runLTO() {
1014 // Map to own RAII objects that manage the file opening and releasing
1015 // interfaces with gold. This is needed only for ThinLTO mode, since
1016 // unlike regular LTO, where addModule will result in the opened file
1017 // being merged into a new combined module, we need to keep these files open
1018 // through Lto->run().
1019 DenseMap<void *, std::unique_ptr<PluginInputFile>> HandleToInputFile;
1020
1021 // Owns string objects and tells if index file was already created.
1022 StringMap<bool> ObjectToIndexFileState;
1023
1024 std::unique_ptr<raw_fd_ostream> LinkedObjects = CreateLinkedObjectsFile();
1025 std::unique_ptr<LTO> Lto = createLTO(
1026 OnIndexWrite: [&ObjectToIndexFileState](const std::string &Identifier) {
1027 ObjectToIndexFileState[Identifier] = true;
1028 },
1029 LinkedObjectsFile: LinkedObjects.get());
1030
1031 std::string OldPrefix, NewPrefix;
1032 if (options::thinlto_index_only)
1033 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
1034
1035 std::string OldSuffix, NewSuffix;
1036 getThinLTOOldAndNewSuffix(OldSuffix, NewSuffix);
1037
1038 for (claimed_file &F : Modules) {
1039 if (options::thinlto && !HandleToInputFile.count(Val: F.leader_handle))
1040 HandleToInputFile.insert(KV: std::make_pair(
1041 x&: F.leader_handle, y: std::make_unique<PluginInputFile>(args&: F.handle)));
1042 // In case we are thin linking with a minimized bitcode file, ensure
1043 // the module paths encoded in the index reflect where the backends
1044 // will locate the full bitcode files for compiling/importing.
1045 std::string Identifier =
1046 getThinLTOObjectFileName(Path: F.name, OldSuffix, NewSuffix);
1047 auto ObjFilename = ObjectToIndexFileState.insert(KV: {Identifier, false});
1048 assert(ObjFilename.second);
1049 if (const void *View = getSymbolsAndView(F))
1050 addModule(Lto&: *Lto, F, View, Filename: ObjFilename.first->first());
1051 else if (options::thinlto_index_only) {
1052 ObjFilename.first->second = true;
1053 writeEmptyDistributedBuildOutputs(ModulePath: Identifier, OldPrefix, NewPrefix,
1054 /* SkipModule */ true);
1055 }
1056 }
1057
1058 SmallString<128> Filename;
1059 // Note that getOutputFileName will append a unique ID for each task
1060 if (!options::obj_path.empty())
1061 Filename = options::obj_path;
1062 else if (options::TheOutputType == options::OT_SAVE_TEMPS)
1063 Filename = output_name + ".lto.o";
1064 else if (options::TheOutputType == options::OT_ASM_ONLY)
1065 Filename = output_name;
1066 bool SaveTemps = !Filename.empty();
1067
1068 size_t MaxTasks = Lto->getMaxTasks();
1069 std::vector<std::pair<SmallString<128>, bool>> Files(MaxTasks);
1070
1071 auto AddStream =
1072 [&](size_t Task,
1073 const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
1074 Files[Task].second = !SaveTemps;
1075 int FD = getOutputFileName(InFilename: Filename, /* TempOutFile */ !SaveTemps,
1076 NewFilename&: Files[Task].first, TaskID: Task);
1077 return std::make_unique<CachedFileStream>(
1078 args: std::make_unique<llvm::raw_fd_ostream>(args&: FD, args: true));
1079 };
1080
1081 auto AddBuffer = [&](size_t Task, const Twine &moduleName,
1082 std::unique_ptr<MemoryBuffer> MB) {
1083 *AddStream(Task, moduleName)->OS << MB->getBuffer();
1084 };
1085
1086 FileCache Cache;
1087 if (!options::cache_dir.empty())
1088 Cache = check(E: localCache(CacheNameRef: "ThinLTO", TempFilePrefixRef: "Thin", CacheDirectoryPathRef: options::cache_dir, AddBuffer));
1089
1090 check(E: Lto->run(AddStream, Cache));
1091
1092 // Write empty output files that may be expected by the distributed build
1093 // system.
1094 if (options::thinlto_index_only)
1095 for (auto &Identifier : ObjectToIndexFileState)
1096 if (!Identifier.getValue())
1097 writeEmptyDistributedBuildOutputs(ModulePath: std::string(Identifier.getKey()),
1098 OldPrefix, NewPrefix,
1099 /* SkipModule */ false);
1100
1101 return Files;
1102}
1103
1104/// gold informs us that all symbols have been read. At this point, we use
1105/// get_symbols to see if any of our definitions have been overridden by a
1106/// native object file. Then, perform optimization and codegen.
1107static ld_plugin_status allSymbolsReadHook() {
1108 if (Modules.empty())
1109 return LDPS_OK;
1110
1111 if (unsigned NumOpts = options::extra.size())
1112 cl::ParseCommandLineOptions(argc: NumOpts, argv: &options::extra[0]);
1113
1114 std::vector<std::pair<SmallString<128>, bool>> Files = runLTO();
1115
1116 if (options::TheOutputType == options::OT_DISABLE ||
1117 options::TheOutputType == options::OT_BC_ONLY ||
1118 options::TheOutputType == options::OT_ASM_ONLY)
1119 return LDPS_OK;
1120
1121 if (options::thinlto_index_only) {
1122 llvm_shutdown();
1123 cleanup_hook();
1124 exit(status: 0);
1125 }
1126
1127 for (const auto &F : Files)
1128 if (!F.first.empty())
1129 recordFile(Filename: std::string(F.first.str()), TempOutFile: F.second);
1130
1131 if (!options::extra_library_path.empty() &&
1132 set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK)
1133 message(LDPL_FATAL, "Unable to set the extra library path.");
1134
1135 return LDPS_OK;
1136}
1137
1138static ld_plugin_status all_symbols_read_hook(void) {
1139 ld_plugin_status Ret = allSymbolsReadHook();
1140 llvm_shutdown();
1141
1142 if (options::TheOutputType == options::OT_BC_ONLY ||
1143 options::TheOutputType == options::OT_ASM_ONLY ||
1144 options::TheOutputType == options::OT_DISABLE) {
1145 if (options::TheOutputType == options::OT_DISABLE) {
1146 // Remove the output file here since ld.bfd creates the output file
1147 // early.
1148 std::error_code EC = sys::fs::remove(path: output_name);
1149 if (EC)
1150 message(LDPL_ERROR, "Failed to delete '%s': %s", output_name.c_str(),
1151 EC.message().c_str());
1152 }
1153 exit(status: 0);
1154 }
1155
1156 return Ret;
1157}
1158
1159static ld_plugin_status cleanup_hook(void) {
1160 for (std::string &Name : Cleanup) {
1161 std::error_code EC = sys::fs::remove(path: Name);
1162 if (EC)
1163 message(LDPL_ERROR, "Failed to delete '%s': %s", Name.c_str(),
1164 EC.message().c_str());
1165 }
1166
1167 // Prune cache
1168 if (!options::cache_dir.empty()) {
1169 CachePruningPolicy policy = check(E: parseCachePruningPolicy(PolicyStr: options::cache_policy));
1170 pruneCache(Path: options::cache_dir, Policy: policy);
1171 }
1172
1173 return LDPS_OK;
1174}
1175

source code of llvm/tools/gold/gold-plugin.cpp