From d98c925f53dc55bc6d0cdfb8111ae03d1f2bb250 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 9 Jun 2009 13:12:45 -0700 Subject: [PATCH] Some compiler cleanup and minor memory leak fixes. This patch cleans up some unneeded code. Releases some allocated memory before the compiler quits and fixes a couple minor memory leaks in the compiler and vvp code generator. --- StringHeap.cc | 30 ++++++++++++++++++++++++++++-- StringHeap.h | 3 ++- compiler.h | 1 + config.h.in | 8 +++++++- elaborate.cc | 7 +++---- lexor.lex | 14 ++++++++++++++ main.cc | 37 +++++++++++++++++++++++++++++++++---- parse_misc.h | 2 ++ pform.cc | 1 + sys_funcs.cc | 14 ++++++++++++-- tgt-vvp/draw_mux.c | 3 --- tgt-vvp/draw_net_input.c | 12 ++++++++++-- tgt-vvp/vvp.c | 1 + tgt-vvp/vvp_priv.h | 3 ++- tgt-vvp/vvp_scope.c | 32 ++++++++++---------------------- 15 files changed, 126 insertions(+), 42 deletions(-) diff --git a/StringHeap.cc b/StringHeap.cc index dc2909e69..5ac7006da 100644 --- a/StringHeap.cc +++ b/StringHeap.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com) + * 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 @@ -25,6 +25,11 @@ # include # include +#ifdef CHECK_WITH_VALGRIND +static char **string_pool = NULL; +static unsigned string_pool_count = 0; +#endif + StringHeap::StringHeap() { cell_base_ = 0; @@ -46,6 +51,12 @@ const char* StringHeap::add(const char*text) 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); @@ -80,6 +91,22 @@ 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_; @@ -175,4 +202,3 @@ bool operator < (perm_string a, perm_string b) return false; } - diff --git a/StringHeap.h b/StringHeap.h index a8d76ed7d..664483d83 100644 --- a/StringHeap.h +++ b/StringHeap.h @@ -1,7 +1,7 @@ #ifndef __StringHeap_H #define __StringHeap_H /* - * Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com) + * 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 @@ -104,6 +104,7 @@ class StringHeapLex : private StringHeap { unsigned add_count() const; unsigned add_hit_count() const; + void cleanup(); private: enum { HASH_SIZE = 4096 }; diff --git a/compiler.h b/compiler.h index 5ced0b0b0..934344b74 100644 --- a/compiler.h +++ b/compiler.h @@ -202,5 +202,6 @@ struct sfunc_return_type { extern const struct sfunc_return_type* lookup_sys_func(const char*name); extern int load_sys_func_table(const char*path); +extern void cleanup_sys_func_table(); #endif diff --git a/config.h.in b/config.h.in index 7ba02b763..d8f3c9161 100644 --- a/config.h.in +++ b/config.h.in @@ -1,7 +1,7 @@ #ifndef __config_H /* -*- c++ -*- */ #define __config_H /* - * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-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 @@ -50,4 +50,10 @@ # include #endif +/* + * Define this if you want to compile vvp with memory freeing and + * special valgrind hooks for the memory pools. + */ +# undef CHECK_WITH_VALGRIND + #endif /* __config_H */ diff --git a/elaborate.cc b/elaborate.cc index 3dec83463..935d1b846 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3786,14 +3786,12 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const /* Do not elaborate specify delay paths if this feature is turned off. */ - if (!gn_specify_blocks_flag) - return; + if (!gn_specify_blocks_flag) return; ivl_assert(*this, conditional || (condition==0)); ndelays = delays.size(); - if (ndelays > 12) - ndelays = 12; + if (ndelays > 12) ndelays = 12; /* Print a warning if we find default and `timescale based * delays in the design, since this is likely an error. */ @@ -4453,6 +4451,7 @@ Design* elaborate(listroots) NetScope *scope = root_elems[i]->scope; rc &= rmod->elaborate(des, scope); + delete root_elems[i]; } if (rc == false) { diff --git a/lexor.lex b/lexor.lex index d62325d87..954a2ab61 100644 --- a/lexor.lex +++ b/lexor.lex @@ -1374,3 +1374,17 @@ void reset_lexor() /* Announce the first file name. */ yylloc.text = set_file_name(strdupnew(vl_file.c_str())); } + +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ +void destroy_lexor() +{ +# ifdef FLEX_SCANNER +# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 +# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 + yylex_destroy(); +# endif +# endif +# endif +} diff --git a/main.cc b/main.cc index ad4de617a..c80b2baed 100644 --- a/main.cc +++ b/main.cc @@ -77,7 +77,7 @@ extern "C" const char*optarg; /* Count errors detected in flag processing. */ unsigned flag_errors = 0; -const char*basedir = "."; +const char*basedir = strdup("."); /* * These are the language support control flags. These support which @@ -280,7 +280,7 @@ static void parm_to_flagmap(const string&flag) unsigned off = flag.find('='); if (off > flag.size()) { key = flag; - value = ""; + value = strdup(""); } else { key = flag.substr(0, off); @@ -399,6 +399,7 @@ static void read_iconfig_file(const char*ipath) } if (strcmp(buf, "basedir") == 0) { + free((char *)basedir); basedir = strdup(cp); } else if (strcmp(buf, "debug") == 0) { @@ -472,6 +473,7 @@ static void read_iconfig_file(const char*ipath) flags["VPI_MODULE_LIST"] = vpi_module_list; } else if (strcmp(buf, "out") == 0) { + free((char *)flags["-o"]); flags["-o"] = strdup(cp); } else if (strcmp(buf, "sys_func") == 0) { @@ -529,6 +531,7 @@ static void read_iconfig_file(const char*ipath) } } + fclose(ifile); } extern Design* elaborate(list root); @@ -555,6 +558,30 @@ inline static void times(struct tms *) { } inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; } #endif // ! defined(HAVE_TIMES) +static void EOC_cleanup(void) +{ + cleanup_sys_func_table(); + + for (list::iterator suf = library_suff.begin() ; + suf != library_suff.end() ; suf ++ ) { + free((char *)*suf); + } + library_suff.clear(); + + free((char *) basedir); + free(ivlpp_string); + free(depfile_name); + + for (map::iterator flg = flags.begin() ; + flg != flags.end() ; flg ++ ) { + free((char *)flg->second); + } + flags.clear(); + + lex_strings.cleanup(); + filename_strings.cleanup(); +} + int main(int argc, char*argv[]) { bool help_flag = false; @@ -567,11 +594,11 @@ int main(int argc, char*argv[]) struct tms cycles[5]; - library_suff.push_back(".v"); + library_suff.push_back(strdup(".v")); vpi_module_list = strdup("system"); flags["VPI_MODULE_LIST"] = vpi_module_list; - flags["-o"] = "a.out"; + flags["-o"] = strdup("a.out"); min_typ_max_flag = TYP; min_typ_max_warn = 10; @@ -933,6 +960,8 @@ int main(int argc, char*argv[]) << endl; } + delete des; + EOC_cleanup(); return 0; errors_summary: diff --git a/parse_misc.h b/parse_misc.h index 0a33c6999..8b58aa4e8 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -60,6 +60,8 @@ extern void VLerror(const YYLTYPE&loc, const char*msg); #define yywarn VLwarn extern void VLwarn(const YYLTYPE&loc, const char*msg); +extern void destroy_lexor(); + extern ostream& operator << (ostream&, const YYLTYPE&loc); extern unsigned error_count, warn_count; diff --git a/pform.cc b/pform.cc index 69ca9de36..1e881c80f 100644 --- a/pform.cc +++ b/pform.cc @@ -2170,6 +2170,7 @@ int pform_parse(const char*path, FILE*file) error_count += 1; } + destroy_lexor(); return error_count; } diff --git a/sys_funcs.cc b/sys_funcs.cc index a82ac0b62..4d2002606 100644 --- a/sys_funcs.cc +++ b/sys_funcs.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-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 @@ -46,6 +46,16 @@ struct sfunc_return_type_cell : sfunc_return_type { static struct sfunc_return_type_cell*sfunc_stack = 0; +void cleanup_sys_func_table() +{ + struct sfunc_return_type_cell *next, *cur = sfunc_stack; + while (cur) { + next = cur->next; + delete cur; + cur = next; + } +} + const struct sfunc_return_type* lookup_sys_func(const char*name) { /* First, try to find then name in the function stack. */ @@ -186,7 +196,7 @@ int load_sys_func_table(const char*path) fprintf(stderr, "%s:%s: Unknown type: %s\n", path, name, stype); } + fclose(fd); return 0; } - diff --git a/tgt-vvp/draw_mux.c b/tgt-vvp/draw_mux.c index 0ccd46cf7..592afea73 100644 --- a/tgt-vvp/draw_mux.c +++ b/tgt-vvp/draw_mux.c @@ -19,9 +19,6 @@ # include "vvp_priv.h" # include -#ifdef HAVE_MALLOC_H -# include -#endif # include # include diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 5f1394a8e..c65e826f0 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -505,6 +505,16 @@ static char* draw_island_port(ivl_island_t island, /* Omit LPMPART_BI device pin-data(0) drivers. */ # define OMIT_PART_BI_DATA 0x0001 +static ivl_nexus_ptr_t *drivers = 0x0; +static unsigned adrivers = 0; + +void EOC_cleanup_drivers() +{ + free(drivers); + drivers = NULL; + adrivers = 0; +} + char* draw_net_input_x(ivl_nexus_t nex, ivl_nexus_ptr_t omit_ptr, int omit_flags, struct vvp_nexus_data*nex_data) @@ -515,8 +525,6 @@ char* draw_net_input_x(ivl_nexus_t nex, unsigned idx; int level; unsigned ndrivers = 0; - static ivl_nexus_ptr_t *drivers = 0x0; - static unsigned adrivers = 0; const char*resolv_type; diff --git a/tgt-vvp/vvp.c b/tgt-vvp/vvp.c index d8e847a86..8f0cb882e 100644 --- a/tgt-vvp/vvp.c +++ b/tgt-vvp/vvp.c @@ -140,6 +140,7 @@ int target_design(ivl_design_t des) } fclose(vvp_out); + EOC_cleanup_drivers(); return rc + vvp_errors; } diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index fda6bb5ad..f67e94506 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -1,7 +1,7 @@ #ifndef __vvp_priv_H #define __vvp_priv_H /* - * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-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 @@ -141,6 +141,7 @@ struct vvp_nexus_data { * cache it. */ extern const char* draw_net_input(ivl_nexus_t nex); +void EOC_cleanup_drivers(); /* * See draw_net_input.c for details on draw_net_input_x. (It would be diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 3d6b119ca..160044b1a 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -665,25 +665,12 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) ivl_drive_t str0, str1; int level; - int ninp = ivl_logic_pins(lptr) - 1; - typedef const char*const_charp; - const_charp*input_strings = calloc(ninp, sizeof(const_charp)); - - for (pdx = 0 ; pdx < ninp ; pdx += 1) { - ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1); - if (nex == 0) { - /* Only UDPs can have unconnected inputs. */ - assert(ivl_logic_type(lptr) == IVL_LO_UDP); - input_strings[pdx] = 0; - } else { - input_strings[pdx] = draw_net_input(nex); - } - } + int ninp; + const char **input_strings; switch (ivl_logic_type(lptr)) { case IVL_LO_UDP: - free(input_strings); draw_udp_in_scope(lptr); return; @@ -706,7 +693,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) /* Skip pullup and pulldown objects. Things that have pull objects as inputs will instead generate the appropriate C symbol. */ - free(input_strings); return; case IVL_LO_AND: @@ -1862,12 +1848,14 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) fprintf(vvp_out, ">;\n"); break; case IVL_EX_REALNUM: - fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; value=%#g\n", - par, ivl_parameter_basename(par), - ivl_file_table_index(ivl_parameter_file(par)), - ivl_parameter_lineno(par), - draw_Cr_to_string(ivl_expr_dvalue(pex)), - ivl_expr_dvalue(pex)); + { char *res = draw_Cr_to_string(ivl_expr_dvalue(pex)); + fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; " + "value=%#g\n", par, ivl_parameter_basename(par), + ivl_file_table_index(ivl_parameter_file(par)), + ivl_parameter_lineno(par), res, + ivl_expr_dvalue(pex)); + free(res); + } break; default: fprintf(vvp_out, "; parameter type %d unsupported\n",