//===-- ModuleFileExtension.h - Module File Extensions ----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
#define LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/ExtensibleRTTI.h"
#include "llvm/Support/HashBuilder.h"
#include "llvm/Support/MD5.h"
#include <memory>
#include <string>
namespace llvm {
class BitstreamCursor;
class BitstreamWriter;
class raw_ostream;
}
namespace clang {
class ASTReader;
class ASTWriter;
class Sema;
namespace serialization {
class ModuleFile;
} // end namespace serialization
/// Metadata for a module file extension.
struct ModuleFileExtensionMetadata {
/// The name used to identify this particular extension block within
/// the resulting module file. It should be unique to the particular
/// extension, because this name will be used to match the name of
/// an extension block to the appropriate reader.
std::string BlockName;
/// The major version of the extension data.
unsigned MajorVersion;
/// The minor version of the extension data.
unsigned MinorVersion;
/// A string containing additional user information that will be
/// stored with the metadata.
std::string UserInfo;
};
class ModuleFileExtensionReader;
class ModuleFileExtensionWriter;
/// An abstract superclass that describes a custom extension to the
/// module/precompiled header file format.
///
/// A module file extension can introduce additional information into
/// compiled module files (.pcm) and precompiled headers (.pch) via a
/// custom writer that can then be accessed via a custom reader when
/// the module file or precompiled header is loaded.
///
/// Subclasses must use LLVM RTTI for open class hierarchies.
class ModuleFileExtension
: public llvm::RTTIExtends<ModuleFileExtension, llvm::RTTIRoot> {
public:
/// Discriminator for LLVM RTTI.
static char ID;
virtual ~ModuleFileExtension();
/// Retrieves the metadata for this module file extension.
virtual ModuleFileExtensionMetadata getExtensionMetadata() const = 0;
/// Hash information about the presence of this extension into the
/// module hash.
///
/// The module hash is used to distinguish different variants of a module that
/// are incompatible. If the presence, absence, or version of the module file
/// extension should force the creation of a separate set of module files,
/// override this method to combine that distinguishing information into the
/// module hash.
///
/// The default implementation of this function simply does nothing, so the
/// presence/absence of this extension does not distinguish module files.
using ExtensionHashBuilder =
llvm::HashBuilderImpl<llvm::MD5,
llvm::support::endian::system_endianness()>;
virtual void hashExtension(ExtensionHashBuilder &HBuilder) const;
/// Create a new module file extension writer, which will be
/// responsible for writing the extension contents into a particular
/// module file.
virtual std::unique_ptr<ModuleFileExtensionWriter>
createExtensionWriter(ASTWriter &Writer) = 0;
/// Create a new module file extension reader, given the
/// metadata read from the block and the cursor into the extension
/// block.
///
/// May return null to indicate that an extension block with the
/// given metadata cannot be read.
virtual std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
ASTReader &Reader, serialization::ModuleFile &Mod,
const llvm::BitstreamCursor &Stream) = 0;
};
/// Abstract base class that writes a module file extension block into
/// a module file.
class ModuleFileExtensionWriter {
ModuleFileExtension *Extension;
protected:
ModuleFileExtensionWriter(ModuleFileExtension *Extension)
: Extension(Extension) { }
public:
virtual ~ModuleFileExtensionWriter();
/// Retrieve the module file extension with which this writer is
/// associated.
ModuleFileExtension *getExtension() const { return Extension; }
/// Write the contents of the extension block into the given bitstream.
///
/// Responsible for writing the contents of the extension into the
/// given stream. All of the contents should be written into custom
/// records with IDs >= FIRST_EXTENSION_RECORD_ID.
virtual void writeExtensionContents(Sema &SemaRef,
llvm::BitstreamWriter &Stream) = 0;
};
/// Abstract base class that reads a module file extension block from
/// a module file.
///
/// Subclasses
class ModuleFileExtensionReader {
ModuleFileExtension *Extension;
protected:
ModuleFileExtensionReader(ModuleFileExtension *Extension)
: Extension(Extension) { }
public:
/// Retrieve the module file extension with which this reader is
/// associated.
ModuleFileExtension *getExtension() const { return Extension; }
virtual ~ModuleFileExtensionReader();
};
} // end namespace clang
#endif // LLVM_CLANG_SERIALIZATION_MODULEFILEEXTENSION_H