Skip to content

Commit

Permalink
Add option to include detailed type information in AST JSON output
Browse files Browse the repository at this point in the history
  • Loading branch information
MikePopoloski committed Jan 11, 2025
1 parent 86a2937 commit 2d2d39f
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 45 deletions.
5 changes: 5 additions & 0 deletions docs/command-line-ref.dox
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ symbols are dumped.

When dumping AST to JSON, include source line and file information.

`--ast-json-detailed-types`

When dumping AST to JSON, include expanded type information in the output instead of
condensing all types into a human-friendly string.

@section compilation-limits Compilation

`--top <name>`
Expand Down
7 changes: 7 additions & 0 deletions include/slang/ast/ASTSerializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//------------------------------------------------------------------------------
#pragma once

#include "slang/util/Hash.h"
#include "slang/util/Util.h"

namespace slang {
Expand Down Expand Up @@ -42,6 +43,10 @@ class SLANG_EXPORT ASTSerializer {
/// information should be included in the JSON output.
void setIncludeSourceInfo(bool set) { includeSourceInfo = set; }

/// Sets a flag that indicates whether detailed type information
/// is included in the output.
void setDetailedTypeInfo(bool set) { detailedTypeInfo = set; }

/// Serializes a symbol to JSON.
void serialize(const Symbol& symbol, bool inMembersArray = false);

Expand Down Expand Up @@ -174,6 +179,8 @@ class SLANG_EXPORT ASTSerializer {
JsonWriter& writer;
bool includeAddrs = true;
bool includeSourceInfo = false;
bool detailedTypeInfo = false;
flat_hash_set<const void*> visiting;
};

} // namespace slang::ast
35 changes: 35 additions & 0 deletions include/slang/ast/types/AllTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class SLANG_EXPORT ScalarType : public IntegralType {
ScalarType(Kind scalarKind);
ScalarType(Kind scalarKind, bool isSigned);

void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::ScalarType; }
};

Expand All @@ -78,6 +80,8 @@ class SLANG_EXPORT PredefinedIntegerType : public IntegralType {
PredefinedIntegerType(Kind integerKind);
PredefinedIntegerType(Kind integerKind, bool isSigned);

void serializeTo(ASTSerializer&) const {}

static bool isDefaultSigned(Kind integerKind);

static bool isKind(SymbolKind kind) { return kind == SymbolKind::PredefinedIntegerType; }
Expand All @@ -93,6 +97,7 @@ class SLANG_EXPORT FloatingType : public Type {
explicit FloatingType(Kind floatKind);

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::FloatingType; }
};
Expand All @@ -111,6 +116,8 @@ class SLANG_EXPORT EnumType : public IntegralType, public Scope {
EnumType(Compilation& compilation, SourceLocation loc, const Type& baseType,
const ASTContext& context);

void serializeTo(ASTSerializer& serializer) const;

static const Type& fromSyntax(Compilation& compilation, const syntax::EnumTypeSyntax& syntax,
const ASTContext& context,
function_ref<void(const Symbol&)> insertCB);
Expand Down Expand Up @@ -161,6 +168,8 @@ class SLANG_EXPORT PackedArrayType : public IntegralType {

PackedArrayType(const Type& elementType, ConstantRange range, bitwidth_t fullWidth);

void serializeTo(ASTSerializer& serializer) const;

static const Type& fromSyntax(const Scope& scope, const Type& elementType,
const EvaluatedDimension& dimension,
const syntax::SyntaxNode& syntax);
Expand Down Expand Up @@ -190,6 +199,8 @@ class SLANG_EXPORT FixedSizeUnpackedArrayType : public Type {
FixedSizeUnpackedArrayType(const Type& elementType, ConstantRange range,
uint64_t selectableWidth, uint64_t bitstreamWidth);

void serializeTo(ASTSerializer& serializer) const;

static const Type& fromDims(const Scope& scope, const Type& elementType,
std::span<const ConstantRange> dimensions,
syntax::DeferredSourceRange sourceRange);
Expand All @@ -211,6 +222,7 @@ class SLANG_EXPORT DynamicArrayType : public Type {
explicit DynamicArrayType(const Type& elementType);

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer& serializer) const;

static bool isKind(SymbolKind kind) { return kind == SymbolKind::DynamicArrayType; }
};
Expand All @@ -228,6 +240,7 @@ class SLANG_EXPORT DPIOpenArrayType : public Type {
DPIOpenArrayType(const Type& elementType, bool isPacked);

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer& serializer) const;

static bool isKind(SymbolKind kind) { return kind == SymbolKind::DPIOpenArrayType; }
};
Expand All @@ -247,6 +260,7 @@ class SLANG_EXPORT AssociativeArrayType : public Type {
/// @returns true if the array has a wildcard index type
bool hasWildcardIndexType() const { return indexType == nullptr; }
ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer& serializer) const;

static bool isKind(SymbolKind kind) { return kind == SymbolKind::AssociativeArrayType; }
};
Expand All @@ -263,6 +277,7 @@ class SLANG_EXPORT QueueType : public Type {
QueueType(const Type& elementType, uint32_t maxBound);

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer& serializer) const;

