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