Skip to content

Commit b985236

Browse files
rebase and review comments
Created using spr 1.3.5
2 parents e575483 + f1e2056 commit b985236

21 files changed

+3468
-0
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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::vfs {
21+
22+
/// raw_pwrite_stream that writes to a hasher.
23+
template <typename HasherT>
24+
class HashingStream : public llvm::raw_pwrite_stream {
25+
private:
26+
SmallVector<char> Buffer;
27+
raw_svector_ostream OS;
28+
29+
using HashBuilderT = HashBuilder<HasherT, support::endianness::native>;
30+
HashBuilderT Builder;
31+
32+
void write_impl(const char *Ptr, size_t Size) override {
33+
OS.write(Ptr, Size);
34+
}
35+
36+
void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override {
37+
OS.pwrite(Ptr, Size, Offset);
38+
}
39+
40+
uint64_t current_pos() const override { return OS.str().size(); }
41+
42+
public:
43+
HashingStream() : OS(Buffer) { SetUnbuffered(); }
44+
45+
auto final() {
46+
Builder.update(OS.str());
47+
return Builder.final();
48+
}
49+
};
50+
51+
template <typename HasherT> class HashingOutputFile;
52+
53+
/// An output backend that only generates the hash for outputs.
54+
template <typename HasherT> class HashingOutputBackend : public OutputBackend {
55+
private:
56+
friend class HashingOutputFile<HasherT>;
57+
void addOutputFile(StringRef Path, StringRef Hash) {
58+
OutputHashes[Path] = std::string(Hash);
59+
}
60+
61+
protected:
62+
IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
63+
return const_cast<HashingOutputBackend<HasherT> *>(this);
64+
}
65+
66+
Expected<std::unique_ptr<OutputFileImpl>>
67+
createFileImpl(StringRef Path, std::optional<OutputConfig> Config) override {
68+
return std::make_unique<HashingOutputFile<HasherT>>(Path, *this);
69+
}
70+
71+
public:
72+
/// Iterator for all the output file names.
73+
auto outputFiles() const { return OutputHashes.keys(); }
74+
75+
/// Get hash value for the output files in hex representation.
76+
/// Return None if the requested path is not generated.
77+
std::optional<std::string> getHashValueForFile(StringRef Path) {
78+
auto F = OutputHashes.find(Path);
79+
if (F == OutputHashes.end())
80+
return std::nullopt;
81+
return toHex(F->second);
82+
}
83+
84+
private:
85+
StringMap<std::string> OutputHashes;
86+
};
87+
88+
/// HashingOutputFile.
89+
template <typename HasherT>
90+
class HashingOutputFile final : public OutputFileImpl {
91+
public:
92+
Error keep() override {
93+
auto Result = OS.final();
94+
Backend.addOutputFile(OutputPath, toStringRef(Result));
95+
return Error::success();
96+
}
97+
Error discard() override { return Error::success(); }
98+
raw_pwrite_stream &getOS() override { return OS; }
99+
100+
HashingOutputFile(StringRef OutputPath,
101+
HashingOutputBackend<HasherT> &Backend)
102+
: OutputPath(OutputPath.str()), Backend(Backend) {}
103+
104+
private:
105+
const std::string OutputPath;
106+
HashingStream<HasherT> OS;
107+
HashingOutputBackend<HasherT> &Backend;
108+
};
109+
110+
} // namespace llvm::vfs
111+
112+
#endif // LLVM_SUPPORT_HASHINGOUTPUTBACKEND_H
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===- VirtualOutputBackend.h - Output virtualization -----------*- 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_VIRTUALOUTPUTBACKEND_H
10+
#define LLVM_SUPPORT_VIRTUALOUTPUTBACKEND_H
11+
12+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
13+
#include "llvm/Support/Error.h"
14+
#include "llvm/Support/VirtualOutputConfig.h"
15+
#include "llvm/Support/VirtualOutputFile.h"
16+
17+
namespace llvm::vfs {
18+
19+
/// Interface for virtualized outputs.
20+
///
21+
/// If virtual functions are added here, also add them to \a
22+
/// ProxyOutputBackend.
23+
class OutputBackend : public RefCountedBase<OutputBackend> {
24+
virtual void anchor();
25+
26+
public:
27+
/// Get a backend that points to the same destination as this one but that
28+
/// has independent settings.
29+
///
30+
/// Not thread-safe, but all operations are thread-safe when performed on
31+
/// separate clones of the same backend.
32+
IntrusiveRefCntPtr<OutputBackend> clone() const { return cloneImpl(); }
33+
34+
/// Create a file. If \p Config is \c std::nullopt, uses the backend's default
35+
/// OutputConfig (may match \a OutputConfig::OutputConfig(), or may
36+
/// have been customized).
37+
///
38+
/// Thread-safe.
39+
Expected<OutputFile>
40+
createFile(const Twine &Path,
41+
std::optional<OutputConfig> Config = std::nullopt);
42+
43+
protected:
44+
/// Must be thread-safe. Virtual function has a different name than \a
45+
/// clone() so that implementations can override the return value.
46+
virtual IntrusiveRefCntPtr<OutputBackend> cloneImpl() const = 0;
47+
48+
/// Create a file for \p Path. Must be thread-safe.
49+
///
50+
/// \pre \p Config is valid or std::nullopt.
51+
virtual Expected<std::unique_ptr<OutputFileImpl>>
52+
createFileImpl(StringRef Path, std::optional<OutputConfig> Config) = 0;
53+
54+
OutputBackend() = default;
55+
56+
public:
57+
virtual ~OutputBackend() = default;
58+
};
59+
60+
} // namespace llvm::vfs
61+
62+
#endif // LLVM_SUPPORT_VIRTUALOUTPUTBACKEND_H
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//===- VirtualOutputBackends.h - Virtual 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_VIRTUALOUTPUTBACKENDS_H
10+
#define LLVM_SUPPORT_VIRTUALOUTPUTBACKENDS_H
11+
12+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
13+
#include "llvm/Support/VirtualOutputBackend.h"
14+
#include "llvm/Support/VirtualOutputConfig.h"
15+
16+
namespace llvm::vfs {
17+
18+
/// Create a backend that ignores all output.
19+
IntrusiveRefCntPtr<OutputBackend> makeNullOutputBackend();
20+
21+
/// Make a backend where \a OutputBackend::createFile() forwards to
22+
/// \p UnderlyingBackend when \p Filter is true, and otherwise returns a
23+
/// \a NullOutput.
24+
IntrusiveRefCntPtr<OutputBackend> makeFilteringOutputBackend(
25+
IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend,
26+
std::function<bool(StringRef, std::optional<OutputConfig>)> Filter);
27+
28+
/// Create a backend that forwards \a OutputBackend::createFile() to both \p
29+
/// Backend1 and \p Backend2 and sends content to both places.
30+
IntrusiveRefCntPtr<OutputBackend>
31+
makeMirroringOutputBackend(IntrusiveRefCntPtr<OutputBackend> Backend1,
32+
IntrusiveRefCntPtr<OutputBackend> Backend2);
33+
34+
/// A helper class for proxying another backend, with the default
35+
/// implementation to forward to the underlying backend.
36+
class ProxyOutputBackend : public OutputBackend {
37+
void anchor() override;
38+
39+
protected:
40+
// Require subclass to implement cloneImpl().
41+
//
42+
// IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override;
43+
44+
Expected<std::unique_ptr<OutputFileImpl>>
45+
createFileImpl(StringRef Path, std::optional<OutputConfig> Config) override {
46+
OutputFile File;
47+
if (Error E = UnderlyingBackend->createFile(Path, Config).moveInto(File))
48+
return std::move(E);
49+
return File.takeImpl();
50+
}
51+
52+
OutputBackend &getUnderlyingBackend() const { return *UnderlyingBackend; }
53+
54+
public:
55+
ProxyOutputBackend(IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend)
56+
: UnderlyingBackend(std::move(UnderlyingBackend)) {
57+
assert(this->UnderlyingBackend && "Expected non-null backend");
58+
}
59+
60+
private:
61+
IntrusiveRefCntPtr<OutputBackend> UnderlyingBackend;
62+
};
63+
64+
/// An output backend that creates files on disk, wrapping APIs in sys::fs.
65+
class OnDiskOutputBackend : public OutputBackend {
66+
void anchor() override;
67+
68+
protected:
69+
IntrusiveRefCntPtr<OutputBackend> cloneImpl() const override {
70+
return clone();
71+
}
72+
73+
Expected<std::unique_ptr<OutputFileImpl>>
74+
createFileImpl(StringRef Path, std::optional<OutputConfig> Config) override;
75+
76+
public:
77+
/// Resolve an absolute path.
78+
Error makeAbsolute(SmallVectorImpl<char> &Path) const;
79+
80+
/// On disk output settings.
81+
struct OutputSettings {
82+
/// Register output files to be deleted if a signal is received. Also
83+
/// disabled for outputs with \a OutputConfig::getNoDiscardOnSignal().
84+
bool DisableRemoveOnSignal = false;
85+
86+
/// Disable temporary files. Also disabled for outputs with \a
87+
/// OutputConfig::getNoAtomicWrite().
88+
bool DisableTemporaries = false;
89+
90+
// Default configuration for this backend.
91+
OutputConfig DefaultConfig;
92+
};
93+
94+
IntrusiveRefCntPtr<OnDiskOutputBackend> clone() const {
95+
auto Clone = makeIntrusiveRefCnt<OnDiskOutputBackend>();
96+
Clone->Settings = Settings;
97+
return Clone;
98+
}
99+
100+
OnDiskOutputBackend() = default;
101+
102+
/// Settings for this backend.
103+
///
104+
/// Access is not thread-safe.
105+
OutputSettings Settings;
106+
};
107+
108+
} // namespace llvm::vfs
109+
110+
#endif // LLVM_SUPPORT_VIRTUALOUTPUTBACKENDS_H
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===- VirtualOutputConfig.def - Virtual output config defs -----*- 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 HANDLE_OUTPUT_CONFIG_FLAG
10+
#error "Missing macro definition of HANDLE_OUTPUT_CONFIG_FLAG"
11+
#endif
12+
13+
// Define HANDLE_OUTPUT_CONFIG_FLAG before including.
14+
//
15+
// #define HANDLE_OUTPUT_CONFIG_FLAG(NAME, DEFAULT)
16+
17+
HANDLE_OUTPUT_CONFIG_FLAG(Text, false) // OF_Text.
18+
HANDLE_OUTPUT_CONFIG_FLAG(CRLF, false) // OF_CRLF.
19+
HANDLE_OUTPUT_CONFIG_FLAG(Append, false) // OF_Append.
20+
HANDLE_OUTPUT_CONFIG_FLAG(DiscardOnSignal, true) // E.g., RemoveFileOnSignal.
21+
HANDLE_OUTPUT_CONFIG_FLAG(AtomicWrite, true) // E.g., use temporaries.
22+
HANDLE_OUTPUT_CONFIG_FLAG(ImplyCreateDirectories, true)
23+
// Skip atomic write if existing file content is the same
24+
HANDLE_OUTPUT_CONFIG_FLAG(OnlyIfDifferent, false)
25+
26+
#undef HANDLE_OUTPUT_CONFIG_FLAG

0 commit comments

Comments
 (0)