static bool isKind(SymbolKind kind) { return kind == SymbolKind::QueueType; }
};
Expand All @@ -276,6 +291,8 @@ class SLANG_EXPORT PackedStructType : public IntegralType, public Scope {
PackedStructType(Compilation& compilation, bool isSigned, SourceLocation loc,
const ASTContext& context);

void serializeTo(ASTSerializer&) const {}

static const Type& fromSyntax(Compilation& compilation,
const syntax::StructUnionTypeSyntax& syntax,
const ASTContext& context);
Expand All @@ -300,6 +317,8 @@ class SLANG_EXPORT UnpackedStructType : public Type, public Scope {

UnpackedStructType(Compilation& compilation, SourceLocation loc, const ASTContext& context);

void serializeTo(ASTSerializer&) const {}

static const Type& fromSyntax(const ASTContext& context,
const syntax::StructUnionTypeSyntax& syntax);

Expand Down Expand Up @@ -327,6 +346,8 @@ class SLANG_EXPORT PackedUnionType : public IntegralType, public Scope {
PackedUnionType(Compilation& compilation, bool isSigned, bool isTagged, bool isSoft,
SourceLocation loc, const ASTContext& context);

void serializeTo(ASTSerializer& serializer) const;

static const Type& fromSyntax(Compilation& compilation,
const syntax::StructUnionTypeSyntax& syntax,
const ASTContext& context);
Expand Down Expand Up @@ -355,6 +376,8 @@ class SLANG_EXPORT UnpackedUnionType : public Type, public Scope {
UnpackedUnionType(Compilation& compilation, bool isTagged, SourceLocation loc,
const ASTContext& context);

void serializeTo(ASTSerializer& serializer) const;

static const Type& fromSyntax(const ASTContext& context,
const syntax::StructUnionTypeSyntax& syntax);

Expand All @@ -372,6 +395,7 @@ class SLANG_EXPORT VoidType : public Type {
VoidType() : Type(SymbolKind::VoidType, "void", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::VoidType; }
};
Expand All @@ -385,6 +409,7 @@ class SLANG_EXPORT NullType : public Type {
NullType() : Type(SymbolKind::NullType, "null", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::NullType; }
};
Expand All @@ -395,6 +420,7 @@ class SLANG_EXPORT CHandleType : public Type {
CHandleType() : Type(SymbolKind::CHandleType, "chandle", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::CHandleType; }
};
Expand All @@ -405,6 +431,7 @@ class SLANG_EXPORT StringType : public Type {
StringType() : Type(SymbolKind::StringType, "string", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::StringType; }
};
Expand All @@ -416,6 +443,7 @@ class SLANG_EXPORT EventType : public Type {
EventType() : Type(SymbolKind::EventType, "event", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::EventType; }
};
Expand All @@ -427,6 +455,7 @@ class SLANG_EXPORT UnboundedType : public Type {
UnboundedType() : Type(SymbolKind::UnboundedType, "$", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::UnboundedType; }
};
Expand All @@ -437,6 +466,7 @@ class SLANG_EXPORT TypeRefType : public Type {
TypeRefType() : Type(SymbolKind::TypeRefType, "type reference", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::TypeRefType; }
};
Expand All @@ -447,6 +477,7 @@ class SLANG_EXPORT UntypedType : public Type {
UntypedType() : Type(SymbolKind::UntypedType, "untyped", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::UntypedType; }
};
Expand All @@ -457,6 +488,7 @@ class SLANG_EXPORT SequenceType : public Type {
SequenceType() : Type(SymbolKind::SequenceType, "sequence", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::SequenceType; }
};
Expand All @@ -467,6 +499,7 @@ class SLANG_EXPORT PropertyType : public Type {
PropertyType() : Type(SymbolKind::PropertyType, "property", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::PropertyType; }
};
Expand All @@ -490,6 +523,7 @@ class SLANG_EXPORT VirtualInterfaceType : public Type {
isRealIface(isRealIface) {}

ConstantValue getDefaultValueImpl() const;
void serializeTo(ASTSerializer& serializer) const;

static const Type& fromSyntax(const ASTContext& context,
const syntax::VirtualInterfaceTypeSyntax& syntax);
Expand Down Expand Up @@ -576,6 +610,7 @@ class SLANG_EXPORT ErrorType : public Type {
ErrorType() : Type(SymbolKind::ErrorType, "", SourceLocation()) {}

ConstantValue getDefaultValueImpl() const { return nullptr; }
void serializeTo(ASTSerializer&) const {}

static bool isKind(SymbolKind kind) { return kind == SymbolKind::ErrorType; }

Expand Down
28 changes: 22 additions & 6 deletions source/ast/ASTSerializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,20 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) {
}
writer.endObject();
}
else if constexpr (std::is_base_of_v<Type, T> && !std::is_same_v<TypeAliasType, T> &&
!std::is_same_v<ClassType, T> && !std::is_same_v<CovergroupType, T>) {
writer.writeValue(elem.toString());
}
else {
if constexpr (std::is_base_of_v<Type, T>) {
if (!inMembersArray) {
// If we're not including detailed type info, we can just write the type name,
// unless this a type alias, class, or covergroup. Otherwise we will fall through
// and serialize full detailed type info.
if (!detailedTypeInfo && (!inMembersArray || (!std::is_same_v<TypeAliasType, T> &&
!std::is_same_v<ClassType, T> &&
!std::is_same_v<CovergroupType, T>))) {
writer.writeValue(elem.toString());
return;
}

// Avoid infinite loops with recursive types.
if (!visiting.insert(&elem).second) {
writer.writeValue(elem.toString());
return;
}
Expand All @@ -261,6 +268,10 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) {
return;
}

// Ignore transparent members.
if (elem.kind == SymbolKind::TransparentMember)
return;

writer.startObject();
write("name", elem.name);
write("kind", toString(elem.kind));
Expand All @@ -284,7 +295,8 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) {
}

if constexpr (std::is_base_of_v<ValueSymbol, T>) {
write("type", elem.getType());
if (elem.kind != SymbolKind::EnumValue)
write("type", elem.getType());

if (auto init = elem.getInitializer())
write("initializer", *init);
Expand All @@ -304,6 +316,10 @@ void ASTSerializer::visit(const T& elem, bool inMembersArray) {
}

writer.endObject();

if constexpr (std::is_base_of_v<Type, T>) {
visiting.erase(&elem);
}
}
}

Expand Down
Loading

0 comments on commit 2d2d39f

Please sign in to comment.