From a7e258fad191319173ca32b1db4cea476e143f0e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 16 Aug 2026 14:46:36 -0700 Subject: [PATCH] symbol_search(): Add lookup flags `symbol_search()` currently uses a boolean argument to allow forward references to the terminal name. Additional lookup options would require more boolean arguments and make call sites difficult to read. Replace the boolean with a bitmask and use a named flag at the existing forward-reference call sites. Add a second flag that stops lookup at an unelaborated signal instead of elaborating it. Stopping the lookup makes the signal continue to hide matching symbols in outer scopes. Forward-reference permission applies only to the terminal name, while signal elaboration suppression applies to the complete path. This allows callers that only need to classify a name to avoid triggering signal elaboration during lookup. Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 9 ++++++--- elaborate.cc | 3 ++- netmisc.h | 12 +++++++++--- symbol_search.cc | 37 ++++++++++++++++++++++++++----------- 4 files changed, 43 insertions(+), 18 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 50e8937a6..ec3307ffa 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -310,7 +310,8 @@ static const netclass_t* resolve_call_chain_prefix_class(Design*des, NetScope*sc if (link->peek_chain_prefix() == 0) { symbol_search_results sr; if (!symbol_search(link, des, scope, link->peek_path(), - link->lexical_pos(), &sr, true)) { + link->lexical_pos(), &sr, + SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE)) { return 0; } if (!sr.is_scope() || sr.scope->type() != NetScope::FUNC) { @@ -2102,7 +2103,8 @@ unsigned PECallFunction::test_width(Design*des, NetScope*scope, // Search for the symbol. This should turn up a scope. symbol_search_results search_results; bool search_flag = symbol_search(this, des, scope, path_, lexical_pos(), - &search_results, true); + &search_results, + SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE); if (debug_elaborate) { cerr << get_fileline() << ": PECallFunction::test_width: " @@ -3242,7 +3244,8 @@ NetExpr* PECallFunction::elaborate_expr_(Design*des, NetScope*scope, // Search for the symbol. This should turn up a scope. symbol_search_results search_results; bool search_flag = symbol_search(this, des, scope, path_, lexical_pos(), - &search_results, true); + &search_results, + SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE); if (debug_elaborate) { cerr << get_fileline() << ": PECallFunction::elaborate_expr: " diff --git a/elaborate.cc b/elaborate.cc index 95dc0ce34..e9c0b06d1 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3957,7 +3957,8 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const NetScope *task = nullptr; NetScope *func_scope = nullptr; if (symbol_search(this, des, scope, call_path, lexical_pos(), - &search_results, true)) { + &search_results, + SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE)) { if (!search_results.require_non_type( this, des, "in a task or function call")) return nullptr; diff --git a/netmisc.h b/netmisc.h index 0f958f885..5bc4b4b82 100644 --- a/netmisc.h +++ b/netmisc.h @@ -129,6 +129,11 @@ struct symbol_search_results { pform_name_t path_head; }; +enum symbol_search_flag_t { + SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE = 1U << 0, + SYMBOL_SEARCH_NO_SIGNAL_ELABORATION = 1U << 1 +}; + /* * Test the search results and return true if this represents a function * return value. That will be the case if the object is a net, the scope @@ -145,15 +150,16 @@ static inline bool test_function_return_value(const symbol_search_results&search extern bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, pform_name_t path, unsigned int lexical_pos, - struct symbol_search_results *res); + struct symbol_search_results *res, + unsigned int flags = 0); /* The forward-reference flag applies only to the terminal name. Prefix - components still use lexical_pos. */ + components still use lexical_pos. Other flags apply to the complete path. */ extern bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, const pform_scoped_name_t &path, unsigned int lexical_pos, struct symbol_search_results *res, - bool allow_terminal_forward_reference = false); + unsigned int flags = 0); extern bool check_interface_modport_access(const LineInfo *li, Design *des, const symbol_search_results &res, diff --git a/symbol_search.cc b/symbol_search.cc index 7e829c382..ef73c1c78 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -55,7 +55,7 @@ static scope_object_search_result_t symbol_search_scope_objects( const LineInfo *li, Design *des, NetScope *scope, NetScope *start_scope, const pform_name_t &path, const name_component_t &path_tail, unsigned int visibility_pos, - struct symbol_search_results *res) + struct symbol_search_results *res, unsigned int flags) { // Special case `super` keyword. Return the `this` object, but // with the type of the base class. @@ -206,6 +206,12 @@ static scope_object_search_result_t symbol_search_scope_objects( // been elaborated yet. if (PWire *wire = scope->find_signal_placeholder(path_tail.name)) { if (wire->lexical_pos() <= visibility_pos) { + if (flags & SYMBOL_SEARCH_NO_SIGNAL_ELABORATION) { + // The signal still hides matching symbols in outer + // scopes. Stop the lookup without elaborating it. + return scope_object_search_result_t::failed; + } + NetNet *net = wire->elaborate_sig(des, scope); if (!net) return scope_object_search_result_t::failed; @@ -322,7 +328,8 @@ static bool symbol_search_(const LineInfo *li, Design *des, NetScope *scope, pform_name_t path, unsigned int lexical_pos, unsigned int prefix_lexical_pos, struct symbol_search_results *res, - NetScope *start_scope, bool scope_is_bound) + NetScope *start_scope, bool scope_is_bound, + unsigned int flags) { assert(scope); @@ -349,10 +356,12 @@ static bool symbol_search_(const LineInfo *li, Design *des, NetScope *scope, // recursively. Ideally, the result is a scope that we search // for the tail key, but there are other special cases as well. if (! path.empty()) { + const unsigned int prefix_flags = + flags & ~SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE; bool flag = symbol_search_(li, des, scope, path, prefix_lexical_pos, prefix_lexical_pos, res, - start_scope, scope_is_bound); + start_scope, scope_is_bound, prefix_flags); if (! flag) return false; @@ -460,7 +469,7 @@ static bool symbol_search_(const LineInfo *li, Design *des, NetScope *scope, scope_object_search_result_t object_result = symbol_search_scope_objects( li, des, scope, start_scope, path, path_tail, - visibility_pos, res); + visibility_pos, res, flags); if (object_result == scope_object_search_result_t::found) return true; if (object_result == scope_object_search_result_t::failed) @@ -577,16 +586,20 @@ static bool symbol_search_(const LineInfo *li, Design *des, NetScope *scope, bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, pform_name_t path, unsigned int lexical_pos, - struct symbol_search_results *res) + struct symbol_search_results *res, unsigned int flags) { - return symbol_search_(li, des, scope, path, lexical_pos, lexical_pos, - res, scope, false); + const bool allow_forward_reference = + flags & SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE; + const unsigned int terminal_lexical_pos = allow_forward_reference + ? UINT_MAX : lexical_pos; + return symbol_search_(li, des, scope, path, terminal_lexical_pos, + lexical_pos, + res, scope, false, flags); } bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, const pform_scoped_name_t &path, unsigned int lexical_pos, - struct symbol_search_results *res, - bool allow_terminal_forward_reference) + struct symbol_search_results *res, unsigned int flags) { NetScope *search_scope = scope; bool scope_is_bound = false; @@ -598,11 +611,13 @@ bool symbol_search(const LineInfo *li, Design *des, NetScope *scope, scope_is_bound = true; } - const unsigned int terminal_lexical_pos = allow_terminal_forward_reference + const bool allow_forward_reference = + flags & SYMBOL_SEARCH_ALLOW_FORWARD_REFERENCE; + const unsigned int terminal_lexical_pos = allow_forward_reference ? UINT_MAX : lexical_pos; return symbol_search_(li, des, search_scope, path.name, terminal_lexical_pos, lexical_pos, res, - search_scope, scope_is_bound); + search_scope, scope_is_bound, flags); } bool check_interface_modport_access(const LineInfo *li, Design *des,