Skip to content

Merge clang abstraction serialization into the stable branch #483

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7d25a00
Use scope qualifiers in Clang's tblgen backends to get useful
rjmccall Oct 1, 2019
daf9c5c
Emit TypeNodes.def with tblgen.
rjmccall Oct 1, 2019
08ad4b0
Remove TypeNodes.def from the modulemap.
rjmccall Oct 2, 2019
ed58beb
Rename TypeNodes.def to TypeNodes.inc for consistency across all
rjmccall Oct 2, 2019
c9b4abc
Add Record::getValueAsOptionalDef().
rjmccall Oct 25, 2019
fd13a8e
[NFC] Add a tablegen node for the root of the AST node hierarchies.
rjmccall Oct 25, 2019
831a775
[NFC] Rename ClangASTEmitters.h -> ASTTableGen.h
rjmccall Oct 26, 2019
e12542c
[NFC] Correct accidental use of tabs.
rjmccall Oct 28, 2019
474c42d
Introduce some types and functions to make it easier to work with
rjmccall Oct 28, 2019
1942f51
Add a function to get the ExceptionSpecInfo of a function type; NFC.
rjmccall Dec 10, 2019
5c22dba
Extract out WrappedRecord as a convenience base class; NFC.
rjmccall Dec 10, 2019
2fe0d65
Enable better node-hierarchy metaprogramming; NFC.
rjmccall Dec 10, 2019
62161f1
Extract the TypeClass <-> TypeCode map into a .def file; NFC.
rjmccall Dec 11, 2019
654aeff
Standardize the reader methods in ASTReader; NFC.
rjmccall Dec 13, 2019
4429e44
Abstract serialization: TableGen "basic" reader/writer CRTP
rjmccall Dec 14, 2019
dffa4cd
Abstract serialization: TableGen the (de)serialization code for Types.
rjmccall Dec 14, 2019
1057edf
MSVC build fix: forget some unneeded and incorrect friends.
rjmccall Dec 14, 2019
97d3a38
[clang] Fix modules build after addition of TypeBitCodes.def
Dec 14, 2019
d2f9cfa
Move ASTRecordReader into its own header; NFC.
rjmccall Dec 14, 2019
57670c1
Move ASTRecordWriter into its own header; NFC.
rjmccall Dec 14, 2019
aadc0c8
Always -I clang/include when tblgen'ing in Clang.
rjmccall Dec 15, 2019
4bacd44
Tablegen: Remove the error for duplicate include files.
River707 Nov 21, 2019
ed5e213
Move Basic{Reader,Writer} emission into ASTPropsEmitter; NFC.
rjmccall Dec 15, 2019
c1182d4
Fixing a -Wcovered-switch diagnostic and changing tabs to spaces; NFC.
AaronBallman Dec 16, 2019
e6c5479
Replace tabs with spaces.
rjmccall Dec 16, 2019
bd26cd6
Add the ability to use property-based serialization for "cased" types.
rjmccall Dec 16, 2019
db62b49
Use property-based serialization for DeclarationName.
rjmccall Dec 16, 2019
535385d
Add the ability to declare helper variables when reading
rjmccall Dec 16, 2019
94a3e68
Add the ability for properties to be conditional on other properties.
rjmccall Dec 16, 2019
83864e9
Use property-based serialization for TemplateName.
rjmccall Dec 16, 2019
2c07b1e
Add Optional::map.
rjmccall Dec 16, 2019
5ccdd58
Use property-based serialization for TemplateArgument.
rjmccall Dec 16, 2019
90719e7
Forward {read,write}SomeEnumType to {read,write}Enum instead of
rjmccall Dec 16, 2019
2162c35
Fix a bug in the property-based serialization of
rjmccall Dec 16, 2019
5241189
Abstract serialization fixes for the Apple Clang changes.
rjmccall Dec 17, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion clang/cmake/modules/AddClang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ function(clang_tablegen)
message(FATAL_ERROR "SOURCE source-file required by clang_tablegen")
endif()

set( CLANG_TABLEGEN_ARGUMENTS -I ${CLANG_SOURCE_DIR}/include )
set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} )
tablegen(CLANG ${CTG_UNPARSED_ARGUMENTS})
tablegen(CLANG ${CTG_UNPARSED_ARGUMENTS} ${CLANG_TABLEGEN_ARGUMENTS})

if(CTG_TARGET)
add_public_tablegen_target(${CTG_TARGET})
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ class FullComment;

} // namespace comments

namespace serialization {
template <class> class AbstractTypeReader;
} // namespace serialization

struct TypeInfo {
uint64_t Width = 0;
unsigned Align = 0;
Expand Down Expand Up @@ -428,6 +432,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
friend class ASTDeclReader;
friend class ASTReader;
friend class ASTWriter;
template <class> friend class serialization::AbstractTypeReader;
friend class CXXRecordDecl;

/// A mapping to contain the template or declaration that
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/ASTFwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Stmt;
#include "clang/AST/StmtNodes.inc"
class Type;
#define TYPE(DERIVED, BASE) class DERIVED##Type;
#include "clang/AST/TypeNodes.def"
#include "clang/AST/TypeNodes.inc"
class CXXCtorInitializer;

} // end namespace clang
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/ASTTypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class ASTNodeKind {
#include "clang/AST/StmtNodes.inc"
NKI_Type,
#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
#include "clang/AST/TypeNodes.def"
#include "clang/AST/TypeNodes.inc"
NKI_OMPClause,
#define OPENMP_CLAUSE(TextualSpelling, Class) NKI_##Class,
#include "clang/Basic/OpenMPKinds.def"
Expand Down Expand Up @@ -205,7 +205,7 @@ KIND_TO_KIND_ID(OMPClause)
#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
#include "clang/AST/StmtNodes.inc"
#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
#include "clang/AST/TypeNodes.def"
#include "clang/AST/TypeNodes.inc"
#define OPENMP_CLAUSE(TextualSpelling, Class) KIND_TO_KIND_ID(Class)
#include "clang/Basic/OpenMPKinds.def"
#undef KIND_TO_KIND_ID
Expand Down
263 changes: 263 additions & 0 deletions clang/include/clang/AST/AbstractBasicReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
//==--- AbstractBasiceReader.h - Abstract basic value deserialization -----===//
//
// 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 CLANG_AST_ABSTRACTBASICREADER_H
#define CLANG_AST_ABSTRACTBASICREADER_H

#include "clang/AST/DeclTemplate.h"

namespace clang {
namespace serialization {

template <class T>
inline T makeNullableFromOptional(const Optional<T> &value) {
return (value ? *value : T());
}

template <class T>
inline T *makePointerFromOptional(Optional<T *> value) {
return (value ? *value : nullptr);
}

// PropertyReader is a class concept that requires the following method:
// BasicReader find(llvm::StringRef propertyName);
// where BasicReader is some class conforming to the BasicReader concept.
// An abstract AST-node reader is created with a PropertyReader and
// performs a sequence of calls like so:
// propertyReader.find(propertyName).read##TypeName()
// to read the properties of the node it is deserializing.

// BasicReader is a class concept that requires methods like:
// ValueType read##TypeName();
// where TypeName is the name of a PropertyType node from PropertiesBase.td
// and ValueType is the corresponding C++ type name. The read method may
// require one or more buffer arguments.
//
// In addition to the concrete type names, BasicReader is expected to
// implement these methods:
//
// template <class EnumType>
// void writeEnum(T value);
//
// Reads an enum value from the current property. EnumType will always
// be an enum type. Only necessary if the BasicReader doesn't provide
// type-specific readers for all the enum types.
//
// template <class ValueType>
// Optional<ValueType> writeOptional();
//
// Reads an optional value from the current property.
//
// template <class ValueType>
// ArrayRef<ValueType> readArray(llvm::SmallVectorImpl<ValueType> &buffer);
//
// Reads an array of values from the current property.
//
// PropertyReader readObject();
//
// Reads an object from the current property; the returned property
// reader will be subjected to a sequence of property reads and then
// discarded before any other properties are reader from the "outer"
// property reader (which need not be the same type). The sub-reader
// will be used as if with the following code:
//
// {
// auto &&widget = W.find("widget").readObject();
// auto kind = widget.find("kind").readWidgetKind();
// auto declaration = widget.find("declaration").readDeclRef();
// return Widget(kind, declaration);
// }

// ReadDispatcher does type-based forwarding to one of the read methods
// on the BasicReader passed in:
//
// template <class ValueType>
// struct ReadDispatcher {
// template <class BasicReader, class... BufferTypes>
// static ValueType read(BasicReader &R, BufferTypes &&...);
// };

// BasicReaderBase provides convenience implementations of the read methods
// for EnumPropertyType and SubclassPropertyType types that just defer to
// the "underlying" implementations (for UInt32 and the base class,
// respectively).
//
// template <class Impl>
// class BasicReaderBase {
// protected:
// BasicReaderBase(ASTContext &ctx);
// Impl &asImpl();
// public:
// ASTContext &getASTContext();
// ...
// };

// The actual classes are auto-generated; see ClangASTPropertiesEmitter.cpp.
#include "clang/AST/AbstractBasicReader.inc"

/// DataStreamBasicReader provides convenience implementations for many
/// BasicReader methods based on the assumption that the
/// ultimate reader implementation is based on a variable-length stream
/// of unstructured data (like Clang's module files). It is designed
/// to pair with DataStreamBasicWriter.
///
/// This class can also act as a PropertyReader, implementing find("...")
/// by simply forwarding to itself.
///
/// Unimplemented methods:
/// readBool
/// readUInt32
/// readUInt64
/// readIdentifier
/// readSelector
/// readSourceLocation
/// readQualType
/// readStmtRef
/// readDeclRef
template <class Impl>
class DataStreamBasicReader : public BasicReaderBase<Impl> {
protected:
using BasicReaderBase<Impl>::asImpl;
DataStreamBasicReader(ASTContext &ctx) : BasicReaderBase<Impl>(ctx) {}

public:
using BasicReaderBase<Impl>::getASTContext;

/// Implement property-find by ignoring it. We rely on properties being
/// serialized and deserialized in a reliable order instead.
Impl &find(const char *propertyName) {
return asImpl();
}

template <class T>
T readEnum() {
return T(asImpl().readUInt32());
}

// Implement object reading by forwarding to this, collapsing the
// structure into a single data stream.
Impl &readObject() { return asImpl(); }

template <class T>
llvm::ArrayRef<T> readArray(llvm::SmallVectorImpl<T> &buffer) {
assert(buffer.empty());

uint32_t size = asImpl().readUInt32();
buffer.reserve(size);

for (uint32_t i = 0; i != size; ++i) {
buffer.push_back(ReadDispatcher<T>::read(asImpl()));
}
return buffer;
}

template <class T, class... Args>
llvm::Optional<T> readOptional(Args &&...args) {
return UnpackOptionalValue<T>::unpack(
ReadDispatcher<T>::read(asImpl(), std::forward<Args>(args)...));
}

llvm::APSInt readAPSInt() {
bool isUnsigned = asImpl().readBool();
llvm::APInt value = asImpl().readAPInt();
return llvm::APSInt(std::move(value), isUnsigned);
}

llvm::APInt readAPInt() {
unsigned bitWidth = asImpl().readUInt32();
unsigned numWords = llvm::APInt::getNumWords(bitWidth);
llvm::SmallVector<uint64_t, 4> data;
for (uint32_t i = 0; i != numWords; ++i)
data.push_back(asImpl().readUInt64());
return llvm::APInt(bitWidth, numWords, &data[0]);
}

Qualifiers readQualifiers() {
static_assert(sizeof(Qualifiers().getAsOpaqueValue()) <= sizeof(uint64_t),
"update this if the value size changes");
uint64_t value = asImpl().readUInt64();
return Qualifiers::fromOpaqueValue(value);
}

FunctionProtoType::ExceptionSpecInfo
readExceptionSpecInfo(llvm::SmallVectorImpl<QualType> &buffer) {
FunctionProtoType::ExceptionSpecInfo esi;
esi.Type = ExceptionSpecificationType(asImpl().readUInt32());
if (esi.Type == EST_Dynamic) {
esi.Exceptions = asImpl().template readArray<QualType>(buffer);
} else if (isComputedNoexcept(esi.Type)) {
esi.NoexceptExpr = asImpl().readExprRef();
} else if (esi.Type == EST_Uninstantiated) {
esi.SourceDecl = asImpl().readFunctionDeclRef();
esi.SourceTemplate = asImpl().readFunctionDeclRef();
} else if (esi.Type == EST_Unevaluated) {
esi.SourceDecl = asImpl().readFunctionDeclRef();
}
return esi;
}

FunctionProtoType::ExtParameterInfo readExtParameterInfo() {
static_assert(sizeof(FunctionProtoType::ExtParameterInfo().getOpaqueValue())
<= sizeof(uint32_t),
"opaque value doesn't fit into uint32_t");
uint32_t value = asImpl().readUInt32();
return FunctionProtoType::ExtParameterInfo::getFromOpaqueValue(value);
}

NestedNameSpecifier *readNestedNameSpecifier() {
auto &ctx = getASTContext();

// We build this up iteratively.
NestedNameSpecifier *cur = nullptr;

uint32_t depth = asImpl().readUInt32();
for (uint32_t i = 0; i != depth; ++i) {
auto kind = asImpl().readNestedNameSpecifierKind();
switch (kind) {
case NestedNameSpecifier::Identifier:
cur = NestedNameSpecifier::Create(ctx, cur,
asImpl().readIdentifier());
continue;

case NestedNameSpecifier::Namespace:
cur = NestedNameSpecifier::Create(ctx, cur,
asImpl().readNamespaceDeclRef());
continue;

case NestedNameSpecifier::NamespaceAlias:
cur = NestedNameSpecifier::Create(ctx, cur,
asImpl().readNamespaceAliasDeclRef());
continue;

case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
cur = NestedNameSpecifier::Create(ctx, cur,
kind == NestedNameSpecifier::TypeSpecWithTemplate,
asImpl().readQualType().getTypePtr());
continue;

case NestedNameSpecifier::Global:
cur = NestedNameSpecifier::GlobalSpecifier(ctx);
continue;

case NestedNameSpecifier::Super:
cur = NestedNameSpecifier::SuperSpecifier(ctx,
asImpl().readCXXRecordDeclRef());
continue;
}
llvm_unreachable("bad nested name specifier kind");
}

return cur;
}
};

} // end namespace serialization
} // end namespace clang

#endif
Loading