9#include "slang/ast/ASTVisitor.h"
10#include "slang/ast/Expression.h"
11#include "slang/ast/statements/MiscStatements.h"
12#include "slang/ast/symbols/CompilationUnitSymbols.h"
13#include "slang/ast/symbols/InstanceSymbols.h"
14#include "slang/ast/symbols/MemberSymbols.h"
15#include "slang/ast/symbols/VariableSymbols.h"
16#include "slang/syntax/AllSyntax.h"
17#include "slang/text/SourceManager.h"
19#include "mlir/IR/Location.h"
20#include "mlir/Support/FileUtilities.h"
22#include "llvm/ADT/StringExtras.h"
24#include "../Utils/LSPUtils.h"
35inline bool definitelyOutsideMainBuffer(
const T &t, slang::BufferID bufferId) {
36 if constexpr (
requires {
41 return r.buffer() != bufferId;
44 if constexpr (
requires {
47 auto r = t.sourceRange;
48 if (r.start().valid() && r.end().valid())
49 return r.start().buffer() != bufferId && r.end().buffer() != bufferId;
52 if constexpr (
requires { t.getSyntax(); }) {
53 if (
auto *syn = t.getSyntax()) {
54 auto r = syn->sourceRange();
55 if (r.start().valid() && r.end().valid())
56 return r.start().buffer() != bufferId && r.end().buffer() != bufferId;
64 : slang::ast::ASTVisitor<VerilogIndexer, slang::ast::VisitFlags::AllGood> {
66 slang::ast::ASTVisitor<VerilogIndexer, slang::ast::VisitFlags::AllGood>;
71 void recurseIfInMainBuffer(
const T &node) {
72 if (definitelyOutsideMainBuffer(node, index.
getBufferId()))
77 void insertSymbol(
const slang::ast::Symbol *symbol, slang::SourceRange range,
78 bool isDefinition =
true) {
79 if (symbol->name.empty())
81 assert(range.start().valid() && range.end().valid() &&
82 "range must be valid");
86 if (range.start().offset() >= range.end().offset()) {
93 void insertSymbol(
const slang::ast::Symbol *symbol,
94 slang::SourceLocation from,
bool isDefinition =
false) {
95 if (symbol->name.empty())
97 assert(from.valid() &&
"location must be valid");
98 insertSymbol(symbol, slang::SourceRange(from, from + symbol->name.size()),
103 void visitExpression(
const slang::ast::Expression &expr) {
104 auto *symbol = expr.getSymbolReference(
true);
107 insertSymbol(symbol, expr.sourceRange,
false);
110 void visitSymbol(
const slang::ast::Symbol &symbol) {
111 insertSymbol(&symbol, symbol.location,
true);
114 void visit(
const slang::ast::NetSymbol &expr) {
115 insertSymbol(&expr, expr.location,
true);
116 recurseIfInMainBuffer(expr);
119 void visit(
const slang::ast::VariableSymbol &expr) {
120 insertSymbol(&expr, expr.location,
true);
121 recurseIfInMainBuffer(expr);
124 void visit(
const slang::ast::ExplicitImportSymbol &expr) {
125 auto *def = expr.package();
129 if (
auto *syn = expr.getSyntax()) {
130 if (
auto *item = syn->as_if<slang::syntax::PackageImportItemSyntax>()) {
131 insertSymbol(def, item->package.location(),
false);
134 recurseIfInMainBuffer(expr);
137 void visit(
const slang::ast::WildcardImportSymbol &expr) {
138 auto *def = expr.getPackage();
142 if (
auto *syn = expr.getSyntax()) {
143 if (
auto *item = syn->as_if<slang::syntax::PackageImportItemSyntax>()) {
144 insertSymbol(def, item->package.location(),
false);
147 recurseIfInMainBuffer(expr);
150 void visit(
const slang::ast::InstanceBodySymbol &expr) {
153 index.insertSymbolDefinition(symbol);
154 recurseIfInMainBuffer(expr);
157 void visit(
const slang::ast::InstanceSymbol &expr) {
158 auto *def = &expr.getDefinition();
163 insertSymbol(def, def->location,
true);
169 ->as_if<slang::syntax::HierarchicalInstanceSyntax>())
172 ->as_if<slang::syntax::HierarchyInstantiationSyntax>())
174 insertSymbol(def, modInst->type.location(),
false);
177 insertSymbol(def, expr.location,
false);
178 recurseIfInMainBuffer(expr);
181 void visit(
const slang::ast::VariableDeclStatement &expr) {
182 insertSymbol(&expr.symbol, expr.sourceRange,
true);
183 recurseIfInMainBuffer(expr);
186 template <
typename T>
187 void visit(
const T &node) {
188 if constexpr (std::is_base_of_v<slang::ast::Expression, T>)
189 visitExpression(node);
190 if constexpr (std::is_base_of_v<slang::ast::Symbol, T>)
193 recurseIfInMainBuffer(node);
196 template <
typename T>
197 void visitInvalid(
const T &t) {}
202 const auto &root = compilation.getRoot();
203 VerilogIndexer visitor(*
this);
206 for (
auto *package : compilation.getPackages()) {
210 package->visit(visitor);
214 for (
auto *inst : root.topInstances) {
218 inst->body.visit(visitor);
227 if (toParse.contains(
'\n'))
231 SmallVector<StringRef, 3> fileLineColStrs;
235 for (
auto chunk :
llvm::split(toParse,
", ")) {
236 fileLineColStrs.clear();
237 chunk.split(fileLineColStrs,
':');
238 if (fileLineColStrs.size() != 3)
241 auto filePathMaybeEmpty = fileLineColStrs[0].trim();
243 if (!filePathMaybeEmpty.empty())
244 filePath = filePathMaybeEmpty;
246 auto line = fileLineColStrs[1].trim();
247 auto column = fileLineColStrs[2].trim();
251 if (line.getAsInteger(10, lineInt))
256 SmallVector<std::pair<StringRef, const char *>> columns;
259 if (column.starts_with(
'{') && column.ends_with(
'}')) {
261 for (
auto str :
llvm::split(column.drop_back().drop_front(),
',')) {
262 columns.emplace_back(str,
263 first ? filePathMaybeEmpty.data() : str.data());
267 columns.push_back({column, filePathMaybeEmpty.data()});
271 for (
auto [column, start] : columns) {
273 if (column.getAsInteger(10, columnInt))
275 auto loc = mlir::FileLineColRange::get(&
mlirContext, filePath,
276 lineInt - 1, columnInt - 1,
277 lineInt - 1, columnInt - 1);
278 const char *
end = column.end();
287 auto getMainBuffer = sourceMgr.getSourceText(
getBufferId());
288 StringRef text(getMainBuffer);
295 StringRef start =
"// @[";
296 auto loc = text.find(start);
297 if (loc == StringRef::npos)
300 text = text.drop_front(loc + start.size());
301 auto endPos = text.find_first_of(
"]\n");
302 if (endPos == StringRef::npos)
304 auto toParse = text.take_front(endPos);
311 slang::SourceRange from,
bool isDefinition) {
312 assert(from.start().valid() && from.end().valid());
315 if (from.start().offset() >= from.end().offset())
318 auto lhsBufferId = from.start().buffer();
319 auto rhsBufferId = from.end().buffer();
320 if (lhsBufferId.getId() != rhsBufferId.getId() || !rhsBufferId.valid() ||
321 !lhsBufferId.valid())
326 const auto *lhsBound = buffer.data() + from.start().offset();
327 const auto *rhsBound = buffer.data() + from.end().offset();
329 if (lhsBound >= rhsBound)
340 if (!symbol->location)
342 auto size = symbol->name.size() ? symbol->name.size() : 1;
343 auto range = slang::SourceRange(symbol->location, symbol->location + size);
assert(baseType &&"element must be base type")
static SmallVector< PortInfo > getPortList(ModuleTy &mod)
ReferenceMap references
References of symbols.
void parseSourceLocation()
Parse source location emitted by ExportVerilog.
void insertSymbolDefinition(const slang::ast::Symbol *symbol)
mlir::MLIRContext mlirContext
void insertSymbol(const slang::ast::Symbol *symbol, slang::SourceRange from, bool isDefinition=false)
Register a reference to a symbol symbol from from.
const slang::BufferID & getBufferId() const
MapT intervalMap
An interval map containing a corresponding definition mapped to a source interval.
void initialize(slang::ast::Compilation &compilation)
Initialize the index with the given compilation unit.
const slang::SourceManager & getSlangSourceManager() const