LLVM: lib/Support/VirtualOutputBackends.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

28

29using namespace llvm;

31

32void ProxyOutputBackend::anchor() {}

33void OnDiskOutputBackend::anchor() {}

34

38 return const_cast<NullOutputBackend *>(this);

39 }

41 createFileImpl(StringRef Path, std::optional) override {

42 return std::make_unique();

43 }

44 };

45

47}

48

51 std::function<bool(StringRef, std::optional)> Filter) {

55 std::optional Config) override {

56 if (Filter(Path, Config))

58 return std::make_unique();

59 }

60

63 getUnderlyingBackend().clone(), Filter);

64 }

65

66 FilteringOutputBackend(

68 std::function<bool(StringRef, std::optional)> Filter)

71 assert(this->Filter && "Expected a non-null function");

72 }

74 };

75

77 std::move(UnderlyingBackend), std::move(Filter));

78}

79

85 };

88 };

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 }

99

100 void write_impl(const char *Ptr, size_t Size) override {

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 F1,

130 std::unique_ptr F2)

131 : PreferredBufferSize(std::max(F1->getOS().GetBufferSize(),

132 F1->getOS().GetBufferSize())),

133 F1(std::move(F1)), F2(std::move(F2)) {

134

135 this->F1->getOS().SetUnbuffered();

136 this->F2->getOS().SetUnbuffered();

137 }

138 size_t PreferredBufferSize;

139 std::unique_ptr F1;

140 std::unique_ptr F2;

141 };

142 struct MirroringOutputBackend : public ProxyOutputBackend1,

143 public ProxyOutputBackend2 {

146 std::optional Config) override {

147 std::unique_ptr File1;

148 std::unique_ptr File2;

150 ProxyOutputBackend1::createFileImpl(Path, Config).moveInto(File1))

151 return std::move(E);

153 ProxyOutputBackend2::createFileImpl(Path, Config).moveInto(File2))

154 return joinErrors(std::move(E), File1->discard());

155

156

159 return std::move(File2);

160 }

163 return std::move(File1);

164 }

165 return std::make_unique(std::move(File1),

166 std::move(File2));

167 }

168

172 ProxyOutputBackend1::getUnderlyingBackend().clone(),

173 ProxyOutputBackend2::getUnderlyingBackend().clone()));

174 }

175 void Retain() const { ProxyOutputBackend1::Retain(); }

176 void Release() const { ProxyOutputBackend1::Release(); }

177

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

194 if (!Config)

197 Config->setNoAtomicWrite();

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

216

217

218

219

220

221

222

223 Error tryToCreateTemporary(std::optional &FD);

224

225 Error initializeFile(std::optional &FD);

226 Error initializeStream();

228

229 OnDiskOutputFile(StringRef OutputPath, std::optional Config,

230 const OnDiskOutputBackend::OutputSettings &Settings)

232 OutputPath(OutputPath.str()) {}

233

234 OutputConfig Config;

235 const std::string OutputPath;

236 std::optionalstd::string TempPath;

237 std::optional<raw_fd_ostream> FileOS;

238 std::optional<buffer_ostream> BufferOS;

239};

240}

241

245 return handleErrors(CreateFile(), [&](std::unique_ptr EC) {

246 if (EC->convertToErrorCode() != std::errc::no_such_file_or_directory ||

247 Config.getNoImplyCreateDirectories())

248 return Error(std::move(EC));

249

253 return CreateFile();

254 });

255}

256

261 else if (Config.getText())

263

264

265 if (Config.getAppend() && !Config.getAtomicWrite())

267

268 return OF;

269}

270

271Error OnDiskOutputFile::tryToCreateTemporary(std::optional &FD) {

272

273

274

275

277 SmallString<128> ModelPath =

278 StringRef(OutputPath).drop_back(OutputExtension.size());

279 ModelPath += "-%%%%%%%%";

280 ModelPath += OutputExtension;

281 ModelPath += ".tmp";

282

284 int NewFD;

285 SmallString<128> UniquePath;

287 if (std::error_code EC =

290

291 if (Config.getDiscardOnSignal())

293

294 TempPath = UniquePath.str().str();

295 FD.emplace(NewFD);

297 });

