diff options
Diffstat (limited to 'gcc/c-objc-common.c')
-rw-r--r-- | gcc/c-objc-common.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c index be3b847..6554cf5 100644 --- a/gcc/c-objc-common.c +++ b/gcc/c-objc-common.c @@ -31,9 +31,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "diagnostic.h" #include "tree-inline.h" +#include "varray.h" +#include "ggc.h" static int c_tree_printer PARAMS ((output_buffer *)); static tree inline_forbidden_p PARAMS ((tree *, int *, void *)); +static void expand_deferred_fns PARAMS ((void)); +static tree start_cdtor PARAMS ((int)); +static void finish_cdtor PARAMS ((tree)); + +static varray_type deferred_fns; int c_missing_noreturn_ok_p (decl) @@ -227,9 +234,133 @@ c_objc_common_init (filename) mesg_implicit_function_declaration = 0; } + VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns"); + ggc_add_tree_varray_root (&deferred_fns, 1); + return filename; } +/* Register a function tree, so that its optimization and conversion + to RTL is only done at the end of the compilation. */ + +int +defer_fn (fn) + tree fn; +{ + VARRAY_PUSH_TREE (deferred_fns, fn); + + return 1; +} + +/* Expand deferred functions for C and ObjC. */ + +static void +expand_deferred_fns () +{ + unsigned int i; + + for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_fns); i++) + { + tree decl = VARRAY_TREE (deferred_fns, i); + + if (! TREE_ASM_WRITTEN (decl)) + { + /* For static inline functions, delay the decision whether to + emit them or not until wrapup_global_declarations. */ + if (! TREE_PUBLIC (decl)) + DECL_DEFER_OUTPUT (decl) = 1; + c_expand_deferred_function (decl); + } + } + + VARRAY_FREE (deferred_fns); +} + +static tree +start_cdtor (method_type) + int method_type; +{ + tree fnname = get_file_function_name (method_type); + tree void_list_node_1 = build_tree_list (NULL_TREE, void_type_node); + tree body; + + start_function (void_list_node_1, + build_nt (CALL_EXPR, fnname, + tree_cons (NULL_TREE, NULL_TREE, void_list_node_1), + NULL_TREE), + NULL_TREE); + store_parm_decls (); + + current_function_cannot_inline + = "static constructors and destructors cannot be inlined"; + + body = c_begin_compound_stmt (); + + pushlevel (0); + clear_last_expr (); + add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); + + return body; +} + +static void +finish_cdtor (body) + tree body; +{ + tree scope; + tree block; + + scope = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); + block = poplevel (0, 0, 0); + SCOPE_STMT_BLOCK (TREE_PURPOSE (scope)) = block; + SCOPE_STMT_BLOCK (TREE_VALUE (scope)) = block; + + RECHAIN_STMTS (body, COMPOUND_BODY (body)); + + finish_function (0); +} + +/* Called at end of parsing, but before end-of-file processing. */ + +void +c_objc_common_finish_file () +{ + expand_deferred_fns (); + + if (static_ctors) + { + tree body = start_cdtor ('I'); + + for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors)) + c_expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors), + NULL_TREE)); + + finish_cdtor (body); + } + + if (static_dtors) + { + tree body = start_cdtor ('D'); + + for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors)) + c_expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors), + NULL_TREE)); + + finish_cdtor (body); + } + + { + int flags; + FILE *stream = dump_begin (TDI_all, &flags); + + if (stream) + { + dump_node (getdecls (), flags & ~TDF_SLIM, stream); + dump_end (TDI_all, stream); + } + } +} + /* Called during diagnostic message formatting process to print a source-level entity onto BUFFER. The meaning of the format specifiers is as follows: |