Skip to content

Commit

Permalink
Convert Definition to a first-class symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
MikePopoloski committed Dec 12, 2023
1 parent 49bbf04 commit 6fedcb1
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 79 deletions.
25 changes: 0 additions & 25 deletions bindings/python/CompBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,31 +35,6 @@ void registerCompilation(py::module_& m) {
EXPOSE_ENUM(m, PrimitivePortDirection);
EXPOSE_ENUM(m, DriverKind);

py::class_<DefinitionSymbol>(m, "DefinitionSymbol")
.def_readonly("name", &DefinitionSymbol::name)
.def_readonly("location", &DefinitionSymbol::location)
.def_readonly("definitionKind", &DefinitionSymbol::definitionKind)
.def_readonly("defaultLifetime", &DefinitionSymbol::defaultLifetime)
.def_readonly("unconnectedDrive", &DefinitionSymbol::unconnectedDrive)
.def_readonly("timeScale", &DefinitionSymbol::timeScale)
.def_readonly("attributes", &DefinitionSymbol::attributes)
.def_property_readonly("syntax", [](const DefinitionSymbol& self) { return &self.syntax; })
.def_property_readonly("defaultNetType",
[](const DefinitionSymbol& self) { return &self.defaultNetType; })
.def_property_readonly("scope", [](const DefinitionSymbol& self) { return &self.scope; })
.def_property_readonly("hierarchicalPath",
[](const DefinitionSymbol& self) {
std::string str;
self.getHierarchicalPath(str);
return str;
})
.def_property_readonly("isInstantiated", &DefinitionSymbol::isInstantiated)
.def("getKindString", &DefinitionSymbol::getKindString)
.def("getArticleKindString", &DefinitionSymbol::getArticleKindString)
.def("__repr__", [](const DefinitionSymbol& self) {
return fmt::format("DefinitionSymbol(\"{}\")", self.name);
});

py::enum_<MinTypMax>(m, "MinTypMax")
.value("Min", MinTypMax::Min)
.value("Typ", MinTypMax::Typ)
Expand Down
14 changes: 14 additions & 0 deletions bindings/python/SymbolBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,20 @@ void registerSymbols(py::module_& m) {
.def_readonly("topInstances", &RootSymbol::topInstances)
.def_readonly("compilationUnits", &RootSymbol::compilationUnits);

py::class_<DefinitionSymbol, Symbol>(m, "DefinitionSymbol")
.def_readonly("definitionKind", &DefinitionSymbol::definitionKind)
.def_readonly("defaultLifetime", &DefinitionSymbol::defaultLifetime)
.def_readonly("unconnectedDrive", &DefinitionSymbol::unconnectedDrive)
.def_readonly("timeScale", &DefinitionSymbol::timeScale)
.def_property_readonly("defaultNetType",
[](const DefinitionSymbol& self) { return &self.defaultNetType; })
.def_property_readonly("isInstantiated", &DefinitionSymbol::isInstantiated)
.def("getKindString", &DefinitionSymbol::getKindString)
.def("getArticleKindString", &DefinitionSymbol::getArticleKindString)
.def("__repr__", [](const DefinitionSymbol& self) {
return fmt::format("DefinitionSymbol(\"{}\")", self.name);
});

py::class_<ValueSymbol, Symbol>(m, "ValueSymbol")
.def_property_readonly("type", &ValueSymbol::getType)
.def_property_readonly("initializer", &ValueSymbol::getInitializer)
Expand Down
1 change: 1 addition & 0 deletions include/slang/ast/ASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ decltype(auto) Symbol::visit(TVisitor&& visitor, Args&&... args) const {
case SymbolKind::TypeAlias: return visitor.visit(*static_cast<const TypeAliasType*>(this), std::forward<Args>(args)...);
SYMBOL(Root);
SYMBOL(CompilationUnit);
SYMBOL(Definition);
SYMBOL(Attribute);
SYMBOL(TransparentMember);
SYMBOL(EmptyMember);
Expand Down
27 changes: 4 additions & 23 deletions include/slang/ast/symbols/CompilationUnitSymbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ class SyntaxTree;

namespace slang::ast {

class AttributeSymbol;
class Expression;
class InstanceSymbol;
class Type;
Expand Down Expand Up @@ -90,7 +89,7 @@ class SLANG_EXPORT RootSymbol : public Symbol, public Scope {
};

/// Represents a module, interface, or program definition.
class SLANG_EXPORT DefinitionSymbol {
class SLANG_EXPORT DefinitionSymbol : public Symbol {
public:
/// Information about a single parameter declaration.
struct ParameterDecl {
Expand Down Expand Up @@ -150,24 +149,9 @@ class SLANG_EXPORT DefinitionSymbol {
bool hasDefault() const;
};

/// The name of the definition.
std::string_view name;

/// The source location where the definition is declared.
SourceLocation location;

/// The syntax node describing the definition.
const syntax::ModuleDeclarationSyntax& syntax;

/// The default nettype for implicit nets within this definition.
const NetType& defaultNetType;

/// The scope containing the definition.
const Scope& scope;

/// The index of this definition within its parent scope.
SymbolIndex indexInScope;

/// The kind of definition (module, interface, or program).
DefinitionKind definitionKind;

Expand All @@ -190,9 +174,6 @@ class SLANG_EXPORT DefinitionSymbol {
/// A set of modport names declared by this definition.
flat_hash_set<std::string_view> modports;

/// A set of attributes associated with this definition.
std::span<const AttributeSymbol* const> attributes;

/// A set of bind directives that apply to all instances of this definition.
std::vector<const syntax::BindDirectiveSyntax*> bindDirectives;

Expand Down Expand Up @@ -227,9 +208,9 @@ class SLANG_EXPORT DefinitionSymbol {
/// Notes that the definition has been instantiated.
void noteInstantiated() const { instantiated = true; }

/// Gets the hierarchical path to the definition, appending it
/// to the provided string.
void getHierarchicalPath(std::string& buffer) const;
void serializeTo(ASTSerializer& serializer) const;

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

private:
mutable bool instantiated = false;
Expand Down
31 changes: 19 additions & 12 deletions source/ast/Compilation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,8 @@ const RootSymbol& Compilation::getRoot(bool skipDefParamsAndBinds) {
}

// Otherwise, issue an error because the user asked us to instantiate this.
def->scope.addDiag(diag::InvalidTopModule, SourceLocation::NoLocation)
def->getParentScope()->addDiag(diag::InvalidTopModule,
SourceLocation::NoLocation)
<< def->name;
}
}
Expand Down Expand Up @@ -477,8 +478,9 @@ const RootSymbol& Compilation::getRoot(bool skipDefParamsAndBinds) {
if (!param.isTypeParam && param.hasSyntax) {
auto it = cliOverrides.find(param.name);
if (it != cliOverrides.end()) {
hierarchyOverrides.childrenBySyntax[def->syntax].overridesBySyntax.emplace(
param.valueDecl, std::pair{*it->second, nullptr});
hierarchyOverrides.childrenBySyntax[*def->getSyntax()]
.overridesBySyntax.emplace(param.valueDecl,
std::pair{*it->second, nullptr});
}
}
}
Expand All @@ -504,7 +506,7 @@ const RootSymbol& Compilation::getRoot(bool skipDefParamsAndBinds) {
SmallVector<const InstanceSymbol*> topList;
for (auto [def, config] : topDefs) {
HierarchyOverrideNode* hierarchyOverrideNode = nullptr;
if (auto sit = hierarchyOverrides.childrenBySyntax.find(def->syntax);
if (auto sit = hierarchyOverrides.childrenBySyntax.find(*def->getSyntax());
sit != hierarchyOverrides.childrenBySyntax.end()) {
hierarchyOverrideNode = &sit->second;
}
Expand Down Expand Up @@ -612,8 +614,9 @@ const DefinitionSymbol* Compilation::getDefinition(const ModuleDeclarationSyntax
// it probably got booted by an (illegal) duplicate definition.
// We don't want to return anything in that case.
auto def = it->second;
auto targetScope = def->scope.asSymbol().kind == SymbolKind::CompilationUnit ? root.get()
: &def->scope;
auto& defScope = *def->getParentScope();
auto targetScope = defScope.asSymbol().kind == SymbolKind::CompilationUnit ? root.get()
: &defScope;

auto dmIt = definitionMap.find(std::make_tuple(def->name, targetScope));
if (dmIt != definitionMap.end() &&
Expand Down Expand Up @@ -1372,15 +1375,15 @@ const Diagnostics& Compilation::getSemanticDiagnostics() {
continue;

auto hasUnusedAttrib = [&] {
for (auto attr : def->attributes) {
for (auto attr : getAttributes(*def)) {
if (attr->name == "unused"sv || attr->name == "maybe_unused"sv)
return attr->getValue().isTrue();
}
return false;
};

if (!def->name.empty() && def->name != "_"sv && !hasUnusedAttrib())
def->scope.addDiag(diag::UnusedDefinition, def->location)
def->getParentScope()->addDiag(diag::UnusedDefinition, def->location)
<< def->getKindString();
}

Expand Down Expand Up @@ -1895,8 +1898,10 @@ void Compilation::checkElemTimeScale(std::optional<TimeScale> timeScale, SourceR
return;

anyElemsWithTimescales = true;
for (auto& def : definitionMemory)
checkElemTimeScale(def->timeScale, def->syntax.header->name.range());
for (auto& def : definitionMemory) {
auto& syntax = def->getSyntax()->as<ModuleDeclarationSyntax>();
checkElemTimeScale(def->timeScale, syntax.header->name.range());
}

for (auto [name, package] : packageMap) {
if (auto syntax = package->getSyntax()) {
Expand Down Expand Up @@ -2141,8 +2146,10 @@ void Compilation::resolveDefParamsAndBinds() {
for (auto target : instTargets)
binds.emplace_back(BindEntry{InstancePath(*target), syntax});

if (defTarget)
binds.emplace_back(BindEntry{{}, syntax, &defTarget->syntax});
if (defTarget) {
auto& modSyntax = defTarget->getSyntax()->as<ModuleDeclarationSyntax>();
binds.emplace_back(BindEntry{{}, syntax, &modSyntax});
}
}
};

Expand Down
26 changes: 10 additions & 16 deletions source/ast/symbols/CompilationUnitSymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "ParameterBuilder.h"

#include "slang/ast/Compilation.h"
#include "slang/ast/symbols/AttributeSymbol.h"
#include "slang/ast/symbols/MemberSymbols.h"
#include "slang/diagnostics/DeclarationsDiags.h"
#include "slang/syntax/AllSyntax.h"
Expand Down Expand Up @@ -237,18 +236,18 @@ DefinitionSymbol::DefinitionSymbol(const Scope& scope, LookupLocation lookupLoca
std::optional<TimeScale> directiveTimeScale,
const SyntaxTree* syntaxTree,
const SourceLibrary* sourceLibrary) :
syntax(syntax),
defaultNetType(defaultNetType), scope(scope), unconnectedDrive(unconnectedDrive),
syntaxTree(syntaxTree), sourceLibrary(sourceLibrary) {
Symbol(SymbolKind::Definition, syntax.header->name.valueText(), syntax.header->name.location()),
defaultNetType(defaultNetType), unconnectedDrive(unconnectedDrive), syntaxTree(syntaxTree),
sourceLibrary(sourceLibrary) {

// Extract and save various properties of the definition.
name = syntax.header->name.valueText();
location = syntax.header->name.location();
indexInScope = lookupLocation.getIndex();
setParent(scope, lookupLocation.getIndex());
setSyntax(syntax);
setAttributes(scope, syntax.attributes);

definitionKind = SemanticFacts::getDefinitionKind(syntax.kind);
defaultLifetime = SemanticFacts::getVariableLifetime(syntax.header->lifetime)
.value_or(VariableLifetime::Static);
attributes = AttributeSymbol::fromSyntax(syntax.attributes, scope, lookupLocation);

auto header = syntax.header.get();
if (header->ports && header->ports->kind == SyntaxKind::WildcardPortList) {
Expand Down Expand Up @@ -328,14 +327,8 @@ std::string_view DefinitionSymbol::getArticleKindString() const {
}
}

void DefinitionSymbol::getHierarchicalPath(std::string& buffer) const {
auto& parentSym = scope.asSymbol();
if (parentSym.kind != SymbolKind::Root && parentSym.kind != SymbolKind::CompilationUnit) {
parentSym.getHierarchicalPath(buffer);
buffer.append(".");
}

buffer.append(name);
void DefinitionSymbol::serializeTo(ASTSerializer&) const {
// TODO:
}

ConfigBlockSymbol& ConfigBlockSymbol::fromSyntax(const Scope& scope,
Expand Down Expand Up @@ -423,6 +416,7 @@ ConfigBlockSymbol& ConfigBlockSymbol::fromSyntax(const Scope& scope,
}

void ConfigBlockSymbol::serializeTo(ASTSerializer&) const {
// TODO:
}

} // namespace slang::ast
8 changes: 5 additions & 3 deletions source/ast/symbols/InstanceSymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,14 +714,16 @@ InstanceBodySymbol::InstanceBodySymbol(Compilation& compilation, const Definitio
Symbol(SymbolKind::InstanceBody, definition.name, definition.location),
Scope(compilation, this), hierarchyOverrideNode(hierarchyOverrideNode),
isUninstantiated(isUninstantiated), isFromBind(isFromBind), definition(definition) {
setParent(definition.scope, definition.indexInScope);

setParent(*definition.getParentScope(), definition.getIndex());
}

InstanceBodySymbol& InstanceBodySymbol::fromDefinition(
Compilation& compilation, const DefinitionSymbol& definition, SourceLocation instanceLoc,
bool isUninstantiated, const HierarchyOverrideNode* hierarchyOverrideNode) {

ParameterBuilder paramBuilder(definition.scope, definition.name, definition.parameters);
ParameterBuilder paramBuilder(*definition.getParentScope(), definition.name,
definition.parameters);
paramBuilder.setForceInvalidValues(isUninstantiated);
if (hierarchyOverrideNode)
paramBuilder.setOverrides(hierarchyOverrideNode);
Expand All @@ -739,7 +741,7 @@ InstanceBodySymbol& InstanceBodySymbol::fromDefinition(Compilation& comp,
auto result = comp.emplace<InstanceBodySymbol>(comp, definition, overrideNode, isUninstantiated,
isFromBind);

auto& declSyntax = definition.syntax;
auto& declSyntax = definition.getSyntax()->as<ModuleDeclarationSyntax>();
result->setSyntax(declSyntax);

// Package imports from the header always come first.
Expand Down

0 comments on commit 6fedcb1

Please sign in to comment.