Commit e2ecd91c by Bernd Schmidt Committed by Mark Mitchell

c-decl.c (struct language_function): Renamed from struct c_function.

	* c-decl.c (struct language_function): Renamed from struct c_function.
	Delete elt NEXT.
	(c_function_chain): Delete.
	(push_c_function_context): New arg F.  Don't warn about nested
	functions here.  Fill LANGUAGE elt of F.  Delete code to update
	c_function_chain.  Don't call push_function_context.
	(pop_c_function_context): New arg F.  Restore from there instead of
	from c_function_chain.  Don't call pop_function_context.  Clear out
	LANGUAGE field of F when done.
	* c-lang.c: Include "function.h"
	(lang_init): Initialize save_lang_status and restore_lang_status.
	* c-parse.in (nested_function, nested_function_notype): Warn about
	nested functions.  Call push_function_context/pop_function_context
	instead of the _c_ variants.
	* c-tree.h (push_c_function_context, pop_c_function_context): Update
	prototype.
	* Makefile.in (c-lang.o): Update dependencies.

	* emit-rtl.c (init_emit): Use xmalloc to allocate regno_reg_rtx,
	regno_pointer_flag, regno_pointer_align.
	(gen_reg_rtx): Use xrealloc to enlarge them.
	(free_emit_status): New function.
	* function.c (mark_machine_status, mark_lang_status): New variables.
	(assign_stack_local_1): Renamed from assign_outer_stack_local.  Merge
	in some bits from assign_stack_local.  All callers changed to use new
	name.
	(assign_stack_local): Just call assign_stack_local_1.
	(free_after_compilation): New function.
	(put_reg_into_stack): Simplify to always call assign_stack_local_1.
	(trampoline_address): Likewise.
	(assign_parms): Use xcalloc/xrealloc to allocate parm_reg_stack_loc.
	(prepare_function_start): Explicitly clear some more variables.
	* function.h (struct function): New elt can_garbage_collect.
	(mark_machine_status, mark_lang_status): Declare variables.
	(free_after_compilation, free_emit_status, free_varasm_status,
	init_varasm_status): Declare functions.
	* toplev.c (rest_of_compilation): Call free_after_compilation when
	done with the current function.
	* varasm.c (free_varasm_status): New function.

From-SVN: r29117
parent 6308c574
Sat Sep 4 18:01:45 1999 Bernd Schmidt <bernds@cygnus.co.uk>
* c-decl.c (struct language_function): Renamed from struct c_function.
Delete elt NEXT.
(c_function_chain): Delete.
(push_c_function_context): New arg F. Don't warn about nested
functions here. Fill LANGUAGE elt of F. Delete code to update
c_function_chain. Don't call push_function_context.
(pop_c_function_context): New arg F. Restore from there instead of
from c_function_chain. Don't call pop_function_context. Clear out
LANGUAGE field of F when done.
* c-lang.c: Include "function.h"
(lang_init): Initialize save_lang_status and restore_lang_status.
* c-parse.in (nested_function, nested_function_notype): Warn about
nested functions. Call push_function_context/pop_function_context
instead of the _c_ variants.
* c-tree.h (push_c_function_context, pop_c_function_context): Update
prototype.
* Makefile.in (c-lang.o): Update dependencies.
* emit-rtl.c (init_emit): Use xmalloc to allocate regno_reg_rtx,
regno_pointer_flag, regno_pointer_align.
(gen_reg_rtx): Use xrealloc to enlarge them.
(free_emit_status): New function.
* function.c (mark_machine_status, mark_lang_status): New variables.
(assign_stack_local_1): Renamed from assign_outer_stack_local. Merge
in some bits from assign_stack_local. All callers changed to use new
name.
(assign_stack_local): Just call assign_stack_local_1.
(free_after_compilation): New function.
(put_reg_into_stack): Simplify to always call assign_stack_local_1.
(trampoline_address): Likewise.
(assign_parms): Use xcalloc/xrealloc to allocate parm_reg_stack_loc.
(prepare_function_start): Explicitly clear some more variables.
* function.h (struct function): New elt can_garbage_collect.
(mark_machine_status, mark_lang_status): Declare variables.
(free_after_compilation, free_emit_status, free_varasm_status,
init_varasm_status): Declare functions.
* toplev.c (rest_of_compilation): Call free_after_compilation when
done with the current function.
* varasm.c (free_varasm_status): New function.
Sat Sep 4 17:15:13 1999 Richard Henderson <rth@cygnus.com> Sat Sep 4 17:15:13 1999 Richard Henderson <rth@cygnus.com>
* sparc.h (EXPAND_BUILTIN_VA_START): Define. * sparc.h (EXPAND_BUILTIN_VA_START): Define.
......
...@@ -1335,7 +1335,7 @@ c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \ ...@@ -1335,7 +1335,7 @@ c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \ c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h
c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \ c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
c-lex.h toplev.h output.h c-lex.h toplev.h output.h function.h
c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h c-tree.h \ c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h c-tree.h \
c-common.h $(srcdir)/c-parse.h $(srcdir)/c-gperf.h c-pragma.h input.h \ c-common.h $(srcdir)/c-parse.h $(srcdir)/c-gperf.h c-pragma.h input.h \
intl.h flags.h toplev.h output.h mbchar.h intl.h flags.h toplev.h output.h mbchar.h
......
...@@ -6981,9 +6981,8 @@ finish_function (nested) ...@@ -6981,9 +6981,8 @@ finish_function (nested)
that keep track of the progress of compilation of the current function. that keep track of the progress of compilation of the current function.
Used for nested functions. */ Used for nested functions. */
struct c_function struct language_function
{ {
struct c_function *next;
tree named_labels; tree named_labels;
tree shadowed_labels; tree shadowed_labels;
int returns_value; int returns_value;
...@@ -6993,24 +6992,16 @@ struct c_function ...@@ -6993,24 +6992,16 @@ struct c_function
struct binding_level *binding_level; struct binding_level *binding_level;
}; };
struct c_function *c_function_chain;
/* Save and reinitialize the variables /* Save and reinitialize the variables
used during compilation of a C function. */ used during compilation of a C function. */
void void
push_c_function_context () push_c_function_context (f)
struct function *f;
{ {
struct c_function *p struct language_function *p;
= (struct c_function *) xmalloc (sizeof (struct c_function)); p = (struct language_function *) xmalloc (sizeof (struct language_function));
f->language = p;
if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
p->next = c_function_chain;
c_function_chain = p;
p->named_labels = named_labels; p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels; p->shadowed_labels = shadowed_labels;
...@@ -7024,9 +7015,10 @@ push_c_function_context () ...@@ -7024,9 +7015,10 @@ push_c_function_context ()
/* Restore the variables used during compilation of a C function. */ /* Restore the variables used during compilation of a C function. */
void void
pop_c_function_context () pop_c_function_context (f)
struct function *f;
{ {
struct c_function *p = c_function_chain; struct language_function *p = f->language;
tree link; tree link;
/* Bring back all the labels that were shadowed. */ /* Bring back all the labels that were shadowed. */
...@@ -7044,10 +7036,6 @@ pop_c_function_context () ...@@ -7044,10 +7036,6 @@ pop_c_function_context ()
DECL_ARGUMENTS (current_function_decl) = 0; DECL_ARGUMENTS (current_function_decl) = 0;
} }
pop_function_context ();
c_function_chain = p->next;
named_labels = p->named_labels; named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels; shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value; current_function_returns_value = p->returns_value;
...@@ -7057,6 +7045,7 @@ pop_c_function_context () ...@@ -7057,6 +7045,7 @@ pop_c_function_context ()
current_binding_level = p->binding_level; current_binding_level = p->binding_level;
free (p); free (p);
f->language = 0;
} }
/* integrate_decl_tree calls this function, but since we don't use the /* integrate_decl_tree calls this function, but since we don't use the
......
...@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "tree.h" #include "tree.h"
#include "function.h"
#include "input.h" #include "input.h"
#include "c-tree.h" #include "c-tree.h"
#include "c-lex.h" #include "c-lex.h"
...@@ -68,6 +69,9 @@ lang_init () ...@@ -68,6 +69,9 @@ lang_init ()
check_newline (); check_newline ();
yy_cur--; yy_cur--;
#endif #endif
save_lang_status = &push_c_function_context;
restore_lang_status = &pop_c_function_context;
} }
void void
......
...@@ -1301,11 +1301,14 @@ end ifc ...@@ -1301,11 +1301,14 @@ end ifc
nested_function: nested_function:
declarator declarator
{ push_c_function_context (); { if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
if (! start_function (current_declspecs, $1, if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1)) prefix_attributes, NULL_TREE, 1))
{ {
pop_c_function_context (); pop_function_context ();
YYERROR1; YYERROR1;
} }
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -1319,16 +1322,19 @@ nested_function: ...@@ -1319,16 +1322,19 @@ nested_function:
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt compstmt
{ finish_function (1); { finish_function (1);
pop_c_function_context (); } pop_function_context (); }
; ;
notype_nested_function: notype_nested_function:
notype_declarator notype_declarator
{ push_c_function_context (); { if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
if (! start_function (current_declspecs, $1, if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1)) prefix_attributes, NULL_TREE, 1))
{ {
pop_c_function_context (); pop_function_context ();
YYERROR1; YYERROR1;
} }
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -1342,7 +1348,7 @@ notype_nested_function: ...@@ -1342,7 +1348,7 @@ notype_nested_function:
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt compstmt
{ finish_function (1); { finish_function (1);
pop_c_function_context (); } pop_function_context (); }
; ;
/* Any kind of declarator (thus, all declarators allowed /* Any kind of declarator (thus, all declarators allowed
......
...@@ -1133,11 +1133,14 @@ designator: ...@@ -1133,11 +1133,14 @@ designator:
nested_function: nested_function:
declarator declarator
{ push_c_function_context (); { if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
if (! start_function (current_declspecs, $1, if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1)) prefix_attributes, NULL_TREE, 1))
{ {
pop_c_function_context (); pop_function_context ();
YYERROR1; YYERROR1;
} }
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -1151,16 +1154,19 @@ nested_function: ...@@ -1151,16 +1154,19 @@ nested_function:
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt compstmt
{ finish_function (1); { finish_function (1);
pop_c_function_context (); } pop_function_context (); }
; ;
notype_nested_function: notype_nested_function:
notype_declarator notype_declarator
{ push_c_function_context (); { if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
if (! start_function (current_declspecs, $1, if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1)) prefix_attributes, NULL_TREE, 1))
{ {
pop_c_function_context (); pop_function_context ();
YYERROR1; YYERROR1;
} }
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -1174,7 +1180,7 @@ notype_nested_function: ...@@ -1174,7 +1180,7 @@ notype_nested_function:
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt compstmt
{ finish_function (1); { finish_function (1);
pop_c_function_context (); } pop_function_context (); }
; ;
/* Any kind of declarator (thus, all declarators allowed /* Any kind of declarator (thus, all declarators allowed
......
...@@ -222,13 +222,13 @@ extern tree lookup_name_current_level_global PROTO((tree)); ...@@ -222,13 +222,13 @@ extern tree lookup_name_current_level_global PROTO((tree));
extern tree maybe_build_cleanup PROTO((tree)); extern tree maybe_build_cleanup PROTO((tree));
extern void parmlist_tags_warning PROTO((void)); extern void parmlist_tags_warning PROTO((void));
extern void pending_xref_error PROTO((void)); extern void pending_xref_error PROTO((void));
extern void pop_c_function_context PROTO((void)); extern void push_c_function_context PROTO((struct function *));
extern void pop_c_function_context PROTO((struct function *));
extern void pop_label_level PROTO((void)); extern void pop_label_level PROTO((void));
extern tree poplevel PROTO((int, int, int)); extern tree poplevel PROTO((int, int, int));
extern void print_lang_decl PROTO((FILE *, tree, int)); extern void print_lang_decl PROTO((FILE *, tree, int));
extern void print_lang_identifier PROTO((FILE *, tree, int)); extern void print_lang_identifier PROTO((FILE *, tree, int));
extern void print_lang_type PROTO((FILE *, tree, int)); extern void print_lang_type PROTO((FILE *, tree, int));
extern void push_c_function_context PROTO((void));
extern void push_label_level PROTO((void)); extern void push_label_level PROTO((void));
extern void push_parm_decl PROTO((tree)); extern void push_parm_decl PROTO((tree));
extern tree pushdecl PROTO((tree)); extern tree pushdecl PROTO((tree));
......
...@@ -502,18 +502,17 @@ gen_reg_rtx (mode) ...@@ -502,18 +502,17 @@ gen_reg_rtx (mode)
{ {
int old_size = f->emit->regno_pointer_flag_length; int old_size = f->emit->regno_pointer_flag_length;
rtx *new1; rtx *new1;
char *new = (char *) savealloc (old_size * 2); char *new;
memcpy (new, f->emit->regno_pointer_flag, old_size); new = xrealloc (f->emit->regno_pointer_flag, old_size * 2);
memset (new + old_size, 0, old_size); memset (new + old_size, 0, old_size);
f->emit->regno_pointer_flag = new; f->emit->regno_pointer_flag = new;
new = (char *) savealloc (old_size * 2); new = xrealloc (f->emit->regno_pointer_align, old_size * 2);
memcpy (new, f->emit->regno_pointer_align, old_size);
memset (new + old_size, 0, old_size); memset (new + old_size, 0, old_size);
f->emit->regno_pointer_align = new; f->emit->regno_pointer_align = new;
new1 = (rtx *) savealloc (old_size * 2 * sizeof (rtx)); new1 = (rtx *) xrealloc (f->emit->x_regno_reg_rtx,
memcpy (new1, regno_reg_rtx, old_size * sizeof (rtx)); old_size * 2 * sizeof (rtx));
memset (new1 + old_size, 0, old_size * sizeof (rtx)); memset (new1 + old_size, 0, old_size * sizeof (rtx));
regno_reg_rtx = new1; regno_reg_rtx = new1;
...@@ -1597,6 +1596,19 @@ restore_emit_status (p) ...@@ -1597,6 +1596,19 @@ restore_emit_status (p)
last_label_num = 0; last_label_num = 0;
clear_emit_caches (); clear_emit_caches ();
} }
/* Clear out all parts of our state in F that can safely be discarded
after the function has been compiled, to let garbage collection
reclaim the memory. */
void
free_emit_status (f)
struct function *f;
{
free (f->emit->x_regno_reg_rtx);
free (f->emit->regno_pointer_flag);
free (f->emit->regno_pointer_align);
f->emit->x_regno_reg_rtx = 0;
}
/* Go through all the RTL insn bodies and copy any invalid shared structure. /* Go through all the RTL insn bodies and copy any invalid shared structure.
It does not work to do this twice, because the mark bits set here It does not work to do this twice, because the mark bits set here
...@@ -3404,15 +3416,15 @@ init_emit () ...@@ -3404,15 +3416,15 @@ init_emit ()
f->emit->regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101; f->emit->regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
f->emit->regno_pointer_flag f->emit->regno_pointer_flag
= (char *) savealloc (f->emit->regno_pointer_flag_length); = (char *) xmalloc (f->emit->regno_pointer_flag_length);
bzero (f->emit->regno_pointer_flag, f->emit->regno_pointer_flag_length); bzero (f->emit->regno_pointer_flag, f->emit->regno_pointer_flag_length);
f->emit->regno_pointer_align f->emit->regno_pointer_align
= (char *) savealloc (f->emit->regno_pointer_flag_length); = (char *) xmalloc (f->emit->regno_pointer_flag_length);
bzero (f->emit->regno_pointer_align, f->emit->regno_pointer_flag_length); bzero (f->emit->regno_pointer_align, f->emit->regno_pointer_flag_length);
regno_reg_rtx regno_reg_rtx
= (rtx *) savealloc (f->emit->regno_pointer_flag_length * sizeof (rtx)); = (rtx *) xmalloc (f->emit->regno_pointer_flag_length * sizeof (rtx));
bzero ((char *) regno_reg_rtx, bzero ((char *) regno_reg_rtx,
f->emit->regno_pointer_flag_length * sizeof (rtx)); f->emit->regno_pointer_flag_length * sizeof (rtx));
......
...@@ -184,6 +184,9 @@ struct function ...@@ -184,6 +184,9 @@ struct function
struct emit_status *emit; struct emit_status *emit;
struct varasm_status *varasm; struct varasm_status *varasm;
/* Nonzero if we are done compiling this function. */
int can_garbage_collect;
/* For function.c. */ /* For function.c. */
/* Name of this function. */ /* Name of this function. */
...@@ -533,10 +536,12 @@ extern HOST_WIDE_INT get_func_frame_size PROTO((struct function *)); ...@@ -533,10 +536,12 @@ extern HOST_WIDE_INT get_func_frame_size PROTO((struct function *));
save and restore machine-specific data, save and restore machine-specific data,
in push_function_context and pop_function_context. */ in push_function_context and pop_function_context. */
extern void (*init_machine_status) PROTO((struct function *)); extern void (*init_machine_status) PROTO((struct function *));
extern void (*mark_machine_status) PROTO((struct function *));
extern void (*save_machine_status) PROTO((struct function *)); extern void (*save_machine_status) PROTO((struct function *));
extern void (*restore_machine_status) PROTO((struct function *)); extern void (*restore_machine_status) PROTO((struct function *));
/* Likewise, but for language-specific data. */ /* Likewise, but for language-specific data. */
extern void (*mark_lang_status) PROTO((struct function *));
extern void (*save_lang_status) PROTO((struct function *)); extern void (*save_lang_status) PROTO((struct function *));
extern void (*restore_lang_status) PROTO((struct function *)); extern void (*restore_lang_status) PROTO((struct function *));
...@@ -544,7 +549,11 @@ extern void (*restore_lang_status) PROTO((struct function *)); ...@@ -544,7 +549,11 @@ extern void (*restore_lang_status) PROTO((struct function *));
extern void save_tree_status PROTO((struct function *)); extern void save_tree_status PROTO((struct function *));
extern void restore_tree_status PROTO((struct function *)); extern void restore_tree_status PROTO((struct function *));
extern void restore_emit_status PROTO((struct function *)); extern void restore_emit_status PROTO((struct function *));
extern void free_after_compilation PROTO((struct function *));
extern void init_varasm_status PROTO((struct function *));
extern void free_varasm_status PROTO((struct function *));
extern void free_emit_status PROTO((struct function *));
extern rtx get_first_block_beg PROTO((void)); extern rtx get_first_block_beg PROTO((void));
extern void init_virtual_regs PROTO((struct emit_status *)); extern void init_virtual_regs PROTO((struct emit_status *));
......
...@@ -1258,11 +1258,14 @@ designator: ...@@ -1258,11 +1258,14 @@ designator:
nested_function: nested_function:
declarator declarator
{ push_c_function_context (); { if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
if (! start_function (current_declspecs, $1, if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1)) prefix_attributes, NULL_TREE, 1))
{ {
pop_c_function_context (); pop_function_context ();
YYERROR1; YYERROR1;
} }
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -1276,16 +1279,19 @@ nested_function: ...@@ -1276,16 +1279,19 @@ nested_function:
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt compstmt
{ finish_function (1); { finish_function (1);
pop_c_function_context (); } pop_function_context (); }
; ;
notype_nested_function: notype_nested_function:
notype_declarator notype_declarator
{ push_c_function_context (); { if (pedantic)
pedwarn ("ANSI C forbids nested functions");
push_function_context ();
if (! start_function (current_declspecs, $1, if (! start_function (current_declspecs, $1,
prefix_attributes, NULL_TREE, 1)) prefix_attributes, NULL_TREE, 1))
{ {
pop_c_function_context (); pop_function_context ();
YYERROR1; YYERROR1;
} }
reinit_parse_for_function (); } reinit_parse_for_function (); }
...@@ -1299,7 +1305,7 @@ notype_nested_function: ...@@ -1299,7 +1305,7 @@ notype_nested_function:
which called YYERROR1 again, and so on. */ which called YYERROR1 again, and so on. */
compstmt compstmt
{ finish_function (1); { finish_function (1);
pop_c_function_context (); } pop_function_context (); }
; ;
/* Any kind of declarator (thus, all declarators allowed /* Any kind of declarator (thus, all declarators allowed
......
...@@ -4452,6 +4452,10 @@ rest_of_compilation (decl) ...@@ -4452,6 +4452,10 @@ rest_of_compilation (decl)
init_recog_no_volatile (); init_recog_no_volatile ();
/* We're done with this function. */
if (! DECL_DEFER_OUTPUT (decl))
free_after_compilation (current_function);
/* The parsing time is all the time spent in yyparse /* The parsing time is all the time spent in yyparse
*except* what is spent in this function. */ *except* what is spent in this function. */
......
...@@ -3185,6 +3185,22 @@ init_varasm_status (f) ...@@ -3185,6 +3185,22 @@ init_varasm_status (f)
p->x_pool_offset = 0; p->x_pool_offset = 0;
p->x_const_double_chain = 0; p->x_const_double_chain = 0;
} }
/* Clear out all parts of our state in F that can safely be discarded
after the function has been compiled. */
void
free_varasm_status (f)
struct function *f;
{
struct varasm_status *p = f->varasm;
free (p->x_const_rtx_hash_table);
free (p->x_const_rtx_sym_hash_table);
p->x_first_pool = p->x_last_pool = 0;
p->x_const_rtx_hash_table = 0;
p->x_const_rtx_sym_hash_table = 0;
p->x_const_double_chain = 0;
}
enum kind { RTX_DOUBLE, RTX_INT }; enum kind { RTX_DOUBLE, RTX_INT };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment