slang::ast::Compilation class

A centralized location for creating and caching symbols.

This includes creating symbols from syntax nodes as well as fabricating them synthetically. Common symbols such as built in types are exposed here as well.

A Compilation object is the entry point for building ASTs. Typically you add one or more SyntaxTrees to the compilation and then call getRoot() to retrieve the root of the elaborated AST, and getAllDiagnostics() to get a list of all diagnostics issued in the design.

Base classes

class slang::BumpAllocator
BumpAllocator - Fast O(1) allocator.

Public types

struct DefinitionLookupResult
A struct containing the result of a definition lookup.

Constructors, destructors, conversion operators

Compilation(const Bag& options = {}, const SourceLibrary* defaultLib = nullptr) explicit
Constructs a new instance of the Compilation class.

Allocation functions

auto allocConstant(ConstantValue&& value) -> ConstantValue*
Allocates space for a constant value in the pool of constants.
auto allocSymbolMap() -> SymbolMap*
Allocates a symbol map.
auto allocPointerMap() -> PointerMap*
Allocates a pointer map.
auto allocAssertionDetails() -> AssertionInstanceDetails*
Allocates an assertion instance details object.
template<typename... Args>
auto allocGenericClass(Args && ... args) -> GenericClassDefSymbol*
Allocates a generic class symbol.
auto allocConfigBlock(std::string_view name, SourceLocation loc) -> ConfigBlockSymbol*
Allocates a config block symbol.
auto getDriverMapAllocator() -> DriverIntervalMap::allocator_type&
Gets the driver map allocator.
auto getUnrollIntervalMapAllocator() -> UnrollIntervalMap::allocator_type&
Gets the unroll interval map allocator.
auto createEmptyTypeSyntax(SourceLocation loc) -> const syntax::ImplicitTypeSyntax&
Creates an empty ImplicitTypeSyntax object.

Top-level API

auto getOptions() const -> const CompilationOptions&
Gets the set of options used to construct the compilation.
auto hasFlag(bitmask<CompilationFlags> flags) const -> bool
Returns true if the given flag(s) are enabled for this compilation.
auto getSourceManager() const -> const SourceManager*
Gets the source manager associated with the compilation.
void addSyntaxTree(std::shared_ptr<syntax::SyntaxTree> tree)
Adds a syntax tree to the compilation.
auto getSyntaxTrees() const -> std::span<const std::shared_ptr<syntax::SyntaxTree>>
Gets the set of syntax trees that have been added to the compilation.
auto getRoot() -> const RootSymbol&
Gets the root of the design.
auto isFinalized() const -> bool
Indicates whether the design has been compiled and can no longer accept modifications.
auto getParseDiagnostics() -> const Diagnostics&
Gets the diagnostics produced during lexing, preprocessing, and syntax parsing.
auto getSemanticDiagnostics() -> const Diagnostics&
Gets the diagnostics produced during semantic analysis, including the creation of symbols, type checking, and name lookup.
auto getAllDiagnostics() -> const Diagnostics&
Gets all of the diagnostics produced during compilation.

Utility and convenience methods

auto parseName(std::string_view name) -> const syntax::NameSyntax&
A convenience method for parsing a name string and turning it into a set of syntax nodes.
auto tryParseName(std::string_view name, Diagnostics& diags) -> const syntax::NameSyntax&
A convenience method for parsing a name string and turning it into a set of syntax nodes.
auto createScriptScope() -> CompilationUnitSymbol&
Creates a new compilation unit within the design that can be modified dynamically, which is useful in runtime scripting scenarios.

Lookup and query methods

