1 //===-- ModuleFileExtension.h - Module File Extensions ----------*- 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_MODULEFILEEXTENSION_H
10 #define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
11 
12 #include "llvm/ADT/IntrusiveRefCntPtr.h"
13 #include "llvm/Support/ExtensibleRTTI.h"
14 #include "llvm/Support/HashBuilder.h"
15 #include "llvm/Support/MD5.h"
16 #include <memory>
17 #include <string>
18 
19 namespace llvm {
20 class BitstreamCursor;
21 class BitstreamWriter;
22 class raw_ostream;
23 }
24 
25 namespace clang {
26 
27 class ASTReader;
28 class ASTWriter;
29 class Sema;
30 
31 namespace serialization {
32   class ModuleFile;
33 } // end namespace serialization
34 
35 /// Metadata for a module file extension.
36 struct ModuleFileExtensionMetadata {
37   /// The name used to identify this particular extension block within
38   /// the resulting module file. It should be unique to the particular
39   /// extension, because this name will be used to match the name of
40   /// an extension block to the appropriate reader.
41   std::string BlockName;
42 
43   /// The major version of the extension data.
44   unsigned MajorVersion;
45 
46   /// The minor version of the extension data.
47   unsigned MinorVersion;
48 
49   /// A string containing additional user information that will be
50   /// stored with the metadata.
51   std::string UserInfo;
52 };
53 
54 class ModuleFileExtensionReader;
55 class ModuleFileExtensionWriter;
56 
57 /// An abstract superclass that describes a custom extension to the
58 /// module/precompiled header file format.
59 ///
60 /// A module file extension can introduce additional information into
61 /// compiled module files (.pcm) and precompiled headers (.pch) via a
62 /// custom writer that can then be accessed via a custom reader when
63 /// the module file or precompiled header is loaded.
64 ///
65 /// Subclasses must use LLVM RTTI for open class hierarchies.
66 class ModuleFileExtension
67     : public llvm::RTTIExtends<ModuleFileExtension, llvm::RTTIRoot> {
68 public:
69   /// Discriminator for LLVM RTTI.
70   static char ID;
71 
72   virtual ~ModuleFileExtension();
73 
74   /// Retrieves the metadata for this module file extension.
75   virtual ModuleFileExtensionMetadata getExtensionMetadata() const = 0;
76 
77   /// Hash information about the presence of this extension into the
78   /// module hash.
79   ///
80   /// The module hash is used to distinguish different variants of a module that
81   /// are incompatible. If the presence, absence, or version of the module file
82   /// extension should force the creation of a separate set of module files,
83   /// override this method to combine that distinguishing information into the
84   /// module hash.
85   ///
86   /// The default implementation of this function simply does nothing, so the
87   /// presence/absence of this extension does not distinguish module files.
88   using ExtensionHashBuilder =
89       llvm::HashBuilder<llvm::MD5, llvm::endianness::native>;
90   virtual void hashExtension(ExtensionHashBuilder &HBuilder) const;
91 
92   /// Create a new module file extension writer, which will be
93   /// responsible for writing the extension contents into a particular
94   /// module file.
95   virtual std::unique_ptr<ModuleFileExtensionWriter>
96   createExtensionWriter(ASTWriter &Writer) = 0;
97 
98   /// Create a new module file extension reader, given the
99   /// metadata read from the block and the cursor into the extension
100   /// block.
101   ///
102   /// May return null to indicate that an extension block with the
103   /// given metadata cannot be read.
104   virtual std::unique_ptr<ModuleFileExtensionReader>
105   createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
106                         ASTReader &Reader, serialization::ModuleFile &Mod,
107                         const llvm::BitstreamCursor &Stream) = 0;
108 };
109 
110 /// Abstract base class that writes a module file extension block into
111 /// a module file.
112 class ModuleFileExtensionWriter {
113   ModuleFileExtension *Extension;
114 
115 protected:
116   ModuleFileExtensionWriter(ModuleFileExtension *Extension)
117     : Extension(Extension) { }
118 
119 public:
120   virtual ~ModuleFileExtensionWriter();
121 
122   /// Retrieve the module file extension with which this writer is
123   /// associated.
124   ModuleFileExtension *getExtension() const { return Extension; }
125 
126   /// Write the contents of the extension block into the given bitstream.
127   ///
128   /// Responsible for writing the contents of the extension into the
129   /// given stream. All of the contents should be written into custom
130   /// records with IDs >= FIRST_EXTENSION_RECORD_ID.
131   virtual void writeExtensionContents(Sema &SemaRef,
132                                       llvm::BitstreamWriter &Stream) = 0;
133 };
134 
135 /// Abstract base class that reads a module file extension block from
136 /// a module file.
137 ///
138 /// Subclasses
139 class ModuleFileExtensionReader {
140   ModuleFileExtension *Extension;
141 
142 protected:
143   ModuleFileExtensionReader(ModuleFileExtension *Extension)
144     : Extension(Extension) { }
145 
146 public:
147   /// Retrieve the module file extension with which this reader is
148   /// associated.
149   ModuleFileExtension *getExtension() const { return Extension; }
150 
151   virtual ~ModuleFileExtensionReader();
152 };
153 
154 } // end namespace clang
155 
156 #endif // LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
157