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 // Don't double buffer.
136 this->F1->getOS().SetUnbuffered();
137 this->F2->getOS().SetUnbuffered();
138 }
139 size_t PreferredBufferSize;
140 std::unique_ptr<OutputFileImpl> F1;
141 std::unique_ptr<OutputFileImpl> F2;
142 };
143 struct MirroringOutputBackend : public ProxyOutputBackend1,
144 public ProxyOutputBackend2 {
146 createFileImpl(StringRef Path,
147 std::optional<OutputConfig> Config) override {
148 std::unique_ptr<OutputFileImpl> File1;
149 std::unique_ptr<OutputFileImpl> File2;
150 if (Error E =
151 ProxyOutputBackend1::createFileImpl(Path, Config).moveInto(File1))
152 return std::move(E);
153 if (Error E =
154 ProxyOutputBackend2::createFileImpl(Path, Config).moveInto(File2))
155 return joinErrors(std::move(E), File1->discard());
156
157 // Skip the extra indirection if one of these is a null output.
158 if (isa<NullOutputFileImpl>(*File1)) {
159 consumeError(File1->discard());
160 return std::move(File2);
161 }
162 if (isa<NullOutputFileImpl>(*File2)) {
163 consumeError(File2->discard());
164 return std::move(File1);
165 }
166 return std::make_unique<MirroringOutput>(std::move(File1),
167 std::move(File2));
168 }
169
170 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
173 ProxyOutputBackend1::getUnderlyingBackend().clone(),
174 ProxyOutputBackend2::getUnderlyingBackend().clone()));
175 }
176 void Retain() const { ProxyOutputBackend1::Retain(); }
177 void Release() const { ProxyOutputBackend1::Release(); }
178
179 MirroringOutputBackend(IntrusiveRefCntPtr<OutputBackend> Backend1,
181 : ProxyOutputBackend1(std::move(Backend1)),
182 ProxyOutputBackend2(std::move(Backend2)) {}
183 };
184
185 assert(Backend1 && "Expected actual backend");
186 assert(Backend2 && "Expected actual backend");
189 std::move(Backend2)));
190}
191
192static OutputConfig
193applySettings(std::optional<OutputConfig> &&Config,
194 const OnDiskOutputBackend::OutputSettings &Settings) {
195 if (!Config)
196 Config = Settings.DefaultConfig;
197 if (!Settings.UseTemporaries)
198 Config->setNoAtomicWrite();
199 if (!Settings.RemoveOnSignal)
200 Config->setNoDiscardOnSignal();
201 return *Config;
202}
203
204namespace {
205class OnDiskOutputFile final : public OutputFileImpl {
206public:
207 Error keep() override;
208 Error discard() override;
209 raw_pwrite_stream &getOS() override {
210 assert(FileOS && "Expected valid file");
211 if (BufferOS)
212 return *BufferOS;
213 return *FileOS;
214 }
215
216 /// Attempt to open a temporary file for \p OutputPath.
217 ///
218 /// This tries to open a uniquely-named temporary file for \p OutputPath,
219 /// possibly also creating any missing directories if \a
220 /// OnDiskOutputConfig::UseTemporaryCreateMissingDirectories is set in \a
221 /// Config.
222 ///
223 /// \post FD and \a TempPath are initialized if this is successful.
224 Error tryToCreateTemporary(std::optional<int> &FD);
225
226 Error initializeFile(std::optional<int> &FD);
227 Error initializeStream();
228 Error reset();
229
230 OnDiskOutputFile(StringRef OutputPath, std::optional<OutputConfig> Config,
231 const OnDiskOutputBackend::OutputSettings &Settings)
232 : Config(applySettings(std::move(Config), Settings)),
233 OutputPath(OutputPath.str()) {}
234
235 OutputConfig Config;
236 const std::string OutputPath;
237 std::optional<std::string> TempPath;
238 std::optional<raw_fd_ostream> FileOS;
239 std::optional<buffer_ostream> BufferOS;
240};
241} // end namespace
242
244 OutputConfig Config,
245 llvm::function_ref<Error()> CreateFile) {
246 return handleErrors(CreateFile(), [&](std::unique_ptr<ECError> EC) {
247 if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory ||
248 Config.getNoImplyCreateDirectories())
249 return Error(std::move(EC));
250
251 StringRef ParentPath = sys::path::parent_path(OutputPath);
252 if (std::error_code EC = sys::fs::create_directories(ParentPath))
253 return make_error<OutputError>(ParentPath, EC);
254 return CreateFile();
255 });
256}
257
260 if (Config.getTextWithCRLF())
262 else if (Config.getText())
263 OF |= sys::fs::OF_Text;
264 // Don't pass OF_Append if writting to temporary since OF_Append is
265 // not Atomic Append
266 if (Config.getAppend() && !Config.getAtomicWrite())
267 OF |= sys::fs::OF_Append;
268
269 return OF;
270}
271
272Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
273 auto BypassSandbox = sys::sandbox::scopedDisable();
274
275 // Create a temporary file.
276 // Insert -%%%%%%%% before the extension (if any), and because some tools
277 // (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
278 // artifacts, also append .tmp.
279 StringRef OutputExtension = sys::path::extension(OutputPath);
280 SmallString<128> ModelPath =
281 StringRef(OutputPath).drop_back(OutputExtension.size());
282 ModelPath += "-%%%%%%%%";
283 ModelPath += OutputExtension;
284 ModelPath += ".tmp";
285
286 return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
287 int NewFD;
288 SmallString<128> UniquePath;
290 if (std::error_code EC =
291 sys::fs::createUniqueFile(ModelPath, NewFD, UniquePath, OF))
292 return make_error<TempFileOutputError>(ModelPath, OutputPath, EC);
293
294 if (Config.getDiscardOnSignal())
295 sys::RemoveFileOnSignal(UniquePath);
296
297 TempPath = UniquePath.str().str();
298 FD.emplace(NewFD);
299 return Error::success();
300 });
301}
302
303Error OnDiskOutputFile::initializeFile(std::optional<int> &FD) {
304 auto BypassSandbox = sys::sandbox::scopedDisable();
305
306 assert(OutputPath != "-" && "Unexpected request for FD of stdout");
307
308 // Disable temporary file for other non-regular files, and if we get a status
309 // object, also check if in append mode we can write and disable write-through
310 // buffers if appropriate.
311 if (Config.getAtomicWrite()) {
312 sys::fs::file_status Status;
313 sys::fs::status(OutputPath, Status);
314 if (sys::fs::exists(Status)) {
316 Config.setNoAtomicWrite();
317
318 // In append mode, we will open the file for writing which will need write
319 // permission. Fail now if it is already clear that we can't write to the
320 // final destination.
321 // In non-append mode, we will delete and replace the file. Permission
322 // bits of the file itself are irrelevant in this case.
323 if (Config.getAppend() && !sys::fs::can_write(OutputPath))
325 OutputPath,
326 std::make_error_code(std::errc::operation_not_permitted));
327 }
328 }
329
330 // If (still) using a temporary file, try to create it (and return success if
331 // that works).
332 if (Config.getAtomicWrite())
333 if (!errorToBool(tryToCreateTemporary(FD)))
334 return Error::success();
335
336 // Not using a temporary file. Open the final output file.
337 return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
338 int NewFD;
340 if (std::error_code EC = sys::fs::openFileForWrite(
341 OutputPath, NewFD, sys::fs::CD_CreateAlways, OF))
342 return convertToOutputError(OutputPath, EC);
343 FD.emplace(NewFD);
344
345 if (Config.getDiscardOnSignal())
346 sys::RemoveFileOnSignal(OutputPath);
347 return Error::success();
348 });
349}
350
351Error OnDiskOutputFile::initializeStream() {
352 auto BypassSandbox = sys::sandbox::scopedDisable();
353
354 // Open the file stream.
355 if (OutputPath == "-") {
356 std::error_code EC;
357 FileOS.emplace(OutputPath, EC);
358 if (EC)
359 return make_error<OutputError>(OutputPath, EC);
360 } else {
361 std::optional<int> FD;
362 if (Error E = initializeFile(FD))
363 return E;
364 FileOS.emplace(*FD, /*shouldClose=*/true);
365 }
366
367 // Buffer the stream if necessary.
368 if (!FileOS->supportsSeeking() && !Config.getText())
369 BufferOS.emplace(*FileOS);
370
371 return Error::success();
372}
373
374namespace {
375class OpenFileRAII {
376 static const int InvalidFd = -1;
377
378public:
379 int Fd = InvalidFd;
380
381 ~OpenFileRAII() {
382 if (Fd != InvalidFd)
384 }
385};
386
387enum class FileDifference : uint8_t {
388 /// The source and destination paths refer to the exact same file.
389 IdenticalFile,
390 /// The source and destination paths refer to separate files with identical
391 /// contents.
392 SameContents,
393 /// The source and destination paths refer to separate files with different
394 /// contents.
395 DifferentContents
396};
397} // end anonymous namespace
398
399static Expected<FileDifference>
400areFilesDifferent(const llvm::Twine &Source, const llvm::Twine &Destination) {
401 if (sys::fs::equivalent(Source, Destination))
402 return FileDifference::IdenticalFile;
403
404 OpenFileRAII SourceFile;
405 sys::fs::file_status SourceStatus;
406 // If we can't open the source file, fail.
407 if (std::error_code EC = sys::fs::openFileForRead(Source, SourceFile.Fd))
408 return convertToOutputError(Source, EC);
409
410 // If we can't stat the source file, fail.
411 if (std::error_code EC = sys::fs::status(SourceFile.Fd, SourceStatus))
412 return convertToOutputError(Source, EC);
413
414 OpenFileRAII DestFile;
415 sys::fs::file_status DestStatus;
416 // If we can't open the destination file, report different.
417 if (std::error_code Error =
418 sys::fs::openFileForRead(Destination, DestFile.Fd))
419 return FileDifference::DifferentContents;
420
421 // If we can't open the destination file, report different.
422 if (std::error_code Error = sys::fs::status(DestFile.Fd, DestStatus))
423 return FileDifference::DifferentContents;
424
425 // If the files are different sizes, they must be different.
426 uint64_t Size = SourceStatus.getSize();
427 if (Size != DestStatus.getSize())
428 return FileDifference::DifferentContents;
429
430 // If both files are zero size, they must be the same.
431 if (Size == 0)
432 return FileDifference::SameContents;
433
434 // The two files match in size, so we have to compare the bytes to determine
435 // if they're the same.
436 std::error_code SourceRegionErr;
437 sys::fs::mapped_file_region SourceRegion(
438 sys::fs::convertFDToNativeFile(SourceFile.Fd),
439 sys::fs::mapped_file_region::readonly, Size, 0, SourceRegionErr);
440 if (SourceRegionErr)
441 return convertToOutputError(Source, SourceRegionErr);
442
443 std::error_code DestRegionErr;
447
448 if (DestRegionErr)
449 return FileDifference::DifferentContents;
450
451 if (memcmp(SourceRegion.const_data(), DestRegion.const_data(), Size) != 0)
452 return FileDifference::DifferentContents;
453
454 return FileDifference::SameContents;
455}
456
457Error OnDiskOutputFile::reset() {
458 auto BypassSandbox = sys::sandbox::scopedDisable();
459
460 // Destroy the streams to flush them.
461 BufferOS.reset();
462 if (!FileOS)
463 return Error::success();
464
465 // Remember the error in raw_fd_ostream to be reported later.
466 std::error_code EC = FileOS->error();
467 // Clear the error to avoid fatal error when reset.
468 FileOS->clear_error();
469 FileOS.reset();
470 return errorCodeToError(EC);
471}
472
473Error OnDiskOutputFile::keep() {
474 auto BypassSandbox = sys::sandbox::scopedDisable();
475
476 if (auto E = reset())
477 return E;
478
479 // Close the file descriptor and remove crash cleanup before exit.
480 llvm::scope_exit RemoveDiscardOnSignal([&]() {
481 if (Config.getDiscardOnSignal())
482 sys::DontRemoveFileOnSignal(TempPath ? *TempPath : OutputPath);
483 });
484
485 if (!TempPath)
486 return Error::success();
487
488 // See if we should append instead of move.
489 if (Config.getAppend() && OutputPath != "-") {
490 // Read TempFile for the content to append.
491 auto Content = MemoryBuffer::getFile(*TempPath);
492 if (!Content)
493 return convertToTempFileOutputError(*TempPath, OutputPath,
494 Content.getError());
495 while (1) {
496 // Attempt to lock the output file.
497 // Only one process is allowed to append to this file at a time.
498 llvm::LockFileManager Lock(OutputPath);
499 bool Owned;
500 if (Error Err = Lock.tryLock().moveInto(Owned)) {
501 // If we error acquiring a lock, we cannot ensure appends
502 // to the trace file are atomic - cannot ensure output correctness.
503 Lock.unsafeUnlock();
505 OutputPath, std::make_error_code(std::errc::no_lock_available));
506 }
507 if (Owned) {
508 // Lock acquired, perform the write and release the lock.
509 std::error_code EC;
510 llvm::raw_fd_ostream Out(OutputPath, EC, llvm::sys::fs::OF_Append);
511 if (EC)
512 return convertToOutputError(OutputPath, EC);
513 Out << (*Content)->getBuffer();
514 Out.close();
515 Lock.unsafeUnlock();
516 if (Out.has_error())
517 return convertToOutputError(OutputPath, Out.error());
518 // Remove temp file and done.
519 (void)sys::fs::remove(*TempPath);
520 return Error::success();
521 }
522 // Someone else owns the lock on this file, wait.
523 switch (Lock.waitForUnlockFor(std::chrono::seconds(256))) {
525 [[fallthrough]];
527 continue; // try again to get the lock.
528 }
530 // We could error on timeout to avoid potentially hanging forever, but
531 // it may be more likely that an interrupted process failed to clear
532 // the lock, causing other waiting processes to time-out. Let's clear
533 // the lock and try again right away. If we do start seeing compiler
534 // hangs in this location, we will need to re-consider.
535 Lock.unsafeUnlock();
536 continue;
537 }
538 }
539 break;
540 }
541 }
542
543 if (Config.getOnlyIfDifferent()) {
544 auto Result = areFilesDifferent(*TempPath, OutputPath);
545 if (!Result)
546 return Result.takeError();
547 switch (*Result) {
548 case FileDifference::IdenticalFile:
549 // Do nothing for a self-move.
550 return Error::success();
551
552 case FileDifference::SameContents:
553 // Files are identical; remove the source file.
554 (void)sys::fs::remove(*TempPath);
555 return Error::success();
556
557 case FileDifference::DifferentContents:
558 break; // Rename the file.
559 }
560 }
561
562 // Move temporary to the final output path and remove it if that fails.
563 std::error_code RenameEC = sys::fs::rename(*TempPath, OutputPath);
564 if (!RenameEC)
565 return Error::success();
566
567 // FIXME: TempPath should be in the same directory as OutputPath but try to
568 // copy the output to see if makes any difference. If this path is used,
569 // investigate why we need to copy.
570 RenameEC = sys::fs::copy_file(*TempPath, OutputPath);
571 (void)sys::fs::remove(*TempPath);
572
573 if (!RenameEC)
574 return Error::success();
575
576 return make_error<TempFileOutputError>(*TempPath, OutputPath, RenameEC);
577}
578
579Error OnDiskOutputFile::discard() {
580 auto BypassSandbox = sys::sandbox::scopedDisable();
581
582 // Destroy the streams to flush them.
583 if (auto E = reset())
584 return E;
585
586 // Nothing on the filesystem to remove for stdout.
587 if (OutputPath == "-")
588 return Error::success();
589
590 auto discardPath = [&](StringRef Path) {
591 std::error_code EC = sys::fs::remove(Path);
593 return EC;
594 };
595
596 // Clean up the file that's in-progress.
597 if (!TempPath)
598 return convertToOutputError(OutputPath, discardPath(OutputPath));
599 return convertToTempFileOutputError(*TempPath, OutputPath,
600 discardPath(*TempPath));
601}
602
604 // FIXME: Should this really call sys::fs::make_absolute?
605 auto BypassSandbox = sys::sandbox::scopedDisable();
606 return convertToOutputError(StringRef(Path.data(), Path.size()),
608}
609
612 std::optional<OutputConfig> Config) {
613 auto BypassSandbox = sys::sandbox::scopedDisable();
614
615 SmallString<256> AbsPath;
616 if (Path != "-") {
617 AbsPath = Path;
618 if (Error E = makeAbsolute(AbsPath))
619 return std::move(E);
620 Path = AbsPath;
621 }
622
623 auto File = std::make_unique<OnDiskOutputFile>(Path, Config, Settings);
624 if (Error E = File->initializeStream())
625 return std::move(E);
626
627 return std::move(File);
628}
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