auto getCompilationUnit(const syntax::CompilationUnitSyntax& syntax) const -> const CompilationUnitSymbol*
Gets the compilation unit for the given syntax node.
auto getCompilationUnits() const -> std::span<const CompilationUnitSymbol*const>
Gets the set of compilation units that have been added to the compilation.
auto getSourceLibrary(std::string_view name) const -> const SourceLibrary*
Gets the source library with the given name, or nullptr if there is no such library.
auto getDefaultLibrary() const -> const SourceLibrary&
Gets the default library object.
auto tryGetDefinition(std::string_view name, const Scope& scope) const -> DefinitionLookupResult
Gets the definition with the given name, or nullptr if there is no such definition.
auto getDefinition(std::string_view name, const Scope& scope, SourceRange sourceRange, DiagCode code) const -> DefinitionLookupResult
Gets the definition with the given name, or nullptr if there is no such definition.
auto getDefinition(std::string_view name, const Scope& scope, const ConfigRule& configRule, SourceRange sourceRange, DiagCode code) const -> DefinitionLookupResult
Gets the definition indicated by the given config rule, or nullptr if it does not exist.
auto getDefinition(std::string_view name, const Scope& scope, SourceRange sourceRange, const BindDirectiveInfo& bindInfo) const -> DefinitionLookupResult
Gets the definition indicated by the given bind directive info.
auto getDefinition(const Scope& scope, const syntax::ModuleDeclarationSyntax& syntax) const -> const DefinitionSymbol*
Gets the definition for the given syntax node, or nullptr if it does not exist.
auto getDefinition(const ConfigBlockSymbol& config, std::string_view cellName, std::string_view libName, SourceRange sourceRange) const -> const DefinitionSymbol*
Gets the definition indicated by the given config and cell ID, or nullptr if it does not exist.
auto getDefinitions() const -> std::vector<const Symbol*>
Gets a list of all definitions (including primitives) in the design.
auto getPackage(std::string_view name) const -> const PackageSymbol*
Gets the package with the give name, or nullptr if there is no such package.
auto getStdPackage() const -> const PackageSymbol&
Gets the built-in 'std' package.
auto getPackages() const -> std::vector<const PackageSymbol*>
Gets a list of all packages in the design.
auto getGateType(std::string_view name) const -> const PrimitiveSymbol*
Gets the built-in gate type with the given name, or nullptr if there is no such gate.

System function management

void addSystemSubroutine(std::unique_ptr<SystemSubroutine> subroutine)
Registers a system subroutine handler, which can be accessed by compiled code.
void addSystemSubroutine(const SystemSubroutine& subroutine)
Registers an externally owned system subroutine handler, which can be accessed by compiled code.
void addSystemMethod(SymbolKind typeKind, std::unique_ptr<SystemSubroutine> method)
Registers a type-based system method handler, which can be accessed by compiled code.
void addSystemMethod(SymbolKind typeKind, const SystemSubroutine& subroutine)
Registers an externally owned type-based system method handler, which can be accessed by compiled code.
auto getSystemSubroutine(std::string_view name) const -> const SystemSubroutine*
Gets a system subroutine with the given name, or nullptr if there is no such subroutine registered.
auto getSystemMethod(SymbolKind typeKind, std::string_view name) const -> const SystemSubroutine*
Gets a system method for the specified type with the given name, or nullptr if there is no such method registered.
auto getAttributes(const Symbol& symbol) const -> std::span<const AttributeSymbol*const>
Gets the attributes associated with the given symbol.
auto getAttributes(const Statement& stmt) const -> std::span<const AttributeSymbol*const>
Gets the attributes associated with the given statement.
auto getAttributes(const Expression& expr) const -> std::span<const AttributeSymbol*const>
Gets the attributes associated with the given expression.
auto getAttributes(const PortConnection& conn) const -> std::span<const AttributeSymbol*const>
Gets the attributes associated with the given port connection.

Internal AST construction

