File: | tools/gold/gold-plugin.cpp |
Warning: | line 934, column 29 Potential leak of memory pointed to by field '_M_head_impl' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- gold-plugin.cpp - Plugin to gold for Link Time Optimization ------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This is a gold plugin for LLVM. It provides an LLVM implementation of the | |||
11 | // interface described in http://gcc.gnu.org/wiki/whopr/driver . | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "llvm/ADT/Statistic.h" | |||
16 | #include "llvm/Bitcode/BitcodeReader.h" | |||
17 | #include "llvm/Bitcode/BitcodeWriter.h" | |||
18 | #include "llvm/CodeGen/CommandFlags.def" | |||
19 | #include "llvm/Config/config.h" // plugin-api.h requires HAVE_STDINT_H | |||
20 | #include "llvm/IR/Constants.h" | |||
21 | #include "llvm/IR/DiagnosticPrinter.h" | |||
22 | #include "llvm/LTO/Caching.h" | |||
23 | #include "llvm/LTO/LTO.h" | |||
24 | #include "llvm/Object/Error.h" | |||
25 | #include "llvm/Support/CachePruning.h" | |||
26 | #include "llvm/Support/CommandLine.h" | |||
27 | #include "llvm/Support/FileSystem.h" | |||
28 | #include "llvm/Support/ManagedStatic.h" | |||
29 | #include "llvm/Support/MemoryBuffer.h" | |||
30 | #include "llvm/Support/Path.h" | |||
31 | #include "llvm/Support/TargetSelect.h" | |||
32 | #include "llvm/Support/raw_ostream.h" | |||
33 | #include <list> | |||
34 | #include <map> | |||
35 | #include <plugin-api.h> | |||
36 | #include <string> | |||
37 | #include <system_error> | |||
38 | #include <utility> | |||
39 | #include <vector> | |||
40 | ||||
41 | // FIXME: remove this declaration when we stop maintaining Ubuntu Quantal and | |||
42 | // Precise and Debian Wheezy (binutils 2.23 is required) | |||
43 | #define LDPO_PIE3 3 | |||
44 | ||||
45 | #define LDPT_GET_SYMBOLS_V328 28 | |||
46 | ||||
47 | using namespace llvm; | |||
48 | using namespace lto; | |||
49 | ||||
50 | static ld_plugin_status discard_message(int level, const char *format, ...) { | |||
51 | // Die loudly. Recent versions of Gold pass ld_plugin_message as the first | |||
52 | // callback in the transfer vector. This should never be called. | |||
53 | abort(); | |||
54 | } | |||
55 | ||||
56 | static ld_plugin_release_input_file release_input_file = nullptr; | |||
57 | static ld_plugin_get_input_file get_input_file = nullptr; | |||
58 | static ld_plugin_message message = discard_message; | |||
59 | ||||
60 | namespace { | |||
61 | struct claimed_file { | |||
62 | void *handle; | |||
63 | void *leader_handle; | |||
64 | std::vector<ld_plugin_symbol> syms; | |||
65 | off_t filesize; | |||
66 | std::string name; | |||
67 | }; | |||
68 | ||||
69 | /// RAII wrapper to manage opening and releasing of a ld_plugin_input_file. | |||
70 | struct PluginInputFile { | |||
71 | void *Handle; | |||
72 | std::unique_ptr<ld_plugin_input_file> File; | |||
73 | ||||
74 | PluginInputFile(void *Handle) : Handle(Handle) { | |||
75 | File = llvm::make_unique<ld_plugin_input_file>(); | |||
76 | if (get_input_file(Handle, File.get()) != LDPS_OK) | |||
77 | message(LDPL_FATAL, "Failed to get file information"); | |||
78 | } | |||
79 | ~PluginInputFile() { | |||
80 | // File would have been reset to nullptr if we moved this object | |||
81 | // to a new owner. | |||
82 | if (File) | |||
83 | if (release_input_file(Handle) != LDPS_OK) | |||
84 | message(LDPL_FATAL, "Failed to release file information"); | |||
85 | } | |||
86 | ||||
87 | ld_plugin_input_file &file() { return *File; } | |||
88 | ||||
89 | PluginInputFile(PluginInputFile &&RHS) = default; | |||
90 | PluginInputFile &operator=(PluginInputFile &&RHS) = default; | |||
91 | }; | |||
92 | ||||
93 | struct ResolutionInfo { | |||
94 | bool CanOmitFromDynSym = true; | |||
95 | bool DefaultVisibility = true; | |||
96 | }; | |||
97 | ||||
98 | } | |||
99 | ||||
100 | static ld_plugin_add_symbols add_symbols = nullptr; | |||
101 | static ld_plugin_get_symbols get_symbols = nullptr; | |||
102 | static ld_plugin_add_input_file add_input_file = nullptr; | |||
103 | static ld_plugin_set_extra_library_path set_extra_library_path = nullptr; | |||
104 | static ld_plugin_get_view get_view = nullptr; | |||
105 | static bool IsExecutable = false; | |||
106 | static Optional<Reloc::Model> RelocationModel = None; | |||
107 | static std::string output_name = ""; | |||
108 | static std::list<claimed_file> Modules; | |||
109 | static DenseMap<int, void *> FDToLeaderHandle; | |||
110 | static StringMap<ResolutionInfo> ResInfo; | |||
111 | static std::vector<std::string> Cleanup; | |||
112 | ||||
113 | namespace options { | |||
114 | enum OutputType { | |||
115 | OT_NORMAL, | |||
116 | OT_DISABLE, | |||
117 | OT_BC_ONLY, | |||
118 | OT_SAVE_TEMPS | |||
119 | }; | |||
120 | static OutputType TheOutputType = OT_NORMAL; | |||
121 | static unsigned OptLevel = 2; | |||
122 | // Default parallelism of 0 used to indicate that user did not specify. | |||
123 | // Actual parallelism default value depends on implementation. | |||
124 | // Currently only affects ThinLTO, where the default is | |||
125 | // llvm::heavyweight_hardware_concurrency. | |||
126 | static unsigned Parallelism = 0; | |||
127 | // Default regular LTO codegen parallelism (number of partitions). | |||
128 | static unsigned ParallelCodeGenParallelismLevel = 1; | |||
129 | #ifdef NDEBUG | |||
130 | static bool DisableVerify = true; | |||
131 | #else | |||
132 | static bool DisableVerify = false; | |||
133 | #endif | |||
134 | static std::string obj_path; | |||
135 | static std::string extra_library_path; | |||
136 | static std::string triple; | |||
137 | static std::string mcpu; | |||
138 | // When the thinlto plugin option is specified, only read the function | |||
139 | // the information from intermediate files and write a combined | |||
140 | // global index for the ThinLTO backends. | |||
141 | static bool thinlto = false; | |||
142 | // If false, all ThinLTO backend compilations through code gen are performed | |||
143 | // using multiple threads in the gold-plugin, before handing control back to | |||
144 | // gold. If true, write individual backend index files which reflect | |||
145 | // the import decisions, and exit afterwards. The assumption is | |||
146 | // that the build system will launch the backend processes. | |||
147 | static bool thinlto_index_only = false; | |||
148 | // If non-empty, holds the name of a file in which to write the list of | |||
149 | // oject files gold selected for inclusion in the link after symbol | |||
150 | // resolution (i.e. they had selected symbols). This will only be non-empty | |||
151 | // in the thinlto_index_only case. It is used to identify files, which may | |||
152 | // have originally been within archive libraries specified via | |||
153 | // --start-lib/--end-lib pairs, that should be included in the final | |||
154 | // native link process (since intervening function importing and inlining | |||
155 | // may change the symbol resolution detected in the final link and which | |||
156 | // files to include out of --start-lib/--end-lib libraries as a result). | |||
157 | static std::string thinlto_linked_objects_file; | |||
158 | // If true, when generating individual index files for distributed backends, | |||
159 | // also generate a "${bitcodefile}.imports" file at the same location for each | |||
160 | // bitcode file, listing the files it imports from in plain text. This is to | |||
161 | // support distributed build file staging. | |||
162 | static bool thinlto_emit_imports_files = false; | |||
163 | // Option to control where files for a distributed backend (the individual | |||
164 | // index files and optional imports files) are created. | |||
165 | // If specified, expects a string of the form "oldprefix:newprefix", and | |||
166 | // instead of generating these files in the same directory path as the | |||
167 | // corresponding bitcode file, will use a path formed by replacing the | |||
168 | // bitcode file's path prefix matching oldprefix with newprefix. | |||
169 | static std::string thinlto_prefix_replace; | |||
170 | // Option to control the name of modules encoded in the individual index | |||
171 | // files for a distributed backend. This enables the use of minimized | |||
172 | // bitcode files for the thin link, assuming the name of the full bitcode | |||
173 | // file used in the backend differs just in some part of the file suffix. | |||
174 | // If specified, expects a string of the form "oldsuffix:newsuffix". | |||
175 | static std::string thinlto_object_suffix_replace; | |||
176 | // Optional path to a directory for caching ThinLTO objects. | |||
177 | static std::string cache_dir; | |||
178 | // Optional pruning policy for ThinLTO caches. | |||
179 | static std::string cache_policy; | |||
180 | // Additional options to pass into the code generator. | |||
181 | // Note: This array will contain all plugin options which are not claimed | |||
182 | // as plugin exclusive to pass to the code generator. | |||
183 | static std::vector<const char *> extra; | |||
184 | // Sample profile file path | |||
185 | static std::string sample_profile; | |||
186 | // New pass manager | |||
187 | static bool new_pass_manager = false; | |||
188 | ||||
189 | static void process_plugin_option(const char *opt_) | |||
190 | { | |||
191 | if (opt_ == nullptr) | |||
192 | return; | |||
193 | llvm::StringRef opt = opt_; | |||
194 | ||||
195 | if (opt.startswith("mcpu=")) { | |||
196 | mcpu = opt.substr(strlen("mcpu=")); | |||
197 | } else if (opt.startswith("extra-library-path=")) { | |||
198 | extra_library_path = opt.substr(strlen("extra_library_path=")); | |||
199 | } else if (opt.startswith("mtriple=")) { | |||
200 | triple = opt.substr(strlen("mtriple=")); | |||
201 | } else if (opt.startswith("obj-path=")) { | |||
202 | obj_path = opt.substr(strlen("obj-path=")); | |||
203 | } else if (opt == "emit-llvm") { | |||
204 | TheOutputType = OT_BC_ONLY; | |||
205 | } else if (opt == "save-temps") { | |||
206 | TheOutputType = OT_SAVE_TEMPS; | |||
207 | } else if (opt == "disable-output") { | |||
208 | TheOutputType = OT_DISABLE; | |||
209 | } else if (opt == "thinlto") { | |||
210 | thinlto = true; | |||
211 | } else if (opt == "thinlto-index-only") { | |||
212 | thinlto_index_only = true; | |||
213 | } else if (opt.startswith("thinlto-index-only=")) { | |||
214 | thinlto_index_only = true; | |||
215 | thinlto_linked_objects_file = opt.substr(strlen("thinlto-index-only=")); | |||
216 | } else if (opt == "thinlto-emit-imports-files") { | |||
217 | thinlto_emit_imports_files = true; | |||
218 | } else if (opt.startswith("thinlto-prefix-replace=")) { | |||
219 | thinlto_prefix_replace = opt.substr(strlen("thinlto-prefix-replace=")); | |||
220 | if (thinlto_prefix_replace.find(';') == std::string::npos) | |||
221 | message(LDPL_FATAL, "thinlto-prefix-replace expects 'old;new' format"); | |||
222 | } else if (opt.startswith("thinlto-object-suffix-replace=")) { | |||
223 | thinlto_object_suffix_replace = | |||
224 | opt.substr(strlen("thinlto-object-suffix-replace=")); | |||
225 | if (thinlto_object_suffix_replace.find(';') == std::string::npos) | |||
226 | message(LDPL_FATAL, | |||
227 | "thinlto-object-suffix-replace expects 'old;new' format"); | |||
228 | } else if (opt.startswith("cache-dir=")) { | |||
229 | cache_dir = opt.substr(strlen("cache-dir=")); | |||
230 | } else if (opt.startswith("cache-policy=")) { | |||
231 | cache_policy = opt.substr(strlen("cache-policy=")); | |||
232 | } else if (opt.size() == 2 && opt[0] == 'O') { | |||
233 | if (opt[1] < '0' || opt[1] > '3') | |||
234 | message(LDPL_FATAL, "Optimization level must be between 0 and 3"); | |||
235 | OptLevel = opt[1] - '0'; | |||
236 | } else if (opt.startswith("jobs=")) { | |||
237 | if (StringRef(opt_ + 5).getAsInteger(10, Parallelism)) | |||
238 | message(LDPL_FATAL, "Invalid parallelism level: %s", opt_ + 5); | |||
239 | } else if (opt.startswith("lto-partitions=")) { | |||
240 | if (opt.substr(strlen("lto-partitions=")) | |||
241 | .getAsInteger(10, ParallelCodeGenParallelismLevel)) | |||
242 | message(LDPL_FATAL, "Invalid codegen partition level: %s", opt_ + 5); | |||
243 | } else if (opt == "disable-verify") { | |||
244 | DisableVerify = true; | |||
245 | } else if (opt.startswith("sample-profile=")) { | |||
246 | sample_profile= opt.substr(strlen("sample-profile=")); | |||
247 | } else if (opt == "new-pass-manager") { | |||
248 | new_pass_manager = true; | |||
249 | } else { | |||
250 | // Save this option to pass to the code generator. | |||
251 | // ParseCommandLineOptions() expects argv[0] to be program name. Lazily | |||
252 | // add that. | |||
253 | if (extra.empty()) | |||
254 | extra.push_back("LLVMgold"); | |||
255 | ||||
256 | extra.push_back(opt_); | |||
257 | } | |||
258 | } | |||
259 | } | |||
260 | ||||
261 | static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, | |||
262 | int *claimed); | |||
263 | static ld_plugin_status all_symbols_read_hook(void); | |||
264 | static ld_plugin_status cleanup_hook(void); | |||
265 | ||||
266 | extern "C" ld_plugin_status onload(ld_plugin_tv *tv); | |||
267 | ld_plugin_status onload(ld_plugin_tv *tv) { | |||
268 | InitializeAllTargetInfos(); | |||
269 | InitializeAllTargets(); | |||
270 | InitializeAllTargetMCs(); | |||
271 | InitializeAllAsmParsers(); | |||
272 | InitializeAllAsmPrinters(); | |||
273 | ||||
274 | // We're given a pointer to the first transfer vector. We read through them | |||
275 | // until we find one where tv_tag == LDPT_NULL. The REGISTER_* tagged values | |||
276 | // contain pointers to functions that we need to call to register our own | |||
277 | // hooks. The others are addresses of functions we can use to call into gold | |||
278 | // for services. | |||
279 | ||||
280 | bool registeredClaimFile = false; | |||
281 | bool RegisteredAllSymbolsRead = false; | |||
282 | ||||
283 | for (; tv->tv_tag != LDPT_NULL; ++tv) { | |||
284 | // Cast tv_tag to int to allow values not in "enum ld_plugin_tag", like, for | |||
285 | // example, LDPT_GET_SYMBOLS_V3 when building against an older plugin-api.h | |||
286 | // header. | |||
287 | switch (static_cast<int>(tv->tv_tag)) { | |||
288 | case LDPT_OUTPUT_NAME: | |||
289 | output_name = tv->tv_u.tv_string; | |||
290 | break; | |||
291 | case LDPT_LINKER_OUTPUT: | |||
292 | switch (tv->tv_u.tv_val) { | |||
293 | case LDPO_REL: // .o | |||
294 | IsExecutable = false; | |||
295 | break; | |||
296 | case LDPO_DYN: // .so | |||
297 | IsExecutable = false; | |||
298 | RelocationModel = Reloc::PIC_; | |||
299 | break; | |||
300 | case LDPO_PIE3: // position independent executable | |||
301 | IsExecutable = true; | |||
302 | RelocationModel = Reloc::PIC_; | |||
303 | break; | |||
304 | case LDPO_EXEC: // .exe | |||
305 | IsExecutable = true; | |||
306 | RelocationModel = Reloc::Static; | |||
307 | break; | |||
308 | default: | |||
309 | message(LDPL_ERROR, "Unknown output file type %d", tv->tv_u.tv_val); | |||
310 | return LDPS_ERR; | |||
311 | } | |||
312 | break; | |||
313 | case LDPT_OPTION: | |||
314 | options::process_plugin_option(tv->tv_u.tv_string); | |||
315 | break; | |||
316 | case LDPT_REGISTER_CLAIM_FILE_HOOK: { | |||
317 | ld_plugin_register_claim_file callback; | |||
318 | callback = tv->tv_u.tv_register_claim_file; | |||
319 | ||||
320 | if (callback(claim_file_hook) != LDPS_OK) | |||
321 | return LDPS_ERR; | |||
322 | ||||
323 | registeredClaimFile = true; | |||
324 | } break; | |||
325 | case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: { | |||
326 | ld_plugin_register_all_symbols_read callback; | |||
327 | callback = tv->tv_u.tv_register_all_symbols_read; | |||
328 | ||||
329 | if (callback(all_symbols_read_hook) != LDPS_OK) | |||
330 | return LDPS_ERR; | |||
331 | ||||
332 | RegisteredAllSymbolsRead = true; | |||
333 | } break; | |||
334 | case LDPT_REGISTER_CLEANUP_HOOK: { | |||
335 | ld_plugin_register_cleanup callback; | |||
336 | callback = tv->tv_u.tv_register_cleanup; | |||
337 | ||||
338 | if (callback(cleanup_hook) != LDPS_OK) | |||
339 | return LDPS_ERR; | |||
340 | } break; | |||
341 | case LDPT_GET_INPUT_FILE: | |||
342 | get_input_file = tv->tv_u.tv_get_input_file; | |||
343 | break; | |||
344 | case LDPT_RELEASE_INPUT_FILE: | |||
345 | release_input_file = tv->tv_u.tv_release_input_file; | |||
346 | break; | |||
347 | case LDPT_ADD_SYMBOLS: | |||
348 | add_symbols = tv->tv_u.tv_add_symbols; | |||
349 | break; | |||
350 | case LDPT_GET_SYMBOLS_V2: | |||
351 | // Do not override get_symbols_v3 with get_symbols_v2. | |||
352 | if (!get_symbols) | |||
353 | get_symbols = tv->tv_u.tv_get_symbols; | |||
354 | break; | |||
355 | case LDPT_GET_SYMBOLS_V328: | |||
356 | get_symbols = tv->tv_u.tv_get_symbols; | |||
357 | break; | |||
358 | case LDPT_ADD_INPUT_FILE: | |||
359 | add_input_file = tv->tv_u.tv_add_input_file; | |||
360 | break; | |||
361 | case LDPT_SET_EXTRA_LIBRARY_PATH: | |||
362 | set_extra_library_path = tv->tv_u.tv_set_extra_library_path; | |||
363 | break; | |||
364 | case LDPT_GET_VIEW: | |||
365 | get_view = tv->tv_u.tv_get_view; | |||
366 | break; | |||
367 | case LDPT_MESSAGE: | |||
368 | message = tv->tv_u.tv_message; | |||
369 | break; | |||
370 | default: | |||
371 | break; | |||
372 | } | |||
373 | } | |||
374 | ||||
375 | if (!registeredClaimFile) { | |||
376 | message(LDPL_ERROR, "register_claim_file not passed to LLVMgold."); | |||
377 | return LDPS_ERR; | |||
378 | } | |||
379 | if (!add_symbols) { | |||
380 | message(LDPL_ERROR, "add_symbols not passed to LLVMgold."); | |||
381 | return LDPS_ERR; | |||
382 | } | |||
383 | ||||
384 | if (!RegisteredAllSymbolsRead) | |||
385 | return LDPS_OK; | |||
386 | ||||
387 | if (!get_input_file) { | |||
388 | message(LDPL_ERROR, "get_input_file not passed to LLVMgold."); | |||
389 | return LDPS_ERR; | |||
390 | } | |||
391 | if (!release_input_file) { | |||
392 | message(LDPL_ERROR, "release_input_file not passed to LLVMgold."); | |||
393 | return LDPS_ERR; | |||
394 | } | |||
395 | ||||
396 | return LDPS_OK; | |||
397 | } | |||
398 | ||||
399 | static void diagnosticHandler(const DiagnosticInfo &DI) { | |||
400 | std::string ErrStorage; | |||
401 | { | |||
402 | raw_string_ostream OS(ErrStorage); | |||
403 | DiagnosticPrinterRawOStream DP(OS); | |||
404 | DI.print(DP); | |||
405 | } | |||
406 | ld_plugin_level Level; | |||
407 | switch (DI.getSeverity()) { | |||
408 | case DS_Error: | |||
409 | message(LDPL_FATAL, "LLVM gold plugin has failed to create LTO module: %s", | |||
410 | ErrStorage.c_str()); | |||
411 | case DS_Warning: | |||
412 | Level = LDPL_WARNING; | |||
413 | break; | |||
414 | case DS_Note: | |||
415 | case DS_Remark: | |||
416 | Level = LDPL_INFO; | |||
417 | break; | |||
418 | } | |||
419 | message(Level, "LLVM gold plugin: %s", ErrStorage.c_str()); | |||
420 | } | |||
421 | ||||
422 | static void check(Error E, std::string Msg = "LLVM gold plugin") { | |||
423 | handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) -> Error { | |||
424 | message(LDPL_FATAL, "%s: %s", Msg.c_str(), EIB.message().c_str()); | |||
425 | return Error::success(); | |||
426 | }); | |||
427 | } | |||
428 | ||||
429 | template <typename T> static T check(Expected<T> E) { | |||
430 | if (E) | |||
431 | return std::move(*E); | |||
432 | check(E.takeError()); | |||
433 | return T(); | |||
434 | } | |||
435 | ||||
436 | /// Called by gold to see whether this file is one that our plugin can handle. | |||
437 | /// We'll try to open it and register all the symbols with add_symbol if | |||
438 | /// possible. | |||
439 | static ld_plugin_status claim_file_hook(const ld_plugin_input_file *file, | |||
440 | int *claimed) { | |||
441 | MemoryBufferRef BufferRef; | |||
442 | std::unique_ptr<MemoryBuffer> Buffer; | |||
443 | if (get_view) { | |||
444 | const void *view; | |||
445 | if (get_view(file->handle, &view) != LDPS_OK) { | |||
446 | message(LDPL_ERROR, "Failed to get a view of %s", file->name); | |||
447 | return LDPS_ERR; | |||
448 | } | |||
449 | BufferRef = | |||
450 | MemoryBufferRef(StringRef((const char *)view, file->filesize), ""); | |||
451 | } else { | |||
452 | int64_t offset = 0; | |||
453 | // Gold has found what might be IR part-way inside of a file, such as | |||
454 | // an .a archive. | |||
455 | if (file->offset) { | |||
456 | offset = file->offset; | |||
457 | } | |||
458 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = | |||
459 | MemoryBuffer::getOpenFileSlice(file->fd, file->name, file->filesize, | |||
460 | offset); | |||
461 | if (std::error_code EC = BufferOrErr.getError()) { | |||
462 | message(LDPL_ERROR, EC.message().c_str()); | |||
463 | return LDPS_ERR; | |||
464 | } | |||
465 | Buffer = std::move(BufferOrErr.get()); | |||
466 | BufferRef = Buffer->getMemBufferRef(); | |||
467 | } | |||
468 | ||||
469 | *claimed = 1; | |||
470 | ||||
471 | Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef); | |||
472 | if (!ObjOrErr) { | |||
473 | handleAllErrors(ObjOrErr.takeError(), [&](const ErrorInfoBase &EI) { | |||
474 | std::error_code EC = EI.convertToErrorCode(); | |||
475 | if (EC == object::object_error::invalid_file_type || | |||
476 | EC == object::object_error::bitcode_section_not_found) | |||
477 | *claimed = 0; | |||
478 | else | |||
479 | message(LDPL_FATAL, | |||
480 | "LLVM gold plugin has failed to create LTO module: %s", | |||
481 | EI.message().c_str()); | |||
482 | }); | |||
483 | ||||
484 | return *claimed ? LDPS_ERR : LDPS_OK; | |||
485 | } | |||
486 | ||||
487 | std::unique_ptr<InputFile> Obj = std::move(*ObjOrErr); | |||
488 | ||||
489 | Modules.emplace_back(); | |||
490 | claimed_file &cf = Modules.back(); | |||
491 | ||||
492 | cf.handle = file->handle; | |||
493 | // Keep track of the first handle for each file descriptor, since there are | |||
494 | // multiple in the case of an archive. This is used later in the case of | |||
495 | // ThinLTO parallel backends to ensure that each file is only opened and | |||
496 | // released once. | |||
497 | auto LeaderHandle = | |||
498 | FDToLeaderHandle.insert(std::make_pair(file->fd, file->handle)).first; | |||
499 | cf.leader_handle = LeaderHandle->second; | |||
500 | // Save the filesize since for parallel ThinLTO backends we can only | |||
501 | // invoke get_input_file once per archive (only for the leader handle). | |||
502 | cf.filesize = file->filesize; | |||
503 | // In the case of an archive library, all but the first member must have a | |||
504 | // non-zero offset, which we can append to the file name to obtain a | |||
505 | // unique name. | |||
506 | cf.name = file->name; | |||
507 | if (file->offset) | |||
508 | cf.name += ".llvm." + std::to_string(file->offset) + "." + | |||
509 | sys::path::filename(Obj->getSourceFileName()).str(); | |||
510 | ||||
511 | for (auto &Sym : Obj->symbols()) { | |||
512 | cf.syms.push_back(ld_plugin_symbol()); | |||
513 | ld_plugin_symbol &sym = cf.syms.back(); | |||
514 | sym.version = nullptr; | |||
515 | StringRef Name = Sym.getName(); | |||
516 | sym.name = strdup(Name.str().c_str()); | |||
517 | ||||
518 | ResolutionInfo &Res = ResInfo[Name]; | |||
519 | ||||
520 | Res.CanOmitFromDynSym &= Sym.canBeOmittedFromSymbolTable(); | |||
521 | ||||
522 | sym.visibility = LDPV_DEFAULT; | |||
523 | GlobalValue::VisibilityTypes Vis = Sym.getVisibility(); | |||
524 | if (Vis != GlobalValue::DefaultVisibility) | |||
525 | Res.DefaultVisibility = false; | |||
526 | switch (Vis) { | |||
527 | case GlobalValue::DefaultVisibility: | |||
528 | break; | |||
529 | case GlobalValue::HiddenVisibility: | |||
530 | sym.visibility = LDPV_HIDDEN; | |||
531 | break; | |||
532 | case GlobalValue::ProtectedVisibility: | |||
533 | sym.visibility = LDPV_PROTECTED; | |||
534 | break; | |||
535 | } | |||
536 | ||||
537 | if (Sym.isUndefined()) { | |||
538 | sym.def = LDPK_UNDEF; | |||
539 | if (Sym.isWeak()) | |||
540 | sym.def = LDPK_WEAKUNDEF; | |||
541 | } else if (Sym.isCommon()) | |||
542 | sym.def = LDPK_COMMON; | |||
543 | else if (Sym.isWeak()) | |||
544 | sym.def = LDPK_WEAKDEF; | |||
545 | else | |||
546 | sym.def = LDPK_DEF; | |||
547 | ||||
548 | sym.size = 0; | |||
549 | sym.comdat_key = nullptr; | |||
550 | int CI = Sym.getComdatIndex(); | |||
551 | if (CI != -1) { | |||
552 | StringRef C = Obj->getComdatTable()[CI]; | |||
553 | sym.comdat_key = strdup(C.str().c_str()); | |||
554 | } | |||
555 | ||||
556 | sym.resolution = LDPR_UNKNOWN; | |||
557 | } | |||
558 | ||||
559 | if (!cf.syms.empty()) { | |||
560 | if (add_symbols(cf.handle, cf.syms.size(), cf.syms.data()) != LDPS_OK) { | |||
561 | message(LDPL_ERROR, "Unable to add symbols!"); | |||
562 | return LDPS_ERR; | |||
563 | } | |||
564 | } | |||
565 | ||||
566 | return LDPS_OK; | |||
567 | } | |||
568 | ||||
569 | static void freeSymName(ld_plugin_symbol &Sym) { | |||
570 | free(Sym.name); | |||
571 | free(Sym.comdat_key); | |||
572 | Sym.name = nullptr; | |||
573 | Sym.comdat_key = nullptr; | |||
574 | } | |||
575 | ||||
576 | /// Helper to get a file's symbols and a view into it via gold callbacks. | |||
577 | static const void *getSymbolsAndView(claimed_file &F) { | |||
578 | ld_plugin_status status = get_symbols(F.handle, F.syms.size(), F.syms.data()); | |||
579 | if (status == LDPS_NO_SYMS) | |||
580 | return nullptr; | |||
581 | ||||
582 | if (status != LDPS_OK) | |||
583 | message(LDPL_FATAL, "Failed to get symbol information"); | |||
584 | ||||
585 | const void *View; | |||
586 | if (get_view(F.handle, &View) != LDPS_OK) | |||
587 | message(LDPL_FATAL, "Failed to get a view of file"); | |||
588 | ||||
589 | return View; | |||
590 | } | |||
591 | ||||
592 | /// Parse the thinlto-object-suffix-replace option into the \p OldSuffix and | |||
593 | /// \p NewSuffix strings, if it was specified. | |||
594 | static void getThinLTOOldAndNewSuffix(std::string &OldSuffix, | |||
595 | std::string &NewSuffix) { | |||
596 | assert(options::thinlto_object_suffix_replace.empty() ||(static_cast <bool> (options::thinlto_object_suffix_replace .empty() || options::thinlto_object_suffix_replace.find(";") != StringRef::npos) ? void (0) : __assert_fail ("options::thinlto_object_suffix_replace.empty() || options::thinlto_object_suffix_replace.find(\";\") != StringRef::npos" , "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 597, __extension__ __PRETTY_FUNCTION__)) | |||
597 | options::thinlto_object_suffix_replace.find(";") != StringRef::npos)(static_cast <bool> (options::thinlto_object_suffix_replace .empty() || options::thinlto_object_suffix_replace.find(";") != StringRef::npos) ? void (0) : __assert_fail ("options::thinlto_object_suffix_replace.empty() || options::thinlto_object_suffix_replace.find(\";\") != StringRef::npos" , "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 597, __extension__ __PRETTY_FUNCTION__)); | |||
598 | StringRef SuffixReplace = options::thinlto_object_suffix_replace; | |||
599 | std::tie(OldSuffix, NewSuffix) = SuffixReplace.split(';'); | |||
600 | } | |||
601 | ||||
602 | /// Given the original \p Path to an output file, replace any filename | |||
603 | /// suffix matching \p OldSuffix with \p NewSuffix. | |||
604 | static std::string getThinLTOObjectFileName(StringRef Path, StringRef OldSuffix, | |||
605 | StringRef NewSuffix) { | |||
606 | if (OldSuffix.empty() && NewSuffix.empty()) | |||
607 | return Path; | |||
608 | StringRef NewPath = Path; | |||
609 | NewPath.consume_back(OldSuffix); | |||
610 | std::string NewNewPath = NewPath; | |||
611 | NewNewPath += NewSuffix; | |||
612 | return NewNewPath; | |||
613 | } | |||
614 | ||||
615 | // Returns true if S is valid as a C language identifier. | |||
616 | static bool isValidCIdentifier(StringRef S) { | |||
617 | return !S.empty() && (isAlpha(S[0]) || S[0] == '_') && | |||
618 | std::all_of(S.begin() + 1, S.end(), | |||
619 | [](char C) { return C == '_' || isAlnum(C); }); | |||
620 | } | |||
621 | ||||
622 | static bool isUndefined(ld_plugin_symbol &Sym) { | |||
623 | return Sym.def == LDPK_UNDEF || Sym.def == LDPK_WEAKUNDEF; | |||
624 | } | |||
625 | ||||
626 | static void addModule(LTO &Lto, claimed_file &F, const void *View, | |||
627 | StringRef Filename) { | |||
628 | MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), | |||
629 | Filename); | |||
630 | Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef); | |||
631 | ||||
632 | if (!ObjOrErr) | |||
633 | message(LDPL_FATAL, "Could not read bitcode from file : %s", | |||
634 | toString(ObjOrErr.takeError()).c_str()); | |||
635 | ||||
636 | unsigned SymNum = 0; | |||
637 | std::unique_ptr<InputFile> Input = std::move(ObjOrErr.get()); | |||
638 | auto InputFileSyms = Input->symbols(); | |||
639 | assert(InputFileSyms.size() == F.syms.size())(static_cast <bool> (InputFileSyms.size() == F.syms.size ()) ? void (0) : __assert_fail ("InputFileSyms.size() == F.syms.size()" , "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 639, __extension__ __PRETTY_FUNCTION__)); | |||
640 | std::vector<SymbolResolution> Resols(F.syms.size()); | |||
641 | for (ld_plugin_symbol &Sym : F.syms) { | |||
642 | const InputFile::Symbol &InpSym = InputFileSyms[SymNum]; | |||
643 | SymbolResolution &R = Resols[SymNum++]; | |||
644 | ||||
645 | ld_plugin_symbol_resolution Resolution = | |||
646 | (ld_plugin_symbol_resolution)Sym.resolution; | |||
647 | ||||
648 | ResolutionInfo &Res = ResInfo[Sym.name]; | |||
649 | ||||
650 | switch (Resolution) { | |||
651 | case LDPR_UNKNOWN: | |||
652 | llvm_unreachable("Unexpected resolution")::llvm::llvm_unreachable_internal("Unexpected resolution", "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 652); | |||
653 | ||||
654 | case LDPR_RESOLVED_IR: | |||
655 | case LDPR_RESOLVED_EXEC: | |||
656 | case LDPR_RESOLVED_DYN: | |||
657 | case LDPR_PREEMPTED_IR: | |||
658 | case LDPR_PREEMPTED_REG: | |||
659 | case LDPR_UNDEF: | |||
660 | break; | |||
661 | ||||
662 | case LDPR_PREVAILING_DEF_IRONLY: | |||
663 | R.Prevailing = !isUndefined(Sym); | |||
664 | break; | |||
665 | ||||
666 | case LDPR_PREVAILING_DEF: | |||
667 | R.Prevailing = !isUndefined(Sym); | |||
668 | R.VisibleToRegularObj = true; | |||
669 | break; | |||
670 | ||||
671 | case LDPR_PREVAILING_DEF_IRONLY_EXP: | |||
672 | R.Prevailing = !isUndefined(Sym); | |||
673 | if (!Res.CanOmitFromDynSym) | |||
674 | R.VisibleToRegularObj = true; | |||
675 | break; | |||
676 | } | |||
677 | ||||
678 | // If the symbol has a C identifier section name, we need to mark | |||
679 | // it as visible to a regular object so that LTO will keep it around | |||
680 | // to ensure the linker generates special __start_<secname> and | |||
681 | // __stop_<secname> symbols which may be used elsewhere. | |||
682 | if (isValidCIdentifier(InpSym.getSectionName())) | |||
683 | R.VisibleToRegularObj = true; | |||
684 | ||||
685 | if (Resolution != LDPR_RESOLVED_DYN && Resolution != LDPR_UNDEF && | |||
686 | (IsExecutable || !Res.DefaultVisibility)) | |||
687 | R.FinalDefinitionInLinkageUnit = true; | |||
688 | ||||
689 | freeSymName(Sym); | |||
690 | } | |||
691 | ||||
692 | check(Lto.add(std::move(Input), Resols), | |||
693 | std::string("Failed to link module ") + F.name); | |||
694 | } | |||
695 | ||||
696 | static void recordFile(const std::string &Filename, bool TempOutFile) { | |||
697 | if (add_input_file(Filename.c_str()) != LDPS_OK) | |||
698 | message(LDPL_FATAL, | |||
699 | "Unable to add .o file to the link. File left behind in: %s", | |||
700 | Filename.c_str()); | |||
701 | if (TempOutFile) | |||
702 | Cleanup.push_back(Filename); | |||
703 | } | |||
704 | ||||
705 | /// Return the desired output filename given a base input name, a flag | |||
706 | /// indicating whether a temp file should be generated, and an optional task id. | |||
707 | /// The new filename generated is returned in \p NewFilename. | |||
708 | static int getOutputFileName(StringRef InFilename, bool TempOutFile, | |||
709 | SmallString<128> &NewFilename, int TaskID) { | |||
710 | int FD = -1; | |||
711 | if (TempOutFile) { | |||
712 | std::error_code EC = | |||
713 | sys::fs::createTemporaryFile("lto-llvm", "o", FD, NewFilename); | |||
714 | if (EC) | |||
715 | message(LDPL_FATAL, "Could not create temporary file: %s", | |||
716 | EC.message().c_str()); | |||
717 | } else { | |||
718 | NewFilename = InFilename; | |||
719 | if (TaskID > 0) | |||
720 | NewFilename += utostr(TaskID); | |||
721 | std::error_code EC = | |||
722 | sys::fs::openFileForWrite(NewFilename, FD, sys::fs::F_None); | |||
723 | if (EC) | |||
724 | message(LDPL_FATAL, "Could not open file %s: %s", NewFilename.c_str(), | |||
725 | EC.message().c_str()); | |||
726 | } | |||
727 | return FD; | |||
728 | } | |||
729 | ||||
730 | /// Parse the thinlto_prefix_replace option into the \p OldPrefix and | |||
731 | /// \p NewPrefix strings, if it was specified. | |||
732 | static void getThinLTOOldAndNewPrefix(std::string &OldPrefix, | |||
733 | std::string &NewPrefix) { | |||
734 | StringRef PrefixReplace = options::thinlto_prefix_replace; | |||
735 | assert(PrefixReplace.empty() || PrefixReplace.find(";") != StringRef::npos)(static_cast <bool> (PrefixReplace.empty() || PrefixReplace .find(";") != StringRef::npos) ? void (0) : __assert_fail ("PrefixReplace.empty() || PrefixReplace.find(\";\") != StringRef::npos" , "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 735, __extension__ __PRETTY_FUNCTION__)); | |||
736 | std::tie(OldPrefix, NewPrefix) = PrefixReplace.split(';'); | |||
737 | } | |||
738 | ||||
739 | /// Creates instance of LTO. | |||
740 | /// OnIndexWrite is callback to let caller know when LTO writes index files. | |||
741 | /// LinkedObjectsFile is an output stream to write the list of object files for | |||
742 | /// the final ThinLTO linking. Can be nullptr. | |||
743 | static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite, | |||
744 | raw_fd_ostream *LinkedObjectsFile) { | |||
745 | Config Conf; | |||
746 | ThinBackend Backend; | |||
747 | ||||
748 | Conf.CPU = options::mcpu; | |||
749 | Conf.Options = InitTargetOptionsFromCodeGenFlags(); | |||
750 | ||||
751 | // Disable the new X86 relax relocations since gold might not support them. | |||
752 | // FIXME: Check the gold version or add a new option to enable them. | |||
753 | Conf.Options.RelaxELFRelocations = false; | |||
754 | ||||
755 | // Enable function/data sections by default. | |||
756 | Conf.Options.FunctionSections = true; | |||
757 | Conf.Options.DataSections = true; | |||
758 | ||||
759 | Conf.MAttrs = MAttrs; | |||
760 | Conf.RelocModel = RelocationModel; | |||
761 | Conf.DisableVerify = options::DisableVerify; | |||
762 | Conf.OptLevel = options::OptLevel; | |||
763 | if (options::Parallelism) | |||
764 | Backend = createInProcessThinBackend(options::Parallelism); | |||
765 | if (options::thinlto_index_only) { | |||
766 | std::string OldPrefix, NewPrefix; | |||
767 | getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); | |||
768 | Backend = createWriteIndexesThinBackend(OldPrefix, NewPrefix, | |||
769 | options::thinlto_emit_imports_files, | |||
770 | LinkedObjectsFile, OnIndexWrite); | |||
771 | } | |||
772 | ||||
773 | Conf.OverrideTriple = options::triple; | |||
774 | Conf.DefaultTriple = sys::getDefaultTargetTriple(); | |||
775 | ||||
776 | Conf.DiagHandler = diagnosticHandler; | |||
777 | ||||
778 | switch (options::TheOutputType) { | |||
779 | case options::OT_NORMAL: | |||
780 | break; | |||
781 | ||||
782 | case options::OT_DISABLE: | |||
783 | Conf.PreOptModuleHook = [](size_t Task, const Module &M) { return false; }; | |||
784 | break; | |||
785 | ||||
786 | case options::OT_BC_ONLY: | |||
787 | Conf.PostInternalizeModuleHook = [](size_t Task, const Module &M) { | |||
788 | std::error_code EC; | |||
789 | raw_fd_ostream OS(output_name, EC, sys::fs::OpenFlags::F_None); | |||
790 | if (EC) | |||
791 | message(LDPL_FATAL, "Failed to write the output file."); | |||
792 | WriteBitcodeToFile(M, OS, /* ShouldPreserveUseListOrder */ false); | |||
793 | return false; | |||
794 | }; | |||
795 | break; | |||
796 | ||||
797 | case options::OT_SAVE_TEMPS: | |||
798 | check(Conf.addSaveTemps(output_name + ".", | |||
799 | /* UseInputModulePath */ true)); | |||
800 | break; | |||
801 | } | |||
802 | ||||
803 | if (!options::sample_profile.empty()) | |||
804 | Conf.SampleProfile = options::sample_profile; | |||
805 | ||||
806 | // Use new pass manager if set in driver | |||
807 | Conf.UseNewPM = options::new_pass_manager; | |||
808 | ||||
809 | return llvm::make_unique<LTO>(std::move(Conf), Backend, | |||
810 | options::ParallelCodeGenParallelismLevel); | |||
811 | } | |||
812 | ||||
813 | // Write empty files that may be expected by a distributed build | |||
814 | // system when invoked with thinlto_index_only. This is invoked when | |||
815 | // the linker has decided not to include the given module in the | |||
816 | // final link. Frequently the distributed build system will want to | |||
817 | // confirm that all expected outputs are created based on all of the | |||
818 | // modules provided to the linker. | |||
819 | // If SkipModule is true then .thinlto.bc should contain just | |||
820 | // SkipModuleByDistributedBackend flag which requests distributed backend | |||
821 | // to skip the compilation of the corresponding module and produce an empty | |||
822 | // object file. | |||
823 | static void writeEmptyDistributedBuildOutputs(const std::string &ModulePath, | |||
824 | const std::string &OldPrefix, | |||
825 | const std::string &NewPrefix, | |||
826 | bool SkipModule) { | |||
827 | std::string NewModulePath = | |||
828 | getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix); | |||
829 | std::error_code EC; | |||
830 | { | |||
831 | raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC, | |||
832 | sys::fs::OpenFlags::F_None); | |||
833 | if (EC) | |||
834 | message(LDPL_FATAL, "Failed to write '%s': %s", | |||
835 | (NewModulePath + ".thinlto.bc").c_str(), EC.message().c_str()); | |||
836 | ||||
837 | if (SkipModule) { | |||
838 | ModuleSummaryIndex Index(false); | |||
839 | Index.setSkipModuleByDistributedBackend(); | |||
840 | WriteIndexToFile(Index, OS, nullptr); | |||
841 | } | |||
842 | } | |||
843 | if (options::thinlto_emit_imports_files) { | |||
844 | raw_fd_ostream OS(NewModulePath + ".imports", EC, | |||
845 | sys::fs::OpenFlags::F_None); | |||
846 | if (EC) | |||
847 | message(LDPL_FATAL, "Failed to write '%s': %s", | |||
848 | (NewModulePath + ".imports").c_str(), EC.message().c_str()); | |||
849 | } | |||
850 | } | |||
851 | ||||
852 | // Creates and returns output stream with a list of object files for final | |||
853 | // linking of distributed ThinLTO. | |||
854 | static std::unique_ptr<raw_fd_ostream> CreateLinkedObjectsFile() { | |||
855 | if (options::thinlto_linked_objects_file.empty()) | |||
856 | return nullptr; | |||
857 | assert(options::thinlto_index_only)(static_cast <bool> (options::thinlto_index_only) ? void (0) : __assert_fail ("options::thinlto_index_only", "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 857, __extension__ __PRETTY_FUNCTION__)); | |||
858 | std::error_code EC; | |||
859 | auto LinkedObjectsFile = llvm::make_unique<raw_fd_ostream>( | |||
860 | options::thinlto_linked_objects_file, EC, sys::fs::OpenFlags::F_None); | |||
861 | if (EC) | |||
862 | message(LDPL_FATAL, "Failed to create '%s': %s", | |||
863 | options::thinlto_linked_objects_file.c_str(), EC.message().c_str()); | |||
864 | return LinkedObjectsFile; | |||
865 | } | |||
866 | ||||
867 | /// Runs LTO and return a list of pairs <FileName, IsTemporary>. | |||
868 | static std::vector<std::pair<SmallString<128>, bool>> runLTO() { | |||
869 | // Map to own RAII objects that manage the file opening and releasing | |||
870 | // interfaces with gold. This is needed only for ThinLTO mode, since | |||
871 | // unlike regular LTO, where addModule will result in the opened file | |||
872 | // being merged into a new combined module, we need to keep these files open | |||
873 | // through Lto->run(). | |||
874 | DenseMap<void *, std::unique_ptr<PluginInputFile>> HandleToInputFile; | |||
875 | ||||
876 | // Owns string objects and tells if index file was already created. | |||
877 | StringMap<bool> ObjectToIndexFileState; | |||
878 | ||||
879 | std::unique_ptr<raw_fd_ostream> LinkedObjects = CreateLinkedObjectsFile(); | |||
880 | std::unique_ptr<LTO> Lto = createLTO( | |||
881 | [&ObjectToIndexFileState](const std::string &Identifier) { | |||
882 | ObjectToIndexFileState[Identifier] = true; | |||
883 | }, | |||
884 | LinkedObjects.get()); | |||
885 | ||||
886 | std::string OldPrefix, NewPrefix; | |||
887 | if (options::thinlto_index_only) | |||
888 | getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix); | |||
889 | ||||
890 | std::string OldSuffix, NewSuffix; | |||
891 | getThinLTOOldAndNewSuffix(OldSuffix, NewSuffix); | |||
892 | ||||
893 | for (claimed_file &F : Modules) { | |||
894 | if (options::thinlto && !HandleToInputFile.count(F.leader_handle)) | |||
895 | HandleToInputFile.insert(std::make_pair( | |||
896 | F.leader_handle, llvm::make_unique<PluginInputFile>(F.handle))); | |||
897 | // In case we are thin linking with a minimized bitcode file, ensure | |||
898 | // the module paths encoded in the index reflect where the backends | |||
899 | // will locate the full bitcode files for compiling/importing. | |||
900 | std::string Identifier = | |||
901 | getThinLTOObjectFileName(F.name, OldSuffix, NewSuffix); | |||
902 | auto ObjFilename = ObjectToIndexFileState.insert({Identifier, false}); | |||
903 | assert(ObjFilename.second)(static_cast <bool> (ObjFilename.second) ? void (0) : __assert_fail ("ObjFilename.second", "/build/llvm-toolchain-snapshot-7~svn326551/tools/gold/gold-plugin.cpp" , 903, __extension__ __PRETTY_FUNCTION__)); | |||
904 | if (const void *View = getSymbolsAndView(F)) | |||
905 | addModule(*Lto, F, View, ObjFilename.first->first()); | |||
906 | else if (options::thinlto_index_only) { | |||
907 | ObjFilename.first->second = true; | |||
908 | writeEmptyDistributedBuildOutputs(Identifier, OldPrefix, NewPrefix, | |||
909 | /* SkipModule */ true); | |||
910 | } | |||
911 | } | |||
912 | ||||
913 | SmallString<128> Filename; | |||
914 | // Note that getOutputFileName will append a unique ID for each task | |||
915 | if (!options::obj_path.empty()) | |||
916 | Filename = options::obj_path; | |||
917 | else if (options::TheOutputType == options::OT_SAVE_TEMPS) | |||
918 | Filename = output_name + ".o"; | |||
919 | bool SaveTemps = !Filename.empty(); | |||
920 | ||||
921 | size_t MaxTasks = Lto->getMaxTasks(); | |||
922 | std::vector<std::pair<SmallString<128>, bool>> Files(MaxTasks); | |||
923 | ||||
924 | auto AddStream = | |||
925 | [&](size_t Task) -> std::unique_ptr<lto::NativeObjectStream> { | |||
926 | Files[Task].second = !SaveTemps; | |||
927 | int FD = getOutputFileName(Filename, /* TempOutFile */ !SaveTemps, | |||
928 | Files[Task].first, Task); | |||
929 | return llvm::make_unique<lto::NativeObjectStream>( | |||
930 | llvm::make_unique<llvm::raw_fd_ostream>(FD, true)); | |||
931 | }; | |||
932 | ||||
933 | auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) { | |||
934 | *AddStream(Task)->OS << MB->getBuffer(); | |||
| ||||
| ||||
935 | }; | |||
936 | ||||
937 | NativeObjectCache Cache; | |||
938 | if (!options::cache_dir.empty()) | |||
939 | Cache = check(localCache(options::cache_dir, AddBuffer)); | |||
940 | ||||
941 | check(Lto->run(AddStream, Cache)); | |||
942 | ||||
943 | // Write empty output files that may be expected by the distributed build | |||
944 | // system. | |||
945 | if (options::thinlto_index_only) | |||
946 | for (auto &Identifier : ObjectToIndexFileState) | |||
947 | if (!Identifier.getValue()) | |||
948 | writeEmptyDistributedBuildOutputs(Identifier.getKey(), OldPrefix, | |||
949 | NewPrefix, /* SkipModule */ false); | |||
950 | ||||
951 | return Files; | |||
952 | } | |||
953 | ||||
954 | /// gold informs us that all symbols have been read. At this point, we use | |||
955 | /// get_symbols to see if any of our definitions have been overridden by a | |||
956 | /// native object file. Then, perform optimization and codegen. | |||
957 | static ld_plugin_status allSymbolsReadHook() { | |||
958 | if (Modules.empty()) | |||
959 | return LDPS_OK; | |||
960 | ||||
961 | if (unsigned NumOpts = options::extra.size()) | |||
962 | cl::ParseCommandLineOptions(NumOpts, &options::extra[0]); | |||
963 | ||||
964 | std::vector<std::pair<SmallString<128>, bool>> Files = runLTO(); | |||
965 | ||||
966 | if (options::TheOutputType == options::OT_DISABLE || | |||
967 | options::TheOutputType == options::OT_BC_ONLY) | |||
968 | return LDPS_OK; | |||
969 | ||||
970 | if (options::thinlto_index_only) { | |||
971 | if (llvm::AreStatisticsEnabled()) | |||
972 | llvm::PrintStatistics(); | |||
973 | cleanup_hook(); | |||
974 | exit(0); | |||
975 | } | |||
976 | ||||
977 | for (const auto &F : Files) | |||
978 | if (!F.first.empty()) | |||
979 | recordFile(F.first.str(), F.second); | |||
980 | ||||
981 | if (!options::extra_library_path.empty() && | |||
982 | set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) | |||
983 | message(LDPL_FATAL, "Unable to set the extra library path."); | |||
984 | ||||
985 | return LDPS_OK; | |||
986 | } | |||
987 | ||||
988 | static ld_plugin_status all_symbols_read_hook(void) { | |||
989 | ld_plugin_status Ret = allSymbolsReadHook(); | |||
990 | llvm_shutdown(); | |||
991 | ||||
992 | if (options::TheOutputType == options::OT_BC_ONLY || | |||
993 | options::TheOutputType == options::OT_DISABLE) { | |||
994 | if (options::TheOutputType == options::OT_DISABLE) { | |||
995 | // Remove the output file here since ld.bfd creates the output file | |||
996 | // early. | |||
997 | std::error_code EC = sys::fs::remove(output_name); | |||
998 | if (EC) | |||
999 | message(LDPL_ERROR, "Failed to delete '%s': %s", output_name.c_str(), | |||
1000 | EC.message().c_str()); | |||
1001 | } | |||
1002 | exit(0); | |||
1003 | } | |||
1004 | ||||
1005 | return Ret; | |||
1006 | } | |||
1007 | ||||
1008 | static ld_plugin_status cleanup_hook(void) { | |||
1009 | for (std::string &Name : Cleanup) { | |||
1010 | std::error_code EC = sys::fs::remove(Name); | |||
1011 | if (EC) | |||
1012 | message(LDPL_ERROR, "Failed to delete '%s': %s", Name.c_str(), | |||
1013 | EC.message().c_str()); | |||
1014 | } | |||
1015 | ||||
1016 | // Prune cache | |||
1017 | if (!options::cache_dir.empty()) { | |||
1018 | CachePruningPolicy policy = check(parseCachePruningPolicy(options::cache_policy)); | |||
1019 | pruneCache(options::cache_dir, policy); | |||
1020 | } | |||
1021 | ||||
1022 | return LDPS_OK; | |||
1023 | } |
1 | //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file contains some templates that are useful if you are working with the |
11 | // STL at all. |
12 | // |
13 | // No library is required when using these functions. |
14 | // |
15 | //===----------------------------------------------------------------------===// |
16 | |
17 | #ifndef LLVM_ADT_STLEXTRAS_H |
18 | #define LLVM_ADT_STLEXTRAS_H |
19 | |
20 | #include "llvm/ADT/Optional.h" |
21 | #include "llvm/ADT/SmallVector.h" |
22 | #include "llvm/ADT/iterator.h" |
23 | #include "llvm/ADT/iterator_range.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include <algorithm> |
26 | #include <cassert> |
27 | #include <cstddef> |
28 | #include <cstdint> |
29 | #include <cstdlib> |
30 | #include <functional> |
31 | #include <initializer_list> |
32 | #include <iterator> |
33 | #include <limits> |
34 | #include <memory> |
35 | #include <tuple> |
36 | #include <type_traits> |
37 | #include <utility> |
38 | |
39 | namespace llvm { |
40 | |
41 | // Only used by compiler if both template types are the same. Useful when |
42 | // using SFINAE to test for the existence of member functions. |
43 | template <typename T, T> struct SameType; |
44 | |
45 | namespace detail { |
46 | |
47 | template <typename RangeT> |
48 | using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); |
49 | |
50 | template <typename RangeT> |
51 | using ValueOfRange = typename std::remove_reference<decltype( |
52 | *std::begin(std::declval<RangeT &>()))>::type; |
53 | |
54 | } // end namespace detail |
55 | |
56 | //===----------------------------------------------------------------------===// |
57 | // Extra additions to <functional> |
58 | //===----------------------------------------------------------------------===// |
59 | |
60 | template <class Ty> struct identity { |
61 | using argument_type = Ty; |
62 | |
63 | Ty &operator()(Ty &self) const { |
64 | return self; |
65 | } |
66 | const Ty &operator()(const Ty &self) const { |
67 | return self; |
68 | } |
69 | }; |
70 | |
71 | template <class Ty> struct less_ptr { |
72 | bool operator()(const Ty* left, const Ty* right) const { |
73 | return *left < *right; |
74 | } |
75 | }; |
76 | |
77 | template <class Ty> struct greater_ptr { |
78 | bool operator()(const Ty* left, const Ty* right) const { |
79 | return *right < *left; |
80 | } |
81 | }; |
82 | |
83 | /// An efficient, type-erasing, non-owning reference to a callable. This is |
84 | /// intended for use as the type of a function parameter that is not used |
85 | /// after the function in question returns. |
86 | /// |
87 | /// This class does not own the callable, so it is not in general safe to store |
88 | /// a function_ref. |
89 | template<typename Fn> class function_ref; |
90 | |
91 | template<typename Ret, typename ...Params> |
92 | class function_ref<Ret(Params...)> { |
93 | Ret (*callback)(intptr_t callable, Params ...params) = nullptr; |
94 | intptr_t callable; |
95 | |
96 | template<typename Callable> |
97 | static Ret callback_fn(intptr_t callable, Params ...params) { |
98 | return (*reinterpret_cast<Callable*>(callable))( |
99 | std::forward<Params>(params)...); |
100 | } |
101 | |
102 | public: |
103 | function_ref() = default; |
104 | function_ref(std::nullptr_t) {} |
105 | |
106 | template <typename Callable> |
107 | function_ref(Callable &&callable, |
108 | typename std::enable_if< |
109 | !std::is_same<typename std::remove_reference<Callable>::type, |
110 | function_ref>::value>::type * = nullptr) |
111 | : callback(callback_fn<typename std::remove_reference<Callable>::type>), |
112 | callable(reinterpret_cast<intptr_t>(&callable)) {} |
113 | |
114 | Ret operator()(Params ...params) const { |
115 | return callback(callable, std::forward<Params>(params)...); |
116 | } |
117 | |
118 | operator bool() const { return callback; } |
119 | }; |
120 | |
121 | // deleter - Very very very simple method that is used to invoke operator |
122 | // delete on something. It is used like this: |
123 | // |
124 | // for_each(V.begin(), B.end(), deleter<Interval>); |
125 | template <class T> |
126 | inline void deleter(T *Ptr) { |
127 | delete Ptr; |
128 | } |
129 | |
130 | //===----------------------------------------------------------------------===// |
131 | // Extra additions to <iterator> |
132 | //===----------------------------------------------------------------------===// |
133 | |
134 | namespace adl_detail { |
135 | |
136 | using std::begin; |
137 | |
138 | template <typename ContainerTy> |
139 | auto adl_begin(ContainerTy &&container) |
140 | -> decltype(begin(std::forward<ContainerTy>(container))) { |
141 | return begin(std::forward<ContainerTy>(container)); |
142 | } |
143 | |
144 | using std::end; |
145 | |
146 | template <typename ContainerTy> |
147 | auto adl_end(ContainerTy &&container) |
148 | -> decltype(end(std::forward<ContainerTy>(container))) { |
149 | return end(std::forward<ContainerTy>(container)); |
150 | } |
151 | |
152 | using std::swap; |
153 | |
154 | template <typename T> |
155 | void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), |
156 | std::declval<T>()))) { |
157 | swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
158 | } |
159 | |
160 | } // end namespace adl_detail |
161 | |
162 | template <typename ContainerTy> |
163 | auto adl_begin(ContainerTy &&container) |
164 | -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) { |
165 | return adl_detail::adl_begin(std::forward<ContainerTy>(container)); |
166 | } |
167 | |
168 | template <typename ContainerTy> |
169 | auto adl_end(ContainerTy &&container) |
170 | -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) { |
171 | return adl_detail::adl_end(std::forward<ContainerTy>(container)); |
172 | } |
173 | |
174 | template <typename T> |
175 | void adl_swap(T &&lhs, T &&rhs) noexcept( |
176 | noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { |
177 | adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); |
178 | } |
179 | |
180 | // mapped_iterator - This is a simple iterator adapter that causes a function to |
181 | // be applied whenever operator* is invoked on the iterator. |
182 | |
183 | template <typename ItTy, typename FuncTy, |
184 | typename FuncReturnTy = |
185 | decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> |
186 | class mapped_iterator |
187 | : public iterator_adaptor_base< |
188 | mapped_iterator<ItTy, FuncTy>, ItTy, |
189 | typename std::iterator_traits<ItTy>::iterator_category, |
190 | typename std::remove_reference<FuncReturnTy>::type> { |
191 | public: |
192 | mapped_iterator(ItTy U, FuncTy F) |
193 | : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} |
194 | |
195 | ItTy getCurrent() { return this->I; } |
196 | |
197 | FuncReturnTy operator*() { return F(*this->I); } |
198 | |
199 | private: |
200 | FuncTy F; |
201 | }; |
202 | |
203 | // map_iterator - Provide a convenient way to create mapped_iterators, just like |
204 | // make_pair is useful for creating pairs... |
205 | template <class ItTy, class FuncTy> |
206 | inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { |
207 | return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); |
208 | } |
209 | |
210 | /// Helper to determine if type T has a member called rbegin(). |
211 | template <typename Ty> class has_rbegin_impl { |
212 | using yes = char[1]; |
213 | using no = char[2]; |
214 | |
215 | template <typename Inner> |
216 | static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); |
217 | |
218 | template <typename> |
219 | static no& test(...); |
220 | |
221 | public: |
222 | static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); |
223 | }; |
224 | |
225 | /// Metafunction to determine if T& or T has a member called rbegin(). |
226 | template <typename Ty> |
227 | struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { |
228 | }; |
229 | |
230 | // Returns an iterator_range over the given container which iterates in reverse. |
231 | // Note that the container must have rbegin()/rend() methods for this to work. |
232 | template <typename ContainerTy> |
233 | auto reverse(ContainerTy &&C, |
234 | typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = |
235 | nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { |
236 | return make_range(C.rbegin(), C.rend()); |
237 | } |
238 | |
239 | // Returns a std::reverse_iterator wrapped around the given iterator. |
240 | template <typename IteratorTy> |
241 | std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { |
242 | return std::reverse_iterator<IteratorTy>(It); |
243 | } |
244 | |
245 | // Returns an iterator_range over the given container which iterates in reverse. |
246 | // Note that the container must have begin()/end() methods which return |
247 | // bidirectional iterators for this to work. |
248 | template <typename ContainerTy> |
249 | auto reverse( |
250 | ContainerTy &&C, |
251 | typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) |
252 | -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), |
253 | llvm::make_reverse_iterator(std::begin(C)))) { |
254 | return make_range(llvm::make_reverse_iterator(std::end(C)), |
255 | llvm::make_reverse_iterator(std::begin(C))); |
256 | } |
257 | |
258 | /// An iterator adaptor that filters the elements of given inner iterators. |
259 | /// |
260 | /// The predicate parameter should be a callable object that accepts the wrapped |
261 | /// iterator's reference type and returns a bool. When incrementing or |
262 | /// decrementing the iterator, it will call the predicate on each element and |
263 | /// skip any where it returns false. |
264 | /// |
265 | /// \code |
266 | /// int A[] = { 1, 2, 3, 4 }; |
267 | /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); |
268 | /// // R contains { 1, 3 }. |
269 | /// \endcode |
270 | template <typename WrappedIteratorT, typename PredicateT> |
271 | class filter_iterator |
272 | : public iterator_adaptor_base< |
273 | filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, |
274 | typename std::common_type< |
275 | std::forward_iterator_tag, |
276 | typename std::iterator_traits< |
277 | WrappedIteratorT>::iterator_category>::type> { |
278 | using BaseT = iterator_adaptor_base< |
279 | filter_iterator<WrappedIteratorT, PredicateT>, WrappedIteratorT, |
280 | typename std::common_type< |
281 | std::forward_iterator_tag, |
282 | typename std::iterator_traits<WrappedIteratorT>::iterator_category>:: |
283 | type>; |
284 | |
285 | struct PayloadType { |
286 | WrappedIteratorT End; |
287 | PredicateT Pred; |
288 | }; |
289 | |
290 | Optional<PayloadType> Payload; |
291 | |
292 | void findNextValid() { |
293 | assert(Payload && "Payload should be engaged when findNextValid is called")(static_cast <bool> (Payload && "Payload should be engaged when findNextValid is called" ) ? void (0) : __assert_fail ("Payload && \"Payload should be engaged when findNextValid is called\"" , "/build/llvm-toolchain-snapshot-7~svn326551/include/llvm/ADT/STLExtras.h" , 293, __extension__ __PRETTY_FUNCTION__)); |
294 | while (this->I != Payload->End && !Payload->Pred(*this->I)) |
295 | BaseT::operator++(); |
296 | } |
297 | |
298 | // Construct the begin iterator. The begin iterator requires to know where end |
299 | // is, so that it can properly stop when it hits end. |
300 | filter_iterator(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred) |
301 | : BaseT(std::move(Begin)), |
302 | Payload(PayloadType{std::move(End), std::move(Pred)}) { |
303 | findNextValid(); |
304 | } |
305 | |
306 | // Construct the end iterator. It's not incrementable, so Payload doesn't |
307 | // have to be engaged. |
308 | filter_iterator(WrappedIteratorT End) : BaseT(End) {} |
309 | |
310 | public: |
311 | using BaseT::operator++; |
312 | |
313 | filter_iterator &operator++() { |
314 | BaseT::operator++(); |
315 | findNextValid(); |
316 | return *this; |
317 | } |
318 | |
319 | template <typename RT, typename PT> |
320 | friend iterator_range<filter_iterator<detail::IterOfRange<RT>, PT>> |
321 | make_filter_range(RT &&, PT); |
322 | }; |
323 | |
324 | /// Convenience function that takes a range of elements and a predicate, |
325 | /// and return a new filter_iterator range. |
326 | /// |
327 | /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the |
328 | /// lifetime of that temporary is not kept by the returned range object, and the |
329 | /// temporary is going to be dropped on the floor after the make_iterator_range |
330 | /// full expression that contains this function call. |
331 | template <typename RangeT, typename PredicateT> |
332 | iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> |
333 | make_filter_range(RangeT &&Range, PredicateT Pred) { |
334 | using FilterIteratorT = |
335 | filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; |
336 | return make_range(FilterIteratorT(std::begin(std::forward<RangeT>(Range)), |
337 | std::end(std::forward<RangeT>(Range)), |
338 | std::move(Pred)), |
339 | FilterIteratorT(std::end(std::forward<RangeT>(Range)))); |
340 | } |
341 | |
342 | // forward declarations required by zip_shortest/zip_first |
343 | template <typename R, typename UnaryPredicate> |
344 | bool all_of(R &&range, UnaryPredicate P); |
345 | |
346 | template <size_t... I> struct index_sequence; |
347 | |
348 | template <class... Ts> struct index_sequence_for; |
349 | |
350 | namespace detail { |
351 | |
352 | using std::declval; |
353 | |
354 | // We have to alias this since inlining the actual type at the usage site |
355 | // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. |
356 | template<typename... Iters> struct ZipTupleType { |
357 | using type = std::tuple<decltype(*declval<Iters>())...>; |
358 | }; |
359 | |
360 | template <typename ZipType, typename... Iters> |
361 | using zip_traits = iterator_facade_base< |
362 | ZipType, typename std::common_type<std::bidirectional_iterator_tag, |
363 | typename std::iterator_traits< |
364 | Iters>::iterator_category...>::type, |
365 | // ^ TODO: Implement random access methods. |
366 | typename ZipTupleType<Iters...>::type, |
367 | typename std::iterator_traits<typename std::tuple_element< |
368 | 0, std::tuple<Iters...>>::type>::difference_type, |
369 | // ^ FIXME: This follows boost::make_zip_iterator's assumption that all |
370 | // inner iterators have the same difference_type. It would fail if, for |
371 | // instance, the second field's difference_type were non-numeric while the |
372 | // first is. |
373 | typename ZipTupleType<Iters...>::type *, |
374 | typename ZipTupleType<Iters...>::type>; |
375 | |
376 | template <typename ZipType, typename... Iters> |
377 | struct zip_common : public zip_traits<ZipType, Iters...> { |
378 | using Base = zip_traits<ZipType, Iters...>; |
379 | using value_type = typename Base::value_type; |
380 | |
381 | std::tuple<Iters...> iterators; |
382 | |
383 | protected: |
384 | template <size_t... Ns> value_type deref(index_sequence<Ns...>) const { |
385 | return value_type(*std::get<Ns>(iterators)...); |
386 | } |
387 | |
388 | template <size_t... Ns> |
389 | decltype(iterators) tup_inc(index_sequence<Ns...>) const { |
390 | return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); |
391 | } |
392 | |
393 | template <size_t... Ns> |
394 | decltype(iterators) tup_dec(index_sequence<Ns...>) const { |
395 | return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); |
396 | } |
397 | |
398 | public: |
399 | zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} |
400 | |
401 | value_type operator*() { return deref(index_sequence_for<Iters...>{}); } |
402 | |
403 | const value_type operator*() const { |
404 | return deref(index_sequence_for<Iters...>{}); |
405 | } |
406 | |
407 | ZipType &operator++() { |
408 | iterators = tup_inc(index_sequence_for<Iters...>{}); |
409 | return *reinterpret_cast<ZipType *>(this); |
410 | } |
411 | |
412 | ZipType &operator--() { |
413 | static_assert(Base::IsBidirectional, |
414 | "All inner iterators must be at least bidirectional."); |
415 | iterators = tup_dec(index_sequence_for<Iters...>{}); |
416 | return *reinterpret_cast<ZipType *>(this); |
417 | } |
418 | }; |
419 | |
420 | template <typename... Iters> |
421 | struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { |
422 | using Base = zip_common<zip_first<Iters...>, Iters...>; |
423 | |
424 | bool operator==(const zip_first<Iters...> &other) const { |
425 | return std::get<0>(this->iterators) == std::get<0>(other.iterators); |
426 | } |
427 | |
428 | zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} |
429 | }; |
430 | |
431 | template <typename... Iters> |
432 | class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { |
433 | template <size_t... Ns> |
434 | bool test(const zip_shortest<Iters...> &other, index_sequence<Ns...>) const { |
435 | return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != |
436 | std::get<Ns>(other.iterators)...}, |
437 | identity<bool>{}); |
438 | } |
439 | |
440 | public: |
441 | using Base = zip_common<zip_shortest<Iters...>, Iters...>; |
442 | |
443 | zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} |
444 | |
445 | bool operator==(const zip_shortest<Iters...> &other) const { |
446 | return !test(other, index_sequence_for<Iters...>{}); |
447 | } |
448 | }; |
449 | |
450 | template <template <typename...> class ItType, typename... Args> class zippy { |
451 | public: |
452 | using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; |
453 | using iterator_category = typename iterator::iterator_category; |
454 | using value_type = typename iterator::value_type; |
455 | using difference_type = typename iterator::difference_type; |
456 | using pointer = typename iterator::pointer; |
457 | using reference = typename iterator::reference; |
458 | |
459 | private: |
460 | std::tuple<Args...> ts; |
461 | |
462 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) const { |
463 | return iterator(std::begin(std::get<Ns>(ts))...); |
464 | } |
465 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) const { |
466 | return iterator(std::end(std::get<Ns>(ts))...); |
467 | } |
468 | |
469 | public: |
470 | zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} |
471 | |
472 | iterator begin() const { return begin_impl(index_sequence_for<Args...>{}); } |
473 | iterator end() const { return end_impl(index_sequence_for<Args...>{}); } |
474 | }; |
475 | |
476 | } // end namespace detail |
477 | |
478 | /// zip iterator for two or more iteratable types. |
479 | template <typename T, typename U, typename... Args> |
480 | detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, |
481 | Args &&... args) { |
482 | return detail::zippy<detail::zip_shortest, T, U, Args...>( |
483 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); |
484 | } |
485 | |
486 | /// zip iterator that, for the sake of efficiency, assumes the first iteratee to |
487 | /// be the shortest. |
488 | template <typename T, typename U, typename... Args> |
489 | detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, |
490 | Args &&... args) { |
491 | return detail::zippy<detail::zip_first, T, U, Args...>( |
492 | std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); |
493 | } |
494 | |
495 | /// Iterator wrapper that concatenates sequences together. |
496 | /// |
497 | /// This can concatenate different iterators, even with different types, into |
498 | /// a single iterator provided the value types of all the concatenated |
499 | /// iterators expose `reference` and `pointer` types that can be converted to |
500 | /// `ValueT &` and `ValueT *` respectively. It doesn't support more |
501 | /// interesting/customized pointer or reference types. |
502 | /// |
503 | /// Currently this only supports forward or higher iterator categories as |
504 | /// inputs and always exposes a forward iterator interface. |
505 | template <typename ValueT, typename... IterTs> |
506 | class concat_iterator |
507 | : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, |
508 | std::forward_iterator_tag, ValueT> { |
509 | using BaseT = typename concat_iterator::iterator_facade_base; |
510 | |
511 | /// We store both the current and end iterators for each concatenated |
512 | /// sequence in a tuple of pairs. |
513 | /// |
514 | /// Note that something like iterator_range seems nice at first here, but the |
515 | /// range properties are of little benefit and end up getting in the way |
516 | /// because we need to do mutation on the current iterators. |
517 | std::tuple<std::pair<IterTs, IterTs>...> IterPairs; |
518 | |
519 | /// Attempts to increment a specific iterator. |
520 | /// |
521 | /// Returns true if it was able to increment the iterator. Returns false if |
522 | /// the iterator is already at the end iterator. |
523 | template <size_t Index> bool incrementHelper() { |
524 | auto &IterPair = std::get<Index>(IterPairs); |
525 | if (IterPair.first == IterPair.second) |
526 | return false; |
527 | |
528 | ++IterPair.first; |
529 | return true; |
530 | } |
531 | |
532 | /// Increments the first non-end iterator. |
533 | /// |
534 | /// It is an error to call this with all iterators at the end. |
535 | template <size_t... Ns> void increment(index_sequence<Ns...>) { |
536 | // Build a sequence of functions to increment each iterator if possible. |
537 | bool (concat_iterator::*IncrementHelperFns[])() = { |
538 | &concat_iterator::incrementHelper<Ns>...}; |
539 | |
540 | // Loop over them, and stop as soon as we succeed at incrementing one. |
541 | for (auto &IncrementHelperFn : IncrementHelperFns) |
542 | if ((this->*IncrementHelperFn)()) |
543 | return; |
544 | |
545 | llvm_unreachable("Attempted to increment an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to increment an end concat iterator!" , "/build/llvm-toolchain-snapshot-7~svn326551/include/llvm/ADT/STLExtras.h" , 545); |
546 | } |
547 | |
548 | /// Returns null if the specified iterator is at the end. Otherwise, |
549 | /// dereferences the iterator and returns the address of the resulting |
550 | /// reference. |
551 | template <size_t Index> ValueT *getHelper() const { |
552 | auto &IterPair = std::get<Index>(IterPairs); |
553 | if (IterPair.first == IterPair.second) |
554 | return nullptr; |
555 | |
556 | return &*IterPair.first; |
557 | } |
558 | |
559 | /// Finds the first non-end iterator, dereferences, and returns the resulting |
560 | /// reference. |
561 | /// |
562 | /// It is an error to call this with all iterators at the end. |
563 | template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const { |
564 | // Build a sequence of functions to get from iterator if possible. |
565 | ValueT *(concat_iterator::*GetHelperFns[])() const = { |
566 | &concat_iterator::getHelper<Ns>...}; |
567 | |
568 | // Loop over them, and return the first result we find. |
569 | for (auto &GetHelperFn : GetHelperFns) |
570 | if (ValueT *P = (this->*GetHelperFn)()) |
571 | return *P; |
572 | |
573 | llvm_unreachable("Attempted to get a pointer from an end concat iterator!")::llvm::llvm_unreachable_internal("Attempted to get a pointer from an end concat iterator!" , "/build/llvm-toolchain-snapshot-7~svn326551/include/llvm/ADT/STLExtras.h" , 573); |
574 | } |
575 | |
576 | public: |
577 | /// Constructs an iterator from a squence of ranges. |
578 | /// |
579 | /// We need the full range to know how to switch between each of the |
580 | /// iterators. |
581 | template <typename... RangeTs> |
582 | explicit concat_iterator(RangeTs &&... Ranges) |
583 | : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {} |
584 | |
585 | using BaseT::operator++; |
586 | |
587 | concat_iterator &operator++() { |
588 | increment(index_sequence_for<IterTs...>()); |
589 | return *this; |
590 | } |
591 | |
592 | ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); } |
593 | |
594 | bool operator==(const concat_iterator &RHS) const { |
595 | return IterPairs == RHS.IterPairs; |
596 | } |
597 | }; |
598 | |
599 | namespace detail { |
600 | |
601 | /// Helper to store a sequence of ranges being concatenated and access them. |
602 | /// |
603 | /// This is designed to facilitate providing actual storage when temporaries |
604 | /// are passed into the constructor such that we can use it as part of range |
605 | /// based for loops. |
606 | template <typename ValueT, typename... RangeTs> class concat_range { |
607 | public: |
608 | using iterator = |
609 | concat_iterator<ValueT, |
610 | decltype(std::begin(std::declval<RangeTs &>()))...>; |
611 | |
612 | private: |
613 | std::tuple<RangeTs...> Ranges; |
614 | |
615 | template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) { |
616 | return iterator(std::get<Ns>(Ranges)...); |
617 | } |
618 | template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) { |
619 | return iterator(make_range(std::end(std::get<Ns>(Ranges)), |
620 | std::end(std::get<Ns>(Ranges)))...); |
621 | } |
622 | |
623 | public: |
624 | concat_range(RangeTs &&... Ranges) |
625 | : Ranges(std::forward<RangeTs>(Ranges)...) {} |
626 | |
627 | iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); } |
628 | iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); } |
629 | }; |
630 | |
631 | } // end namespace detail |
632 | |
633 | /// Concatenated range across two or more ranges. |
634 | /// |
635 | /// The desired value type must be explicitly specified. |
636 | template <typename ValueT, typename... RangeTs> |
637 | detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { |
638 | static_assert(sizeof...(RangeTs) > 1, |
639 | "Need more than one range to concatenate!"); |
640 | return detail::concat_range<ValueT, RangeTs...>( |
641 | std::forward<RangeTs>(Ranges)...); |
642 | } |
643 | |
644 | //===----------------------------------------------------------------------===// |
645 | // Extra additions to <utility> |
646 | //===----------------------------------------------------------------------===// |
647 | |
648 | /// \brief Function object to check whether the first component of a std::pair |
649 | /// compares less than the first component of another std::pair. |
650 | struct less_first { |
651 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { |
652 | return lhs.first < rhs.first; |
653 | } |
654 | }; |
655 | |
656 | /// \brief Function object to check whether the second component of a std::pair |
657 | /// compares less than the second component of another std::pair. |
658 | struct less_second { |
659 | template <typename T> bool operator()(const T &lhs, const T &rhs) const { |
660 | return lhs.second < rhs.second; |
661 | } |
662 | }; |
663 | |
664 | // A subset of N3658. More stuff can be added as-needed. |
665 | |
666 | /// \brief Represents a compile-time sequence of integers. |
667 | template <class T, T... I> struct integer_sequence { |
668 | using value_type = T; |
669 | |
670 | static constexpr size_t size() { return sizeof...(I); } |
671 | }; |
672 | |
673 | /// \brief Alias for the common case of a sequence of size_ts. |
674 | template <size_t... I> |
675 | struct index_sequence : integer_sequence<std::size_t, I...> {}; |
676 | |
677 | template <std::size_t N, std::size_t... I> |
678 | struct build_index_impl : build_index_impl<N - 1, N - 1, I...> {}; |
679 | template <std::size_t... I> |
680 | struct build_index_impl<0, I...> : index_sequence<I...> {}; |
681 | |
682 | /// \brief Creates a compile-time integer sequence for a parameter pack. |
683 | template <class... Ts> |
684 | struct index_sequence_for : build_index_impl<sizeof...(Ts)> {}; |
685 | |
686 | /// Utility type to build an inheritance chain that makes it easy to rank |
687 | /// overload candidates. |
688 | template <int N> struct rank : rank<N - 1> {}; |
689 | template <> struct rank<0> {}; |
690 | |
691 | /// \brief traits class for checking whether type T is one of any of the given |
692 | /// types in the variadic list. |
693 | template <typename T, typename... Ts> struct is_one_of { |
694 | static const bool value = false; |
695 | }; |
696 | |
697 | template <typename T, typename U, typename... Ts> |
698 | struct is_one_of<T, U, Ts...> { |
699 | static const bool value = |
700 | std::is_same<T, U>::value || is_one_of<T, Ts...>::value; |
701 | }; |
702 | |
703 | /// \brief traits class for checking whether type T is a base class for all |
704 | /// the given types in the variadic list. |
705 | template <typename T, typename... Ts> struct are_base_of { |
706 | static const bool value = true; |
707 | }; |
708 | |
709 | template <typename T, typename U, typename... Ts> |
710 | struct are_base_of<T, U, Ts...> { |
711 | static const bool value = |
712 | std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value; |
713 | }; |
714 | |
715 | //===----------------------------------------------------------------------===// |
716 | // Extra additions for arrays |
717 | //===----------------------------------------------------------------------===// |
718 | |
719 | /// Find the length of an array. |
720 | template <class T, std::size_t N> |
721 | constexpr inline size_t array_lengthof(T (&)[N]) { |
722 | return N; |
723 | } |
724 | |
725 | /// Adapt std::less<T> for array_pod_sort. |
726 | template<typename T> |
727 | inline int array_pod_sort_comparator(const void *P1, const void *P2) { |
728 | if (std::less<T>()(*reinterpret_cast<const T*>(P1), |
729 | *reinterpret_cast<const T*>(P2))) |
730 | return -1; |
731 | if (std::less<T>()(*reinterpret_cast<const T*>(P2), |
732 | *reinterpret_cast<const T*>(P1))) |
733 | return 1; |
734 | return 0; |
735 | } |
736 | |
737 | /// get_array_pod_sort_comparator - This is an internal helper function used to |
738 | /// get type deduction of T right. |
739 | template<typename T> |
740 | inline int (*get_array_pod_sort_comparator(const T &)) |
741 | (const void*, const void*) { |
742 | return array_pod_sort_comparator<T>; |
743 | } |
744 | |
745 | /// array_pod_sort - This sorts an array with the specified start and end |
746 | /// extent. This is just like std::sort, except that it calls qsort instead of |
747 | /// using an inlined template. qsort is slightly slower than std::sort, but |
748 | /// most sorts are not performance critical in LLVM and std::sort has to be |
749 | /// template instantiated for each type, leading to significant measured code |
750 | /// bloat. This function should generally be used instead of std::sort where |
751 | /// possible. |
752 | /// |
753 | /// This function assumes that you have simple POD-like types that can be |
754 | /// compared with std::less and can be moved with memcpy. If this isn't true, |
755 | /// you should use std::sort. |
756 | /// |
757 | /// NOTE: If qsort_r were portable, we could allow a custom comparator and |
758 | /// default to std::less. |
759 | template<class IteratorTy> |
760 | inline void array_pod_sort(IteratorTy Start, IteratorTy End) { |
761 | // Don't inefficiently call qsort with one element or trigger undefined |
762 | // behavior with an empty sequence. |
763 | auto NElts = End - Start; |
764 | if (NElts <= 1) return; |
765 | qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); |
766 | } |
767 | |
768 | template <class IteratorTy> |
769 | inline void array_pod_sort( |
770 | IteratorTy Start, IteratorTy End, |
771 | int (*Compare)( |
772 | const typename std::iterator_traits<IteratorTy>::value_type *, |
773 | const typename std::iterator_traits<IteratorTy>::value_type *)) { |
774 | // Don't inefficiently call qsort with one element or trigger undefined |
775 | // behavior with an empty sequence. |
776 | auto NElts = End - Start; |
777 | if (NElts <= 1) return; |
778 | qsort(&*Start, NElts, sizeof(*Start), |
779 | reinterpret_cast<int (*)(const void *, const void *)>(Compare)); |
780 | } |
781 | |
782 | //===----------------------------------------------------------------------===// |
783 | // Extra additions to <algorithm> |
784 | //===----------------------------------------------------------------------===// |
785 | |
786 | /// For a container of pointers, deletes the pointers and then clears the |
787 | /// container. |
788 | template<typename Container> |
789 | void DeleteContainerPointers(Container &C) { |
790 | for (auto V : C) |
791 | delete V; |
792 | C.clear(); |
793 | } |
794 | |
795 | /// In a container of pairs (usually a map) whose second element is a pointer, |
796 | /// deletes the second elements and then clears the container. |
797 | template<typename Container> |
798 | void DeleteContainerSeconds(Container &C) { |
799 | for (auto &V : C) |
800 | delete V.second; |
801 | C.clear(); |
802 | } |
803 | |
804 | /// Provide wrappers to std::for_each which take ranges instead of having to |
805 | /// pass begin/end explicitly. |
806 | template <typename R, typename UnaryPredicate> |
807 | UnaryPredicate for_each(R &&Range, UnaryPredicate P) { |
808 | return std::for_each(adl_begin(Range), adl_end(Range), P); |
809 | } |
810 | |
811 | /// Provide wrappers to std::all_of which take ranges instead of having to pass |
812 | /// begin/end explicitly. |
813 | template <typename R, typename UnaryPredicate> |
814 | bool all_of(R &&Range, UnaryPredicate P) { |
815 | return std::all_of(adl_begin(Range), adl_end(Range), P); |
816 | } |
817 | |
818 | /// Provide wrappers to std::any_of which take ranges instead of having to pass |
819 | /// begin/end explicitly. |
820 | template <typename R, typename UnaryPredicate> |
821 | bool any_of(R &&Range, UnaryPredicate P) { |
822 | return std::any_of(adl_begin(Range), adl_end(Range), P); |
823 | } |
824 | |
825 | /// Provide wrappers to std::none_of which take ranges instead of having to pass |
826 | /// begin/end explicitly. |
827 | template <typename R, typename UnaryPredicate> |
828 | bool none_of(R &&Range, UnaryPredicate P) { |
829 | return std::none_of(adl_begin(Range), adl_end(Range), P); |
830 | } |
831 | |
832 | /// Provide wrappers to std::find which take ranges instead of having to pass |
833 | /// begin/end explicitly. |
834 | template <typename R, typename T> |
835 | auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { |
836 | return std::find(adl_begin(Range), adl_end(Range), Val); |
837 | } |
838 | |
839 | /// Provide wrappers to std::find_if which take ranges instead of having to pass |
840 | /// begin/end explicitly. |
841 | template <typename R, typename UnaryPredicate> |
842 | auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
843 | return std::find_if(adl_begin(Range), adl_end(Range), P); |
844 | } |
845 | |
846 | template <typename R, typename UnaryPredicate> |
847 | auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
848 | return std::find_if_not(adl_begin(Range), adl_end(Range), P); |
849 | } |
850 | |
851 | /// Provide wrappers to std::remove_if which take ranges instead of having to |
852 | /// pass begin/end explicitly. |
853 | template <typename R, typename UnaryPredicate> |
854 | auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
855 | return std::remove_if(adl_begin(Range), adl_end(Range), P); |
856 | } |
857 | |
858 | /// Provide wrappers to std::copy_if which take ranges instead of having to |
859 | /// pass begin/end explicitly. |
860 | template <typename R, typename OutputIt, typename UnaryPredicate> |
861 | OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { |
862 | return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); |
863 | } |
864 | |
865 | template <typename R, typename OutputIt> |
866 | OutputIt copy(R &&Range, OutputIt Out) { |
867 | return std::copy(adl_begin(Range), adl_end(Range), Out); |
868 | } |
869 | |
870 | /// Wrapper function around std::find to detect if an element exists |
871 | /// in a container. |
872 | template <typename R, typename E> |
873 | bool is_contained(R &&Range, const E &Element) { |
874 | return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); |
875 | } |
876 | |
877 | /// Wrapper function around std::count to count the number of times an element |
878 | /// \p Element occurs in the given range \p Range. |
879 | template <typename R, typename E> |
880 | auto count(R &&Range, const E &Element) -> |
881 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { |
882 | return std::count(adl_begin(Range), adl_end(Range), Element); |
883 | } |
884 | |
885 | /// Wrapper function around std::count_if to count the number of times an |
886 | /// element satisfying a given predicate occurs in a range. |
887 | template <typename R, typename UnaryPredicate> |
888 | auto count_if(R &&Range, UnaryPredicate P) -> |
889 | typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { |
890 | return std::count_if(adl_begin(Range), adl_end(Range), P); |
891 | } |
892 | |
893 | /// Wrapper function around std::transform to apply a function to a range and |
894 | /// store the result elsewhere. |
895 | template <typename R, typename OutputIt, typename UnaryPredicate> |
896 | OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { |
897 | return std::transform(adl_begin(Range), adl_end(Range), d_first, P); |
898 | } |
899 | |
900 | /// Provide wrappers to std::partition which take ranges instead of having to |
901 | /// pass begin/end explicitly. |
902 | template <typename R, typename UnaryPredicate> |
903 | auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { |
904 | return std::partition(adl_begin(Range), adl_end(Range), P); |
905 | } |
906 | |
907 | /// Provide wrappers to std::lower_bound which take ranges instead of having to |
908 | /// pass begin/end explicitly. |
909 | template <typename R, typename ForwardIt> |
910 | auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range)) { |
911 | return std::lower_bound(adl_begin(Range), adl_end(Range), I); |
912 | } |
913 | |
914 | /// \brief Given a range of type R, iterate the entire range and return a |
915 | /// SmallVector with elements of the vector. This is useful, for example, |
916 | /// when you want to iterate a range and then sort the results. |
917 | template <unsigned Size, typename R> |
918 | SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size> |
919 | to_vector(R &&Range) { |
920 | return {adl_begin(Range), adl_end(Range)}; |
921 | } |
922 | |
923 | /// Provide a container algorithm similar to C++ Library Fundamentals v2's |
924 | /// `erase_if` which is equivalent to: |
925 | /// |
926 | /// C.erase(remove_if(C, pred), C.end()); |
927 | /// |
928 | /// This version works for any container with an erase method call accepting |
929 | /// two iterators. |
930 | template <typename Container, typename UnaryPredicate> |
931 | void erase_if(Container &C, UnaryPredicate P) { |
932 | C.erase(remove_if(C, P), C.end()); |
933 | } |
934 | |
935 | //===----------------------------------------------------------------------===// |
936 | // Extra additions to <memory> |
937 | //===----------------------------------------------------------------------===// |
938 | |
939 | // Implement make_unique according to N3656. |
940 | |
941 | /// \brief Constructs a `new T()` with the given args and returns a |
942 | /// `unique_ptr<T>` which owns the object. |
943 | /// |
944 | /// Example: |
945 | /// |
946 | /// auto p = make_unique<int>(); |
947 | /// auto p = make_unique<std::tuple<int, int>>(0, 1); |
948 | template <class T, class... Args> |
949 | typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type |
950 | make_unique(Args &&... args) { |
951 | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); |
952 | } |
953 | |
954 | /// \brief Constructs a `new T[n]` with the given args and returns a |
955 | /// `unique_ptr<T[]>` which owns the object. |
956 | /// |
957 | /// \param n size of the new array. |
958 | /// |
959 | /// Example: |
960 | /// |
961 | /// auto p = make_unique<int[]>(2); // value-initializes the array with 0's. |
962 | template <class T> |
963 | typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, |
964 | std::unique_ptr<T>>::type |
965 | make_unique(size_t n) { |
966 | return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]()); |
967 | } |
968 | |
969 | /// This function isn't used and is only here to provide better compile errors. |
970 | template <class T, class... Args> |
971 | typename std::enable_if<std::extent<T>::value != 0>::type |
972 | make_unique(Args &&...) = delete; |
973 | |
974 | struct FreeDeleter { |
975 | void operator()(void* v) { |
976 | ::free(v); |
977 | } |
978 | }; |
979 | |
980 | template<typename First, typename Second> |
981 | struct pair_hash { |
982 | size_t operator()(const std::pair<First, Second> &P) const { |
983 | return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); |
984 | } |
985 | }; |
986 | |
987 | /// A functor like C++14's std::less<void> in its absence. |
988 | struct less { |
989 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { |
990 | return std::forward<A>(a) < std::forward<B>(b); |
991 | } |
992 | }; |
993 | |
994 | /// A functor like C++14's std::equal<void> in its absence. |
995 | struct equal { |
996 | template <typename A, typename B> bool operator()(A &&a, B &&b) const { |
997 | return std::forward<A>(a) == std::forward<B>(b); |
998 | } |
999 | }; |
1000 | |
1001 | /// Binary functor that adapts to any other binary functor after dereferencing |
1002 | /// operands. |
1003 | template <typename T> struct deref { |
1004 | T func; |
1005 | |
1006 | // Could be further improved to cope with non-derivable functors and |
1007 | // non-binary functors (should be a variadic template member function |
1008 | // operator()). |
1009 | template <typename A, typename B> |
1010 | auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { |
1011 | assert(lhs)(static_cast <bool> (lhs) ? void (0) : __assert_fail ("lhs" , "/build/llvm-toolchain-snapshot-7~svn326551/include/llvm/ADT/STLExtras.h" , 1011, __extension__ __PRETTY_FUNCTION__)); |
1012 | assert(rhs)(static_cast <bool> (rhs) ? void (0) : __assert_fail ("rhs" , "/build/llvm-toolchain-snapshot-7~svn326551/include/llvm/ADT/STLExtras.h" , 1012, __extension__ __PRETTY_FUNCTION__)); |
1013 | return func(*lhs, *rhs); |
1014 | } |
1015 | }; |
1016 | |
1017 | namespace detail { |
1018 | |
1019 | template <typename R> class enumerator_iter; |
1020 | |
1021 | template <typename R> struct result_pair { |
1022 | friend class enumerator_iter<R>; |
1023 | |
1024 | result_pair() = default; |
1025 | result_pair(std::size_t Index, IterOfRange<R> Iter) |
1026 | : Index(Index), Iter(Iter) {} |
1027 | |
1028 | result_pair<R> &operator=(const result_pair<R> &Other) { |
1029 | Index = Other.Index; |
1030 | Iter = Other.Iter; |
1031 | return *this; |
1032 | } |
1033 | |
1034 | std::size_t index() const { return Index; } |
1035 | const ValueOfRange<R> &value() const { return *Iter; } |
1036 | ValueOfRange<R> &value() { return *Iter; } |
1037 | |
1038 | private: |
1039 | std::size_t Index = std::numeric_limits<std::size_t>::max(); |
1040 | IterOfRange<R> Iter; |
1041 | }; |
1042 | |
1043 | template <typename R> |
1044 | class enumerator_iter |
1045 | : public iterator_facade_base< |
1046 | enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>, |
1047 | typename std::iterator_traits<IterOfRange<R>>::difference_type, |
1048 | typename std::iterator_traits<IterOfRange<R>>::pointer, |
1049 | typename std::iterator_traits<IterOfRange<R>>::reference> { |
1050 | using result_type = result_pair<R>; |
1051 | |
1052 | public: |
1053 | explicit enumerator_iter(IterOfRange<R> EndIter) |
1054 | : Result(std::numeric_limits<size_t>::max(), EndIter) {} |
1055 | |
1056 | enumerator_iter(std::size_t Index, IterOfRange<R> Iter) |
1057 | : Result(Index, Iter) {} |
1058 | |
1059 | result_type &operator*() { return Result; } |
1060 | const result_type &operator*() const { return Result; } |
1061 | |
1062 | enumerator_iter<R> &operator++() { |
1063 | assert(Result.Index != std::numeric_limits<size_t>::max())(static_cast <bool> (Result.Index != std::numeric_limits <size_t>::max()) ? void (0) : __assert_fail ("Result.Index != std::numeric_limits<size_t>::max()" , "/build/llvm-toolchain-snapshot-7~svn326551/include/llvm/ADT/STLExtras.h" , 1063, __extension__ __PRETTY_FUNCTION__)); |
1064 | ++Result.Iter; |
1065 | ++Result.Index; |
1066 | return *this; |
1067 | } |
1068 | |
1069 | bool operator==(const enumerator_iter<R> &RHS) const { |
1070 | // Don't compare indices here, only iterators. It's possible for an end |
1071 | // iterator to have different indices depending on whether it was created |
1072 | // by calling std::end() versus incrementing a valid iterator. |
1073 | return Result.Iter == RHS.Result.Iter; |
1074 | } |
1075 | |
1076 | enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) { |
1077 | Result = Other.Result; |
1078 | return *this; |
1079 | } |
1080 | |
1081 | private: |
1082 | result_type Result; |
1083 | }; |
1084 | |
1085 | template <typename R> class enumerator { |
1086 | public: |
1087 | explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} |
1088 | |
1089 | enumerator_iter<R> begin() { |
1090 | return enumerator_iter<R>(0, std::begin(TheRange)); |
1091 | } |
1092 | |
1093 | enumerator_iter<R> end() { |
1094 | return enumerator_iter<R>(std::end(TheRange)); |
1095 | } |
1096 | |
1097 | private: |
1098 | R TheRange; |
1099 | }; |
1100 | |
1101 | } // end namespace detail |
1102 | |
1103 | /// Given an input range, returns a new range whose values are are pair (A,B) |
1104 | /// such that A is the 0-based index of the item in the sequence, and B is |
1105 | /// the value from the original sequence. Example: |
1106 | /// |
1107 | /// std::vector<char> Items = {'A', 'B', 'C', 'D'}; |
1108 | /// for (auto X : enumerate(Items)) { |
1109 | /// printf("Item %d - %c\n", X.index(), X.value()); |
1110 | /// } |
1111 | /// |
1112 | /// Output: |
1113 | /// Item 0 - A |
1114 | /// Item 1 - B |
1115 | /// Item 2 - C |
1116 | /// Item 3 - D |
1117 | /// |
1118 | template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { |
1119 | return detail::enumerator<R>(std::forward<R>(TheRange)); |
1120 | } |
1121 | |
1122 | namespace detail { |
1123 | |
1124 | template <typename F, typename Tuple, std::size_t... I> |
1125 | auto apply_tuple_impl(F &&f, Tuple &&t, index_sequence<I...>) |
1126 | -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) { |
1127 | return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); |
1128 | } |
1129 | |
1130 | } // end namespace detail |
1131 | |
1132 | /// Given an input tuple (a1, a2, ..., an), pass the arguments of the |
1133 | /// tuple variadically to f as if by calling f(a1, a2, ..., an) and |
1134 | /// return the result. |
1135 | template <typename F, typename Tuple> |
1136 | auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( |
1137 | std::forward<F>(f), std::forward<Tuple>(t), |
1138 | build_index_impl< |
1139 | std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { |
1140 | using Indices = build_index_impl< |
1141 | std::tuple_size<typename std::decay<Tuple>::type>::value>; |
1142 | |
1143 | return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), |
1144 | Indices{}); |
1145 | } |
1146 | |
1147 | } // end namespace llvm |
1148 | |
1149 | #endif // LLVM_ADT_STLEXTRAS_H |