2012-04-13 01:08:20 +00:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 11:35:28 +00:00
|
|
|
//*************************************************************************
|
|
|
|
// DESCRIPTION: Verilator: Symbol table
|
|
|
|
//
|
2019-11-08 03:33:59 +00:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
|
|
|
//
|
2020-03-21 15:24:24 +00:00
|
|
|
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 21:07:57 +00:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
// Version 2.0.
|
2020-03-21 15:24:24 +00:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
2019-10-05 00:17:11 +00:00
|
|
|
|
2020-06-02 03:16:02 +00:00
|
|
|
#ifndef _V3SYMTABLE_H_
|
|
|
|
#define _V3SYMTABLE_H_ 1
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2006-12-18 19:20:45 +00:00
|
|
|
#include "config_build.h"
|
|
|
|
#include "verilatedos.h"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
#include "V3Global.h"
|
2011-11-30 03:09:50 +00:00
|
|
|
#include "V3Ast.h"
|
2012-06-20 10:13:28 +00:00
|
|
|
#include "V3File.h"
|
2019-07-14 00:30:32 +00:00
|
|
|
#include "V3String.h"
|
2012-06-20 10:13:28 +00:00
|
|
|
|
2018-10-14 17:43:24 +00:00
|
|
|
#include <cstdarg>
|
|
|
|
#include <map>
|
|
|
|
#include <iomanip>
|
|
|
|
#include <memory>
|
|
|
|
|
2012-06-20 10:13:28 +00:00
|
|
|
class VSymGraph;
|
2012-07-18 01:29:10 +00:00
|
|
|
class VSymEnt;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
// Symbol table
|
|
|
|
|
2020-11-26 01:57:30 +00:00
|
|
|
typedef std::unordered_set<const VSymEnt*> VSymConstMap;
|
2012-07-18 01:29:10 +00:00
|
|
|
|
2020-11-19 02:32:16 +00:00
|
|
|
class VSymEnt final {
|
2006-08-26 11:35:28 +00:00
|
|
|
// Symbol table that can have a "superior" table for resolving upper references
|
|
|
|
// MEMBERS
|
2020-04-14 02:51:35 +00:00
|
|
|
typedef std::multimap<string, VSymEnt*> IdNameMap;
|
|
|
|
IdNameMap m_idNameMap; // Hash of variables by name
|
|
|
|
AstNode* m_nodep; // Node that entry belongs to
|
|
|
|
VSymEnt* m_fallbackp; // Table "above" this one in name scope, for fallback resolution
|
|
|
|
VSymEnt* m_parentp; // Table that created this table, dot notation needed to resolve into it
|
2020-11-25 02:56:03 +00:00
|
|
|
AstNodeModule* m_classOrPackagep; // Package node is in (for V3LinkDot, unused here)
|
2020-04-14 02:51:35 +00:00
|
|
|
string m_symPrefix; // String to prefix symbols with (for V3LinkDot, unused here)
|
|
|
|
bool m_exported; // Allow importing
|
|
|
|
bool m_imported; // Was imported
|
2012-08-16 01:28:30 +00:00
|
|
|
#ifdef VL_DEBUG
|
2012-07-21 13:27:57 +00:00
|
|
|
static int debug() {
|
2019-05-19 20:13:13 +00:00
|
|
|
static int level = -1;
|
|
|
|
if (VL_UNLIKELY(level < 0)) level = v3Global.opt.debugSrcLevel("V3LinkDot.cpp");
|
|
|
|
return level;
|
2012-07-21 13:27:57 +00:00
|
|
|
}
|
|
|
|
#else
|
2012-11-03 12:01:19 +00:00
|
|
|
static inline int debug() { return 0; } // NOT runtime, too hot of a function
|
2012-07-21 13:27:57 +00:00
|
|
|
#endif
|
2012-07-18 01:29:10 +00:00
|
|
|
public:
|
2020-04-05 13:30:23 +00:00
|
|
|
typedef IdNameMap::const_iterator const_iterator;
|
|
|
|
const_iterator begin() const { return m_idNameMap.begin(); }
|
|
|
|
const_iterator end() const { return m_idNameMap.end(); }
|
|
|
|
|
2018-03-10 21:51:34 +00:00
|
|
|
void dumpIterate(std::ostream& os, VSymConstMap& doneSymsr, const string& indent,
|
2018-03-10 21:32:04 +00:00
|
|
|
int numLevels, const string& searchName) const {
|
2020-04-14 02:51:35 +00:00
|
|
|
os << indent << "+ " << std::left << std::setw(30)
|
|
|
|
<< (searchName == "" ? "\"\"" : searchName) << std::setw(0) << std::right;
|
|
|
|
os << " se" << cvtToHex(this) << std::setw(0);
|
|
|
|
os << " fallb=se" << cvtToHex(m_fallbackp);
|
|
|
|
if (m_symPrefix != "") os << " symPrefix=" << m_symPrefix;
|
|
|
|
os << " n=" << nodep();
|
2020-11-19 02:03:23 +00:00
|
|
|
os << '\n';
|
2020-05-29 23:35:54 +00:00
|
|
|
if (VL_UNCOVERABLE(doneSymsr.find(this) != doneSymsr.end())) {
|
|
|
|
os << indent << "| ^ duplicate, so no children printed\n"; // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
} else {
|
|
|
|
doneSymsr.insert(this);
|
2020-04-14 02:51:35 +00:00
|
|
|
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end();
|
|
|
|
++it) {
|
2019-05-19 20:13:13 +00:00
|
|
|
if (numLevels >= 1) {
|
2020-04-14 02:51:35 +00:00
|
|
|
it->second->dumpIterate(os, doneSymsr, indent + "| ", numLevels - 1,
|
|
|
|
it->first);
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
}
|
2020-04-14 02:51:35 +00:00
|
|
|
void dump(std::ostream& os, const string& indent = "", int numLevels = 1) const {
|
2019-05-19 20:13:13 +00:00
|
|
|
VSymConstMap doneSyms;
|
|
|
|
dumpIterate(os, doneSyms, indent, numLevels, "TOP");
|
2012-07-18 01:29:10 +00:00
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
// METHODS
|
2012-12-18 01:26:40 +00:00
|
|
|
VSymEnt(VSymGraph* graphp, const VSymEnt* symp); // Below
|
2012-06-20 10:13:28 +00:00
|
|
|
VSymEnt(VSymGraph* graphp, AstNode* nodep); // Below
|
2012-08-16 01:28:30 +00:00
|
|
|
~VSymEnt() {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Change links so we coredump if used
|
2012-08-16 01:28:30 +00:00
|
|
|
#ifdef VL_DEBUG
|
2020-04-05 22:30:46 +00:00
|
|
|
m_nodep = reinterpret_cast<AstNode*>(1);
|
|
|
|
m_fallbackp = reinterpret_cast<VSymEnt*>(1);
|
|
|
|
m_parentp = reinterpret_cast<VSymEnt*>(1);
|
2020-11-25 02:56:03 +00:00
|
|
|
m_classOrPackagep = reinterpret_cast<AstNodeModule*>(1);
|
2012-08-16 01:28:30 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#if defined(VL_DEBUG) && !defined(VL_LEAK_CHECKS)
|
2019-05-19 20:13:13 +00:00
|
|
|
// For testing, leak so above destructor 1 assignments work
|
|
|
|
void operator delete(void* objp, size_t size) {}
|
2012-08-16 01:28:30 +00:00
|
|
|
#endif
|
2012-06-20 10:13:28 +00:00
|
|
|
void fallbackp(VSymEnt* entp) { m_fallbackp = entp; }
|
2020-10-08 11:54:01 +00:00
|
|
|
VSymEnt* fallbackp() const { return m_fallbackp; }
|
2012-06-20 10:13:28 +00:00
|
|
|
void parentp(VSymEnt* entp) { m_parentp = entp; }
|
|
|
|
VSymEnt* parentp() const { return m_parentp; }
|
2020-11-25 02:56:03 +00:00
|
|
|
void classOrPackagep(AstNodeModule* entp) { m_classOrPackagep = entp; }
|
|
|
|
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
2016-02-03 02:02:00 +00:00
|
|
|
AstNode* nodep() const { return m_nodep; }
|
2012-06-20 10:13:28 +00:00
|
|
|
string symPrefix() const { return m_symPrefix; }
|
|
|
|
void symPrefix(const string& name) { m_symPrefix = name; }
|
2012-12-18 01:26:40 +00:00
|
|
|
bool exported() const { return m_exported; }
|
|
|
|
void exported(bool flag) { m_exported = flag; }
|
|
|
|
bool imported() const { return m_imported; }
|
|
|
|
void imported(bool flag) { m_imported = flag; }
|
2012-06-20 10:13:28 +00:00
|
|
|
void insert(const string& name, VSymEnt* entp) {
|
2020-04-14 02:51:35 +00:00
|
|
|
UINFO(9, " SymInsert se" << cvtToHex(this) << " '" << name << "' se" << cvtToHex(entp)
|
|
|
|
<< " " << entp->nodep() << endl);
|
2019-05-19 20:13:13 +00:00
|
|
|
if (name != "" && m_idNameMap.find(name) != m_idNameMap.end()) {
|
|
|
|
if (!V3Error::errorCount()) { // Else may have just reported warning
|
2020-04-14 02:51:35 +00:00
|
|
|
if (debug() >= 9 || V3Error::debugDefault()) dump(cout, "- err-dump: ", 1);
|
2020-11-19 02:03:23 +00:00
|
|
|
entp->nodep()->v3fatalSrc("Inserting two symbols with same name: " << name);
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
m_idNameMap.insert(make_pair(name, entp));
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
void reinsert(const string& name, VSymEnt* entp) {
|
2020-08-16 15:43:49 +00:00
|
|
|
const auto it = m_idNameMap.find(name);
|
2020-04-14 02:51:35 +00:00
|
|
|
if (name != "" && it != m_idNameMap.end()) {
|
|
|
|
UINFO(9, " SymReinsert se" << cvtToHex(this) << " '" << name << "' se"
|
|
|
|
<< cvtToHex(entp) << " " << entp->nodep() << endl);
|
2019-05-19 20:13:13 +00:00
|
|
|
it->second = entp; // Replace
|
|
|
|
} else {
|
|
|
|
insert(name, entp);
|
|
|
|
}
|
2009-10-31 14:14:04 +00:00
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
VSymEnt* findIdFlat(const string& name) const {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Find identifier without looking upward through symbol hierarchy
|
|
|
|
// First, scan this begin/end block or module for the name
|
2020-08-16 15:43:49 +00:00
|
|
|
const auto it = m_idNameMap.find(name);
|
2020-04-14 02:51:35 +00:00
|
|
|
UINFO(9, " SymFind se"
|
|
|
|
<< cvtToHex(this) << " '" << name << "' -> "
|
|
|
|
<< (it == m_idNameMap.end()
|
|
|
|
? "NONE"
|
|
|
|
: "se" + cvtToHex(it->second) + " n=" + cvtToHex(it->second->nodep()))
|
|
|
|
<< endl);
|
2019-05-19 20:13:13 +00:00
|
|
|
if (it != m_idNameMap.end()) return (it->second);
|
2020-08-15 14:12:55 +00:00
|
|
|
return nullptr;
|
2009-03-23 18:57:15 +00:00
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
VSymEnt* findIdFallback(const string& name) const {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Find identifier looking upward through symbol hierarchy
|
|
|
|
// First, scan this begin/end block or module for the name
|
|
|
|
if (VSymEnt* entp = findIdFlat(name)) return entp;
|
|
|
|
// Then scan the upper begin/end block or module for the name
|
|
|
|
if (m_fallbackp) return m_fallbackp->findIdFallback(name);
|
2020-08-15 14:12:55 +00:00
|
|
|
return nullptr;
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2019-07-14 00:30:32 +00:00
|
|
|
void candidateIdFlat(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const {
|
|
|
|
// Suggest alternative symbol candidates without looking upward through symbol hierarchy
|
2020-04-14 02:51:35 +00:00
|
|
|
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
2020-02-04 04:21:56 +00:00
|
|
|
const AstNode* itemp = it->second->nodep();
|
|
|
|
if (itemp && (!matcherp || matcherp->nodeMatch(itemp))) {
|
|
|
|
spellerp->pushCandidate(itemp->prettyName());
|
2019-07-14 00:30:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void candidateIdFallback(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const {
|
|
|
|
// Suggest alternative symbol candidates with looking upward through symbol hierarchy
|
|
|
|
// Note VSpellCheck wants the most important (closest) items pushed first
|
|
|
|
candidateIdFlat(spellerp, matcherp);
|
|
|
|
// Then suggest the upper begin/end block or module
|
|
|
|
if (m_fallbackp) m_fallbackp->candidateIdFallback(spellerp, matcherp);
|
|
|
|
}
|
2020-04-14 02:51:35 +00:00
|
|
|
|
2013-01-09 00:06:52 +00:00
|
|
|
private:
|
2020-06-10 00:59:45 +00:00
|
|
|
void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp,
|
|
|
|
bool honorExport) {
|
|
|
|
if ((!honorExport || srcp->exported())
|
|
|
|
&& !findIdFlat(name)) { // Don't insert over existing entry
|
2019-05-19 20:13:13 +00:00
|
|
|
VSymEnt* symp = new VSymEnt(graphp, srcp);
|
|
|
|
symp->exported(false); // Can't reimport an import without an export
|
|
|
|
symp->imported(true);
|
|
|
|
reinsert(name, symp);
|
|
|
|
}
|
2017-09-21 01:04:59 +00:00
|
|
|
}
|
2020-06-02 03:16:02 +00:00
|
|
|
void exportOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) const {
|
2019-05-19 20:13:13 +00:00
|
|
|
if (srcp->exported()) {
|
|
|
|
if (VSymEnt* symp = findIdFlat(name)) { // Should already exist in current table
|
|
|
|
if (!symp->exported()) symp->exported(true);
|
|
|
|
}
|
|
|
|
}
|
2013-01-09 00:06:52 +00:00
|
|
|
}
|
2020-04-14 02:51:35 +00:00
|
|
|
|
2013-01-09 00:06:52 +00:00
|
|
|
public:
|
2020-06-10 00:59:45 +00:00
|
|
|
void importFromClass(VSymGraph* graphp, const VSymEnt* srcp) {
|
|
|
|
// Import tokens from source symbol table into this symbol table
|
|
|
|
// Used for classes in early parsing only to handle "extends"
|
|
|
|
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
|
|
|
it != srcp->m_idNameMap.end(); ++it) {
|
|
|
|
importOneSymbol(graphp, it->first, it->second, false);
|
|
|
|
}
|
|
|
|
}
|
2017-09-21 01:04:59 +00:00
|
|
|
void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Import tokens from source symbol table into this symbol table
|
|
|
|
if (id_or_star != "*") {
|
2020-08-16 15:43:49 +00:00
|
|
|
const auto it = srcp->m_idNameMap.find(id_or_star);
|
2020-06-10 00:59:45 +00:00
|
|
|
if (it != srcp->m_idNameMap.end()) {
|
|
|
|
importOneSymbol(graphp, it->first, it->second, true);
|
|
|
|
}
|
2019-05-19 20:13:13 +00:00
|
|
|
} else {
|
|
|
|
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
|
|
|
it != srcp->m_idNameMap.end(); ++it) {
|
2020-06-10 00:59:45 +00:00
|
|
|
importOneSymbol(graphp, it->first, it->second, true);
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
|
|
|
}
|
2017-09-21 01:04:59 +00:00
|
|
|
}
|
|
|
|
void exportFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Export tokens from source symbol table into this symbol table
|
|
|
|
if (id_or_star != "*") {
|
2020-08-16 15:43:49 +00:00
|
|
|
const auto it = vlstd::as_const(srcp->m_idNameMap).find(id_or_star);
|
2020-04-14 02:51:35 +00:00
|
|
|
if (it != srcp->m_idNameMap.end()) exportOneSymbol(graphp, it->first, it->second);
|
2019-05-19 20:13:13 +00:00
|
|
|
} else {
|
|
|
|
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
|
|
|
it != srcp->m_idNameMap.end(); ++it) {
|
|
|
|
exportOneSymbol(graphp, it->first, it->second);
|
|
|
|
}
|
|
|
|
}
|
2017-09-21 01:04:59 +00:00
|
|
|
}
|
|
|
|
void exportStarStar(VSymGraph* graphp) {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Export *:*: Export all tokens from imported packages
|
2020-04-14 02:51:35 +00:00
|
|
|
for (IdNameMap::const_iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
2019-05-19 20:13:13 +00:00
|
|
|
VSymEnt* symp = it->second;
|
|
|
|
if (!symp->exported()) symp->exported(true);
|
|
|
|
}
|
2009-11-10 00:07:59 +00:00
|
|
|
}
|
2017-05-10 23:05:42 +00:00
|
|
|
void importFromIface(VSymGraph* graphp, const VSymEnt* srcp, bool onlyUnmodportable = false) {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Import interface tokens from source symbol table into this symbol table, recursively
|
2020-04-14 02:51:35 +00:00
|
|
|
UINFO(9, " importIf se" << cvtToHex(this) << " from se" << cvtToHex(srcp) << endl);
|
2019-05-19 20:13:13 +00:00
|
|
|
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
|
|
|
|
it != srcp->m_idNameMap.end(); ++it) {
|
|
|
|
const string& name = it->first;
|
|
|
|
VSymEnt* subSrcp = it->second;
|
2018-02-02 02:32:58 +00:00
|
|
|
const AstVar* varp = VN_CAST(subSrcp->nodep(), Var);
|
2019-05-19 20:13:13 +00:00
|
|
|
if (!onlyUnmodportable || (varp && varp->varType() == AstVarType::GPARAM)) {
|
|
|
|
VSymEnt* subSymp = new VSymEnt(graphp, subSrcp);
|
|
|
|
reinsert(name, subSymp);
|
|
|
|
// And recurse to create children
|
|
|
|
subSymp->importFromIface(graphp, subSrcp);
|
|
|
|
}
|
|
|
|
}
|
2013-05-28 01:39:19 +00:00
|
|
|
}
|
2020-04-14 02:51:35 +00:00
|
|
|
void cellErrorScopes(AstNode* lookp, string prettyName = "") {
|
|
|
|
if (prettyName == "") prettyName = lookp->prettyName();
|
2019-05-19 20:13:13 +00:00
|
|
|
string scopes;
|
2020-04-14 02:51:35 +00:00
|
|
|
for (IdNameMap::iterator it = m_idNameMap.begin(); it != m_idNameMap.end(); ++it) {
|
2020-02-04 04:21:56 +00:00
|
|
|
AstNode* itemp = it->second->nodep();
|
2020-04-14 02:51:35 +00:00
|
|
|
if (VN_IS(itemp, Cell) || (VN_IS(itemp, Module) && VN_CAST(itemp, Module)->isTop())) {
|
2019-05-19 20:13:13 +00:00
|
|
|
if (scopes != "") scopes += ", ";
|
|
|
|
scopes += AstNode::prettyName(it->first);
|
|
|
|
}
|
|
|
|
}
|
2020-04-14 02:51:35 +00:00
|
|
|
if (scopes == "") scopes = "<no cells found>";
|
|
|
|
std::cerr << V3Error::warnMore() << "... Known scopes under '" << prettyName
|
|
|
|
<< "': " << scopes << endl;
|
2019-10-05 21:35:08 +00:00
|
|
|
if (debug()) dump(std::cerr, " KnownScope: ", 1);
|
2012-06-20 10:13:28 +00:00
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
};
|
|
|
|
|
2012-06-20 10:13:28 +00:00
|
|
|
//######################################################################
|
|
|
|
// Symbol tables
|
|
|
|
|
2020-11-19 02:32:16 +00:00
|
|
|
class VSymGraph final {
|
2012-06-20 10:13:28 +00:00
|
|
|
// Collection of symbol tables
|
|
|
|
// TYPES
|
2018-02-02 02:24:41 +00:00
|
|
|
typedef std::vector<VSymEnt*> SymStack;
|
2012-06-20 10:13:28 +00:00
|
|
|
|
|
|
|
// MEMBERS
|
2020-04-14 02:51:35 +00:00
|
|
|
VSymEnt* m_symRootp; // Root symbol table
|
|
|
|
SymStack m_symsp; // All symbol tables, to cleanup
|
2012-06-20 10:13:28 +00:00
|
|
|
|
2017-11-01 22:51:41 +00:00
|
|
|
// CONSTRUCTORS
|
|
|
|
VL_UNCOPYABLE(VSymGraph);
|
2020-04-14 02:51:35 +00:00
|
|
|
|
2017-11-01 22:51:41 +00:00
|
|
|
public:
|
2020-04-14 02:51:35 +00:00
|
|
|
explicit VSymGraph(AstNetlist* nodep) { m_symRootp = new VSymEnt(this, nodep); }
|
2017-11-01 22:51:41 +00:00
|
|
|
~VSymGraph() {
|
2020-08-16 15:43:49 +00:00
|
|
|
for (const VSymEnt* entp : m_symsp) delete entp;
|
2017-11-01 22:51:41 +00:00
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
|
2017-11-01 22:51:41 +00:00
|
|
|
// METHODS
|
2012-06-20 10:13:28 +00:00
|
|
|
VSymEnt* rootp() const { return m_symRootp; }
|
|
|
|
// Debug
|
2020-04-14 02:51:35 +00:00
|
|
|
void dump(std::ostream& os, const string& indent = "") {
|
2019-05-19 20:13:13 +00:00
|
|
|
VSymConstMap doneSyms;
|
2020-04-14 02:51:35 +00:00
|
|
|
os << "SymEnt Dump:\n";
|
2019-05-19 20:13:13 +00:00
|
|
|
m_symRootp->dumpIterate(os, doneSyms, indent, 9999, "$root");
|
|
|
|
bool first = true;
|
|
|
|
for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) {
|
|
|
|
if (doneSyms.find(*it) == doneSyms.end()) {
|
2020-04-14 02:51:35 +00:00
|
|
|
if (first) {
|
|
|
|
first = false;
|
|
|
|
os << "%%Warning: SymEnt Orphans:\n";
|
|
|
|
}
|
2019-05-19 20:13:13 +00:00
|
|
|
(*it)->dumpIterate(os, doneSyms, indent, 9999, "Orphan");
|
|
|
|
}
|
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
}
|
|
|
|
void dumpFilePrefixed(const string& nameComment) {
|
2019-05-19 20:13:13 +00:00
|
|
|
if (v3Global.opt.dumpTree()) {
|
2020-04-14 02:51:35 +00:00
|
|
|
string filename = v3Global.debugFilename(nameComment) + ".txt";
|
|
|
|
UINFO(2, "Dumping " << filename << endl);
|
2020-08-15 14:03:34 +00:00
|
|
|
const std::unique_ptr<std::ofstream> logp(V3File::new_ofstream(filename));
|
2020-04-14 02:51:35 +00:00
|
|
|
if (logp->fail()) v3fatal("Can't write " << filename);
|
2019-05-19 20:13:13 +00:00
|
|
|
dump(*logp, "");
|
|
|
|
}
|
2012-06-20 10:13:28 +00:00
|
|
|
}
|
2017-11-01 22:51:41 +00:00
|
|
|
|
|
|
|
protected:
|
|
|
|
friend class VSymEnt;
|
|
|
|
void pushNewEnt(VSymEnt* entp) { m_symsp.push_back(entp); }
|
2012-06-20 10:13:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
2012-12-18 01:26:40 +00:00
|
|
|
inline VSymEnt::VSymEnt(VSymGraph* graphp, AstNode* nodep)
|
2012-06-20 10:13:28 +00:00
|
|
|
: m_nodep(nodep) {
|
|
|
|
// No argument to set fallbackp, as generally it's wrong to set it in the new call,
|
|
|
|
// Instead it needs to be set on a "findOrNew()" return, as it may have been new'ed
|
|
|
|
// by an earlier search insertion.
|
2020-08-15 14:12:55 +00:00
|
|
|
m_fallbackp = nullptr;
|
|
|
|
m_parentp = nullptr;
|
2020-11-25 02:56:03 +00:00
|
|
|
m_classOrPackagep = nullptr;
|
2012-12-18 01:26:40 +00:00
|
|
|
m_exported = true;
|
|
|
|
m_imported = false;
|
|
|
|
graphp->pushNewEnt(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline VSymEnt::VSymEnt(VSymGraph* graphp, const VSymEnt* symp)
|
2016-02-03 02:02:00 +00:00
|
|
|
: m_nodep(symp->m_nodep) {
|
2012-12-18 01:26:40 +00:00
|
|
|
m_fallbackp = symp->m_fallbackp;
|
2020-04-14 02:51:35 +00:00
|
|
|
m_parentp = symp->m_parentp;
|
2020-11-25 02:56:03 +00:00
|
|
|
m_classOrPackagep = symp->m_classOrPackagep;
|
2012-12-18 01:26:40 +00:00
|
|
|
m_exported = symp->m_exported;
|
|
|
|
m_imported = symp->m_imported;
|
|
|
|
graphp->pushNewEnt(this);
|
2012-06-20 10:13:28 +00:00
|
|
|
}
|
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
#endif // guard
|