void createDefinition(const Scope& scope, LookupLocation location, const syntax::ModuleDeclarationSyntax& syntax)
Creates a new definition in the given scope based on the given syntax.
auto createPackage(const Scope& scope, const syntax::ModuleDeclarationSyntax& syntax) -> const PackageSymbol&
Creates a new package in the given scope based on the given syntax.
auto createConfigBlock(const Scope& scope, const syntax::ConfigDeclarationSyntax& syntax) -> const ConfigBlockSymbol&
Creates a new config block in the given scope based on the given syntax.
auto createPrimitive(Scope& scope, const syntax::UdpDeclarationSyntax& syntax) -> const PrimitiveSymbol&
Creates a new primitive in the given scope based on the given syntax.
void addGateType(const PrimitiveSymbol& primitive)
Registers a built-in gate symbol.
void setAttributes(const Symbol& symbol, std::span<const AttributeSymbol*const> attributes)
Sets the attributes associated with the given symbol.
void setAttributes(const Statement& stmt, std::span<const AttributeSymbol*const> attributes)
Sets the attributes associated with the given statement.
void setAttributes(const Expression& expr, std::span<const AttributeSymbol*const> attributes)
Sets the attributes associated with the given expression.
void setAttributes(const PortConnection& conn, std::span<const AttributeSymbol*const> attributes)
Sets the attributes associated with the given port connection.
void notePackageExportCandidate(const PackageSymbol& packageScope, const Symbol& symbol)
Notes that the given symbol was imported into the current scope via a package import, and further that the current scope is within a package declaration.
auto findPackageExportCandidate(const PackageSymbol& packageScope, std::string_view name) const -> const Symbol*
Tries to find a symbol that can be exported from the given package to satisfy an import of a given name from that package.
void noteBindDirective(const syntax::BindDirectiveSyntax& syntax, const Scope& scope)
Notes the presence of a bind directive.
void noteInstanceWithDefBind(const Symbol& instance)
Notes an instance that contains a bind directive targeting a global definition.
void noteDPIExportDirective(const syntax::DPIExportSyntax& syntax, const Scope& scope)
Notes the presence of a DPI export directive.
void addOutOfBlockDecl(const Scope& scope, const syntax::ScopedNameSyntax& name, const syntax::SyntaxNode& syntax, SymbolIndex index)
Tracks the existence of an out-of-block declaration (method or constraint) in the given scope.
auto findOutOfBlockDecl(const Scope& scope, std::string_view className, std::string_view declName) const -> std::tuple<const syntax::SyntaxNode*, SymbolIndex, bool*>
Searches for an out-of-block declaration in the given scope with declName for a className class.
void addExternInterfaceMethod(const SubroutineSymbol& method)
Tracks the existence of an extern interface method implementation.
void noteDefaultClocking(const Scope& scope, const Symbol& clocking, SourceRange range)
Notes that there is a default clocking block associated with the specified scope.
void noteDefaultClocking(const ASTContext& context, const syntax::DefaultClockingReferenceSyntax& syntax)
Notes that there is a default clocking block associated with the specified scope.
auto getDefaultClocking(const Scope& scope) const -> const Symbol*
Finds an applicable default clocking block for the given scope, or returns nullptr if no default clocking is in effect.
void noteGlobalClocking(const Scope& scope, const Symbol& clocking, SourceRange range)
Notes that there is a global clocking block associated with the specified scope.
auto getGlobalClocking(const Scope& scope) const -> const Symbol*
Finds an applicable global clocking block for the given scope, or returns nullptr if no global clocking is in effect.
void noteDefaultDisable(const Scope& scope, const Expression& expr)
Notes that there is a default disable associated with the specified scope.
auto getDefaultDisable(const Scope& scope) const -> const Expression*
Finds an applicable default disable expression for the given scope, or returns nullptr if no such declaration is in effect.
void noteExternDefinition(const Scope& scope, const syntax::SyntaxNode& syntax)
Notes the existence of an extern module/interface/program/primitive declaration.
auto getExternDefinition(std::string_view name, const Scope& scope) const -> const syntax::SyntaxNode*
Performs a lookup for an extern module/interface/program/primitive declaration of the given name.
void noteReference(const syntax::SyntaxNode& node, bool isLValue = false)
Notes that the given syntax node is "referenced" somewhere in the AST.
void noteReference(const Symbol& symbol, bool isLValue = false)
Notes that the given symbol is "referenced" somewhere in the AST.
auto isReferenced(const syntax::SyntaxNode& node) const -> std::pair<bool, bool>
Checks whether the given syntax node has been referenced in the AST thus far.
void noteNameConflict(const Symbol& symbol)
Notes that the given symbol has a name conflict in its parent scope.
void addDiagnostics(const Diagnostics& diagnostics)
Adds a set of diagnostics to the compilation's list of semantic diagnostics.
void forceElaborate(const Symbol& symbol)
Forces the given symbol and all children underneath it in the hierarchy to be elaborated and any relevant diagnostics to be issued.
auto getDefaultTimeScale() const -> std::optional<TimeScale>
Gets the default time scale to use when none is specified in the source code.
auto getNextEnumSystemId() -> int
Gets the next system ID to use for identifying enum types.
auto getNextStructSystemId() -> int
Gets the next system ID to use for identifying struct types.
auto getNextUnionSystemId() -> int
Gets the next system ID to use for identifying union types.

Types

