LLVM 24.0.0git
VirtualOutputBackends.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the VirtualOutputBackend types, including:
11/// * NullOutputBackend: Outputs to NullOutputBackend are discarded.
12/// * FilteringOutputBackend: Filter paths from output.
13/// * MirroringOutputBackend: Mirror the output into two different backend.
14/// * OnDiskOutputBackend: Write output files to disk.
15///
16//===----------------------------------------------------------------------===//
17
19#include "llvm/ADT/ScopeExit.h"
24#include "llvm/Support/Path.h"
29
30using namespace llvm;
31using namespace llvm::vfs;
32
33void ProxyOutputBackend::anchor() {}
34void OnDiskOutputBackend::anchor() {}
35
37 struct NullOutputBackend : public OutputBackend {
38 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
39 return const_cast<NullOutputBackend *>(this);
40 }
42 createFileImpl(StringRef Path, std::optional<OutputConfig>) override {
43 return std::make_unique<NullOutputFileImpl>();
44 }
45 };
46
48}
49
51 IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend,
52 std::function<bool(StringRef, std::optional<OutputConfig>)> Filter) {
53 struct FilteringOutputBackend : public ProxyOutputBackend {
55 createFileImpl(StringRef Path,
56 std::optional<OutputConfig> Config) override {
57 if (Filter(Path, Config))
58 return ProxyOutputBackend::createFileImpl(Path, Config);
59 return std::make_unique<NullOutputFileImpl>();
60 }
61
62 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
64 getUnderlyingBackend().clone(), Filter);
65 }
66
67 FilteringOutputBackend(
68 IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend,
69 std::function<bool(StringRef, std::optional<OutputConfig>)> Filter)
70 : ProxyOutputBackend(std::move(UnderlyingBackend)),
71 Filter(std::move(Filter)) {
72 assert(this->Filter && "Expected a non-null function");
73 }
74 std::function<bool(StringRef, std::optional<OutputConfig>)> Filter;
75 };
76
78 std::move(UnderlyingBackend), std::move(Filter));
79}
80
84 struct ProxyOutputBackend1 : public ProxyOutputBackend {
86 };
87 struct ProxyOutputBackend2 : public ProxyOutputBackend {
89 };
90 struct MirroringOutput final : public OutputFileImpl, raw_pwrite_stream {
91 Error keep() final {
92 flush();
93 return joinErrors(F1->keep(), F2->keep());
94 }
95 Error discard() final {
96 flush();
97 return joinErrors(F1->discard(), F2->discard());
98 }
99 raw_pwrite_stream &getOS() final { return *this; }
100
101 void write_impl(const char *Ptr, size_t Size) override {
102 F1->getOS().write(Ptr, Size);
103 F2->getOS().write(Ptr, Size);
104 }
105 void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override {
106 this->flush();
107 F1->getOS().pwrite(Ptr, Size, Offset);
108 F2->getOS().pwrite(Ptr, Size, Offset);
109 }
110 uint64_t current_pos() const override { return F1->getOS().tell(); }
111 size_t preferred_buffer_size() const override {
112 return PreferredBufferSize;
113 }
114 void reserveExtraSpace(uint64_t ExtraSize) override {
115 F1->getOS().reserveExtraSpace(ExtraSize);
116 F2->getOS().reserveExtraSpace(ExtraSize);
117 }
118 bool is_displayed() const override {
119 return F1->getOS().is_displayed() && F2->getOS().is_displayed();
120 }
121 bool has_colors() const override {
122 return F1->getOS().has_colors() && F2->getOS().has_colors();
123 }
124 void enable_colors(bool enable) override {
126 F1->getOS().enable_colors(enable);
127 F2->getOS().enable_colors(enable);
128 }
129
130 MirroringOutput(std::unique_ptr<OutputFileImpl> F1,
131 std::unique_ptr<OutputFileImpl> F2)
132 : PreferredBufferSize(std::max(F1->getOS().GetBufferSize(),
133 F1->getOS().GetBufferSize())),
134 F1(std::move(F1)), F2(std::move(F2)) {}
135
136 size_t PreferredBufferSize;
137 std::unique_ptr<OutputFileImpl> F1;
138 std::unique_ptr<OutputFileImpl> F2;
139 };
140 struct MirroringOutputBackend : public ProxyOutputBackend1,
141 public ProxyOutputBackend2 {
143 createFileImpl(StringRef Path,
144 std::optional<OutputConfig> Config) override {
145 std::unique_ptr<OutputFileImpl> File1;
146 std::unique_ptr<OutputFileImpl> File2;
147 if (Error E =
148 ProxyOutputBackend1::createFileImpl(Path, Config).moveInto(File1))
149 return std::move(E);
150 if (Error E =
151 ProxyOutputBackend2::createFileImpl(Path, Config).moveInto(File2))
152 return joinErrors(std::move(E), File1->discard());
153
154 // Skip the extra indirection if one of these is a null output.
155 if (isa<NullOutputFileImpl>(*File1)) {
156 consumeError(File1->discard());
157 return std::move(File2);
158 }
159 if (isa<NullOutputFileImpl>(*File2)) {
160 consumeError(File2->discard());
161 return std::move(File1);
162 }
163 return std::make_unique<MirroringOutput>(std::move(File1),
164 std::move(File2));
165 }
166
167 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
170 ProxyOutputBackend1::getUnderlyingBackend().clone(),
171 ProxyOutputBackend2::getUnderlyingBackend().clone()));
172 }
173 void Retain() const { ProxyOutputBackend1::Retain(); }
174 void Release() const { ProxyOutputBackend1::Release(); }
175
176 MirroringOutputBackend(IntrusiveRefCntPtr<OutputBackend> Backend1,
178 : ProxyOutputBackend1(std::move(Backend1)),
179 ProxyOutputBackend2(std::move(Backend2)) {}
180 };
181
182 assert(Backend1 && "Expected actual backend");
183 assert(Backend2 && "Expected actual backend");
186 std::move(Backend2)));
187}
188
189static OutputConfig
190applySettings(std::optional<OutputConfig> &&Config,
191 const OnDiskOutputBackend::OutputSettings &Settings) {
192 if (!Config)
193 Config = Settings.DefaultConfig;
194 if (!Settings.UseTemporaries)
195 Config->setNoAtomicWrite();
196 if (!Settings.RemoveOnSignal)
197 Config->setNoDiscardOnSignal();
198 return *Config;
199}
200
201namespace {
202class OnDiskOutputFile final : public OutputFileImpl {
203public:
204 Error keep() override;
205 Error discard() override;
206 raw_pwrite_stream &getOS() override {
207 assert(FileOS && "Expected valid file");
208 if (BufferOS)
209 return *BufferOS;
210 return *FileOS;
211 }
212
213 /// Attempt to open a temporary file for \p OutputPath.
214 ///
215 /// This tries to open a uniquely-named temporary file for \p OutputPath,
216 /// possibly also creating any missing directories if \a
217 /// OnDiskOutputConfig::UseTemporaryCreateMissingDirectories is set in \a
218 /// Config.
219 ///
220 /// \post FD and \a TempPath are initialized if this is successful.
221 Error tryToCreateTemporary(std::optional<int> &FD);
222
223 Error initializeFile(std::optional<int> &FD);
224 Error initializeStream();
225 Error reset();
226
227 OnDiskOutputFile(StringRef OutputPath, std::optional<OutputConfig> Config,
228 const OnDiskOutputBackend::OutputSettings &Settings)
229 : Config(applySettings(std::move(Config), Settings)),
230 OutputPath(OutputPath.str()) {}
231
232 OutputConfig Config;
233 const std::string OutputPath;
234 std::optional<std::string> TempPath;
235 std::optional<raw_fd_ostream> FileOS;
236 std::optional<buffer_ostream> BufferOS;
237};
238} // end namespace
239
241 OutputConfig Config,
242 llvm::function_ref<Error()> CreateFile) {
243 return handleErrors(CreateFile(), [&](std::unique_ptr<ECError> EC) {
244 if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory ||
245 Config.getNoImplyCreateDirectories())
246 return Error(std::move(EC));
247
248 StringRef ParentPath = sys::path::parent_path(OutputPath);
249 if (std::error_code EC = sys::fs::create_directories(ParentPath))
250 return make_error<OutputError>(ParentPath, EC);
251 return CreateFile();
252 });
253}
254
257 if (Config.getTextWithCRLF())
259 else if (Config.getText())
260 OF |= sys::fs::OF_Text;
261 // Don't pass OF_Append if writting to temporary since OF_Append is
262 // not Atomic Append
263 if (Config.getAppend() && !Config.getAtomicWrite())
264 OF |= sys::fs::OF_Append;
265
266 return OF;
267}
268
269Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
270 auto BypassSandbox = sys::sandbox::scopedDisable();
271
272 // Create a temporary file.
273 // Insert -%%%%%%%% before the extension (if any), and because some tools
274 // (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
275 // artifacts, also append .tmp.
276 StringRef OutputExtension = sys::path::extension(OutputPath);
277 SmallString<128> ModelPath =
278 StringRef(OutputPath).drop_back(OutputExtension.size());
279 ModelPath += "-%%%%%%%%";
280 ModelPath += OutputExtension;
281 ModelPath += ".tmp";
282
283 return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
284 int NewFD;
285 SmallString<128> UniquePath;
287 if (std::error_code EC =
288 sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath, OF))
289 return make_error<TempFileOutputError>(ModelPath, OutputPath, EC);
290
291 if (Config.getDiscardOnSignal())
292 sys::RemoveFileOnSignal(UniquePath);
293
294 TempPath = UniquePath.str().str();
295 FD.emplace(NewFD);
296 return Error::success();
297 });
298}
299
300Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
301 auto BypassSandbox = sys::sandbox::scopedDisable();
302
303 assert(OutputPath != "-" && "Unexpected request for FD of stdout");
304
305 // Disable temporary file for other non-regular files, and if we get a status
306 // object, also check if in append mode we can write and disable write-through
307 // buffers if appropriate.
308 if (Config.getAtomicWrite()) {
309 sys::fs::file_status Status;
310 sys::fs::status(OutputPath, Status);
311 if (sys::fs::exists(Status)) {
313 Config.setNoAtomicWrite();
314
315 // In append mode, we will open the file for writing which will need write
316 // permission. Fail now if it is already clear that we can't write to the
317 // final destination.
318 // In non-append mode, we will delete and replace the file. Permission
319 // bits of the file itself are irrelevant in this case.
320 if (Config.getAppend() && !sys::fs::can_write(OutputPath))
322 OutputPath,
323 std::make_error_code(std::errc::operation_not_permitted));
324 }
325 }
326
327 // If (still) using a temporary file, try to create it (and return success if
328 // that works).
329 if (Config.getAtomicWrite())
330 if (!errorToBool(tryToCreateTemporary(FD)))
331 return Error::success();
332
333 // Not using a temporary file. Open the final output file.
334 return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
335 int NewFD;
337 if (std::error_code EC = sys::fs::openFileForWrite(
338 OutputPath, NewFD, sys::fs::CD_CreateAlways, OF))
339 return convertToOutputError(OutputPath, EC);
340 FD.emplace(NewFD);
341
342 if (Config.getDiscardOnSignal())
343 sys::RemoveFileOnSignal(OutputPath);
344 return Error::success();
345 });
346}
347
348Error OnDiskOutputFile::initializeStream() {
349 auto BypassSandbox = sys::sandbox::scopedDisable();
350
351 // Open the file stream.
352 if (OutputPath == "-") {
353 std::error_code EC;
354 FileOS.emplace(OutputPath, EC);
355 if (EC)
356 return make_error<OutputError>(OutputPath, EC);
357 } else {
358 std::optional<int> FD;
359 if (Error E = initializeFile(FD))
360 return E;
361 FileOS.emplace(*FD, /*shouldClose=*/true);
362 }
363
364 // Buffer the stream if necessary.
365 if (!FileOS->supportsSeeking() && !Config.getText())
366 BufferOS.emplace(*FileOS);
367
368 return Error::success();
369}
370
371namespace {
372class OpenFileRAII {
373 static const int InvalidFd = -1;
374
375public:
376 int Fd = InvalidFd;
377
378 ~OpenFileRAII() {
379 if (Fd != InvalidFd)
381 }
382};
383
384enum class FileDifference : uint8_t {
385 /// The source and destination paths refer to the exact same file.
386 IdenticalFile,
387 /// The source and destination paths refer to separate files with identical
388 /// contents.
389 SameContents,
390 /// The source and destination paths refer to separate files with different
391 /// contents.
392 DifferentContents
393};
394} // end anonymous namespace
395
396static Expected<FileDifference>
397areFilesDifferent(const llvm::Twine &Source, const llvm::Twine &Destination) {
398 if (sys::fs::equivalent(Source, Destination))
399 return FileDifference::IdenticalFile;
400
401 OpenFileRAII SourceFile;
402 sys::fs::file_status SourceStatus;
403 // If we can't open the source file, fail.
404 if (std::error_code EC = sys::fs::openFileForRead(Source, SourceFile.Fd))
405 return convertToOutputError(Source, EC);
406
407 // If we can't stat the source file, fail.
408 if (std::error_code EC = sys::fs::status(SourceFile.Fd, SourceStatus))
409 return convertToOutputError(Source, EC);
410
411 OpenFileRAII DestFile;
412 sys::fs::file_status DestStatus;
413 // If we can't open the destination file, report different.
414 if (std::error_code Error =
415 sys::fs::openFileForRead(Destination, DestFile.Fd))
416 return FileDifference::DifferentContents;
417
418 // If we can't open the destination file, report different.
419 if (std::error_code Error = sys::fs::status(DestFile.Fd, DestStatus))
420 return FileDifference::DifferentContents;
421
422 // If the files are different sizes, they must be different.
423 uint64_t Size = SourceStatus.getSize();
424 if (Size != DestStatus.getSize())
425 return FileDifference::DifferentContents;
426
427 // If both files are zero size, they must be the same.
428 if (Size == 0)
429 return FileDifference::SameContents;
430
431 // The two files match in size, so we have to compare the bytes to determine
432 // if they're the same.
433 std::error_code SourceRegionErr;
434 sys::fs::mapped_file_region SourceRegion(
435 sys::fs::convertFDToNativeFile(SourceFile.Fd),
436 sys::fs::mapped_file_region::readonly, Size, 0, SourceRegionErr);
437 if (SourceRegionErr)
438 return convertToOutputError(Source, SourceRegionErr);
439
440 std::error_code DestRegionErr;
444
445 if (DestRegionErr)
446 return FileDifference::DifferentContents;
447
448 if (memcmp(SourceRegion.const_data(), DestRegion.const_data(), Size) != 0)
449 return FileDifference::DifferentContents;
450
451 return FileDifference::SameContents;
452}
453
454Error OnDiskOutputFile::reset() {
455 auto BypassSandbox = sys::sandbox::scopedDisable();
456
457 // Destroy the streams to flush them.
458 BufferOS.reset();
459 if (!FileOS)
460 return Error::success();
461
462 // Remember the error in raw_fd_ostream to be reported later.
463 std::error_code EC = FileOS->error();
464 // Clear the error to avoid fatal error when reset.
465 FileOS->clear_error();
466 FileOS.reset();
467 return errorCodeToError(EC);
468}
469
470Error OnDiskOutputFile::keep() {
471 auto BypassSandbox = sys::sandbox::scopedDisable();
472
473 if (auto E = reset())
474 return E;
475
476 // Close the file descriptor and remove crash cleanup before exit.
477 llvm::scope_exit RemoveDiscardOnSignal([&]() {
478 if (Config.getDiscardOnSignal())
479 sys::DontRemoveFileOnSignal(TempPath ? *TempPath : OutputPath);
480 });
481
482 if (!TempPath)
483 return Error::success();
484
485 // See if we should append instead of move.
486 if (Config.getAppend() && OutputPath != "-") {
487 // Read TempFile for the content to append.
488 auto Content = MemoryBuffer::getFile(*TempPath);
489 if (!Content)
490 return convertToTempFileOutputError(*TempPath, OutputPath,
491 Content.getError());
492 while (1) {
493 // Attempt to lock the output file.
494 // Only one process is allowed to append to this file at a time.
495 llvm::LockFileManager Lock(OutputPath);
496 bool Owned;
497 if (Error Err = Lock.tryLock().moveInto(Owned)) {
498 // If we error acquiring a lock, we cannot ensure appends
499 // to the trace file are atomic - cannot ensure output correctness.
500 Lock.unsafeUnlock();
502 OutputPath, std::make_error_code(std::errc::no_lock_available));
503 }
504 if (Owned) {
505 // Lock acquired, perform the write and release the lock.
506 std::error_code EC;
507 llvm::raw_fd_ostream Out(OutputPath, EC, llvm::sys::fs::OF_Append);
508 if (EC)
509 return convertToOutputError(OutputPath, EC);
510 Out << (*Content)->getBuffer();
511 Out.close();
512 Lock.unsafeUnlock();
513 if (Out.has_error())
514 return convertToOutputError(OutputPath, Out.error());
515 // Remove temp file and done.
516 (void)sys::fs::remove(*TempPath);
517 return Error::success();
518 }
519 // Someone else owns the lock on this file, wait.
520 switch (Lock.waitForUnlockFor(std::chrono::seconds(256))) {
522 [[fallthrough]];
524 continue; // try again to get the lock.
525 }
527 // We could error on timeout to avoid potentially hanging forever, but
528 // it may be more likely that an interrupted process failed to clear
529 // the lock, causing other waiting processes to time-out. Let's clear
530 // the lock and try again right away. If we do start seeing compiler
531 // hangs in this location, we will need to re-consider.
532 Lock.unsafeUnlock();
533 continue;
534 }
535 }
536 break;
537 }
538 }
539
540 if (Config.getOnlyIfDifferent()) {
541 auto Result = areFilesDifferent(*TempPath, OutputPath);
542 if (!Result)
543 return Result.takeError();
544 switch (*Result) {
545 case FileDifference::IdenticalFile:
546 // Do nothing for a self-move.
547 return Error::success();
548
549 case FileDifference::SameContents:
550 // Files are identical; remove the source file.
551 (void)sys::fs::remove(*TempPath);
552 return Error::success();
553
554 case FileDifference::DifferentContents:
555 break; // Rename the file.
556 }
557 }
558
559 // Move temporary to the final output path and remove it if that fails.
560 std::error_code RenameEC = sys::fs::rename(*TempPath, OutputPath);
561 if (!RenameEC)
562 return Error::success();
563
564 // FIXME: TempPath should be in the same directory as OutputPath but try to
565 // copy the output to see if makes any difference. If this path is used,
566 // investigate why we need to copy.
567 RenameEC = sys::fs::copy_file(*TempPath, OutputPath);
568 (void)sys::fs::remove(*TempPath);
569
570 if (!RenameEC)
571 return Error::success();
572
573 return make_error<TempFileOutputError>(*TempPath, OutputPath, RenameEC);
574}
575
576Error OnDiskOutputFile::discard() {
577 auto BypassSandbox = sys::sandbox::scopedDisable();
578
579 // Destroy the streams to flush them.
580 if (auto E = reset())
581 return E;
582
583 // Nothing on the filesystem to remove for stdout.
584 if (OutputPath == "-")
585 return Error::success();
586
587 auto discardPath = [&](StringRef Path) {
588 std::error_code EC = sys::fs::remove(Path);
590 return EC;
591 };
592
593 // Clean up the file that's in-progress.
594 if (!TempPath)
595 return convertToOutputError(OutputPath, discardPath(OutputPath));
596 return convertToTempFileOutputError(*TempPath, OutputPath,
597 discardPath(*TempPath));
598}
599
601 // FIXME: Should this really call sys::fs::make_absolute?
602 auto BypassSandbox = sys::sandbox::scopedDisable();
603 return convertToOutputError(StringRef(Path.data(), Path.size()),
605}
606
609 std::optional<OutputConfig> Config) {
610 auto BypassSandbox = sys::sandbox::scopedDisable();
611
612 SmallString<256> AbsPath;
613 if (Path != "-") {
614 AbsPath = Path;
615 if (Error E = makeAbsolute(AbsPath))
616 return std::move(E);
617 Path = AbsPath;
618 }
619
620 auto File = std::make_unique<OnDiskOutputFile>(Path, Config, Settings);
621 if (Error E = File->initializeStream())
622 return std::move(E);
623
624 return std::move(File);
625}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static Error createDirectoriesOnDemand(StringRef OutputPath, OutputConfig Config, llvm::function_ref< Error()> CreateFile)
static Expected< FileDifference > areFilesDifferent(const llvm::Twine &Source, const llvm::Twine &Destination)
static sys::fs::OpenFlags generateFlagsFromConfig(OutputConfig Config)
static OutputConfig applySettings(std::optional< OutputConfig > &&Config, const OnDiskOutputBackend::OutputSettings &Settings)
This file contains the declarations of the concrete VirtualOutputBackend classes, which are the imple...
This file contains the declarations of the OutputConfig class.
This file contains the declarations of the OutputError class.
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr size_t size() const
Get the string size.
Definition StringRef.h:144
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
An efficient, type-erasing, non-owning reference to a callable.
raw_ostream & write(unsigned char C)
virtual void enable_colors(bool enable)
An abstract base class for streams implementations that also support a pwrite operation.
static LLVM_ABI std::error_code SafelyCloseFileDescriptor(int FD)
Represents the result of a call to sys::fs::status().
Definition FileSystem.h:222
This class represents a memory mapped file.
@ readonly
May only access map via const_data as read only.
LLVM_ABI const char * const_data() const
Get a const view of the data.
Definition Path.cpp:1222
Represents an open file.
Expected< std::unique_ptr< OutputFileImpl > > createFileImpl(StringRef Path, std::optional< OutputConfig > Config) override
Create a file for Path.
OutputSettings Settings
Settings for this backend.
Error makeAbsolute(SmallVectorImpl< char > &Path) const
Resolve an absolute path.
Interface for virtualized outputs.
A helper class for proxying another backend, with the default implementation to forward to the underl...
ProxyOutputBackend(IntrusiveRefCntPtr< OutputBackend > UnderlyingBackend)
Expected< std::unique_ptr< OutputFileImpl > > createFileImpl(StringRef Path, std::optional< OutputConfig > Config) override
Create a file for Path.
The result of a status operation.
CallInst * Retain
LLVM_ABI bool is_regular_file(const basic_file_status &status)
Does status represent a regular file?
Definition Path.cpp:1136
LLVM_ABI std::error_code rename(const Twine &from, const Twine &to)
Rename from to to.
bool can_write(const Twine &Path)
Can we write this file?
Definition FileSystem.h:491
LLVM_ABI bool exists(const basic_file_status &status)
Does file exist?
Definition Path.cpp:1107
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
Definition FileSystem.h:795
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition FileSystem.h:804
@ OF_Append
The file should be opened in append mode.
Definition FileSystem.h:807
LLVM_ABI std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, OpenFlags Flags=OF_None, unsigned Mode=all_read|all_write)
Create a uniquely named file.
Definition Path.cpp:891
LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
@ CD_CreateAlways
CD_CreateAlways - When opening a file:
Definition FileSystem.h:767
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
LLVM_ABI std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition Path.cpp:993
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
Definition Path.cpp:979
LLVM_ABI std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition Path.cpp:1042
LLVM_ABI file_t convertFDToNativeFile(int FD)
Converts from a Posix file descriptor number to a native file handle.
LLVM_ABI std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
LLVM_ABI std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
LLVM_ABI bool equivalent(file_status A, file_status B)
Do file_status's represent the same thing?
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
Definition Path.cpp:478
LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get extension.
Definition Path.cpp:607
ScopedSetting scopedDisable()
Definition IOSandbox.h:36
LLVM_ABI void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
LLVM_ABI bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
Error convertToOutputError(const Twine &OutputPath, std::error_code EC)
Return Error::success() or use OutputPath to create an OutputError, depending on EC.
LLVM_ABI IntrusiveRefCntPtr< OutputBackend > makeNullOutputBackend()
Create a backend that ignores all output.
LLVM_ABI IntrusiveRefCntPtr< OutputBackend > makeFilteringOutputBackend(IntrusiveRefCntPtr< OutputBackend > UnderlyingBackend, std::function< bool(StringRef, std::optional< OutputConfig >)> Filter)
Make a backend where OutputBackend::createFile() forwards to UnderlyingBackend when Filter is true,...
LLVM_ABI IntrusiveRefCntPtr< OutputBackend > makeMirroringOutputBackend(IntrusiveRefCntPtr< OutputBackend > Backend1, IntrusiveRefCntPtr< OutputBackend > Backend2)
Create a backend that forwards OutputBackend::createFile() to both Backend1 and Backend2.
Error convertToTempFileOutputError(const Twine &TempPath, const Twine &OutputPath, std::error_code EC)
Return Error::success() or use TempPath and OutputPath to create a TempFileOutputError,...
This is an optimization pass for GlobalISel generic memory operations.
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition Error.h:1129
@ Offset
Definition DWP.cpp:577
scope_exit(Callable) -> scope_exit< Callable >
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition Error.h:990
IntrusiveRefCntPtr< T > makeIntrusiveRefCnt(Args &&...A)
Factory function for creating intrusive ref counted pointers.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition Error.h:442
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
@ Success
The lock was released successfully.
@ OwnerDied
Owner died while holding the lock.
@ Timeout
Reached timeout while waiting for the owner to release the lock.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:107
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
bool RemoveOnSignal
Register output files to be deleted if a signal is received.
Full configuration for an output for use by the OutputBackend.
constexpr bool getTextWithCRLF() const