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
18namespace llvm {
19class raw_pwrite_stream;
20}
21
22namespace clang {
23
24class ASTConsumer;
25class CompilerInstance;
26
27struct 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).
36class PCHContainerWriter {
37public:
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).
55class PCHContainerReader {
56public:
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.
66class 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.
80class 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.
87class PCHContainerOperations {
88  llvm::StringMap<std::unique_ptr<PCHContainerWriter>> Writers;
89  llvm::StringMap<PCHContainerReader *> Readers;
90  llvm::SmallVector<std::unique_ptr<PCHContainerReader>> OwnedReaders;
91
92public:
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