298}

299

300Error OnDiskOutputFile::initializeFile(std::optional &FD) {

301 assert(OutputPath != "-" && "Unexpected request for FD of stdout");

302

303

304

305

306 if (Config.getAtomicWrite()) {

307 sys::fs::file_status Status;

311 Config.setNoAtomicWrite();

312

313

316 OutputPath,

317 std::make_error_code(std::errc::operation_not_permitted));

318 }

319 }

320

321

322

323 if (Config.getAtomicWrite())

324 if (errorToBool(tryToCreateTemporary(FD)))

326

327

329 int NewFD;

334 FD.emplace(NewFD);

335

336 if (Config.getDiscardOnSignal())

339 });

340}

341

342Error OnDiskOutputFile::initializeStream() {

343

344 if (OutputPath == "-") {

345 std::error_code EC;

346 FileOS.emplace(OutputPath, EC);

347 if (EC)

349 } else {

350 std::optional FD;

351 if (Error E = initializeFile(FD))

352 return E;

353 FileOS.emplace(*FD, true);

354 }

355

356

357 if (!FileOS->supportsSeeking() && !Config.getText())

358 BufferOS.emplace(*FileOS);

359

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

378 IdenticalFile,

379

380

381 SameContents,

382

383

384 DifferentContents

385};

386}

387

388static Expected

391 return FileDifference::IdenticalFile;

392

393 OpenFileRAII SourceFile;

395

398

399

400 if (std::error_code EC = sys::fs::status(SourceFile.Fd, SourceStatus))

402

403 OpenFileRAII DestFile;

405

406 if (std::error_code Error =

408 return FileDifference::DifferentContents;

409

410

412 return FileDifference::DifferentContents;

413

414

417 return FileDifference::DifferentContents;

418

419

420 if (Size == 0)

421 return FileDifference::SameContents;

422

423

424

425 std::error_code SourceRegionErr;

429 if (SourceRegionErr)

431

432 std::error_code DestRegionErr;

436

437 if (DestRegionErr)

438 return FileDifference::DifferentContents;

439

441 return FileDifference::DifferentContents;

442

443 return FileDifference::SameContents;

444}

445

446Error OnDiskOutputFile::reset() {

447

448 BufferOS.reset();

449 if (!FileOS)

451

452

453 std::error_code EC = FileOS->error();

454

455 FileOS->clear_error();

456 FileOS.reset();

458}

459

460Error OnDiskOutputFile::keep() {

461 if (auto E = reset())

462 return E;

463

464

466 if (Config.getDiscardOnSignal())

468 });

469

470 if (!TempPath)

472

473

474 if (Config.getAppend() && OutputPath != "-") {

475

477 if (!Content)

479 Content.getError());

480 while (1) {

481

482

483 llvm::LockFileManager Lock(OutputPath);

484 bool Owned;

485 if (Error Err = Lock.tryLock().moveInto(Owned)) {

486

487

488 Lock.unsafeMaybeUnlock();

490 OutputPath, std::make_error_code(std::errc::no_lock_available));

491 }

492 if (Owned) {

493

494 std::error_code EC;

496 if (EC)

498 Out << (*Content)->getBuffer();

499 Out.close();

500 Lock.unsafeMaybeUnlock();

501 if (Out.has_error())

503

506 }

507

508 switch (Lock.waitForUnlockFor(std::chrono::seconds(256))) {

510 [[fallthrough]];

512 continue;

513 }

515

516

517

518

519

520 Lock.unsafeMaybeUnlock();

521 continue;

522 }

523 }

524 break;

525 }

526 }

527

528 if (Config.getOnlyIfDifferent()) {

530 if (!Result)

531 return Result.takeError();

532 switch (*Result) {

533 case FileDifference::IdenticalFile:

534

536

537 case FileDifference::SameContents:

538

541

542 case FileDifference::DifferentContents:

543 break;

544 }

545 }

