Fix some on error memory leaks in vvp.
This patch modifies the vvp main code to cleanup if there was an error compiling the input file. There are still a few issues, but this takes care of most of them.
This commit is contained in:
parent
07ee2e7dff
commit
3868334f5c
67
vvp/main.cc
67
vvp/main.cc
|
|
@ -192,6 +192,41 @@ void set_delay_selection(const char* sel)
|
||||||
delete[] sel;
|
delete[] sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void final_cleanup()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We only need to cleanup the memory if we are checking with valgrind.
|
||||||
|
*/
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
/* Clean up the file name table. */
|
||||||
|
for (vector<const char*>::iterator cur = file_names.begin();
|
||||||
|
cur != file_names.end() ; cur++) {
|
||||||
|
delete[] *cur;
|
||||||
|
}
|
||||||
|
/* Clear the static result buffer. */
|
||||||
|
(void)need_result_buf(0, RBUF_DEL);
|
||||||
|
codespace_delete();
|
||||||
|
root_table_delete();
|
||||||
|
def_table_delete();
|
||||||
|
vpi_mcd_delete();
|
||||||
|
dec_str_delete();
|
||||||
|
modpath_delete();
|
||||||
|
vpi_handle_delete();
|
||||||
|
udp_defns_delete();
|
||||||
|
island_delete();
|
||||||
|
signal_pool_delete();
|
||||||
|
vvp_net_pool_delete();
|
||||||
|
ufunc_pool_delete();
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Unload the VPI modules. This is essential for MinGW, to ensure
|
||||||
|
* dump files are flushed before the main process terminates, as
|
||||||
|
* the DLL termination code is called after all remaining open
|
||||||
|
* files are automatically closed.
|
||||||
|
*/
|
||||||
|
load_module_delete();
|
||||||
|
}
|
||||||
|
|
||||||
unsigned module_cnt = 0;
|
unsigned module_cnt = 0;
|
||||||
const char*module_tab[64];
|
const char*module_tab[64];
|
||||||
|
|
||||||
|
|
@ -385,6 +420,7 @@ int main(int argc, char*argv[])
|
||||||
if (compile_errors > 0) {
|
if (compile_errors > 0) {
|
||||||
vpi_mcd_printf(1, "%s: Program not runnable, %u errors.\n",
|
vpi_mcd_printf(1, "%s: Program not runnable, %u errors.\n",
|
||||||
design_path, compile_errors);
|
design_path, compile_errors);
|
||||||
|
final_cleanup();
|
||||||
return compile_errors;
|
return compile_errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -463,36 +499,7 @@ int main(int argc, char*argv[])
|
||||||
count_gen_events, count_gen_pool());
|
count_gen_events, count_gen_pool());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
final_cleanup();
|
||||||
* We only need to cleanup the memory if we are checking with valgrind.
|
|
||||||
*/
|
|
||||||
#ifdef CHECK_WITH_VALGRIND
|
|
||||||
/* Clean up the memory. */
|
|
||||||
for (vector<const char*>::iterator cur = file_names.begin();
|
|
||||||
cur != file_names.end() ; cur++) {
|
|
||||||
delete[] *cur;
|
|
||||||
}
|
|
||||||
(void)need_result_buf(0, RBUF_DEL);
|
|
||||||
codespace_delete();
|
|
||||||
root_table_delete();
|
|
||||||
def_table_delete();
|
|
||||||
vpi_mcd_delete();
|
|
||||||
dec_str_delete();
|
|
||||||
modpath_delete();
|
|
||||||
vpi_handle_delete();
|
|
||||||
udp_defns_delete();
|
|
||||||
island_delete();
|
|
||||||
signal_pool_delete();
|
|
||||||
vvp_net_pool_delete();
|
|
||||||
ufunc_pool_delete();
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Unload the VPI modules. This is essential for MinGW, to ensure
|
|
||||||
* dump files are flushed before the main process terminates, as
|
|
||||||
* the DLL termination code is called after all remaining open
|
|
||||||
* files are automatically closed.
|
|
||||||
*/
|
|
||||||
load_module_delete();
|
|
||||||
|
|
||||||
return vvp_return_value;
|
return vvp_return_value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -713,6 +713,18 @@ void print_vpi_call_errors()
|
||||||
free(vpi_call_error_lst);
|
free(vpi_call_error_lst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cleanup_vpi_call_args(unsigned argc, vpiHandle*argv)
|
||||||
|
{
|
||||||
|
#ifdef CHECK_WITH_VALGRIND
|
||||||
|
if (argc) {
|
||||||
|
struct __vpiSysTaskCall*obj = new struct __vpiSysTaskCall;
|
||||||
|
obj->nargs = argc;
|
||||||
|
obj->args = argv;
|
||||||
|
vpi_call_delete(&obj->base);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A vpi_call is actually built up into a vpiSysTaskCall VPI object
|
* A vpi_call is actually built up into a vpiSysTaskCall VPI object
|
||||||
* that refers back to the vpiUserSystf VPI object that is the
|
* that refers back to the vpiUserSystf VPI object that is the
|
||||||
|
|
@ -736,6 +748,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||||
struct __vpiUserSystf*defn = vpip_find_systf(name);
|
struct __vpiUserSystf*defn = vpip_find_systf(name);
|
||||||
if (defn == 0) {
|
if (defn == 0) {
|
||||||
add_vpi_call_error(VPI_CALL_NO_DEF, name, file_idx, lineno);
|
add_vpi_call_error(VPI_CALL_NO_DEF, name, file_idx, lineno);
|
||||||
|
cleanup_vpi_call_args(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -744,6 +757,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||||
if (vwid != 0 || fnet != 0) {
|
if (vwid != 0 || fnet != 0) {
|
||||||
add_vpi_call_error(VPI_CALL_TASK_AS_FUNC, name, file_idx,
|
add_vpi_call_error(VPI_CALL_TASK_AS_FUNC, name, file_idx,
|
||||||
lineno);
|
lineno);
|
||||||
|
cleanup_vpi_call_args(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
assert(vbit == 0);
|
assert(vbit == 0);
|
||||||
|
|
@ -754,6 +768,7 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||||
if (func_as_task_err) {
|
if (func_as_task_err) {
|
||||||
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK,
|
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK,
|
||||||
name, file_idx, lineno);
|
name, file_idx, lineno);
|
||||||
|
cleanup_vpi_call_args(argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (func_as_task_warn) {
|
} else if (func_as_task_warn) {
|
||||||
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK_WARN,
|
add_vpi_call_error(VPI_CALL_FUNC_AS_TASK_WARN,
|
||||||
|
|
@ -818,6 +833,8 @@ vpiHandle vpip_build_vpi_call(const char*name, unsigned vbit, int vwid,
|
||||||
void vpi_call_delete(vpiHandle item)
|
void vpi_call_delete(vpiHandle item)
|
||||||
{
|
{
|
||||||
struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall *) item;
|
struct __vpiSysTaskCall*obj = (struct __vpiSysTaskCall *) item;
|
||||||
|
/* The object can be NULL if there was an error. */
|
||||||
|
if (!obj) return;
|
||||||
for (unsigned arg = 0; arg < obj->nargs; arg += 1) {
|
for (unsigned arg = 0; arg < obj->nargs; arg += 1) {
|
||||||
switch (obj->args[arg]->vpi_type->type_code) {
|
switch (obj->args[arg]->vpi_type->type_code) {
|
||||||
case vpiConstant:
|
case vpiConstant:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue