LLVM 22.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"
23#include "llvm/Support/Path.h"
28
29using namespace llvm;
30using namespace llvm::vfs;
31
32void ProxyOutputBackend::anchor() {}
33void OnDiskOutputBackend::anchor() {}
34
36 struct NullOutputBackend : public OutputBackend {
37 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
38 return const_cast<NullOutputBackend *>(this);
39 }
41 createFileImpl(StringRef Path, std::optional<OutputConfig>) override {
42 return std::make_unique<NullOutputFileImpl>();
43 }
44 };
45
47}
48
50 IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend,
51 std::function<bool(StringRef, std::optional<OutputConfig>)> Filter) {
52 struct FilteringOutputBackend : public ProxyOutputBackend {
54 createFileImpl(StringRef Path,
55 std::optional<OutputConfig> Config) override {
56 if (Filter(Path, Config))
57 return ProxyOutputBackend::createFileImpl(Path, Config);
58 return std::make_unique<NullOutputFileImpl>();
59 }
60
61 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
63 getUnderlyingBackend().clone(), Filter);
64 }
65
66 FilteringOutputBackend(
67 IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend,
68 std::function<bool(StringRef, std::optional<OutputConfig>)> Filter)
69 : ProxyOutputBackend(std::move(UnderlyingBackend)),
70 Filter(std::move(Filter)) {
71 assert(this->Filter && "Expected a non-null function");
72 }
73 std::function<bool(StringRef, std::optional<OutputConfig>)> Filter;
74 };
75
77 std::move(UnderlyingBackend), std::move(Filter));
78}
79
83 struct ProxyOutputBackend1 : public ProxyOutputBackend {
85 };
86 struct ProxyOutputBackend2 : public ProxyOutputBackend {
88 };
89 struct MirroringOutput final : public OutputFileImpl, raw_pwrite_stream {
90 Error keep() final {
91 flush();
92 return joinErrors(F1->keep(), F2->keep());
93 }
94 Error discard() final {
95 flush();
96 return joinErrors(F1->discard(), F2->discard());
97 }
98 raw_pwrite_stream &getOS() final { return *this; }
99
100 void write_impl(const char *Ptr, size_t Size) override {
101 F1->getOS().write(Ptr, Size);
102 F2->getOS().write(Ptr, Size);
103 }
104 void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override {
105 this->flush();
106 F1->getOS().pwrite(Ptr, Size, Offset);
107 F2->getOS().pwrite(Ptr, Size, Offset);
108 }
109 uint64_t current_pos() const override { return F1->getOS().tell(); }
110 size_t preferred_buffer_size() const override {
111 return PreferredBufferSize;
112 }
113 void reserveExtraSpace(uint64_t ExtraSize) override {
114 F1->getOS().reserveExtraSpace(ExtraSize);
115 F2->getOS().reserveExtraSpace(ExtraSize);
116 }
117 bool is_displayed() const override {
118 return F1->getOS().is_displayed() && F2->getOS().is_displayed();
119 }
120 bool has_colors() const override {
121 return F1->getOS().has_colors() && F2->getOS().has_colors();
122 }
123 void enable_colors(bool enable) override {
125 F1->getOS().enable_colors(enable);
126 F2->getOS().enable_colors(enable);
127 }
128
129 MirroringOutput(std::unique_ptr<OutputFileImpl> F1,
130 std::unique_ptr<OutputFileImpl> F2)
131 : PreferredBufferSize(std::max(F1->getOS().GetBufferSize(),
132 F1->getOS().GetBufferSize())),
133 F1(std::move(F1)), F2(std::move(F2)) {
134 // Don't double buffer.
135 this->F1->getOS().SetUnbuffered();
136 this->F2->getOS().SetUnbuffered();
137 }
138 size_t PreferredBufferSize;
139 std::unique_ptr<OutputFileImpl> F1;
140 std::unique_ptr<OutputFileImpl> F2;
141 };
142 struct MirroringOutputBackend : public ProxyOutputBackend1,
143 public ProxyOutputBackend2 {
145 createFileImpl(StringRef Path,
146 std::optional<OutputConfig> Config) override {
147 std::unique_ptr<OutputFileImpl> File1;
148 std::unique_ptr<OutputFileImpl> File2;
149 if (Error E =
150 ProxyOutputBackend1::createFileImpl(Path, Config).moveInto(File1))
151 return std::move(E);
152 if (Error E =
153 ProxyOutputBackend2::createFileImpl(Path, Config).moveInto(File2))
154 return joinErrors(std::move(E), File1->discard());
155
156 // Skip the extra indirection if one of these is a null output.
157 if (isa<NullOutputFileImpl>(*File1)) {
158 consumeError(File1->discard());
159 return std::move(File2);
160 }
161 if (isa<NullOutputFileImpl>(*File2)) {
162 consumeError(File2->discard());
163 return std::move(File1);
164 }
165 return std::make_unique<MirroringOutput>(std::move(File1),
166 std::move(File2));
167 }
168
169 IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
172 ProxyOutputBackend1::getUnderlyingBackend().clone(),
173 ProxyOutputBackend2::getUnderlyingBackend().clone()));
174 }
175 void Retain() const { ProxyOutputBackend1::Retain(); }
176 void Release() const { ProxyOutputBackend1::Release(); }
177
178 MirroringOutputBackend(IntrusiveRefCntPtr<OutputBackend> Backend1,
180 : ProxyOutputBackend1(std::move(Backend1)),
181 ProxyOutputBackend2(std::move(Backend2)) {}
182 };
183
184 assert(Backend1 && "Expected actual backend");
185 assert(Backend2 && "Expected actual backend");
188 std::move(Backend2)));
189}
190
191static OutputConfig
192applySettings(std::optional<OutputConfig> &&Config,
193 const OnDiskOutputBackend::OutputSettings &Settings) {
194 if (!Config)
195 Config = Settings.DefaultConfig;
196 if (!Settings.UseTemporaries)
197 Config->setNoAtomicWrite();
198 if (!Settings.RemoveOnSignal)
199 Config->setNoDiscardOnSignal();
200 return *Config;
201}
202
203namespace {
204class OnDiskOutputFile final : public OutputFileImpl {
205public:
206 Error keep() override;
207 Error discard() override;
208 raw_pwrite_stream &getOS() override {
209 assert(FileOS && "Expected valid file");
210 if (BufferOS)
211 return *BufferOS;
212 return *FileOS;
213 }
214
215 /// Attempt to open a temporary file for \p OutputPath.
216 ///
217 /// This tries to open a uniquely-named temporary file for \p OutputPath,
218 /// possibly also creating any missing directories if \a
219 /// OnDiskOutputConfig::UseTemporaryCreateMissingDirectories is set in \a
220 /// Config.
221 ///
222 /// \post FD and \a TempPath are initialized if this is successful.
223 Error tryToCreateTemporary(std::optional<int> &FD);
224
225 Error initializeFile(std::optional<int> &FD);
226 Error initializeStream();
227 Error reset();
228
229 OnDiskOutputFile(StringRef OutputPath, std::optional<OutputConfig> Config,
230 const OnDiskOutputBackend::OutputSettings &Settings)
231 : Config(applySettings(std::move(Config), Settings)),
232 OutputPath(OutputPath.str()) {}
233
234 OutputConfig Config;
235 const std::string OutputPath;
236 std::optional<std::string> TempPath;
237 std::optional<raw_fd_ostream> FileOS;
238 std::optional<buffer_ostream> BufferOS;
239};
240} // end namespace
241
243 OutputConfig Config,
244 llvm::function_ref<Error()> CreateFile) {
245 return handleErrors(CreateFile(), [&](std::unique_ptr<ECError> EC) {
246 if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory ||
247 Config.getNoImplyCreateDirectories())
248 return Error(std::move(EC));
249
250 StringRef ParentPath = sys::path::parent_path(OutputPath);
251 if (std::error_code EC = sys::fs::create_directories(ParentPath))
252 return make_error<OutputError>(ParentPath, EC);
253 return CreateFile();
254 });
255}
256
259 if (Config.getTextWithCRLF())
261 else if (Config.getText())
262 OF |= sys::fs::OF_Text;
263 // Don't pass OF_Append if writting to temporary since OF_Append is
264 // not Atomic Append
265 if (Config.getAppend() && !Config.getAtomicWrite())
266 OF |= sys::fs::OF_Append;
267
268 return OF;
269}
270
271Error OnDiskOutputFile::tryToCreateTemporary(std::optional<int> &FD) {
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 assert(OutputPath != "-" && "Unexpected request for FD of stdout");
302
303 // Disable temporary file for other non-regular files, and if we get a status
304 // object, also check if we can write and disable write-through buffers if
305 // appropriate.
306 if (Config.getAtomicWrite()) {
307 sys::fs::file_status Status;
308 sys::fs::status(OutputPath, Status);
309 if (sys::fs::exists(Status)) {
311 Config.setNoAtomicWrite();
312
313 // Fail now if we can't write to the final destination.
314 if (!sys::fs::can_write(OutputPath))
316 OutputPath,
317 std::make_error_code(std::errc::operation_not_permitted));
318 }
319 }
320
321 // If (still) using a temporary file, try to create it (and return success if
322 // that works).
323 if (Config.getAtomicWrite())
324 if (!errorToBool(tryToCreateTemporary(FD)))
325 return Error::success();
326
327 // Not using a temporary file. Open the final output file.
328 return createDirectoriesOnDemand(OutputPath, Config, [&]() -> Error {
329 int NewFD;
331 if (std::error_code EC = sys::fs::openFileForWrite(
332 OutputPath, NewFD, sys::fs::CD_CreateAlways, OF))
333 return convertToOutputError(OutputPath, EC);
334 FD.emplace(NewFD);
335
336 if (Config.getDiscardOnSignal())
337 sys::RemoveFileOnSignal(OutputPath);
338 return Error::success();
339 });
340}
341
342Error OnDiskOutputFile::initializeStream() {
343 // Open the file stream.
344 if (OutputPath == "-") {
345 std::error_code EC;
346 FileOS.emplace(OutputPath, EC);
347 if (EC)
348 return make_error<OutputError>(OutputPath, EC);
349 } else {
350 std::optional<int> FD;
351 if (Error E = initializeFile(FD))
352 return E;
353 FileOS.emplace(*FD, /*shouldClose=*/true);
354 }
355
356 // Buffer the stream if necessary.
357 if (!FileOS->supportsSeeking() && !Config.getText())
358 BufferOS.emplace(*FileOS);
359
360 return Error::success();
361}
362
363namespace {
364class OpenFileRAII {
365 static const int InvalidFd = -1;
366
367public:
368 int Fd = InvalidFd;
369
370 ~OpenFileRAII() {
371 if (Fd != InvalidFd)
373 }
374};
375
376enum class FileDifference : uint8_t {
377 /// The source and destination paths refer to the exact same file.
378 IdenticalFile,
379 /// The source and destination paths refer to separate files with identical
380 /// contents.
381 SameContents,
382 /// The source and destination paths refer to separate files with different
383 /// contents.
384 DifferentContents
385};
386} // end anonymous namespace
387
388static Expected<FileDifference>
389areFilesDifferent(const llvm::Twine &Source, const llvm::Twine &Destination) {
390 if (sys::fs::equivalent(Source, Destination))
391 return FileDifference::IdenticalFile;
392
393 OpenFileRAII SourceFile;
394 sys::fs::file_status SourceStatus;
395 // If we can't open the source file, fail.
396 if (std::error_code EC = sys::fs::openFileForRead(Source, SourceFile.Fd))
397 return convertToOutputError(Source, EC);
398
399 // If we can't stat the source file, fail.
400 if (std::error_code EC = sys::fs::status(SourceFile.Fd, SourceStatus))
401 return convertToOutputError(Source, EC);
402
403 OpenFileRAII DestFile;
404 sys::fs::file_status DestStatus;
405 // If we can't open the destination file, report different.
406 if (std::error_code Error =
407 sys::fs::openFileForRead(Destination, DestFile.Fd))
408 return FileDifference::DifferentContents;
409
410 // If we can't open the destination file, report different.
411 if (std::error_code Error = sys::fs::status(DestFile.Fd, DestStatus))
412 return FileDifference::DifferentContents;
413
414 // If the files are different sizes, they must be different.
415 uint64_t Size = SourceStatus.getSize();
416 if (Size != DestStatus.getSize())
417 return FileDifference::DifferentContents;
418
419 // If both files are zero size, they must be the same.
420 if (Size == 0)
421 return FileDifference::SameContents;
422
423 // The two files match in size, so we have to compare the bytes to determine
424 // if they're the same.
425 std::error_code SourceRegionErr;
426 sys::fs::mapped_file_region SourceRegion(
427 sys::fs::convertFDToNativeFile(SourceFile.Fd),
428 sys::fs::mapped_file_region::readonly, Size, 0, SourceRegionErr);
429 if (SourceRegionErr)
430 return convertToOutputError(Source, SourceRegionErr);
431
432 std::error_code DestRegionErr;
436
437 if (DestRegionErr)
438 return FileDifference::DifferentContents;
439
440 if (memcmp(SourceRegion.const_data(), DestRegion.const_data(), Size) != 0)
441 return FileDifference::DifferentContents;
442
443 return FileDifference::SameContents;
444}
445
446Error OnDiskOutputFile::reset() {
447 // Destroy the streams to flush them.
448 BufferOS.reset();
449 if (!FileOS)
450 return Error::success();
451
452 // Remember the error in raw_fd_ostream to be reported later.
453 std::error_code EC = FileOS->error();
454 // Clear the error to avoid fatal error when reset.
455 FileOS->clear_error();
456 FileOS.reset();
457 return errorCodeToError(EC);
458}
459
460Error OnDiskOutputFile::keep() {
461 if (auto E = reset())
462 return E;
463
464 // Close the file descriptor and remove crash cleanup before exit.
465 auto RemoveDiscardOnSignal = make_scope_exit([&]() {
466 if (Config.getDiscardOnSignal())
467 sys::DontRemoveFileOnSignal(TempPath ? *TempPath : OutputPath);
468 });
469
470 if (!TempPath)
471 return Error::success();
472
473 // See if we should append instead of move.
474 if (Config.getAppend() && OutputPath != "-") {
475 // Read TempFile for the content to append.
476 auto Content = MemoryBuffer::getFile(*TempPath);
477 if (!Content)
478 return convertToTempFileOutputError(*TempPath, OutputPath,
479 Content.getError());
480 while (1) {
481 // Attempt to lock the output file.
482 // Only one process is allowed to append to this file at a time.
483 llvm::LockFileManager Lock(OutputPath);
484 bool Owned;
485 if (Error Err = Lock.tryLock().moveInto(Owned)) {
486 // If we error acquiring a lock, we cannot ensure appends
487 // to the trace file are atomic - cannot ensure output correctness.
488 Lock.unsafeMaybeUnlock();
490 OutputPath, std::make_error_code(std::errc::no_lock_available));
491 }
492 if (Owned) {
493 // Lock acquired, perform the write and release the lock.
494 std::error_code EC;
495 llvm::raw_fd_ostream Out(OutputPath, EC, llvm::sys::fs::OF_Append);
496 if (EC)
497 return convertToOutputError(OutputPath, EC);
498 Out << (*Content)->getBuffer();
499 Out.close();
500 Lock.unsafeMaybeUnlock();
501 if (Out.has_error())
502 return convertToOutputError(OutputPath, Out.error());
503 // Remove temp file and done.
504 (void)sys::fs::remove(*TempPath);
505 return Error::success();
506 }
507 // Someone else owns the lock on this file, wait.
508 switch (Lock.waitForUnlockFor(std::chrono::seconds(256))) {
510 [[fallthrough]];
512 continue; // try again to get the lock.
513 }
515 // We could error on timeout to avoid potentially hanging forever, but
516 // it may be more likely that an interrupted process failed to clear
517 // the lock, causing other waiting processes to time-out. Let's clear
518 // the lock and try again right away. If we do start seeing compiler
519 // hangs in this location, we will need to re-consider.
520 Lock.unsafeMaybeUnlock();
521 continue;
522 }
523 }
524 break;
525 }
526 }
527
528 if (Config.getOnlyIfDifferent()) {
529 auto Result = areFilesDifferent(*TempPath, OutputPath);
530 if (!Result)
531 return Result.takeError();
532 switch (*Result) {
533 case FileDifference::IdenticalFile:
534 // Do nothing for a self-move.
535 return Error::success();
536
537 case FileDifference::SameContents:
538 // Files are identical; remove the source file.
539 (void)sys::fs::remove(*TempPath);
540 return Error::success();
541
542 case FileDifference::DifferentContents:
543 break; // Rename the file.
544 }
545 }
546
547 // Move temporary to the final output path and remove it if that fails.
548 std::error_code RenameEC = sys::fs::rename(*TempPath, OutputPath);
549 if (!RenameEC)
550 return Error::success();
551
552 // FIXME: TempPath should be in the same directory as OutputPath but try to
553 // copy the output to see if makes any difference. If this path is used,
554 // investigate why we need to copy.
555 RenameEC = sys::fs::copy_file(*TempPath, OutputPath);
556 (void)sys::fs::remove(*TempPath);
557
558 if (!RenameEC)
559 return Error::success();
560
561 return make_error<TempFileOutputError>(*TempPath, OutputPath, RenameEC);
562}
563
564Error OnDiskOutputFile::discard() {
565 // Destroy the streams to flush them.
566 if (auto E = reset())
567 return E;
568
569 // Nothing on the filesystem to remove for stdout.
570 if (OutputPath == "-")
571 return Error::success();
572
573 auto discardPath = [&](StringRef Path) {
574 std::error_code EC = sys::fs::remove(Path);
576 return EC;
577 };
578
579 // Clean up the file that's in-progress.
580 if (!TempPath)
581 return convertToOutputError(OutputPath, discardPath(OutputPath));
582 return convertToTempFileOutputError(*TempPath, OutputPath,
583 discardPath(*TempPath));
584}
585
587 return convertToOutputError(StringRef(Path.data(), Path.size()),
589}
590
593 std::optional<OutputConfig> Config) {
594 SmallString<256> AbsPath;
595 if (Path != "-") {
596 AbsPath = Path;
597 if (Error E = makeAbsolute(AbsPath))
598 return std::move(E);
599 Path = AbsPath;
600 }
601
602 auto File = std::make_unique<OnDiskOutputFile>(Path, Config, Settings);
603 if (Error E = File->initializeStream())
604 return std::move(E);
605
606 return std::move(File);
607}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Merge contiguous icmps into a memcmp
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...
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...
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:225
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
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:1169
Represents an open file.
LLVM_ABI 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:1104
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:469
LLVM_ABI bool exists(const basic_file_status &status)
Does file exist?
Definition Path.cpp:1077
@ OF_Text
The file should be opened in text mode on platforms like z/OS that make this distinction.
Definition FileSystem.h:755
@ OF_TextWithCRLF
The file should be opened in text mode and use a carriage linefeed '\r '.
Definition FileSystem.h:764
@ OF_Append
The file should be opened in append mode.
Definition FileSystem.h:767
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:871
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:727
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:967
LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)
Make path an absolute path.
Definition Path.cpp:955
LLVM_ABI std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition Path.cpp:1016
LLVM_ABI file_t convertFDToNativeFile(int FD)
Converts from a Posix file descriptor number to a native file handle.
Definition FileSystem.h:991
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:467
LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get extension.
Definition Path.cpp:590
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:1113
@ Offset
Definition DWP.cpp:477
detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)
Definition ScopeExit.h:59
Error handleErrors(Error E, HandlerTs &&... Hs)
Pass the ErrorInfo(s) contained in E to their respective handlers.
Definition Error.h:967
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:1867
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition Error.cpp:111
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1083
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