1 //===--- Serialization/PCHContainerOperations.h - PCH Containers --*- 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_CLANG_SERIALIZATION_PCHCONTAINEROPERATIONS_H
10 #define LLVM_CLANG_SERIALIZATION_PCHCONTAINEROPERATIONS_H
11 
12 #include "clang/Basic/Module.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include <memory>
17 
18 namespace llvm {
19 class raw_pwrite_stream;
20 }
21 
22 namespace clang {
23 
24 class ASTConsumer;
25 class CompilerInstance;
26 
27 struct PCHBuffer {
28   ASTFileSignature Signature;
29   llvm::SmallVector<char, 0> Data;
30   bool IsComplete;
31 };
32 
33 /// This abstract interface provides operations for creating
34 /// containers for serialized ASTs (precompiled headers and clang
35 /// modules).
36 class PCHContainerWriter {
37 public:
38   virtual ~PCHContainerWriter() = 0;
39   virtual llvm::StringRef getFormat() const = 0;
40 
41   /// Return an ASTConsumer that can be chained with a
42   /// PCHGenerator that produces a wrapper file format containing a
43   /// serialized AST bitstream.
44   virtual std::unique_ptr<ASTConsumer>
45   CreatePCHContainerGenerator(CompilerInstance &CI,
46                               const std::string &MainFileName,
47                               const std::string &OutputFileName,
48                               std::unique_ptr<llvm::raw_pwrite_stream> OS,
49                               std::shared_ptr<PCHBuffer> Buffer) const = 0;
50 };
51 
52 /// This abstract interface provides operations for unwrapping
53 /// containers for serialized ASTs (precompiled headers and clang
54 /// modules).
55 class PCHContainerReader {
56 public:
57   virtual ~PCHContainerReader() = 0;
58   /// Equivalent to the format passed to -fmodule-format=
59   virtual llvm::ArrayRef<llvm::StringRef> getFormats() const = 0;
60 
61   /// Returns the serialized AST inside the PCH container Buffer.
62   virtual llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0;
63 };
64 
65 /// Implements write operations for a raw pass-through PCH container.
66 class RawPCHContainerWriter : public PCHContainerWriter {
67   llvm::StringRef getFormat() const override { return "raw"; }
68 
69   /// Return an ASTConsumer that can be chained with a
70   /// PCHGenerator that writes the module to a flat file.
71   std::unique_ptr<ASTConsumer>
72   CreatePCHContainerGenerator(CompilerInstance &CI,
73                               const std::string &MainFileName,
74                               const std::string &OutputFileName,
75                               std::unique_ptr<llvm::raw_pwrite_stream> OS,
76                               std::shared_ptr<PCHBuffer> Buffer) const override;
77 };
78 
79 /// Implements read operations for a raw pass-through PCH container.
80 class RawPCHContainerReader : public PCHContainerReader {
81   llvm::ArrayRef<llvm::StringRef> getFormats() const override;
82   /// Simply returns the buffer contained in Buffer.
83   llvm::StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
84 };
85 
86 /// A registry of PCHContainerWriter and -Reader objects for different formats.
87 class PCHContainerOperations {
88   llvm::StringMap<std::unique_ptr<PCHContainerWriter>> Writers;
89   llvm::StringMap<PCHContainerReader *> Readers;
90   llvm::SmallVector<std::unique_ptr<PCHContainerReader>> OwnedReaders;
91 
92 public:
93   /// Automatically registers a RawPCHContainerWriter and
94   /// RawPCHContainerReader.
95   PCHContainerOperations();
96   void registerWriter(std::unique_ptr<PCHContainerWriter> Writer) {
97     Writers[Writer->getFormat()] = std::move(Writer);
98   }
99   void registerReader(std::unique_ptr<PCHContainerReader> Reader) {
100     assert(!Reader->getFormats().empty() &&
101            "PCHContainerReader must handle >=1 format");
102     for (llvm::StringRef Fmt : Reader->getFormats())
103       Readers[Fmt] = Reader.get();
104     OwnedReaders.push_back(std::move(Reader));
105   }
106   const PCHContainerWriter *getWriterOrNull(llvm::StringRef Format) {
107     return Writers[Format].get();
108   }
109   const PCHContainerReader *getReaderOrNull(llvm::StringRef Format) {
110     return Readers[Format];
111   }
112   const PCHContainerReader &getRawReader() {
113     return *getReaderOrNull("raw");
114   }
115 };
116 
117 }
118 
119 #endif
120