From ab8f623cea7dcba9b965f7cdc1da57c19b63c057 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 6 Jan 2011 09:27:30 -0800 Subject: [PATCH] Add file/line information to entities and ports Include the compiler infrastructure to vhdlpp for collecting the file and line information and attaching it to entities and ports. Make the parser store the file name during parse. Create a libmisc library where I can put source files that are used by multiple programs within the source tree. --- Makefile.in | 17 ++- StringHeap.cc | 202 --------------------------- LineInfo.cc => libmisc/LineInfo.cc | 4 +- LineInfo.h => libmisc/LineInfo.h | 0 {vhdlpp => libmisc}/StringHeap.cc | 0 StringHeap.h => libmisc/StringHeap.h | 1 - vhdlpp/Makefile.in | 11 +- vhdlpp/StringHeap.h | 121 ---------------- vhdlpp/compiler.cc | 2 + vhdlpp/compiler.h | 2 + vhdlpp/entity.cc | 5 +- vhdlpp/entity.h | 5 +- vhdlpp/lexor.lex | 1 + vhdlpp/parse.y | 9 ++ 14 files changed, 42 insertions(+), 338 deletions(-) delete mode 100644 StringHeap.cc rename LineInfo.cc => libmisc/LineInfo.cc (98%) rename LineInfo.h => libmisc/LineInfo.h (100%) rename {vhdlpp => libmisc}/StringHeap.cc (100%) rename StringHeap.h => libmisc/StringHeap.h (99%) delete mode 100644 vhdlpp/StringHeap.h diff --git a/Makefile.in b/Makefile.in index 50ca70ee6..48e28d1b8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -80,9 +80,9 @@ PS2PDF = @PS2PDF@ GIT = @GIT@ ifeq (@srcdir@,.) -INCLUDE_PATH = -I. +INCLUDE_PATH = -I. -Ilibmisc else -INCLUDE_PATH = -I. -I$(srcdir) +INCLUDE_PATH = -I. -Ilibmisc -I$(srcdir) -I$(srcdir)/libmisc endif CPPFLAGS = @DEFS@ $(INCLUDE_PATH) @CPPFLAGS@ @@ -91,6 +91,9 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ PICFLAGS = @PICFLAG@ LDFLAGS = @rdynamic@ @LDFLAGS@ +# Source files in the libmisc directory +M = LineInfo.o StringHeap.o + TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o @@ -104,9 +107,9 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \ pform_disciplines.o pform_dump.o pform_types.o set_width.o \ symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \ - Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \ + Attrib.o HName.o Module.o PDelays.o PEvent.o PExpr.o PGate.o \ PGenerate.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \ - Statement.o AStatement.o StringHeap.o $(FF) $(TT) + Statement.o AStatement.o $M $(FF) $(TT) all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man $(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true @@ -197,7 +200,7 @@ ifeq (@WIN32@,yes) # The first step makes an ivl.exe that dlltool can use to make an # export and import library, and the last link makes a, ivl.exe # that really exports the things that the import library imports. -ivl@EXEEXT@: $O $(srcdir)/ivl.def +ivl@EXEEXT@: $O $(srcdir)/ivl.def $(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@ dlltool --dllname ivl@EXEEXT@ --def $(srcdir)/ivl.def \ --output-lib libivl.a --output-exp ivl.exp @@ -229,6 +232,10 @@ version.exe: $(srcdir)/version.c $(srcdir)/version_base.h version_tag.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep/$*.d +%.o: $(srcdir)/libmisc/%.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o + mv $*.d dep/$*.d + # Here are some explicit dependencies needed to get things going. main.o: main.cc version_tag.h diff --git a/StringHeap.cc b/StringHeap.cc deleted file mode 100644 index 4ee081a07..000000000 --- a/StringHeap.cc +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2002-2010 Stephen Williams (steve@icarus.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form under the terms of the GNU - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -# include "StringHeap.h" -# include -# include -# include -# include "ivl_alloc.h" - -#ifdef CHECK_WITH_VALGRIND -static char **string_pool = NULL; -static unsigned string_pool_count = 0; -#endif - -StringHeap::StringHeap() -{ - cell_base_ = 0; - cell_ptr_ = HEAPCELL; - cell_count_ = 0; -} - -StringHeap::~StringHeap() -{ - // This is a planned memory leak. The string heap is intended - // to hold permanently-allocated strings. -} - -const char* StringHeap::add(const char*text) -{ - unsigned len = strlen(text); - assert((len+1) <= HEAPCELL); - - unsigned rem = HEAPCELL - cell_ptr_; - if (rem < (len+1)) { - cell_base_ = (char*)malloc(HEAPCELL); -#ifdef CHECK_WITH_VALGRIND - string_pool_count += 1; - string_pool = (char **) realloc(string_pool, - string_pool_count*sizeof(char **)); - string_pool[string_pool_count-1] = cell_base_; -#endif - cell_ptr_ = 0; - cell_count_ += 1; - assert(cell_base_ != 0); - } - - char*res = cell_base_ + cell_ptr_; - memcpy(res, text, len); - cell_ptr_ += len; - cell_base_[cell_ptr_++] = 0; - - assert(cell_ptr_ <= HEAPCELL); - - return res; -} - -perm_string StringHeap::make(const char*text) -{ - return perm_string(add(text)); -} - - -StringHeapLex::StringHeapLex() -{ - hit_count_ = 0; - add_count_ = 0; - - for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) - hash_table_[idx] = 0; -} - -StringHeapLex::~StringHeapLex() -{ -} - -void StringHeapLex::cleanup() -{ -#ifdef CHECK_WITH_VALGRIND - for (unsigned idx = 0 ; idx < string_pool_count ; idx += 1) { - free(string_pool[idx]); - } - free(string_pool); - string_pool = NULL; - string_pool_count = 0; - - for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) { - hash_table_[idx] = 0; - } -#endif -} - -unsigned StringHeapLex::add_hit_count() const -{ - return hit_count_; -} - -unsigned StringHeapLex::add_count() const -{ - return add_count_; -} - -static unsigned hash_string(const char*text) -{ - unsigned h = 0; - - while (*text) { - h = (h << 4) ^ (h >> 28) ^ *text; - text += 1; - } - return h; -} - -const char* StringHeapLex::add(const char*text) -{ - unsigned hash_value = hash_string(text) % HASH_SIZE; - - /* If we easily find the string in the hash table, then return - that and be done. */ - if (hash_table_[hash_value] - && (strcmp(hash_table_[hash_value], text) == 0)) { - hit_count_ += 1; - return hash_table_[hash_value]; - } - - /* The existing hash entry is not a match. Replace it with the - newly allocated value, and return the new pointer as the - result to the add. */ - const char*res = StringHeap::add(text); - hash_table_[hash_value] = res; - add_count_ += 1; - - return res; -} - -perm_string StringHeapLex::make(const char*text) -{ - return perm_string(add(text)); -} - -perm_string StringHeapLex::make(const string&text) -{ - return perm_string(add(text.c_str())); -} - -bool operator == (perm_string a, const char*b) -{ - if (a.str() == b) - return true; - - if (! (a.str() && b)) - return false; - - if (strcmp(a.str(), b) == 0) - return true; - - return false; -} - -bool operator == (perm_string a, perm_string b) -{ - return a == b.str(); -} - -bool operator != (perm_string a, const char*b) -{ - return ! (a == b); -} - -bool operator != (perm_string a, perm_string b) -{ - return ! (a == b); -} - -bool operator < (perm_string a, perm_string b) -{ - if (b.str() && !a.str()) - return true; - - if (b.str() == a.str()) - return false; - - if (strcmp(a.str(), b.str()) < 0) - return true; - - return false; -} diff --git a/LineInfo.cc b/libmisc/LineInfo.cc similarity index 98% rename from LineInfo.cc rename to libmisc/LineInfo.cc index 5b43d95fd..047cbf4bb 100644 --- a/LineInfo.cc +++ b/libmisc/LineInfo.cc @@ -17,11 +17,11 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "config.h" - # include "LineInfo.h" # include +using namespace std; + LineInfo::LineInfo() : lineno_(0) { diff --git a/LineInfo.h b/libmisc/LineInfo.h similarity index 100% rename from LineInfo.h rename to libmisc/LineInfo.h diff --git a/vhdlpp/StringHeap.cc b/libmisc/StringHeap.cc similarity index 100% rename from vhdlpp/StringHeap.cc rename to libmisc/StringHeap.cc diff --git a/StringHeap.h b/libmisc/StringHeap.h similarity index 99% rename from StringHeap.h rename to libmisc/StringHeap.h index 8457845a8..27ed1a3f4 100644 --- a/StringHeap.h +++ b/libmisc/StringHeap.h @@ -19,7 +19,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "config.h" # include using namespace std; diff --git a/vhdlpp/Makefile.in b/vhdlpp/Makefile.in index d10b5f9d4..01cd46da6 100644 --- a/vhdlpp/Makefile.in +++ b/vhdlpp/Makefile.in @@ -40,9 +40,9 @@ LEX = @LEX@ YACC = @YACC@ ifeq (.,.) -INCLUDE_PATH = -I. -I.. +INCLUDE_PATH = -I. -I.. -I../libmisc else -INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. +INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/../libmisc endif CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @@ -51,8 +51,10 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ @EXTRALIBS@ +M = StringHeap.o LineInfo.o + O = main.o compiler.o entity.o entity_elaborate.o \ - lexor.o lexor_keyword.o parse.o StringHeap.o + lexor.o lexor_keyword.o parse.o $M all: dep vhdlpp@EXEEXT@ @@ -73,6 +75,9 @@ dep: vhdlpp@EXEEXT@: $O $(CXX) -o vhdlpp@EXEEXT@ $(LDFLAGS) $O $(LIBS) +%.o: $(srcdir)/../libmisc/%.cc + $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o + %.o: %.cc vhdlpp_config.h $(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o mv $*.d dep/$*.d diff --git a/vhdlpp/StringHeap.h b/vhdlpp/StringHeap.h deleted file mode 100644 index 8457845a8..000000000 --- a/vhdlpp/StringHeap.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef __StringHeap_H -#define __StringHeap_H -/* - * Copyright (c) 2002-2009 Stephen Williams (steve@icarus.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form under the terms of the GNU - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -# include "config.h" -# include - -using namespace std; - -class perm_string { - - public: - perm_string() : text_(0) { } - perm_string(const perm_string&that) : text_(that.text_) { } - ~perm_string() { } - - perm_string& operator = (const perm_string&that) - { text_ = that.text_; return *this; } - - const char*str() const { return text_; } - operator const char* () const { return str(); } - - // This is an escape for making perm_string objects out of - // literals. For example, perm_string::literal("Label"); Please - // do *not* cheat and pass arbitrary const char* items here. - static perm_string literal(const char*t) { return perm_string(t); } - - private: - friend class StringHeap; - friend class StringHeapLex; - perm_string(const char*t) : text_(t) { }; - - private: - const char*text_; -}; - -extern bool operator == (perm_string a, perm_string b); -extern bool operator == (perm_string a, const char* b); -extern bool operator != (perm_string a, perm_string b); -extern bool operator != (perm_string a, const char* b); -extern bool operator > (perm_string a, perm_string b); -extern bool operator < (perm_string a, perm_string b); -extern bool operator >= (perm_string a, perm_string b); -extern bool operator <= (perm_string a, perm_string b); - -/* - * The string heap is a way to permanently allocate strings - * efficiently. They only take up the space of the string characters - * and the terminating nul, there is no malloc overhead. - */ -class StringHeap { - - public: - StringHeap(); - ~StringHeap(); - - const char*add(const char*); - perm_string make(const char*); - - private: - enum { HEAPCELL = 0x10000 }; - - char*cell_base_; - unsigned cell_ptr_; - unsigned cell_count_; - - private: // not implemented - StringHeap(const StringHeap&); - StringHeap& operator= (const StringHeap&); -}; - -/* - * A lexical string heap is a string heap that makes an effort to - * return the same pointer for identical strings. This saves further - * space by not allocating duplicate strings, so in a system with lots - * of identifiers, this can theoretically save more space. - */ -class StringHeapLex : private StringHeap { - - public: - StringHeapLex(); - ~StringHeapLex(); - - const char*add(const char*); - perm_string make(const char*); - perm_string make(const string&); - - unsigned add_count() const; - unsigned add_hit_count() const; - void cleanup(); - - private: - enum { HASH_SIZE = 4096 }; - const char*hash_table_[HASH_SIZE]; - - unsigned add_count_; - unsigned hit_count_; - - private: // not implemented - StringHeapLex(const StringHeapLex&); - StringHeapLex& operator= (const StringHeapLex&); -}; - -#endif diff --git a/vhdlpp/compiler.cc b/vhdlpp/compiler.cc index 826b6b2d8..ab9d66166 100644 --- a/vhdlpp/compiler.cc +++ b/vhdlpp/compiler.cc @@ -19,3 +19,5 @@ # include "compiler.h" StringHeapLex lex_strings; + +StringHeapLex filename_strings; diff --git a/vhdlpp/compiler.h b/vhdlpp/compiler.h index a1dfe368f..43d352e11 100644 --- a/vhdlpp/compiler.h +++ b/vhdlpp/compiler.h @@ -28,4 +28,6 @@ extern bool verbose_flag; extern StringHeapLex lex_strings; +extern StringHeapLex filename_strings; + #endif diff --git a/vhdlpp/entity.cc b/vhdlpp/entity.cc index d4d6308db..13841e677 100644 --- a/vhdlpp/entity.cc +++ b/vhdlpp/entity.cc @@ -47,7 +47,7 @@ static ostream& operator << (ostream&out, port_mode_t that) static void dump_design_entity(ostream&out, Entity*obj) { - out << "entity " << obj->name << endl; + out << "entity " << obj->name << " file=" << obj->get_fileline() << endl; if (obj->ports.size() == 0) { out << " No ports" << endl; } else { @@ -57,7 +57,8 @@ static void dump_design_entity(ostream&out, Entity*obj) InterfacePort*item = *cur; out << setw(6) << "" << item->name << " : " << item->mode - << ", type=" << item->type_name << endl; + << ", type=" << item->type_name + << ", file=" << item->get_fileline() << endl; } } } diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 03a62aa1b..1feb43fd2 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -22,10 +22,11 @@ # include # include # include "StringHeap.h" +# include "LineInfo.h" typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; -class InterfacePort { +class InterfacePort : public LineInfo { public: // Port direction from the source code. port_mode_t mode; @@ -35,7 +36,7 @@ class InterfacePort { perm_string type_name; }; -class Entity { +class Entity : public LineInfo { public: int elaborate(); diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index a032bdfb9..d0d1d6b06 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -98,6 +98,7 @@ extern void yyparse_set_filepath(const char*path); void reset_lexor(FILE*fd, const char*path) { + yylloc.text = path; yylloc.first_line = 1; yyrestart(fd); diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 26335ccfd..0103167a5 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -25,6 +25,13 @@ # include # include +inline void FILE_NAME(LineInfo*tmp, const struct yyltype&where) +{ + tmp->set_lineno(where.first_line); + tmp->set_file(filename_strings.make(where.text)); +} + + static void yyerror(const char*msg); static void errormsg(const YYLTYPE&loc, const char*msg, ...); @@ -135,6 +142,7 @@ design_units entity_declaration : K_entity IDENTIFIER K_is entity_header K_end K_entity ';' { Entity*tmp = new Entity; + FILE_NAME(tmp, @1); // Store the name tmp->name = lex_strings.make($2); delete[]$2; @@ -170,6 +178,7 @@ factor : primary ; interface_element : IDENTIFIER ':' mode IDENTIFIER { InterfacePort*tmp = new InterfacePort; + FILE_NAME(tmp, @1); tmp->mode = $3; tmp->name = lex_strings.make($1); tmp->type_name = lex_strings.make($4);