Commit 8dc4091a authored by Götz Lindenmaier's avatar Götz Lindenmaier
Browse files

added routines to free memory

[r2458]
parent 5df19460
* 25.2.04 Goetz
Fix memory leak in irprog: free_ir_prog.
Fix memory leak in entity: free_entity_attrs
* 19.12.03 Goetz
Add state management for loops (consistent, inconsistent, invalid).
......
......@@ -20,8 +20,9 @@ INSTALL_HEADERS = irouts.h irdom.h cgana.h irloop.h irtypeinfo.h irsimpletype.h
SOURCES = $(INSTALL_HEADERS)
SOURCES += Makefile.in \
irouts.c irdom_t.h irdom.c cgana.c \
irloop_t.h irbackedge.c irbackedge_t.h irscc.c irtypeinfo.c irsimpletype.c
irouts.c irdom_t.h irdom.c cgana.c \
irloop_t.h irbackedge.c irbackedge_t.h irscc.c irtypeinfo.c irsimpletype.c \
confirmcons.c
include $(topdir)/MakeRules
......
......@@ -23,7 +23,7 @@
#include "entity.h"
/* Methoden sind "frei", wenn ihr Funktionszeiger (potentiell)
*"explizit" bekannt ist, d.h.:
* "explizit" bekannt ist, d.h.:
*
* - die Methode ist von aussen sichtbar (external_visible).
*
......
......@@ -827,7 +827,7 @@ static void scc (ir_node *n) {
* avoid loops without Block or Phi as first node. This should
* severely reduce the number of evaluations of nodes to detect
* a fixpoint in the heap analyses.
* Firther it avoids loops without firm nodes that cause errors
* Further it avoids loops without firm nodes that cause errors
* in the heap analyses. */
#define NO_LOOPS_WITHOUT_HEAD 1
#if NO_LOOPS_WITHOUT_HEAD
......
......@@ -71,7 +71,6 @@ void init_irtypeinfo(void) {
for (i = 0; i < get_irp_n_irgs(); ++i)
set_irg_typeinfo_state(get_irp_irg(i), irg_typeinfo_none);
}
void free_irtypeinfo(void) {
......@@ -83,7 +82,6 @@ void free_irtypeinfo(void) {
} else
assert(0 && "call init_type_info before freeing");
if (type_node_map) {
pmap_destroy(type_node_map);
type_node_map = NULL;
......
......@@ -53,3 +53,24 @@ init_firm (default_initialize_local_variable_func_t *func)
/* Constructs some idents needed. */
init_type();
}
void free_firm (void) {
int i;
for (i = 0; i < get_irp_n_irgs(); i++)
free_ir_graph(get_irp_irg(i));
for (i = 0; i < get_irp_n_types(); i++) {
free_type_entities(get_irp_type(i));
free_type(get_irp_type(i));
}
free_type_entities(get_glob_type());
free_ir_prog();
finish_tarval();
finish_op();
finish_mode();
id_finish();
}
......@@ -110,4 +110,9 @@
*/
void init_firm (default_initialize_local_variable_func_t *func);
/**
* Frees all memory occupied by the firm library.
*/
void free_firm (void);
# endif /* _FIRM_H_ */
......@@ -31,6 +31,11 @@ void id_init(int initial_n_idents)
id_set = new_set(memcmp, initial_n_idents);
}
void id_finish (void) {
del_set(id_set);
id_set = NULL;
}
INLINE ident *id_from_str (const char *str, int len)
{
assert(len > 0);
......
......@@ -16,6 +16,7 @@
# include "ident.h"
void id_init (int initial_n_idents);
void id_finish (void);
#define ID_HASH(str, len) \
((( ((unsigned char *)(str))[0] * 33 \
......
......@@ -163,6 +163,11 @@ copy_node (ir_node *n, void *env) {
ir_node *nn, *block;
int new_arity;
/* The end node looses it's flexible in array. This doesn't matter,
as dead node elimination builds End by hand, inlineing doesn't use
the End node. */
//assert(n->op == op_End || ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC));
if (get_irn_opcode(n) == iro_Block) {
block = NULL;
new_arity = compute_new_arity(n);
......@@ -670,8 +675,9 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
/* -- archive keepalives -- */
for (i = 0; i < get_irn_arity(end); i++)
add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
/* The new end node will die, but the in array is not on the obstack ... */
free_End(end);
/* The new end node will die. We need not free as the in array is on the obstack:
copy_node only generated 'D' arrays. */
/* --
Return nodes by Jump nodes. -- */
......
......@@ -23,6 +23,7 @@
# include "array.h"
# include "irgmod.h"
# include "mangle.h"
# include "irouts.h"
ir_graph *current_ir_graph;
INLINE ir_graph *get_current_ir_graph(void) {
......@@ -207,6 +208,9 @@ ir_graph *new_const_code_irg(void) {
return res;
}
/* Defined in iropt.c */
void del_identities (pset *value_table);
/* Frees the passed irgraph.
Deallocates all nodes in this graph and the ir_graph structure.
Sets the field irgraph in the corresponding entity to NULL.
......@@ -215,12 +219,16 @@ ir_graph *new_const_code_irg(void) {
Does not free types, entities or modes that are used only by this
graph, nor the entity standing for this graph. */
void free_ir_graph (ir_graph *irg) {
set_entity_irg(irg->ent, NULL);
irg->kind = k_BAD;
if (irg->ent) set_entity_irg(irg->ent, NULL); /* not set in const code irg */
free_End(irg->end);
if (irg->frame_type) free_type(irg->frame_type);
if (irg->value_table) del_identities(irg->value_table);
if (irg->outs_state != no_outs) free_outs(irg);
free(irg->obst);
#if USE_EXPLICIT_PHI_IN_STACK
free_Phi_in_stack(irg->Phi_in_stack);
#endif
irg->kind = k_BAD;
free(irg);
}
......
......@@ -984,3 +984,35 @@ init_mode (void)
/* set the machine specific modes to the predifined ones */
mode_P_mach = mode_P;
}
void finish_mode(void) {
obstack_free(&modes, 0);
mode_T = NULL;
mode_X = NULL;
mode_M = NULL;
mode_BB = NULL;
mode_ANY = NULL;
mode_BAD = NULL;
mode_F = NULL;
mode_D = NULL;
mode_E = NULL;
mode_Bs = NULL;
mode_Bu = NULL;
mode_Hs = NULL;
mode_Hu = NULL;
mode_Is = NULL;
mode_Iu = NULL;
mode_Ls = NULL;
mode_Lu = NULL;
mode_C = NULL;
mode_U = NULL;
mode_b = NULL;
mode_P = NULL;
mode_P_mach = NULL;
}
......@@ -420,4 +420,7 @@ int smaller_mode(const ir_mode *sm, const ir_mode *lm);
/** mode module initialization, call once before use of any other function **/
void init_mode (void);
/** mode module finalization. frees all memory. */
void finish_mode(void);
#endif /* _IRMODE_H_ */
......@@ -750,7 +750,7 @@ INLINE void
free_End (ir_node *end) {
assert (end->op == op_End);
end->kind = k_BAD;
/* DEL_ARR_F(end->in); GL @@@ tut nicht ! */
DEL_ARR_F(end->in); /* GL @@@ tut nicht ! */
end->in = NULL; /* @@@ make sure we get an error if we use the
in array afterwards ... */
}
......
......@@ -99,6 +99,9 @@ new_ir_op (opcode code, const char *name, op_pinned p, int labeled, size_t attr_
return res;
}
void free_ir_op (ir_op *code) {
free(code);
}
void
init_op(void)
......@@ -164,6 +167,68 @@ init_op(void)
op_FuncCall = new_ir_op (iro_FuncCall, "FuncCall", floats, 1, sizeof (call_attr));
}
/* free memory used by irop module. */
void finish_op() {
free_ir_op (op_Block); op_Block = NULL;
free_ir_op (op_Start ); op_Start = NULL;
free_ir_op (op_End ); op_End = NULL;
free_ir_op (op_Jmp ); op_Jmp = NULL;
free_ir_op (op_Cond ); op_Cond = NULL;
free_ir_op (op_Return ); op_Return = NULL;
free_ir_op (op_Raise ); op_Raise = NULL;
free_ir_op (op_Const ); op_Const = NULL;
free_ir_op (op_SymConst ); op_SymConst = NULL;
free_ir_op (op_Sel ); op_Sel = NULL;
free_ir_op (op_InstOf ); op_InstOf = NULL;
free_ir_op (op_Call ); op_Call = NULL;
free_ir_op (op_Add ); op_Add = NULL;
free_ir_op (op_Minus ); op_Minus = NULL;
free_ir_op (op_Sub ); op_Sub = NULL;
free_ir_op (op_Mul ); op_Mul = NULL;
free_ir_op (op_Quot ); op_Quot = NULL;
free_ir_op (op_DivMod ); op_DivMod = NULL;
free_ir_op (op_Div ); op_Div = NULL;
free_ir_op (op_Mod ); op_Mod = NULL;
free_ir_op (op_Abs ); op_Abs = NULL;
free_ir_op (op_And ); op_And = NULL;
free_ir_op (op_Or ); op_Or = NULL;
free_ir_op (op_Eor ); op_Eor = NULL;
free_ir_op (op_Not ); op_Not = NULL;
free_ir_op (op_Cmp ); op_Cmp = NULL;
free_ir_op (op_Shl ); op_Shl = NULL;
free_ir_op (op_Shr ); op_Shr = NULL;
free_ir_op (op_Shrs ); op_Shrs = NULL;
free_ir_op (op_Rot ); op_Rot = NULL;
free_ir_op (op_Conv ); op_Conv = NULL;
free_ir_op (op_Cast ); op_Cast = NULL;
free_ir_op (op_Phi ); op_Phi = NULL;
free_ir_op (op_Load ); op_Load = NULL;
free_ir_op (op_Store ); op_Store = NULL;
free_ir_op (op_Alloc ); op_Alloc = NULL;
free_ir_op (op_Free ); op_Free = NULL;
free_ir_op (op_Sync ); op_Sync = NULL;
free_ir_op (op_Proj ); op_Proj = NULL;
free_ir_op (op_Tuple ); op_Tuple = NULL;
free_ir_op (op_Id ); op_Id = NULL;
free_ir_op (op_Bad ); op_Bad = NULL;
free_ir_op (op_Confirm ); op_Confirm = NULL;
free_ir_op (op_Unknown ); op_Unknown = NULL;
free_ir_op (op_Filter ); op_Filter = NULL;
free_ir_op (op_Break ); op_Break = NULL;
free_ir_op (op_CallBegin); op_CallBegin = NULL;
free_ir_op (op_EndReg ); op_EndReg = NULL;
free_ir_op (op_EndExcept); op_EndExcept = NULL;
}
/* Returns the string for the opcode. */
const char *get_op_name (const ir_op *op) {
return get_id_str(op->name);
......
......@@ -20,9 +20,12 @@
struct ir_op {
opcode code;
ident *name;
size_t attr_size; /**< Space needed in memory for private attributes */
int labeled; /**< Output edge labels on in-edges in vcg graph */
int pinned; /**< How to deal with the node in cse, pre. */
size_t attr_size; /**< Space needed in memory for private attributes */
int labeled; /**< Output edge labels on in-edges in vcg graph */
int pinned; /**< How to deal with the node in cse, pre. */
int reqires_fexible_in; /**< The node must always have a flexible array as in. */
/** @@@@ Change constructors for ir_op, and new_ir_node!!!
new_ir_node not only checks the arity, but also the op!!! @@@ */
};
/**
......@@ -41,4 +44,7 @@ ir_op * new_ir_op (opcode code, const char *name, op_pinned p,
/** initialize the irop module */
void init_op (void);
/* free memory used by irop module. */
void finish_op(void);
#endif /* _IROP_T_H_ */
......@@ -76,6 +76,18 @@ ir_prog *new_ir_prog (void) {
return res;
}
/* frees all memory used by irp. Types in type list, irgs in irg
list and entities in global type must be freed by hand before. */
void free_ir_prog() {
free_type(irp->glob_type);
/* @@@ * free_ir_graph(irp->const_code_irg); * ?? End has no in?? */
DEL_ARR_F(irp->graphs);
DEL_ARR_F(irp->types);
irp->kind = k_BAD;
irp->const_code_irg = NULL;
}
/** Functions to access the fields of ir_prog **/
......
......@@ -76,6 +76,10 @@ void init_irprog(void);
Automatically called by init_firm() through init_irprog. */
ir_prog *new_ir_prog (void);
/** frees all memory used by irp. Types in type list and irgs in irg
list must be freed by hand before. */
void free_ir_prog(void);
/** Gets the main routine of the compiled program. */
ir_graph *get_irp_main_irg(void);
......
......@@ -96,12 +96,13 @@ new_entity (type *owner, ident *name, type *type)
res->variability = variability_uninitialized;
res->value = NULL;
res->values = NULL;
res->val_paths = NULL;
}
res->peculiarity = peculiarity_existent;
res->volatility = volatility_non_volatile;
res->ld_name = NULL;
res->overwrites = NEW_ARR_F(entity *, 1);
res->overwrittenby = NEW_ARR_F(entity *, 1);
res->overwrites = NEW_ARR_F(entity *, 0);
res->overwrittenby = NEW_ARR_F(entity *, 0);
res->irg = NULL;
......@@ -121,12 +122,30 @@ new_d_entity (type *owner, ident *name, type *type, dbg_info *db) {
set_entity_dbg_info(res, db);
return res;
}
INLINE void free_compound_graph_path (compound_graph_path *gr);
INLINE int is_compound_graph_path(void *thing);
INLINE int get_compound_graph_path_length(compound_graph_path *gr);
INLINE entity *get_compound_graph_path_node(compound_graph_path *gr, int pos);
INLINE int get_compound_ent_n_values(entity *ent);
INLINE void free_entity_attrs(entity *ent) {
int i;
assert(ent);
if (get_type_tpop(get_entity_owner(ent)) == type_class) {
DEL_ARR_F(ent->overwrites);
DEL_ARR_F(ent->overwrittenby);
DEL_ARR_F(ent->overwrites); ent->overwrites = NULL;
DEL_ARR_F(ent->overwrittenby); ent->overwrittenby = NULL;
}
//if (ent->values) DEL_ARR_F(ent->values); /* @@@ warum nich? */
if (ent->val_paths) {
if (is_compound_entity(ent))
for (i = 0; i < get_compound_ent_n_values(ent); i++)
if (ent->val_paths[i])
free_compound_graph_path(ent->val_paths[i]) ; /* @@@ warum nich? */
//DEL_ARR_F(ent->val_paths);
}
ent->val_paths = NULL;
ent->values = NULL;
}
entity *
......@@ -145,13 +164,13 @@ copy_entity_own (entity *old, type *new_owner) {
new->overwrittenby = DUP_ARR_F(entity *, old->overwrittenby);
} else if ((get_type_tpop(get_entity_owner(old)) != type_class) &&
(get_type_tpop(new_owner) == type_class)) {
new->overwrites = NEW_ARR_F(entity *, 1);
new->overwrittenby = NEW_ARR_F(entity *, 1);
new->overwrites = NEW_ARR_F(entity *, 0);
new->overwrittenby = NEW_ARR_F(entity *, 0);
}
*/
if (is_class_type(new_owner)) {
new->overwrites = NEW_ARR_F(entity *, 1);
new->overwrittenby = NEW_ARR_F(entity *, 1);
new->overwrites = NEW_ARR_F(entity *, 0);
new->overwrittenby = NEW_ARR_F(entity *, 0);
}
#ifdef DEBUG_libfirm
new->nr = get_irp_new_node_nr();
......@@ -342,15 +361,15 @@ set_entity_variability (entity *ent, ent_variability var)
if ((is_compound_type(ent->type)) &&
(ent->variability == variability_uninitialized) && (var != variability_uninitialized)) {
/* Allocate datastructures for constant values */
ent->values = NEW_ARR_F(ir_node *, 1);
ent->val_paths = NEW_ARR_F(compound_graph_path *, 1);
ent->values = NEW_ARR_F(ir_node *, 0);
ent->val_paths = NEW_ARR_F(compound_graph_path *, 0);
}
if ((is_compound_type(ent->type)) &&
(var == variability_uninitialized) && (ent->variability != variability_uninitialized)) {
/* Free datastructures for constant values */
DEL_ARR_F(ent->values);
DEL_ARR_F(ent->val_paths);
DEL_ARR_F(ent->values); ent->values = NULL;
DEL_ARR_F(ent->val_paths); ent->val_paths = NULL;
}
ent->variability = var;
}
......@@ -528,7 +547,7 @@ INLINE int is_proper_compound_graph_path(compound_graph_path *gr, int pos) {
if (get_entity_owner(node) != owner) return false;
owner = get_entity_type(node);
}
if (pos == get_compound_graph_path_length(gr) -1)
if (pos == get_compound_graph_path_length(gr))
if (!is_atomic_type(owner)) return false;
return true;
}
......@@ -567,33 +586,33 @@ add_compound_ent_value_w_path(entity *ent, ir_node *val, compound_graph_path *pa
INLINE void
set_compound_ent_value_w_path(entity *ent, ir_node *val, compound_graph_path *path, int pos) {
assert(ent && is_compound_entity(ent) && (ent->variability != variability_uninitialized));
ent->values[pos+1] = val;
ent->val_paths[pos+1] = path;
ent->values[pos] = val;
ent->val_paths[pos] = path;
}
INLINE int
get_compound_ent_n_values(entity *ent) {
assert(ent && is_compound_entity(ent) && (ent->variability != variability_uninitialized));
return (ARR_LEN (ent->values))-1;
return (ARR_LEN (ent->values));
}
INLINE ir_node *
get_compound_ent_value(entity *ent, int pos) {
assert(ent && is_compound_entity(ent) && (ent->variability != variability_uninitialized));
return ent->values[pos+1];
return ent->values[pos];
}
INLINE compound_graph_path *
get_compound_ent_value_path(entity *ent, int pos) {
assert(ent && is_compound_entity(ent) && (ent->variability != variability_uninitialized));
return ent->val_paths[pos+1];
return ent->val_paths[pos];
}
void
remove_compound_ent_value(entity *ent, entity *value_ent) {
int i;
assert(ent && is_compound_entity(ent) && (ent->variability != variability_uninitialized));
for (i = 1; i < (ARR_LEN (ent->val_paths)); i++) {
for (i = 0; i < (ARR_LEN (ent->val_paths)); i++) {
compound_graph_path *path = ent->val_paths[i];
if (path->nodes[path->len-1] == value_ent) {
for(; i < (ARR_LEN (ent->val_paths))-1; i++) {
......@@ -700,7 +719,7 @@ INLINE int
get_entity_n_overwrites (entity *ent) {
assert(ent);
assert(is_class_type(get_entity_owner(ent)));
return (ARR_LEN (ent->overwrites))-1;
return (ARR_LEN (ent->overwrites));
}
int
......@@ -718,7 +737,7 @@ get_entity_overwrites (entity *ent, int pos) {
assert(ent);
assert(is_class_type(get_entity_owner(ent)));
assert(pos < get_entity_n_overwrites(ent));
return ent->overwrites[pos+1];
return ent->overwrites[pos];
}
INLINE void
......@@ -726,14 +745,14 @@ set_entity_overwrites (entity *ent, int pos, entity *overwritten) {
assert(ent);
assert(is_class_type(get_entity_owner(ent)));
assert(pos < get_entity_n_overwrites(ent));
ent->overwrites[pos+1] = overwritten;
ent->overwrites[pos] = overwritten;
}
void
remove_entity_overwrites(entity *ent, entity *overwritten) {
int i;
assert(ent && is_class_type(get_entity_owner(ent)));
for (i = 1; i < (ARR_LEN (ent->overwrites)); i++)
for (i = 0; i < (ARR_LEN (ent->overwrites)); i++)
if (ent->overwrites[i] == overwritten) {
for(; i < (ARR_LEN (ent->overwrites))-1; i++)
ent->overwrites[i] = ent->overwrites[i+1];
......@@ -753,7 +772,7 @@ INLINE int
get_entity_n_overwrittenby (entity *ent) {
assert(ent);
assert(is_class_type(get_entity_owner(ent)));
return (ARR_LEN (ent->overwrittenby))-1;
return (ARR_LEN (ent->overwrittenby));
}
int
......@@ -771,7 +790,7 @@ get_entity_overwrittenby (entity *ent, int pos) {
assert(ent);
assert(is_class_type(get_entity_owner(ent)));
assert(pos < get_entity_n_overwrittenby(ent));
return ent->overwrittenby[pos+1];
return ent->overwrittenby[pos];
}
INLINE void
......@@ -779,13 +798,13 @@ set_entity_overwrittenby (entity *ent, int pos, entity *overwrites) {
assert(ent);
assert(is_class_type(get_entity_owner(ent)));
assert(pos < get_entity_n_overwrittenby(ent));
ent->overwrittenby[pos+1] = overwrites;
ent->overwrittenby[pos] = overwrites;
}
void remove_entity_overwrittenby(entity *ent, entity *overwrites) {
int i;
assert(ent && is_class_type(get_entity_owner(ent)));
for (i = 1; i < (ARR_LEN (ent->overwrittenby)); i++)
for (i = 0; i < (ARR_LEN (ent->overwrittenby)); i++)
if (ent->overwrittenby[i] == overwrites) {
for(; i < (ARR_LEN (ent->overwrittenby))-1; i++)
ent->overwrittenby[i] = ent->overwrittenby[i+1];
......
......@@ -90,20 +90,6 @@ INLINE void set_master_type_visited(unsigned long val) { type_visited = val; }
INLINE unsigned long get_master_type_visited() { return type_visited; }
INLINE void inc_master_type_visited() { type_visited++; }
void free_type(type *tp) {
if ((get_type_tpop(tp) == tpop_none) || (get_type_tpop(tp) == tpop_unknown))
return;
/* Remove from list of all types */
remove_irp_type(tp);
/* Free the attributes of the type. */
free_type_attrs(tp);
/* Free entities automatically allocated with the type */
if (is_array_type(tp))
free_entity(get_array_element_entity(tp));
/* And now the type itself... */
tp->kind = k_BAD;
free(tp);
}
INLINE type *
new_type(tp_op *type_op, ir_mode *mode, ident* name) {
......@@ -132,6 +118,35 @@ new_type(tp_op *type_op, ir_mode *mode, ident* name) {
return res;
}
void free_type(type *tp) {
if ((get_type_tpop(tp) == tpop_none) || (get_type_tpop(tp) == tpop_unknown))
return;
/* Remove from list of all types */
remove_irp_type(tp);
/* Free the attributes of the type. */
free_type_attrs(tp);
/* Free entities automatically allocated with the type */
if (is_array_type(tp))
free_entity(get_array_element_entity(tp));
/* And now the type itself... */
tp->kind = k_BAD;
free(tp);
}
void free_type_entities(type *tp) {
switch(get_type_tpop_code(tp)) {
case tpo_class: { free_class_entities(tp); } break;
case tpo_struct: { free_struct_entities(tp); } break;
case tpo_method: { free_method_entities(tp); } break;
case tpo_union: { free_union_entities(tp); } break;
case tpo_array: { free_array_entities(tp); } break;
case tpo_enumeration: { free_enumeration_entities(tp); } break;
case tpo_pointer: { free_pointer_entities(tp); } break;
case tpo_primitive: { free_primitive_entities(tp); } break;
default: break;
}