|
| 1 | +//===- HashingOutputBackends.h - Hashing output backends --------*- C++ -*-===// |
| 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 | +#ifndef LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H |
| 10 | +#define LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H |
| 11 | + |
| 12 | +#include "llvm/ADT/StringExtras.h" |
| 13 | +#include "llvm/ADT/StringMap.h" |
| 14 | +#include "llvm/Support/Endian.h" |
| 15 | +#include "llvm/Support/HashBuilder.h" |
| 16 | +#include "llvm/Support/VirtualOutputBackend.h" |
| 17 | +#include "llvm/Support/VirtualOutputConfig.h" |
| 18 | +#include "llvm/Support/raw_ostream.h" |
| 19 | + |
| 20 | +namespace llvm { |
| 21 | +namespace vfs { |
| 22 | + |
| 23 | +/// raw_pwrite_stream that writes to a hasher. |
| 24 | +template <typename HasherT> |
| 25 | +class HashingStream : public llvm::raw_pwrite_stream { |
| 26 | +private: |
| 27 | + SmallVector<char> Buffer; |
| 28 | + raw_svector_ostream OS; |
| 29 | + |
| 30 | + using HashBuilderT = HashBuilder<HasherT, support::endianness::native>; |
| 31 | + HashBuilderT Builder; |
| 32 | + |
| 33 | + void write_impl(const char *Ptr, size_t Size) override { |
| 34 | + OS.write(Ptr, Size); |
| 35 | + } |
| 36 | + |
| 37 | + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override { |
| 38 | + OS.pwrite(Ptr, Size, Offset); |
| 39 | + } |
| 40 | + |
| 41 | + uint64_t current_pos() const override { return OS.str().size(); } |
| 42 | + |
| 43 | +public: |
| 44 | + HashingStream() : OS(Buffer) { SetUnbuffered(); } |
| 45 | + |
| 46 | + auto final() { |
| 47 | + Builder.update(OS.str()); |
| 48 | + return Builder.final(); |
| 49 | + } |
| 50 | +}; |
| 51 | + |
| 52 | +template <typename HasherT> class HashingOutputFile; |
| 53 | + |
| 54 | +/// An output backend that only generates the hash for outputs. |
| 55 | +template <typename HasherT> class HashingOutputBackend : public OutputBackend { |
| 56 | +private: |
| 57 | + friend class HashingOutputFile<HasherT>; |
| 58 | + void addOutputFile(StringRef Path, StringRef Hash) { |
| 59 | + OutputHashes[Path] = std::string(Hash); |
| 60 | + } |
| 61 | + |
| 62 | +protected: |
| 63 | + IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override { |
| 64 | + return const_cast<HashingOutputBackend<HasherT> *>(this); |
| 65 | + } |
| 66 | + |
| 67 | + Expected<std::unique_ptr<OutputFileImpl>> |
| 68 | + createFileImpl(StringRef Path, Optional<OutputConfig> Config) override { |
| 69 | + return std::make_unique<HashingOutputFile<HasherT>>(Path, *this); |
| 70 | + } |
| 71 | + |
| 72 | +public: |
| 73 | + /// Iterator for all the output file names. |
| 74 | + auto outputFiles() const { return OutputHashes.keys(); } |
| 75 | + |
| 76 | + /// Get hash value for the output files in hex representation. |
| 77 | + /// Return None if the requested path is not generated. |
| 78 | + Optional<std::string> getHashValueForFile(StringRef Path) { |
| 79 | + auto F = OutputHashes.find(Path); |
| 80 | + if (F == OutputHashes.end()) |
| 81 | + return None; |
| 82 | + return toHex(F->second); |
| 83 | + } |
| 84 | + |
| 85 | +private: |
| 86 | + StringMap<std::string> OutputHashes; |
| 87 | +}; |
| 88 | + |
| 89 | +/// HashingOutputFile. |
| 90 | +template <typename HasherT> |
| 91 | +class HashingOutputFile final : public OutputFileImpl { |
| 92 | +public: |
| 93 | + Error keep() override { |
| 94 | + auto Result = OS.final(); |
| 95 | + Backend.addOutputFile(OutputPath, toStringRef(Result)); |
| 96 | + return Error::success(); |
| 97 | + } |
| 98 | + Error discard() override { return Error::success(); } |
| 99 | + raw_pwrite_stream &getOS() override { return OS; } |
| 100 | + |
| 101 | + HashingOutputFile(StringRef OutputPath, |
| 102 | + HashingOutputBackend<HasherT> &Backend) |
| 103 | + : OutputPath(OutputPath.str()), Backend(Backend) {} |
| 104 | + |
| 105 | +private: |
| 106 | + const std::string OutputPath; |
| 107 | + HashingStream<HasherT> OS; |
| 108 | + HashingOutputBackend<HasherT> &Backend; |
| 109 | +}; |
| 110 | + |
| 111 | +} // namespace vfs |
| 112 | +} // namespace llvm |
| 113 | + |
| 114 | +#endif // LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H |
0 commit comments