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