auto getType(syntax::SyntaxKind kind) const -> const Type&
Gets the type associated with the given syntax node kind.
auto getType(const syntax::DataTypeSyntax& node, const ASTContext& context, const Type* typedefTarget = nullptr) -> const Type&
Gets the type represented by the given data type syntax node.
auto getType(const Type& elementType, const syntax::SyntaxList<syntax::VariableDimensionSyntax>& dimensions, const ASTContext& context) -> const Type&
Gets an array type created from the given element type and dimensions.
auto getType(bitwidth_t width, bitmask<IntegralFlags> flags) -> const Type&
Gets an integral vector type with the given size and flags.
auto getScalarType(bitmask<IntegralFlags> flags) -> const Type&
Gets a scalar (single bit) type with the given flags.
auto getNetType(parsing::TokenKind kind) const -> const NetType&
Gets the nettype represented by the given token kind.
auto getBitType() const -> const Type&
Get the built-in bit type.
auto getLogicType() const -> const Type&
Get the built-in logic type.
auto getIntType() const -> const Type&
Get the built-in int type.
auto getByteType() const -> const Type&
Get the built-in byte type.
auto getIntegerType() const -> const Type&
Get the built-in integer type.
auto getRealType() const -> const Type&
Get the built-in real type.
auto getShortRealType() const -> const Type&
Get the built-in shortreal type.
auto getStringType() const -> const Type&
Get the built-in string type.
auto getVoidType() const -> const Type&
Get the built-in void type.
auto getErrorType() const -> const Type&
Get the error type, which is used as a placeholder to represent an invalid type.
auto getUnsignedIntType() -> const Type&
Get the built-in int unsigned type.
auto getNullType() -> const Type&
Get the built-in null type.
auto getUnboundedType() -> const Type&
Get the built-in $ type.
auto getTypeRefType() -> const Type&
Get the built-in type used for the result of the type() operator.
auto getWireNetType() const -> const NetType&
Get the wire built in net type.

Function documentation

const SourceManager* slang::ast::Compilation::getSourceManager() const

Gets the source manager associated with the compilation.

If no syntax trees have been added to the design this method will return nullptr.

void slang::ast::Compilation::addSyntaxTree(std::shared_ptr<syntax::SyntaxTree> tree)

Adds a syntax tree to the compilation.

If the compilation has already been finalized by calling getRoot this call will throw an exception.

const RootSymbol& slang::ast::Compilation::getRoot()

Gets the root of the design.

The first time you call this method all top-level instances will be elaborated and the compilation finalized. After that you can no longer make any modifications to the compilation object; any attempts to do so will result in an exception.

const Diagnostics& slang::ast::Compilation::getSemanticDiagnostics()

Gets the diagnostics produced during semantic analysis, including the creation of symbols, type checking, and name lookup.

Note that this will finalize the compilation, including forcing the evaluation of any symbols or expressions that were still waiting for lazy evaluation.

const syntax::NameSyntax& slang::ast::Compilation::parseName(std::string_view name)

A convenience method for parsing a name string and turning it into a set of syntax nodes.

This is mostly for testing and API purposes; normal compilation never does this. Throws an exception if there are errors parsing the name.

const syntax::NameSyntax& slang::ast::Compilation::tryParseName(std::string_view name, Diagnostics& diags)

A convenience method for parsing a name string and turning it into a set of syntax nodes.

This is mostly for testing and API purposes. Errors are added to the provided diagnostics bag.

CompilationUnitSymbol& slang::ast::Compilation::createScriptScope()

Creates a new compilation unit within the design that can be modified dynamically, which is useful in runtime scripting scenarios.

Note that this call will succeed even if the design has been finalized, but in that case any instantiations in the script scope won't affect which modules are determined to be top-level instances.

const CompilationUnitSymbol* slang::ast::Compilation::getCompilationUnit(const syntax::CompilationUnitSyntax& syntax) const

Gets the compilation unit for the given syntax node.

The compilation unit must have already been added to the compilation previously via a call to addSyntaxTree – otherwise returns nullptr.

DefinitionLookupResult slang::ast::Compilation::tryGetDefinition(std::string_view name, const Scope& scope) const

Gets the definition with the given name, or nullptr if there is no such definition.

This takes into account the given scope so that nested definitions are found before more global ones.

DefinitionLookupResult slang::ast::Compilation::getDefinition(std::string_view name, const Scope& scope, SourceRange sourceRange, DiagCode code) const

Gets the definition with the given name, or nullptr if there is no such definition.

If no definition is found an appropriate diagnostic will be issued.

DefinitionLookupResult slang::ast::Compilation::getDefinition(std::string_view name, const Scope& scope, const ConfigRule& configRule, SourceRange sourceRange, DiagCode code) const

Gets the definition indicated by the given config rule, or nullptr if it does not exist.

If no definition is found an appropriate diagnostic will be issued.

const DefinitionSymbol* slang::ast::Compilation::getDefinition(const ConfigBlockSymbol& config, std::string_view cellName, std::string_view libName, SourceRange sourceRange) const

