//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file contains the declarations of the HashingOutputBackend class, which /// is the VirtualOutputBackend that only produces the hashes for the output /// files. This is useful for checking if the outputs are deterministic without /// storing output files in memory or on disk. /// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H #define LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/HashBuilder.h" #include "llvm/Support/VirtualOutputBackend.h" #include "llvm/Support/VirtualOutputConfig.h" #include "llvm/Support/raw_ostream.h" #include namespace llvm::vfs { /// raw_pwrite_stream that writes to a hasher. template class HashingStream : public llvm::raw_pwrite_stream { private: SmallVector Buffer; raw_svector_ostream OS; using HashBuilderT = HashBuilder; HashBuilderT Builder; void write_impl(const char *Ptr, size_t Size) override { OS.write(Ptr, Size); } void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override { OS.pwrite(Ptr, Size, Offset); } uint64_t current_pos() const override { return OS.str().size(); } public: HashingStream() : OS(Buffer) { SetUnbuffered(); } auto final() { Builder.update(OS.str()); return Builder.final(); } }; template class HashingOutputFile; /// An output backend that only generates the hash for outputs. template class HashingOutputBackend : public OutputBackend { private: friend class HashingOutputFile; void addOutputFile(StringRef Path, StringRef Hash) { std::lock_guard Lock(OutputHashLock); OutputHashes[Path] = Hash.str(); } protected: IntrusiveRefCntPtr cloneImpl() const override { return const_cast *>(this); } Expected> createFileImpl(StringRef Path, std::optional Config) override { return std::make_unique>(Path, *this); } public: /// Iterator for all the output file names. /// /// Not thread safe. Should be queried after all outputs are written. auto outputFiles() const { return OutputHashes.keys(); } /// Get hash value for the output files in hex representation. /// Return None if the requested path is not generated. /// /// Not thread safe. Should be queried after all outputs are written. std::optional getHashValueForFile(StringRef Path) { auto F = OutputHashes.find(Path); if (F == OutputHashes.end()) return std::nullopt; return toHex(F->second); } private: std::mutex OutputHashLock; StringMap OutputHashes; }; /// HashingOutputFile. template class HashingOutputFile final : public OutputFileImpl { public: Error keep() override { auto Result = OS.final(); Backend.addOutputFile(OutputPath, toStringRef(Result)); return Error::success(); } Error discard() override { return Error::success(); } raw_pwrite_stream &getOS() override { return OS; } HashingOutputFile(StringRef OutputPath, HashingOutputBackend &Backend) : OutputPath(OutputPath.str()), Backend(Backend) {} private: const std::string OutputPath; HashingStream OS; HashingOutputBackend &Backend; }; } // namespace llvm::vfs #endif // LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H