/* Output code for start of function; the decl of the function is in PREV_SAVED (as created by tree_code_create_function_prototype), the function is at line number LINENO in file FILENAME. The parameter details are in the lists PARMS. Returns nothing. */ void tree_code_create_function_initial (tree prev_saved, unsigned char* filename, int lineno, struct prod_token_parm_item* parms) { tree fn_decl; tree param_decl; tree next_param; tree first_param; tree parm_decl; tree parm_list; tree resultdecl; struct prod_token_parm_item* this_parm; struct prod_token_parm_item* parm; fn_decl = prev_saved; if (!fn_decl) abort (); /* Output message if not -quiet. */ announce_function (fn_decl); /* This has something to do with forcing output also. */ pushdecl (fn_decl); /* Set current function for error msgs etc. */ current_function_decl = fn_decl; DECL_INITIAL (fn_decl) = error_mark_node; DECL_SOURCE_FILE (fn_decl) = (const char *)filename; DECL_SOURCE_LINE (fn_decl) = lineno; /* Prepare creation of rtl for a new function. */ resultdecl = DECL_RESULT (fn_decl) = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl))); DECL_CONTEXT (DECL_RESULT (fn_decl)) = fn_decl; DECL_SOURCE_FILE (resultdecl) = (const char *)filename; DECL_SOURCE_LINE (resultdecl) = lineno; /* Work out the size. ??? is this needed. */ layout_decl (DECL_RESULT (fn_decl), 0); /* Make the argument variable decls. */ parm_list = NULL_TREE; for (parm = parms; parm; parm = parm->tp.par.next) { parm_decl = build_decl (PARM_DECL, get_identifier ((const char*) (parm->tp.par.variable_name)), get_type_for_numeric_type (parm->type)); /* Some languages have different nominal and real types. */ DECL_ARG_TYPE (parm_decl) = TREE_TYPE (parm_decl); if (!DECL_ARG_TYPE (parm_decl)) abort (); if (!fn_decl) abort (); DECL_CONTEXT (parm_decl) = fn_decl; DECL_SOURCE_FILE (parm_decl) = (const char *)filename; DECL_SOURCE_LINE (parm_decl) = lineno; parm_list = chainon (parm_decl, parm_list); } /* Back into reverse order as the back end likes them. */ parm_list = nreverse (parm_list); DECL_ARGUMENTS (fn_decl) = parm_list; /* Save the decls for use when the args are referred to. */ for (param_decl = DECL_ARGUMENTS (fn_decl), this_parm = parms; param_decl; param_decl = TREE_CHAIN (param_decl), this_parm = this_parm->tp.par.next) { if (!this_parm) abort (); /* Too few. */ *this_parm->tp.par.where_to_put_var_tree = param_decl; } if (this_parm) abort (); /* Too many. */ /* Output the decl rtl (not the rtl for the function code). ???. If the function is not defined in this file, when should you execute this? */ make_decl_rtl (fn_decl, NULL); /* Use filename/lineno from above. */ init_function_start (fn_decl, (const char *)filename, lineno); /* Create rtl for startup code of function, such as saving registers. */ expand_function_start (fn_decl, 0); /* Function.c requires a push at the start of the function. that looks like a bug to me but let's make it happy. */ (*lang_hooks.decls.pushlevel) (0); /* Create rtl for the start of a new scope. */ expand_start_bindings (2); /* Put the parameters into the symbol table. */ for (first_param = param_decl = nreverse (DECL_ARGUMENTS (fn_decl)); param_decl; param_decl = next_param) { next_param = TREE_CHAIN (param_decl); TREE_CHAIN (param_decl) = NULL; /* layout_decl (param_decl, 0); Already done in build_decl tej 13/4/2002. */ pushdecl (param_decl); if (DECL_CONTEXT (param_decl) != current_function_decl) abort (); } /* Store back the PARM_DECL nodes. They appear in the right order. */ DECL_ARGUMENTS (fn_decl) = getdecls (); /* Force it to be output, else may be solely inlined. */ TREE_ADDRESSABLE (fn_decl) = 1; /* Stop -O3 from deleting it. */ TREE_USED (fn_decl) = 1; /* Add a new level to the debugger symbol table. */ (*lang_hooks.decls.pushlevel) (0); /* Create rtl for the start of a new scope. */ expand_start_bindings (0); emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ }
static void tree_expand_cfg (void) { basic_block bb, init_block; sbitmap blocks; /* Some backends want to know that we are expanding to RTL. */ currently_expanding_to_rtl = 1; /* Prepare the rtl middle end to start recording block changes. */ reset_block_changes (); /* Expand the variables recorded during gimple lowering. */ expand_used_vars (); #ifdef KEY // Run expand_used_vars above to set DECL_SECTION_NAME. Bug 10876. if (flag_spin_file) return; #endif /* Set up parameters and prepare for return, for the function. */ expand_function_start (current_function_decl); /* If this function is `main', emit a call to `__main' to run global initializers, etc. */ if (DECL_NAME (current_function_decl) && MAIN_NAME_P (DECL_NAME (current_function_decl)) && DECL_FILE_SCOPE_P (current_function_decl)) expand_main_function (); /* Register rtl specific functions for cfg. */ rtl_register_cfg_hooks (); init_block = construct_init_block (); FOR_BB_BETWEEN (bb, init_block->next_bb, EXIT_BLOCK_PTR, next_bb) bb = expand_gimple_basic_block (bb, dump_file); construct_exit_block (); /* We're done expanding trees to RTL. */ currently_expanding_to_rtl = 0; /* Convert tree EH labels to RTL EH labels, and clean out any unreachable EH regions. */ convert_from_eh_region_ranges (); rebuild_jump_labels (get_insns ()); find_exception_handler_labels (); blocks = sbitmap_alloc (last_basic_block); sbitmap_ones (blocks); find_many_sub_basic_blocks (blocks); purge_all_dead_edges (0); sbitmap_free (blocks); compact_blocks (); #ifdef ENABLE_CHECKING verify_flow_info(); #endif /* There's no need to defer outputting this function any more; we know we want to output it. */ DECL_DEFER_OUTPUT (current_function_decl) = 0; /* Now that we're done expanding trees to RTL, we shouldn't have any more CONCATs anywhere. */ generating_concat_p = 0; finalize_block_changes (); if (dump_file) { fprintf (dump_file, "\n\n;;\n;; Full RTL generated for this function:\n;;\n"); /* And the pass manager will dump RTL for us. */ } }
void write_resource_constructor (void) { tree init_name, init_type, init_decl; tree iter; location_t saved_loc = input_location; char *resource_ctor_name; /* Only do work if required. */ if (resources == NULL_TREE) return; resource_ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')), "_resource", NULL); init_name = get_identifier (resource_ctor_name); free (resource_ctor_name); init_type = build_function_type (void_type_node, end_params_node); init_decl = build_decl (FUNCTION_DECL, init_name, init_type); DECL_SOURCE_LINE (init_decl) = 0; SET_DECL_ASSEMBLER_NAME (init_decl, init_name); TREE_STATIC (init_decl) = 1; current_function_decl = init_decl; DECL_RESULT (init_decl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node); /* It can be a static function as long as collect2 does not have to scan the object file to find its ctor/dtor routine. */ TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors; pushlevel (0); make_decl_rtl (init_decl, NULL); init_function_start (init_decl); expand_function_start (init_decl, 0); /* Write out entries in the same order in which they were defined. */ for (iter = nreverse (resources); iter != NULL_TREE; iter = TREE_CHAIN (iter)) { emit_library_call (registerResource_libfunc, 0, VOIDmode, 1, expand_expr (build_address_of (TREE_VALUE (iter)), 0, Pmode, 0), Pmode); } input_location = DECL_SOURCE_LOCATION (init_decl); expand_function_end (); poplevel (1, 0, 1); { /* Force generation, even with -O3 or deeper. Gross hack. FIXME. */ int saved_flag = flag_inline_functions; flag_inline_functions = 0; rest_of_compilation (init_decl); flag_inline_functions = saved_flag; } current_function_decl = NULL_TREE; (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0), DEFAULT_INIT_PRIORITY); input_location = saved_loc; }