Gets the definition indicated by the given config and cell ID, or nullptr if it does not exist.

If no definition is found an appropriate diagnostic will be issued.

void slang::ast::Compilation::addSystemSubroutine(const SystemSubroutine& subroutine)

Registers an externally owned system subroutine handler, which can be accessed by compiled code.

The provided subroutine must remain valid for the lifetime of this object.

void slang::ast::Compilation::addSystemMethod(SymbolKind typeKind, const SystemSubroutine& subroutine)

Registers an externally owned type-based system method handler, which can be accessed by compiled code.

The provided subroutine must remain valid for the lifetime of this object.

void slang::ast::Compilation::notePackageExportCandidate(const PackageSymbol& packageScope, const Symbol& symbol)

Notes that the given symbol was imported into the current scope via a package import, and further that the current scope is within a package declaration.

These symbols are candidates for being exported from that package.

const Symbol* slang::ast::Compilation::findPackageExportCandidate(const PackageSymbol& packageScope, std::string_view name) const

Tries to find a symbol that can be exported from the given package to satisfy an import of a given name from that package.

Returns nullptr if no such symbol can be found.

void slang::ast::Compilation::noteBindDirective(const syntax::BindDirectiveSyntax& syntax, const Scope& scope)

Notes the presence of a bind directive.

These can be later checked during scope elaboration to include the newly bound instances.

void slang::ast::Compilation::noteInstanceWithDefBind(const Symbol& instance)

Notes an instance that contains a bind directive targeting a global definition.

These are later checked for correctness.

void slang::ast::Compilation::noteDPIExportDirective(const syntax::DPIExportSyntax& syntax, const Scope& scope)

Notes the presence of a DPI export directive.

These will be checked for correctness but are otherwise unused by SystemVerilog code.

void slang::ast::Compilation::addOutOfBlockDecl(const Scope& scope, const syntax::ScopedNameSyntax& name, const syntax::SyntaxNode& syntax, SymbolIndex index)

Tracks the existence of an out-of-block declaration (method or constraint) in the given scope.

This can later be retrieved by calling findOutOfBlockDecl().

std::tuple<const syntax::SyntaxNode*, SymbolIndex, bool*> slang::ast::Compilation::findOutOfBlockDecl(const Scope& scope, std::string_view className, std::string_view declName) const

Searches for an out-of-block declaration in the given scope with declName for a className class.

Returns a tuple of syntax pointer and symbol index in the defining scope, along with a pointer that should be set to true if the resulting decl is considered "used". If not found, the syntax pointer will be null.

void slang::ast::Compilation::addExternInterfaceMethod(const SubroutineSymbol& method)

Tracks the existence of an extern interface method implementation.

These are later elaborated by the compilation to hook up connections to their interface prototypes.

void slang::ast::Compilation::noteReference(const syntax::SyntaxNode& node, bool isLValue = false)

Notes that the given syntax node is "referenced" somewhere in the AST.

This is used to diagnose unused variables, nets, etc. The isLValue parameter is used to tell whether a value is only assigned or whether it's also read somewhere.

void slang::ast::Compilation::noteReference(const Symbol& symbol, bool isLValue = false)

Notes that the given symbol is "referenced" somewhere in the AST.

This is used to diagnose unused variables, nets, etc. The isLValue parameter is used to tell whether a value is only assigned or whether it's also read somewhere.

std::pair<bool, bool> slang::ast::Compilation::isReferenced(const syntax::SyntaxNode& node) const

Checks whether the given syntax node has been referenced in the AST thus far.

The result is a pair, the first item of which is true if the node has been used as a non-lvalue, and the second of which is true if the node has been used as an lvalue. The second item is only relevant for nodes where it makes sense; e.g. variables and nets.

void slang::ast::Compilation::noteNameConflict(const Symbol& symbol)

Notes that the given symbol has a name conflict in its parent scope.

This will cause appropriate errors to be issued.

const Type& slang::ast::Compilation::getType(syntax::SyntaxKind kind) const

Gets the type associated with the given syntax node kind.

If the syntax kind doesn't represent a type this will return the error type.

const NetType& slang::ast::Compilation::getNetType(parsing::TokenKind kind) const

Gets the nettype represented by the given token kind.

If the token kind does not represent a nettype this will return the error nettype.

const NetType& slang::ast::Compilation::getWireNetType() const

Get the wire built in net type.

The rest of the built-in net types are rare enough that we don't bother providing dedicated accessors for them.