546

547

548 std::error_code RenameEC = sys::fs::rename(*TempPath, OutputPath);

549 if (!RenameEC)

551

552

553

554

557

558 if (!RenameEC)

560

562}

563

564Error OnDiskOutputFile::discard() {

565

566 if (auto E = reset())

567 return E;

568

569

570 if (OutputPath == "-")

572

573 auto discardPath = [&](StringRef Path) {

576 return EC;

577 };

578

579

580 if (!TempPath)

583 discardPath(*TempPath));

584}

585

590

593 std::optional Config) {

595 if (Path != "-") {

596 AbsPath = Path;

598 return std::move(E);

599 Path = AbsPath;

600 }

601

602 auto File = std::make_unique(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)

Definition VirtualOutputBackends.cpp:242

static Expected< FileDifference > areFilesDifferent(const llvm::Twine &Source, const llvm::Twine &Destination)

Definition VirtualOutputBackends.cpp:389

static sys::fs::OpenFlags generateFlagsFromConfig(OutputConfig Config)

Definition VirtualOutputBackends.cpp:257

static OutputConfig applySettings(std::optional< OutputConfig > &&Config, const OnDiskOutputBackend::OutputSettings &Settings)

Definition VirtualOutputBackends.cpp:192

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.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

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...

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.

std::string str() const

str - Get the contents as an std::string.

constexpr size_t size() const

size - Get the string size.

Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...

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().

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.

LLVM_ABI Expected< std::unique_ptr< OutputFileImpl > > createFileImpl(StringRef Path, std::optional< OutputConfig > Config) override

Create a file for Path.

Definition VirtualOutputBackends.cpp:592

OutputSettings Settings

Settings for this backend.

Error makeAbsolute(SmallVectorImpl< char > &Path) const

Resolve an absolute path.

Definition VirtualOutputBackends.cpp:586

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.

LLVM_ABI bool is_regular_file(const basic_file_status &status)

Does status represent a regular file?

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?

LLVM_ABI bool exists(const basic_file_status &status)

Does file exist?

@ OF_Text

The file should be opened in text mode on platforms like z/OS that make this distinction.

@ OF_TextWithCRLF

The file should be opened in text mode and use a carriage linefeed '\r '.

@ OF_Append

The file should be opened in append mode.

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.

LLVM_ABI std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)

Remove path.

@ CD_CreateAlways

CD_CreateAlways - When opening a file:

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.

LLVM_ABI std::error_code make_absolute(SmallVectorImpl< char > &path)

Make path an absolute path.

LLVM_ABI std::error_code copy_file(const Twine &From, const Twine &To)

Copy the contents of From to To.

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.

LLVM_ABI StringRef extension(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)

Get extension.

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.

Definition VirtualOutputBackends.cpp:35

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,...

Definition VirtualOutputBackends.cpp:49

LLVM_ABI IntrusiveRefCntPtr< OutputBackend > makeMirroringOutputBackend(IntrusiveRefCntPtr< OutputBackend > Backend1, IntrusiveRefCntPtr< OutputBackend > Backend2)

Create a backend that forwards OutputBackend::createFile() to both Backend1 and Backend2.

Definition VirtualOutputBackends.cpp:81

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.

detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)

Error handleErrors(Error E, HandlerTs &&... Hs)

Pass the ErrorInfo(s) contained in E to their respective handlers.

IntrusiveRefCntPtr< T > makeIntrusiveRefCnt(Args &&...A)

Factory function for creating intrusive ref counted pointers.

Error joinErrors(Error E1, Error E2)

Concatenate errors.

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

@ 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.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

void consumeError(Error Err)

Consume a Error without doing anything.

OutputConfig DefaultConfig

bool RemoveOnSignal

Register output files to be deleted if a signal is received.

bool UseTemporaries

Use temporary files.

Full configuration for an output for use by the OutputBackend.

constexpr bool getTextWithCRLF() const