GCC Middle and Back End API Reference
|
Data Fields | |
struct nesting_info * | outer |
struct nesting_info * | inner |
struct nesting_info * | next |
hash_map< tree, tree > * | field_map |
hash_map< tree, tree > * | var_map |
hash_set< tree * > * | mem_refs |
bitmap | suppress_expansion |
tree | context |
tree | new_local_var_chain |
tree | debug_var_chain |
tree | frame_type |
tree | frame_decl |
tree | chain_field |
tree | chain_decl |
tree | nl_goto_field |
bool | thunk_p |
bool | any_parm_remapped |
bool | any_tramp_created |
bool | any_descr_created |
char | static_chain_added |
The object of this pass is to lower the representation of a set of nested functions in order to expose all of the gory details of the various nonlocal references. We want to do this sooner rather than later, in order to give us more freedom in emitting all of the functions in question. Back in olden times, when gcc was young, we developed an insanely complicated scheme whereby variables which were referenced nonlocally were forced to live in the stack of the declaring function, and then the nested functions magically discovered where these variables were placed. In order for this scheme to function properly, it required that the outer function be partially expanded, then we switch to compiling the inner function, and once done with those we switch back to compiling the outer function. Such delicate ordering requirements makes it difficult to do whole translation unit optimizations involving such functions. The implementation here is much more direct. Everything that can be referenced by an inner function is a member of an explicitly created structure herein called the "nonlocal frame struct". The incoming static chain for a nested function is a pointer to this struct in the parent. In this way, we settle on known offsets from a known base, and so are decoupled from the logic that places objects in the function's stack frame. More importantly, we don't have to wait for that to happen -- since the compilation of the inner function is no longer tied to a real stack frame, the nonlocal frame struct can be allocated anywhere. Which means that the outer function is now inlinable. Theory of operation here is very simple. Iterate over all the statements in all the functions (depth first) several times, allocating structures and fields on demand. In general we want to examine inner functions first, so that we can avoid making changes to outer functions which are unnecessary. The order of the passes matters a bit, in that later passes will be skipped if it is discovered that the functions don't actually interact at all. That is, they're nested in the lexical sense but could have been written as independent functions without change.
bool nesting_info::any_descr_created |
Referenced by finalize_nesting_tree_1(), and lookup_descr_for_decl().
bool nesting_info::any_parm_remapped |
Referenced by finalize_nesting_tree_1(), and lookup_field_for_decl().
bool nesting_info::any_tramp_created |
Referenced by finalize_nesting_tree_1(), and lookup_tramp_for_decl().
tree nesting_info::chain_decl |
Referenced by convert_all_function_calls(), finalize_nesting_tree_1(), and get_chain_decl().
tree nesting_info::chain_field |
Referenced by convert_all_function_calls(), finalize_nesting_tree_1(), and get_chain_field().
tree nesting_info::context |
Referenced by convert_all_function_calls(), convert_gimple_call(), convert_local_omp_clauses(), convert_local_reference_op(), convert_local_reference_stmt(), convert_nl_goto_reference(), convert_nonlocal_omp_clauses(), convert_nonlocal_reference_op(), convert_nonlocal_reference_stmt(), convert_tramp_reference_op(), create_nesting_tree(), create_tmp_var_for(), finalize_nesting_tree_1(), get_chain_decl(), get_chain_field(), get_frame_field(), get_frame_type(), get_local_debug_decl(), get_nonlocal_debug_decl(), get_static_chain(), lookup_field_for_decl(), note_nonlocal_vla_type(), remap_vla_decls(), and unnest_nesting_tree_1().
tree nesting_info::debug_var_chain |
Referenced by finalize_nesting_tree_1(), get_local_debug_decl(), and get_nonlocal_debug_decl().
Referenced by create_nesting_tree(), free_nesting_tree(), and lookup_field_for_decl().
tree nesting_info::frame_decl |
Referenced by build_init_call_stmt(), convert_gimple_call(), convert_local_reference_op(), convert_local_reference_stmt(), convert_tramp_reference_stmt(), finalize_nesting_tree_1(), get_frame_field(), get_frame_type(), get_local_debug_decl(), get_nonlocal_debug_decl(), get_static_chain(), and lookup_field_for_decl().
tree nesting_info::frame_type |
Referenced by finalize_nesting_tree_1(), and get_frame_type().
struct nesting_info* nesting_info::inner |
Referenced by convert_all_function_calls(), create_nesting_tree(), finalize_nesting_tree_1(), and iter_nestinfo_start().
Referenced by convert_local_reference_op(), create_nesting_tree(), finalize_nesting_tree_1(), and free_nesting_tree().
tree nesting_info::new_local_var_chain |
struct nesting_info* nesting_info::next |
Referenced by finalize_nesting_tree_1(), free_nesting_tree(), and iter_nestinfo_next().
tree nesting_info::nl_goto_field |
Referenced by finalize_nesting_tree_1(), and get_nl_goto_field().
struct nesting_info* nesting_info::outer |
Referenced by convert_all_function_calls(), convert_gimple_call(), convert_nl_goto_reference(), convert_nonlocal_reference_op(), finalize_nesting_tree_1(), get_chain_decl(), get_chain_field(), get_frame_field(), get_nonlocal_debug_decl(), get_static_chain(), iter_nestinfo_next(), and remap_vla_decls().
char nesting_info::static_chain_added |
bitmap nesting_info::suppress_expansion |
bool nesting_info::thunk_p |
Referenced by convert_all_function_calls(), create_nesting_tree(), finalize_nesting_tree_1(), and unnest_nesting_tree_1().