This patch applies the rule that functions defined in FOO.c must be declared in FOO.h. One of the worst offenders in the code base is tree.h, unsurprisingly. The patch creates several new headers: attribs.h calls.h fold-const.h gcc-symtab.h print-rtl.h print-tree.h stmt.h stor-layout.h stringpool.h tree-nested.h tree-object-size.h varasm.h. Functions in each corresponding .c file got moved to those headers and others that already existed. I wanted to make this patch as mechanical as possible, so I made no attempt to fix problems like having build_addr defined in tree-inline.c. I left that for later. There were some declarations that I could not move out of tree.h because of header poisoning or the use of target macros. We forbid the inclusion of things like expr.h from FE files. While that's a reasonable idea, the FE file *still* manage to at expr.c functionality because the declarations they want to use were defined in tree.h. The affected files are builtins.h, emit-rtl.h and expr.h. If that functionality is allowed to be accessed from the FEs, then I will later move those functions out of expr.c into tree.c. I have moved these declarations to the bottom of tree.h so they are easy to identify later. There is a namespace collision with libcpp. The file gcc/symtab.c cannot use gcc/symtab.h because the #include command picks up libcpp/include/symtab.h first. So I named this file gcc-symtab.h for now. Finally, I added a new header to PLUGIN_HEADERS to account for the tree.h refactoring. I did not add all headers factored out of tree.h because it is unclear (and impossible to tell) what plugins need. This adds the one header used by the plugins in the testsuite. This will be changing quite dramatically as we progress with the header refactoring. This patch should offer some minimal incremental build advantages by reducing the size of tree.h. Changes that would otherwise affected tree.h, will now go to other headers which are less frequently included. * tree.h: Include fold-const.h. (aggregate_value_p): Moved to function.h. (alloca_call_p): Moved to calls.h. (allocate_struct_function): Moved to function.h. (apply_tm_attr): Moved to attribs.h. (array_at_struct_end_p): Moved to expr.h. (array_ref_element_size): Moved to tree-dfa.h. (array_ref_low_bound): Moved to tree-dfa.h. (array_ref_up_bound): Moved to tree.h. (assemble_alias): Moved to cgraph.h. (bit_from_pos): Moved to stor-layout.h. (build_addr): Moved to tree-nested.h. (build_duplicate_type): Moved to tree-inline.h. (build_fold_addr_expr): Moved to fold-const.h. (build_fold_addr_expr_with_type): Moved to fold-const.h. (build_fold_addr_expr_with_type_loc): Moved to fold-const.h. (build_fold_indirect_ref): Moved to fold-const.h. (build_fold_indirect_ref_loc): Moved to fold-const.h. (build_personality_function): Moved to tree.h. (build_range_check): Moved to fold-const.h. (build_simple_mem_ref): Moved to fold-const.h. (build_simple_mem_ref_loc): Moved to fold-const.h. (build_tm_abort_call): Moved to trans-mem.h. (byte_from_pos): Moved to stor-layout.h. (call_expr_flags): Moved to calls.h. (can_move_by_pieces): Moved to expr.h. (categorize_ctor_elements): Moved to expr.h. (change_decl_assembler_name): Moved to gcc-symtab.h. (combine_comparisons): Moved to fold-const.h. (complete_ctor_at_level_p): Moved to tree.h. (component_ref_field_offset): Moved to tree-dfa.h. (compute_builtin_object_size): Moved to tree-object-size.h. (compute_record_mode): Moved to stor-layout.h. (constant_boolean_node): Moved to fold-const.h. (constructor_static_from_elts_p): Moved to varasm.h. (cxx11_attribute_p): Moved to attribs.h. (debug_body): Moved to print-tree.h. (debug_find_tree): Moved to tree-inline.h. (debug_fold_checksum): Moved to fold-const.h. (debug_head): Moved to print-tree.h. (debug_head): Moved to print-tree.h. (debug_raw): Moved to print-tree.h. (debug_tree): Moved to print-tree.h. (debug_vec_tree): Moved to print-tree.h. (debug_verbose): Moved to print-tree.h. (debug_verbose): Moved to print-tree.h. (decl_attributes): Moved to attribs.h. (decl_binds_to_current_def_p): Moved to varasm.h. (decl_default_tls_model): Moved to varasm.h. (decl_replaceable_p): Moved to varasm.h. (div_if_zero_remainder): Moved to fold-const.h. (double_int mem_ref_offset): Moved to fold-const.h. (dump_addr): Moved to print-tree.h. (element_precision): Moved to machmode.h. (expand_dummy_function_end): Moved to function.h. (expand_function_end): Moved to function.h. (expand_function_start): Moved to function.h. (expand_label): Moved to stmt.h. (expr_first): Moved to tree-iterator.h. (expr_last): Moved to tree-iterator.h. (finalize_size_functions): Moved to stor-layout.h. (finish_builtin_struct): Moved to stor-layout.h. (finish_record_layout): Moved to stor-layout.h. (fixup_signed_type): Moved to stor-layout.h. (fixup_unsigned_type): Moved to stor-layout.h. (flags_from_decl_or_type): Moved to calls.h. (fold): Moved to fold-const.h. (fold_abs_const): Moved to fold-const.h. (fold_binary): Moved to fold-const.h. (fold_binary_loc): Moved to fold-const.h. (fold_binary_to_constant): Moved to fold-const.h. (fold_build1): Moved to fold-const.h. (fold_build1_initializer_loc): Moved to fold-const.h. (fold_build1_loc): Moved to fold-const.h. (fold_build1_stat_loc): Moved to fold-const.h. (fold_build2): Moved to fold-const.h. (fold_build2_initializer_loc): Moved to fold-const.h. (fold_build2_loc): Moved to fold-const.h. (fold_build2_stat_loc): Moved to fold-const.h. (fold_build3): Moved to fold-const.h. (fold_build3_loc): Moved to fold-const.h. (fold_build3_stat_loc): Moved to fold-const.h. (fold_build_call_array): Moved to fold-const.h. (fold_build_call_array_initializer): Moved to fold-const.h. (fold_build_call_array_initializer_loc): Moved to fold-const.h. (fold_build_call_array_loc): Moved to fold-const.h. (fold_build_cleanup_point_expr): Moved to fold-const.h. (fold_convert): Moved to fold-const.h. (fold_convert_loc): Moved to fold-const.h. (fold_convertible_p): Moved to fold-const.h. (fold_defer_overflow_warnings): Moved to fold-const.h. (fold_deferring_overflow_warnings_p): Moved to fold-const.h. (fold_fma): Moved to fold-const.h. (fold_ignored_result): Moved to fold-const.h. (fold_indirect_ref): Moved to fold-const.h. (fold_indirect_ref_1): Moved to fold-const.h. (fold_indirect_ref_loc): Moved to fold-const.h. (fold_read_from_constant_string): Moved to fold-const.h. (fold_real_zero_addition_p): Moved to fold-const.h. (fold_single_bit_test): Moved to fold-const.h. (fold_strip_sign_ops): Moved to fold-const.h. (fold_ternary): Moved to fold-const.h. (fold_ternary_loc): Moved to fold-const.h. (fold_unary): Moved to tree-data-ref.h. (fold_unary_ignore_overflow): Moved to fold-const.h. (fold_unary_ignore_overflow_loc): Moved to fold-const.h. (fold_unary_loc): Moved to fold-const.h. (fold_unary_to_constant): Moved to fold-const.h. (fold_undefer_and_ignore_overflow_warnings): Moved to fold-const.h. (fold_undefer_overflow_warnings): Moved to fold-const.h. (folding_initializer): Moved to fold-const.h. (free_temp_slots): Moved to function.h. (generate_setjmp_warnings): Moved to function.h. (get_attribute_name): Moved to attribs.h. (get_identifier): Moved to stringpool.h. (get_identifier_with_length): Moved to stringpool.h. (get_inner_reference): Moved to tree.h. (gimple_alloca_call_p): Moved to calls.h. (gimplify_parameters): Moved to function.h. (highest_pow2_factor): Moved to expr.h. (indent_to): Moved to print-tree.h. (init_attributes): Moved to attribs.h. (init_dummy_function_start): Moved to function.h. (init_function_start): Moved to function.h. (init_inline_once): Moved to tree-inline.h. (init_object_sizes): Moved to tree-object-size.h. (init_temp_slots): Moved to function.h. (init_tree_optimization_optabs): Moved to optabs.h. (initialize_sizetypes): Moved to stor-layout.h. (initializer_constant_valid_for_bitfield_p): Moved to varasm.h. (initializer_constant_valid_p): Moved to varasm.h. (int_const_binop): Moved to fold-const.h. (internal_reference_types): Moved to stor-layout.h. (invert_tree_comparison): Moved to fold-const.h. (invert_truthvalue): Moved to fold-const.h. (invert_truthvalue_loc): Moved to fold-const.h. (is_tm_ending_fndecl): Moved to trans-mem.h. (is_tm_may_cancel_outer): Moved to trans-mem.h. (is_tm_pure): Moved to trans-mem.h. (is_tm_safe): Moved to trans-mem.h. (layout_decl): Moved to stor-layout.h. (layout_type): Moved to stor-layout.h. (lookup_attribute_spec): Moved to attribs.h. (make_accum_type): Moved to stor-layout.h. (make_decl_one_only): Moved to varasm.h. (make_decl_rtl): Moved to tree.h. (make_decl_rtl_for_debug): Moved to varasm.h. (make_fract_type): Moved to stor-layout.h. (make_or_reuse_sat_signed_accum_type): Moved to stor-layout.h. (make_or_reuse_sat_signed_fract_type): Moved to stor-layout.h. (make_or_reuse_sat_unsigned_accum_type): Moved to stor-layout.h. (make_or_reuse_sat_unsigned_fract_type): Moved to stor-layout.h. (make_or_reuse_signed_accum_type): Moved to stor-layout.h. (make_or_reuse_signed_fract_type): Moved to stor-layout.h. (make_or_reuse_unsigned_accum_type): Moved to stor-layout.h. (make_or_reuse_unsigned_fract_type): Moved to stor-layout.h. (make_range): Moved to fold-const.h. (make_range_step): Moved to fold-const.h. (make_sat_signed_accum_type): Moved to stor-layout.h. (make_sat_signed_fract_type): Moved to stor-layout.h. (make_sat_unsigned_accum_type): Moved to stor-layout.h. (make_sat_unsigned_fract_type): Moved to stor-layout.h. (make_signed_accum_type): Moved to stor-layout.h. (make_signed_fract_type): Moved to stor-layout.h. (make_signed_type): Moved to stor-layout.h. (make_unsigned_accum_type): Moved to stor-layout.h. (make_unsigned_fract_type): Moved to stor-layout.h. (make_unsigned_type): Moved to stor-layout.h. (mark_decl_referenced): Moved to varasm.h. (mark_referenced): Moved to varasm.h. (may_negate_without_overflow_p): Moved to fold-const.h. (maybe_get_identifier): Moved to stringpool.h. (merge_ranges): Moved to fold-const.h. (merge_weak): Moved to varasm.h. (mode_for_size_tree): Moved to stor-layout.h. (multiple_of_p): Moved to fold-const.h. (must_pass_in_stack_var_size): Moved to calls.h. (must_pass_in_stack_var_size_or_pad): Moved to calls.h. (native_encode_expr): Moved to fold-const.h. (native_interpret_expr): Moved to fold-const.h. (non_lvalue): Moved to fold-const.h. (non_lvalue_loc): Moved to fold-const.h. (normalize_offset): Moved to stor-layout.h. (normalize_rli): Moved to stor-layout.h. (notice_global_symbol): Moved to varasm.h. (omit_one_operand): Moved to fold-const.h. (omit_one_operand_loc): Moved to fold-const.h. (omit_two_operands): Moved to fold-const.h. (omit_two_operands_loc): Moved to fold-const.h. (operand_equal_p): Moved to tree-data-ref.h. (parse_input_constraint): Moved to stmt.h. (parse_output_constraint): Moved to stmt.h. (place_field): Moved to stor-layout.h. (pop_function_context): Moved to function.h. (pop_temp_slots): Moved to function.h. (pos_from_bit): Moved to stor-layout.h. (preserve_temp_slots): Moved to function.h. (print_node): Moved to print-tree.h. (print_node_brief): Moved to print-tree.h. (print_rtl): Moved to rtl.h. (process_pending_assemble_externals): Moved to varasm.h. (ptr_difference_const): Moved to fold-const.h. (push_function_context): Moved to function.h. (push_struct_function): Moved to function.h. (push_temp_slots): Moved to function.h. (record_tm_replacement): Moved to trans-mem.h. (relayout_decl): Moved to stor-layout.h. (resolve_asm_operand_names): Moved to stmt.h. (resolve_unique_section): Moved to varasm.h. (rli_size_so_far): Moved to stor-layout.h. (rli_size_unit_so_far): Moved to stor-layout.h. (round_down): Moved to fold-const.h. (round_down_loc): Moved to fold-const.h. (round_up): Moved to fold-const.h. (round_up_loc): Moved to fold-const.h. (set_decl_incoming_rtl): Moved to emit-rtl.h. (set_decl_rtl): Moved to tree.h. (set_min_and_max_values_for_integral_type): Moved to stor-layout.h. (set_user_assembler_name): Moved to varasm.h. (setjmp_call_p): Moved to calls.h. (size_binop): Moved to fold-const.h. (size_binop_loc): Moved to fold-const.h. (size_diffop): Moved to fold-const.h. (size_diffop_loc): Moved to fold-const.h. (size_int_kind): Moved to fold-const.h. (stack_protect_epilogue): Moved to function.h. (start_record_layout): Moved to stor-layout.h. (supports_one_only): Moved to varasm.h. (swap_tree_comparison): Moved to fold-const.h. (tm_malloc_replacement): Moved to trans-mem.h. (tree build_fold_addr_expr_loc): Moved to fold-const.h. (tree build_invariant_address): Moved to fold-const.h. (tree_binary_nonnegative_warnv_p): Moved to fold-const.h. (tree_binary_nonzero_warnv_p): Moved to fold-const.h. (tree_call_nonnegative_warnv_p): Moved to fold-const.h. (tree_expr_nonnegative_p): Moved to fold-const.h. (tree_expr_nonnegative_warnv_p): Moved to fold-const.h. (tree_output_constant_def): Moved to varasm.h. (tree_overlaps_hard_reg_set): Moved to stmt.h. (tree_single_nonnegative_warnv_p): Moved to fold-const.h. (tree_single_nonzero_warnv_p): Moved to fold-const.h. (tree_swap_operands_p): Moved to fold-const.h. (tree_unary_nonnegative_warnv_p): Moved to fold-const.h. (tree_unary_nonzero_warnv_p): Moved to fold-const.h. (update_alignment_for_field): Moved to stor-layout.h. (use_register_for_decl): Moved to function.h. (variable_size): Moved to rtl.h. (vector_type_mode): Moved to stor-layout.h. * cgraph.h: Corresponding changes. * emit-rtl.h: Corresponding changes. * expr.h: Corresponding changes. * function.h: Corresponding changes. * optabs.h: Corresponding changes. * trans-mem.h: Corresponding changes. Protect against multiple inclusion. * tree-inline.h: Corresponding changes. * tree-iterator.h: Corresponding changes. * tree-dfa.h: Include expr.h. * tree-ssanames.h: Include stringpool.h. * attribs.h: New file. * calls.h: New file. * fold-const.h: New file. * gcc-symtab.h: New file. * print-rtl.h: New file. * print-tree.h: New file. * stmt.h: New file. * stor-layout.h: New file. * strinpool.h: New file. * tree-nested.h: New file * tree-object-size.h: New file. * varasm.h: New file. * Makefile.in (PLUGIN_HEADERS): Add stringpool.h. * alias.c: Include varasm.h. Include expr.h. * asan.c: Include calls.h. Include stor-layout.h. Include varasm.h. * attribs.c: Include stringpool.h. Include attribs.h. Include stor-layout.h. * builtins.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. Include tree-object-size.h. * calls.c: Include stor-layout.h. Include varasm.h. Include stringpool.h. Include attribs.h. * cfgexpand.c: Include stringpool.h. Include varasm.h. Include stor-layout.h. Include stmt.h. Include print-tree.h. * cgraph.c: Include varasm.h. Include calls.h. Include print-tree.h. * cgraphclones.c: Include stringpool.h. Include function.h. Include emit-rtl.h. Move inclusion of rtl.h earlier in the file. * cgraphunit.c: Include varasm.h. Include stor-layout.h. Include stringpool.h. * cilk-common.c: Include stringpool.h. Include stor-layout.h. * combine.c: Include stor-layout.h. * config/aarch64/aarch64-builtins.c: Include stor-layout.h. Include stringpool.h. Include calls.h. * config/aarch64/aarch64.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * config/alpha/alpha.c: Include stor-layout.h. Include calls.h. Include varasm.h. * config/arc/arc.c: Include varasm.h. Include stor-layout.h. Include stringpool.h. Include calls.h. * config/arm/arm.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * config/avr/avr-c.c: Include stor-layout.h. * config/avr/avr-log.c: Include print-tree.h. * config/avr/avr.c: Include print-tree.h. Include calls.h. Include stor-layout.h. Include stringpool.h. * config/bfin/bfin.c: Include varasm.h. Include calls.h. * config/c6x/c6x.c: Include stor-layout.h. Include varasm.h. Include calls.h. Include stringpool.h. * config/cr16/cr16.c: Include stor-layout.h. Include calls.h. * config/cris/cris.c: Include varasm.h. Include stor-layout.h. Include calls.h. Include stmt.h. * config/darwin.c: Include stringpool.h. Include varasm.h. Include stor-layout.h. * config/epiphany/epiphany.c: Include stor-layout.h. Include varasm.h. Include calls.h. Include stringpool.h. * config/fr30/fr30.c: Include stor-layout.h. Include varasm.h. * config/frv/frv.c: Include varasm.h. Include stor-layout.h. Include stringpool.h. * config/h8300/h8300.c: Include stor-layout.h. Include varasm.h. Include calls.h. Include stringpool.h. * config/i386/i386.c: Include stringpool.h. Include attribs.h. Include calls.h. Include stor-layout.h. Include varasm.h. * config/i386/winnt-cxx.c: Include stringpool.h. Include attribs.h. * config/i386/winnt.c: Include stringpool.h. Include varasm.h. * config/ia64/ia64-c.c: Include stringpool.h. * config/ia64/ia64.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * config/iq2000/iq2000.c: Include stor-layout.h. Include calls.h. Include varasm.h. * config/lm32/lm32.c: Include calls.h. * config/m32c/m32c.c: Include stor-layout.h. Include varasm.h. Include calls.h. * config/m32r/m32r.c: Include stor-layout.h. Include varasm.h. Include stringpool.h. Include calls.h. * config/m68k/m68k.c: Include calls.h. Include stor-layout.h. Include varasm.h. * config/mcore/mcore.c: Include stor-layout.h. Include varasm.h. Include stringpool.h. Include calls.h. * config/mep/mep.c: Include varasm.h. Include calls.h. Include stringpool.h. Include stor-layout.h. * config/microblaze/microblaze.c: Include varasm.h. Include stor-layout.h. Include calls.h. * config/mips/mips.c: Include varasm.h. Include stringpool.h. Include stor-layout.h. Include calls.h. * config/mmix/mmix.c: Include varasm.h. Include stor-layout.h. Include calls.h. * config/mn10300/mn10300.c: Include stor-layout.h. Include varasm.h. Include calls.h. * config/moxie/moxie.c: Include stor-layout.h. Include varasm.h. Include calls.h. * config/msp430/msp430.c: Include stor-layout.h. Include calls.h. * config/nds32/nds32.c: Include stor-layout.h. Include varasm.h. Include calls.h. * config/pa/pa.c: Include stor-layout.h. Include stringpool.h. Include varasm.h. Include calls.h. * config/pdp11/pdp11.c: Include stor-layout.h. Include varasm.h. Include calls.h. * config/picochip/picochip.c: Include calls.h. Include stor-layout.h. Include stringpool.h. Include varasm.h. * config/rl78/rl78.c: Include varasm.h. Include stor-layout.h. Include calls.h. * config/rs6000/rs6000-c.c: Include stor-layout.h. Include stringpool.h. * config/rs6000/rs6000.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include print-tree.h. Include varasm.h. * config/rx/rx.c: Include varasm.h. Include stor-layout.h. Include calls.h. * config/s390/s390.c: Include print-tree.h. Include stringpool.h. Include stor-layout.h. Include varasm.h. Include calls.h. * config/score/score.c: Include stringpool.h. Include calls.h. Include varasm.h. Include stor-layout.h. * config/sh/sh-c.c: Include stringpool.h. Include attribs.h.h. * config/sh/sh.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * config/sol2-c.c: Include stringpool.h. Include attribs.h. * config/sol2-cxx.c: Include stringpool.h. * config/sol2.c: Include stringpool.h. Include varasm.h. * config/sparc/sparc.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * config/spu/spu-c.c: Include stringpool.h. * config/spu/spu.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * config/stormy16/stormy16.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. Include calls.h. * config/tilegx/tilegx.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. Include calls.h. * config/tilepro/tilepro.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. Include calls.h. * config/v850/v850-c.c: Include stringpool.h. Include attribs.h. * config/v850/v850.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. Include calls.h. * config/vax/vax.c: Include calls.h. Include varasm.h. * config/vms/vms.c: Include stringpool.h. * config/vxworks.c: Include stringpool.h. * config/xtensa/xtensa.c: Include stringpool.h. Include stor-layout.h. Include calls.h. Include varasm.h. * convert.c: Include stor-layout.h. * coverage.c: Include stringpool.h. Include stor-layout.h. * dbxout.c: Include varasm.h. Include stor-layout.h. * dojump.c: Include stor-layout.h. * dse.c: Include stor-layout.h. * dwarf2asm.c: Include stringpool.h. Include varasm.h. * dwarf2cfi.c: Include stor-layout.h. * dwarf2out.c: Include rtl.h. Include stringpool.h. Include stor-layout.h. Include varasm.h. Include function.h. Include emit-rtl.h. Move inclusion of rtl.h earlier in the file. * emit-rtl.c: Include varasm.h. * except.c: Include stringpool.h. Include stor-layout.h. * explow.c: Include stor-layout.h. * expmed.c: Include stor-layout.h. * expr.c: Include stringpool.h. Include stor-layout.h. Include attribs.h. Include varasm.h. * final.c: Include varasm.h. * fold-const.c: Include stor-layout.h. Include calls.h. Include tree-iterator.h. * function.c: Include stor-layout.h. Include varasm.h. Include stringpool.h. * genattrtab.c (write_header): Emit includes for varasm.h, stor-layout.h and calls.h. * genautomata.c (main): Likewise. * genemit.c: Likewise. * genopinit.c: Likewise. * genoutput.c (output_prologue): Likewise. * genpeep.c: Likewise. * genpreds.c (write_insn_preds_c): Likewise. * gengtype.c (open_base_files): Add stringpool.h. * gimple-expr.c: Include stringpool.h. Include stor-layout.h. * gimple-fold.c: Include stringpool.h. Include expr.h. Include stmt.h. Include stor-layout.h. * gimple-low.c: Include tree-nested.h. Include calls.h. * gimple-pretty-print.c: Include stringpool.h. * gimple-ssa-strength-reduction.c: Include stor-layout.h. Include expr.h. * gimple-walk.c: Include stmt.h. * gimple.c: Include calls.h. Include stmt.h. Include stor-layout.h. * gimplify.c: Include stringpool.h. Include calls.h. Include varasm.h. Include stor-layout.h. Include stmt.h. Include print-tree.h. Include expr.h. * gimplify-me.c: Include stmt.h Include stor-layout.h * internal-fn.c: Include stor-layout.h. * ipa-devirt.c: Include print-tree.h. Include calls.h. * ipa-inline-analysis.c: Include stor-layout.h. Include stringpool.h. Include print-tree.h. * ipa-inline.c: Include trans-mem.h. Include calls.h. * ipa-prop.c: Include expr.h. Include stor-layout.h. Include print-tree.h. * ipa-pure-const.c: Include print-tree.h. Include calls.h. * ipa-reference.c: Include calls.h. * ipa-split.c: Include stringpool.h. Include expr.h. Include calls.h. * ipa.c: Include calls.h. Include stringpool.h. * langhooks.c: Include stringpool.h. Include attribs.h. * lto-cgraph.c: Include stringpool.h. * lto-streamer-in.c: Include stringpool.h. * lto-streamer-out.c: Include stor-layout.h. Include stringpool.h. * omp-low.c: Include stringpool.h. Include stor-layout.h. Include expr.h. * optabs.c: Include stor-layout.h. Include stringpool.h. Include varasm.h. * passes.c: Include varasm.h. * predict.c: Include calls.h. * print-rtl.c: Include print-tree.h. * print-tree.c: Include varasm.h. Include print-rtl.h. Include stor-layout.h. * realmpfr.c: Include stor-layout.h. * reg-stack.c: Include varasm.h. * sdbout.c: Include varasm.h. Include stor-layout.h. * simplify-rtx.c: Include varasm.h. * stmt.c: Include varasm.h. Include stor-layout.h. * stor-layout.c: Include stor-layout.h. Include stringpool.h. Include varasm.h. Include print-tree.h. * symtab.c: Include rtl.h. Include print-tree.h. Include varasm.h. Include function.h. Include emit-rtl.h. * targhooks.c: Include stor-layout.h. Include varasm.h. * toplev.c: Include varasm.h. Include tree-inline.h. * trans-mem.c: Include calls.h. Include function.h. Include rtl.h. Include emit-rtl.h. * tree-affine.c: Include expr.h. * tree-browser.c: Include print-tree.h. * tree-call-cdce.c: Include stor-layout.h. * tree-cfg.c: Include trans-mem.h. Include stor-layout.h. Include print-tree.h. * tree-complex.c: Include stor-layout.h. * tree-data-ref.c: Include expr.h. * tree-dfa.c: Include stor-layout.h. * tree-eh.c: Include expr.h. Include calls.h. * tree-emutls.c: Include stor-layout.h. Include varasm.h. * tree-if-conv.c: Include stor-layout.h. * tree-inline.c: Include stor-layout.h. Include calls.h. * tree-loop-distribution.c: Include stor-layout.h. * tree-nested.c: Include stringpool.h. Include stor-layout.h. * tree-object-size.c: Include tree-object-size.h. * tree-outof-ssa.c: Include stor-layout.h. * tree-parloops.c: Include stor-layout.h. Include tree-nested.h. * tree-pretty-print.c: Include stor-layout.h. Include expr.h. * tree-profile.c: Include varasm.h. Include tree-nested.h. * tree-scalar-evolution.c: Include expr.h. * tree-sra.c: Include stor-layout.h. * tree-ssa-address.c: Include stor-layout.h. * tree-ssa-ccp.c: Include stor-layout.h. * tree-ssa-dce.c: Include calls.h. * tree-ssa-dom.c: Include stor-layout.h. * tree-ssa-forwprop.c: Include stor-layout.h. * tree-ssa-ifcombine.c: Include stor-layout.h. * tree-ssa-loop-ivopts.c: Include stor-layout.h. * tree-ssa-loop-niter.c: Include calls.h. Include expr.h. * tree-ssa-loop-prefetch.c: Include stor-layout.h. * tree-ssa-math-opts.c: Include stor-layout.h. * tree-ssa-operands.c: Include stmt.h. Include print-tree.h. * tree-ssa-phiopt.c: Include stor-layout.h. * tree-ssa-reassoc.c: Include stor-layout.h. * tree-ssa-sccvn.c: Include stor-layout.h. * tree-ssa-sink.c: Include stor-layout.h. * tree-ssa-strlen.c: Include stor-layout.h. * tree-ssa-structalias.c: Include stor-layout.h. Include stmt.h. * tree-ssa-tail-merge.c: Include stor-layout.h. Include trans-mem.h. * tree-ssa-uncprop.c: Include stor-layout.h. * tree-ssa.c: Include stor-layout.h. * tree-ssanames.c: Include stor-layout.h. * tree-streamer-in.c: Include stringpool.h. * tree-streamer-out.c: Include stor-layout.h. * tree-switch-conversion.c: Include varasm.h. Include stor-layout.h. * tree-tailcall.c: Include stor-layout.h. * tree-vect-data-refs.c: Include stor-layout.h. * tree-vect-generic.c: Include stor-layout.h. * tree-vect-loop.c: Include stor-layout.h. * tree-vect-patterns.c: Include stor-layout.h. * tree-vect-slp.c: Include stor-layout.h. * tree-vect-stmts.c: Include stor-layout.h. * tree-vectorizer.c: Include stor-layout.h. * tree-vrp.c: Include stor-layout.h. Include calls.h. * tree.c: Include stor-layout.h. Include calls.h. Include attribs.h. Include varasm.h. * tsan.c: Include expr.h. * ubsan.c: Include stor-layout.h. Include stringpool.h. * value-prof.c: Include tree-nested.h. Include calls.h. * var-tracking.c: Include varasm.h. Include stor-layout.h. * varasm.c: Include stor-layout.h. Include stringpool.h. Include gcc-symtab.h. Include varasm.h. * varpool.c: Include varasm.h. * vmsdbgout.c: Include varasm.h. * xcoffout.c: Include varasm.h. ada/ChangeLog * gcc-interface/decl.c: Include stringpool.h Include stor-layout.h * gcc-interface/misc.c: Include stor-layout.h Include print-tree.h * gcc-interface/trans.c: Include stringpool.h Include stor-layout.h Include stmt.h Include varasm.h * gcc-interface/utils.c: Include stringpool.h Include stor-layout.h Include attribs.h Include varasm.h * gcc-interface/utils2.c: Include stringpool.h Include stor-layout.h Include attribs.h Include varasm.h c-family/ChangeLog * c-common.c: Include fold-const.h. Include stor-layout.h. Include calls.h. Include stringpool.h. Include attribs.h. Include varasm.h. Include trans-mem.h. * c-cppbuiltin.c: Include stor-layout.h. Include stringpool.h. * c-format.c: Include stringpool.h. * c-lex.c: Include stringpool.h. Include stor-layout.h. * c-pragma.c: Include stringpool.h. Include attribs.h. Include varasm.h. Include gcc-symtab.h. * c-pretty-print.c: Include stor-layout.h. Include attribs.h. * cilk.c: Include stringpool.h. Include calls.h. c/ChangeLog * c-decl.c: Include print-tree.h. Include stor-layout.h. Include varasm.h. Include attribs.h. Include stringpool.h. * c-lang.c: Include fold-const.h. * c-parser.c: Include stringpool.h. Include attribs.h. Include stor-layout.h. Include varasm.h. Include trans-mem.h. * c-typeck.c: Include stor-layout.h. Include trans-mem.h. Include varasm.h. Include stmt.h. cp/ChangeLog * call.c: Include stor-layout.h. Include trans-mem.h. Include stringpool.h. * class.c: Include stringpool.h. Include stor-layout.h. Include attribs.h. * cp-gimplify.c: Include stor-layout.h. * cvt.c: Include stor-layout.h. * decl.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. Include attribs.h. Include calls.h. * decl2.c: Include stringpool.h. Include varasm.h. Include attribs.h. Include stor-layout.h. Include calls.h. * error.c: Include stringpool.h. * except.c: Include stringpool.h. Include trans-mem.h. Include attribs.h. * init.c: Include stringpool.h. Include varasm.h. * lambda.c: Include stringpool.h. * lex.c: Include stringpool.h. * mangle.c: Include stor-layout.h. Include stringpool.h. * method.c: Include stringpool.h. Include varasm.h. * name-lookup.c: Include stringpool.h. Include print-tree.h. Include attribs.h. * optimize.c: Include stringpool.h. * parser.c: Include print-tree.h. Include stringpool.h. Include attribs.h. Include trans-mem.h. * pt.c: Include stringpool.h. Include varasm.h. Include attribs.h. Include stor-layout.h. * ptree.c: Include print-tree.h. * repo.c: Include stringpool.h. * rtti.c: Include stringpool.h. Include stor-layout.h. * semantics.c: Include stmt.h. Include varasm.h. Include stor-layout.h. Include stringpool.h. * tree.c: Include stor-layout.h. Include print-tree.h. Include tree-iterator.h. * typeck.c: Include stor-layout.h. Include varasm.h. * typeck2.c: Include stor-layout.h. Include varasm.h. * vtable-class-hierarchy.c: Include stringpool.h. Include stor-layout.h. fortran/ChangeLog * decl.c: Include stringpool.h. * iresolve.c: Include stringpool.h. * match.c: Include stringpool.h. * module.c: Include stringpool.h. * target-memory.c: Include stor-layout.h. * trans-common.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. * trans-const.c: Include stor-layout.h. * trans-decl.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. Include attribs.h. * trans-expr.c: Include stringpool.h. * trans-intrinsic.c: Include stringpool.h. Include tree-nested.h. Include stor-layout.h. * trans-io.c: Include stringpool.h. Include stor-layout.h. * trans-openmp.c: Include stringpool.h. * trans-stmt.c: Include stringpool.h. * trans-types.c: Include stor-layout.h. Include stringpool.h. * trans.c: Include stringpool.h. go/ChangeLog * go-backend.c: Include stor-layout.h. * go-gcc.cc: Include stringpool.h. Include stor-layout.h. Include varasm.h. * go-lang.c: Include stor-layout.h. java/ChangeLog * builtins.c: Include stor-layout.h. Include stringpool.h. * class.c: Include stringpool.h. Include stor-layout.h. Include varasm.h. * constants.c: Include stringpool.h. Include stor-layout.h. * decl.c: Include stor-layout.h. Include stringpool.h. Include varasm.h. * except.c: Include stringpool.h. Include stor-layout.h. * expr.c: Include stringpool.h. Include stor-layout.h. * jcf-parse.c: Include stringpool.h. * mangle.c: Include stringpool.h. * resource.c: Include stringpool.h. Include stor-layout.h. * typeck.c: Include stor-layout.h. Include stringpool.h. * verify-glue.c: Include stringpool.h. lto/ChangeLog * lto-lang.c: Include stringpool.h. Include stor-layout.h. * lto-partition.c: Include gcc-symtab.h. * lto.c: Include stor-layout.h. objc/ChangeLog * objc-act.c: Include stringpool.h. Include stor-layout.h. Include attribs.h. * objc-encoding.c: Include stringpool.h. Include stor-layout.h. * objc-gnu-runtime-abi-01.c: Include stringpool.h. * objc-next-runtime-abi-01.c: Include stringpool.h. * objc-next-runtime-abi-02.c: Include stringpool.h. * objc-runtime-shared-support.c: Include stringpool.h. testsuite/ChangeLog * gcc.dg/plugin/selfassign.c: Include stringpool.h. * gcc.dg/plugin/start_unit_plugin.c: Likewise. From-SVN: r205023
864 lines
23 KiB
C
864 lines
23 KiB
C
/* Generate code from machine description to emit insns as rtl.
|
||
Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||
|
||
This file is part of GCC.
|
||
|
||
GCC is free software; you can redistribute it and/or modify it under
|
||
the terms of the GNU General Public License as published by the Free
|
||
Software Foundation; either version 3, or (at your option) any later
|
||
version.
|
||
|
||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with GCC; see the file COPYING3. If not see
|
||
<http://www.gnu.org/licenses/>. */
|
||
|
||
|
||
#include "bconfig.h"
|
||
#include "system.h"
|
||
#include "coretypes.h"
|
||
#include "tm.h"
|
||
#include "rtl.h"
|
||
#include "errors.h"
|
||
#include "read-md.h"
|
||
#include "gensupport.h"
|
||
|
||
|
||
static int insn_code_number;
|
||
static int insn_index_number;
|
||
|
||
/* Data structure for recording the patterns of insns that have CLOBBERs.
|
||
We use this to output a function that adds these CLOBBERs to a
|
||
previously-allocated PARALLEL expression. */
|
||
|
||
struct clobber_pat
|
||
{
|
||
struct clobber_ent *insns;
|
||
rtx pattern;
|
||
int first_clobber;
|
||
struct clobber_pat *next;
|
||
int has_hard_reg;
|
||
} *clobber_list;
|
||
|
||
/* Records one insn that uses the clobber list. */
|
||
|
||
struct clobber_ent
|
||
{
|
||
int code_number; /* Counts only insns. */
|
||
struct clobber_ent *next;
|
||
};
|
||
|
||
static void print_code (RTX_CODE);
|
||
static void gen_exp (rtx, enum rtx_code, char *);
|
||
static void gen_insn (rtx, int);
|
||
static void gen_expand (rtx);
|
||
static void gen_split (rtx);
|
||
static void output_add_clobbers (void);
|
||
static void output_added_clobbers_hard_reg_p (void);
|
||
static void gen_rtx_scratch (rtx, enum rtx_code);
|
||
static void output_peephole2_scratches (rtx);
|
||
|
||
|
||
static void
|
||
print_code (RTX_CODE code)
|
||
{
|
||
const char *p1;
|
||
for (p1 = GET_RTX_NAME (code); *p1; p1++)
|
||
putchar (TOUPPER (*p1));
|
||
}
|
||
|
||
static void
|
||
gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
|
||
{
|
||
if (subroutine_type == DEFINE_PEEPHOLE2)
|
||
{
|
||
printf ("operand%d", XINT (x, 0));
|
||
}
|
||
else
|
||
{
|
||
printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
|
||
}
|
||
}
|
||
|
||
/* Print a C expression to construct an RTX just like X,
|
||
substituting any operand references appearing within. */
|
||
|
||
static void
|
||
gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
|
||
{
|
||
RTX_CODE code;
|
||
int i;
|
||
int len;
|
||
const char *fmt;
|
||
|
||
if (x == 0)
|
||
{
|
||
printf ("NULL_RTX");
|
||
return;
|
||
}
|
||
|
||
code = GET_CODE (x);
|
||
|
||
switch (code)
|
||
{
|
||
case MATCH_OPERAND:
|
||
case MATCH_DUP:
|
||
if (used)
|
||
{
|
||
if (used[XINT (x, 0)])
|
||
{
|
||
printf ("copy_rtx (operand%d)", XINT (x, 0));
|
||
return;
|
||
}
|
||
used[XINT (x, 0)] = 1;
|
||
}
|
||
printf ("operand%d", XINT (x, 0));
|
||
return;
|
||
|
||
case MATCH_OP_DUP:
|
||
printf ("gen_rtx_fmt_");
|
||
for (i = 0; i < XVECLEN (x, 1); i++)
|
||
printf ("e");
|
||
printf (" (GET_CODE (operand%d), ", XINT (x, 0));
|
||
if (GET_MODE (x) == VOIDmode)
|
||
printf ("GET_MODE (operand%d)", XINT (x, 0));
|
||
else
|
||
printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
|
||
for (i = 0; i < XVECLEN (x, 1); i++)
|
||
{
|
||
printf (",\n\t\t");
|
||
gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
|
||
}
|
||
printf (")");
|
||
return;
|
||
|
||
case MATCH_OPERATOR:
|
||
printf ("gen_rtx_fmt_");
|
||
for (i = 0; i < XVECLEN (x, 2); i++)
|
||
printf ("e");
|
||
printf (" (GET_CODE (operand%d)", XINT (x, 0));
|
||
printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
|
||
for (i = 0; i < XVECLEN (x, 2); i++)
|
||
{
|
||
printf (",\n\t\t");
|
||
gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
|
||
}
|
||
printf (")");
|
||
return;
|
||
|
||
case MATCH_PARALLEL:
|
||
case MATCH_PAR_DUP:
|
||
printf ("operand%d", XINT (x, 0));
|
||
return;
|
||
|
||
case MATCH_SCRATCH:
|
||
gen_rtx_scratch (x, subroutine_type);
|
||
return;
|
||
|
||
case PC:
|
||
printf ("pc_rtx");
|
||
return;
|
||
case RETURN:
|
||
printf ("ret_rtx");
|
||
return;
|
||
case SIMPLE_RETURN:
|
||
printf ("simple_return_rtx");
|
||
return;
|
||
case CLOBBER:
|
||
if (REG_P (XEXP (x, 0)))
|
||
{
|
||
printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
|
||
REGNO (XEXP (x, 0)));
|
||
return;
|
||
}
|
||
break;
|
||
|
||
case CC0:
|
||
printf ("cc0_rtx");
|
||
return;
|
||
|
||
case CONST_INT:
|
||
if (INTVAL (x) == 0)
|
||
printf ("const0_rtx");
|
||
else if (INTVAL (x) == 1)
|
||
printf ("const1_rtx");
|
||
else if (INTVAL (x) == -1)
|
||
printf ("constm1_rtx");
|
||
else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
|
||
&& INTVAL (x) <= MAX_SAVED_CONST_INT)
|
||
printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
|
||
(int) INTVAL (x));
|
||
else if (INTVAL (x) == STORE_FLAG_VALUE)
|
||
printf ("const_true_rtx");
|
||
else
|
||
{
|
||
printf ("GEN_INT (");
|
||
printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
|
||
printf (")");
|
||
}
|
||
return;
|
||
|
||
case CONST_DOUBLE:
|
||
case CONST_FIXED:
|
||
/* These shouldn't be written in MD files. Instead, the appropriate
|
||
routines in varasm.c should be called. */
|
||
gcc_unreachable ();
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
printf ("gen_rtx_");
|
||
print_code (code);
|
||
printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
|
||
|
||
fmt = GET_RTX_FORMAT (code);
|
||
len = GET_RTX_LENGTH (code);
|
||
for (i = 0; i < len; i++)
|
||
{
|
||
if (fmt[i] == '0')
|
||
break;
|
||
printf (",\n\t");
|
||
switch (fmt[i])
|
||
{
|
||
case 'e': case 'u':
|
||
gen_exp (XEXP (x, i), subroutine_type, used);
|
||
break;
|
||
|
||
case 'i':
|
||
printf ("%u", XINT (x, i));
|
||
break;
|
||
|
||
case 's':
|
||
printf ("\"%s\"", XSTR (x, i));
|
||
break;
|
||
|
||
case 'E':
|
||
{
|
||
int j;
|
||
printf ("gen_rtvec (%d", XVECLEN (x, i));
|
||
for (j = 0; j < XVECLEN (x, i); j++)
|
||
{
|
||
printf (",\n\t\t");
|
||
gen_exp (XVECEXP (x, i, j), subroutine_type, used);
|
||
}
|
||
printf (")");
|
||
break;
|
||
}
|
||
|
||
default:
|
||
gcc_unreachable ();
|
||
}
|
||
}
|
||
printf (")");
|
||
}
|
||
|
||
/* Generate the `gen_...' function for a DEFINE_INSN. */
|
||
|
||
static void
|
||
gen_insn (rtx insn, int lineno)
|
||
{
|
||
struct pattern_stats stats;
|
||
int i;
|
||
|
||
/* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
|
||
registers or MATCH_SCRATCHes. If so, store away the information for
|
||
later. */
|
||
|
||
if (XVEC (insn, 1))
|
||
{
|
||
int has_hard_reg = 0;
|
||
|
||
for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
|
||
{
|
||
if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
|
||
break;
|
||
|
||
if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
|
||
has_hard_reg = 1;
|
||
else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
|
||
break;
|
||
}
|
||
|
||
if (i != XVECLEN (insn, 1) - 1)
|
||
{
|
||
struct clobber_pat *p;
|
||
struct clobber_ent *link = XNEW (struct clobber_ent);
|
||
int j;
|
||
|
||
link->code_number = insn_code_number;
|
||
|
||
/* See if any previous CLOBBER_LIST entry is the same as this
|
||
one. */
|
||
|
||
for (p = clobber_list; p; p = p->next)
|
||
{
|
||
if (p->first_clobber != i + 1
|
||
|| XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
|
||
continue;
|
||
|
||
for (j = i + 1; j < XVECLEN (insn, 1); j++)
|
||
{
|
||
rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0);
|
||
rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0);
|
||
|
||
/* OLD and NEW_INSN are the same if both are to be a SCRATCH
|
||
of the same mode,
|
||
or if both are registers of the same mode and number. */
|
||
if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
|
||
&& ((GET_CODE (old_rtx) == MATCH_SCRATCH
|
||
&& GET_CODE (new_rtx) == MATCH_SCRATCH)
|
||
|| (REG_P (old_rtx) && REG_P (new_rtx)
|
||
&& REGNO (old_rtx) == REGNO (new_rtx)))))
|
||
break;
|
||
}
|
||
|
||
if (j == XVECLEN (insn, 1))
|
||
break;
|
||
}
|
||
|
||
if (p == 0)
|
||
{
|
||
p = XNEW (struct clobber_pat);
|
||
|
||
p->insns = 0;
|
||
p->pattern = insn;
|
||
p->first_clobber = i + 1;
|
||
p->next = clobber_list;
|
||
p->has_hard_reg = has_hard_reg;
|
||
clobber_list = p;
|
||
}
|
||
|
||
link->next = p->insns;
|
||
p->insns = link;
|
||
}
|
||
}
|
||
|
||
/* Don't mention instructions whose names are the null string
|
||
or begin with '*'. They are in the machine description just
|
||
to be recognized. */
|
||
if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
|
||
return;
|
||
|
||
printf ("/* %s:%d */\n", read_md_filename, lineno);
|
||
|
||
/* Find out how many operands this function has. */
|
||
get_pattern_stats (&stats, XVEC (insn, 1));
|
||
if (stats.max_dup_opno > stats.max_opno)
|
||
fatal ("match_dup operand number has no match_operand");
|
||
|
||
/* Output the function name and argument declarations. */
|
||
printf ("rtx\ngen_%s (", XSTR (insn, 0));
|
||
if (stats.num_generator_args)
|
||
for (i = 0; i < stats.num_generator_args; i++)
|
||
if (i)
|
||
printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
|
||
else
|
||
printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
|
||
else
|
||
printf ("void");
|
||
printf (")\n");
|
||
printf ("{\n");
|
||
|
||
/* Output code to construct and return the rtl for the instruction body. */
|
||
|
||
if (XVECLEN (insn, 1) == 1)
|
||
{
|
||
printf (" return ");
|
||
gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
|
||
printf (";\n}\n\n");
|
||
}
|
||
else
|
||
{
|
||
char *used = XCNEWVEC (char, stats.num_generator_args);
|
||
|
||
printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
|
||
XVECLEN (insn, 1));
|
||
|
||
for (i = 0; i < XVECLEN (insn, 1); i++)
|
||
{
|
||
printf (",\n\t\t");
|
||
gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
|
||
}
|
||
printf ("));\n}\n\n");
|
||
XDELETEVEC (used);
|
||
}
|
||
}
|
||
|
||
/* Generate the `gen_...' function for a DEFINE_EXPAND. */
|
||
|
||
static void
|
||
gen_expand (rtx expand)
|
||
{
|
||
struct pattern_stats stats;
|
||
int i;
|
||
char *used;
|
||
|
||
if (strlen (XSTR (expand, 0)) == 0)
|
||
fatal ("define_expand lacks a name");
|
||
if (XVEC (expand, 1) == 0)
|
||
fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
|
||
|
||
/* Find out how many operands this function has. */
|
||
get_pattern_stats (&stats, XVEC (expand, 1));
|
||
|
||
/* Output the function name and argument declarations. */
|
||
printf ("rtx\ngen_%s (", XSTR (expand, 0));
|
||
if (stats.num_generator_args)
|
||
for (i = 0; i < stats.num_generator_args; i++)
|
||
if (i)
|
||
printf (",\n\trtx operand%d", i);
|
||
else
|
||
printf ("rtx operand%d", i);
|
||
else
|
||
printf ("void");
|
||
printf (")\n");
|
||
printf ("{\n");
|
||
|
||
/* If we don't have any C code to write, only one insn is being written,
|
||
and no MATCH_DUPs are present, we can just return the desired insn
|
||
like we do for a DEFINE_INSN. This saves memory. */
|
||
if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
|
||
&& stats.max_opno >= stats.max_dup_opno
|
||
&& XVECLEN (expand, 1) == 1)
|
||
{
|
||
printf (" return ");
|
||
gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
|
||
printf (";\n}\n\n");
|
||
return;
|
||
}
|
||
|
||
/* For each operand referred to only with MATCH_DUPs,
|
||
make a local variable. */
|
||
for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
|
||
printf (" rtx operand%d;\n", i);
|
||
for (; i <= stats.max_scratch_opno; i++)
|
||
printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
|
||
printf (" rtx _val = 0;\n");
|
||
printf (" start_sequence ();\n");
|
||
|
||
/* The fourth operand of DEFINE_EXPAND is some code to be executed
|
||
before the actual construction.
|
||
This code expects to refer to `operands'
|
||
just as the output-code in a DEFINE_INSN does,
|
||
but here `operands' is an automatic array.
|
||
So copy the operand values there before executing it. */
|
||
if (XSTR (expand, 3) && *XSTR (expand, 3))
|
||
{
|
||
printf (" {\n");
|
||
if (stats.num_operand_vars > 0)
|
||
printf (" rtx operands[%d];\n", stats.num_operand_vars);
|
||
|
||
/* Output code to copy the arguments into `operands'. */
|
||
for (i = 0; i < stats.num_generator_args; i++)
|
||
printf (" operands[%d] = operand%d;\n", i, i);
|
||
|
||
/* Output the special code to be executed before the sequence
|
||
is generated. */
|
||
print_md_ptr_loc (XSTR (expand, 3));
|
||
printf ("%s\n", XSTR (expand, 3));
|
||
|
||
/* Output code to copy the arguments back out of `operands'
|
||
(unless we aren't going to use them at all). */
|
||
if (XVEC (expand, 1) != 0)
|
||
{
|
||
for (i = 0; i < stats.num_operand_vars; i++)
|
||
{
|
||
printf (" operand%d = operands[%d];\n", i, i);
|
||
printf (" (void) operand%d;\n", i);
|
||
}
|
||
}
|
||
printf (" }\n");
|
||
}
|
||
|
||
/* Output code to construct the rtl for the instruction bodies.
|
||
Use emit_insn to add them to the sequence being accumulated.
|
||
But don't do this if the user's code has set `no_more' nonzero. */
|
||
|
||
used = XCNEWVEC (char, stats.num_operand_vars);
|
||
|
||
for (i = 0; i < XVECLEN (expand, 1); i++)
|
||
{
|
||
rtx next = XVECEXP (expand, 1, i);
|
||
if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
|
||
|| (GET_CODE (next) == PARALLEL
|
||
&& ((GET_CODE (XVECEXP (next, 0, 0)) == SET
|
||
&& GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
|
||
|| ANY_RETURN_P (XVECEXP (next, 0, 0))))
|
||
|| ANY_RETURN_P (next))
|
||
printf (" emit_jump_insn (");
|
||
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
|
||
|| GET_CODE (next) == CALL
|
||
|| (GET_CODE (next) == PARALLEL
|
||
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
|
||
&& GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
|
||
|| (GET_CODE (next) == PARALLEL
|
||
&& GET_CODE (XVECEXP (next, 0, 0)) == CALL))
|
||
printf (" emit_call_insn (");
|
||
else if (LABEL_P (next))
|
||
printf (" emit_label (");
|
||
else if (GET_CODE (next) == MATCH_OPERAND
|
||
|| GET_CODE (next) == MATCH_DUP
|
||
|| GET_CODE (next) == MATCH_OPERATOR
|
||
|| GET_CODE (next) == MATCH_OP_DUP
|
||
|| GET_CODE (next) == MATCH_PARALLEL
|
||
|| GET_CODE (next) == MATCH_PAR_DUP
|
||
|| GET_CODE (next) == PARALLEL)
|
||
printf (" emit (");
|
||
else
|
||
printf (" emit_insn (");
|
||
gen_exp (next, DEFINE_EXPAND, used);
|
||
printf (");\n");
|
||
if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
|
||
&& GET_CODE (SET_SRC (next)) == LABEL_REF)
|
||
printf (" emit_barrier ();");
|
||
}
|
||
|
||
XDELETEVEC (used);
|
||
|
||
/* Call `get_insns' to extract the list of all the
|
||
insns emitted within this gen_... function. */
|
||
|
||
printf (" _val = get_insns ();\n");
|
||
printf (" end_sequence ();\n");
|
||
printf (" return _val;\n}\n\n");
|
||
}
|
||
|
||
/* Like gen_expand, but generates insns resulting from splitting SPLIT. */
|
||
|
||
static void
|
||
gen_split (rtx split)
|
||
{
|
||
struct pattern_stats stats;
|
||
int i;
|
||
const char *const name =
|
||
((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
|
||
const char *unused;
|
||
char *used;
|
||
|
||
if (XVEC (split, 0) == 0)
|
||
fatal ("define_%s (definition %d) lacks a pattern", name,
|
||
insn_index_number);
|
||
else if (XVEC (split, 2) == 0)
|
||
fatal ("define_%s (definition %d) lacks a replacement pattern", name,
|
||
insn_index_number);
|
||
|
||
/* Find out how many operands this function has. */
|
||
|
||
get_pattern_stats (&stats, XVEC (split, 2));
|
||
unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
|
||
used = XCNEWVEC (char, stats.num_operand_vars);
|
||
|
||
/* Output the prototype, function name and argument declarations. */
|
||
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
|
||
{
|
||
printf ("extern rtx gen_%s_%d (rtx, rtx *);\n",
|
||
name, insn_code_number);
|
||
printf ("rtx\ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
|
||
name, insn_code_number, unused);
|
||
}
|
||
else
|
||
{
|
||
printf ("extern rtx gen_split_%d (rtx, rtx *);\n", insn_code_number);
|
||
printf ("rtx\ngen_split_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
|
||
insn_code_number, unused);
|
||
}
|
||
printf ("{\n");
|
||
|
||
/* Declare all local variables. */
|
||
for (i = 0; i < stats.num_operand_vars; i++)
|
||
printf (" rtx operand%d;\n", i);
|
||
printf (" rtx _val = 0;\n");
|
||
|
||
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
|
||
output_peephole2_scratches (split);
|
||
|
||
printf (" start_sequence ();\n");
|
||
|
||
/* The fourth operand of DEFINE_SPLIT is some code to be executed
|
||
before the actual construction. */
|
||
|
||
if (XSTR (split, 3))
|
||
{
|
||
print_md_ptr_loc (XSTR (split, 3));
|
||
printf ("%s\n", XSTR (split, 3));
|
||
}
|
||
|
||
/* Output code to copy the arguments back out of `operands' */
|
||
for (i = 0; i < stats.num_operand_vars; i++)
|
||
{
|
||
printf (" operand%d = operands[%d];\n", i, i);
|
||
printf (" (void) operand%d;\n", i);
|
||
}
|
||
|
||
/* Output code to construct the rtl for the instruction bodies.
|
||
Use emit_insn to add them to the sequence being accumulated.
|
||
But don't do this if the user's code has set `no_more' nonzero. */
|
||
|
||
for (i = 0; i < XVECLEN (split, 2); i++)
|
||
{
|
||
rtx next = XVECEXP (split, 2, i);
|
||
if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
|
||
|| (GET_CODE (next) == PARALLEL
|
||
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
|
||
&& GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
|
||
|| ANY_RETURN_P (next))
|
||
printf (" emit_jump_insn (");
|
||
else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
|
||
|| GET_CODE (next) == CALL
|
||
|| (GET_CODE (next) == PARALLEL
|
||
&& GET_CODE (XVECEXP (next, 0, 0)) == SET
|
||
&& GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
|
||
|| (GET_CODE (next) == PARALLEL
|
||
&& GET_CODE (XVECEXP (next, 0, 0)) == CALL))
|
||
printf (" emit_call_insn (");
|
||
else if (LABEL_P (next))
|
||
printf (" emit_label (");
|
||
else if (GET_CODE (next) == MATCH_OPERAND
|
||
|| GET_CODE (next) == MATCH_OPERATOR
|
||
|| GET_CODE (next) == MATCH_PARALLEL
|
||
|| GET_CODE (next) == MATCH_OP_DUP
|
||
|| GET_CODE (next) == MATCH_DUP
|
||
|| GET_CODE (next) == PARALLEL)
|
||
printf (" emit (");
|
||
else
|
||
printf (" emit_insn (");
|
||
gen_exp (next, GET_CODE (split), used);
|
||
printf (");\n");
|
||
if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
|
||
&& GET_CODE (SET_SRC (next)) == LABEL_REF)
|
||
printf (" emit_barrier ();");
|
||
}
|
||
|
||
/* Call `get_insns' to make a list of all the
|
||
insns emitted within this gen_... function. */
|
||
|
||
printf (" _val = get_insns ();\n");
|
||
printf (" end_sequence ();\n");
|
||
printf (" return _val;\n}\n\n");
|
||
|
||
free (used);
|
||
}
|
||
|
||
/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
|
||
size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
|
||
the end of the vector. */
|
||
|
||
static void
|
||
output_add_clobbers (void)
|
||
{
|
||
struct clobber_pat *clobber;
|
||
struct clobber_ent *ent;
|
||
int i;
|
||
|
||
printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n");
|
||
printf ("{\n");
|
||
printf (" switch (insn_code_number)\n");
|
||
printf (" {\n");
|
||
|
||
for (clobber = clobber_list; clobber; clobber = clobber->next)
|
||
{
|
||
for (ent = clobber->insns; ent; ent = ent->next)
|
||
printf (" case %d:\n", ent->code_number);
|
||
|
||
for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
|
||
{
|
||
printf (" XVECEXP (pattern, 0, %d) = ", i);
|
||
gen_exp (XVECEXP (clobber->pattern, 1, i),
|
||
GET_CODE (clobber->pattern), NULL);
|
||
printf (";\n");
|
||
}
|
||
|
||
printf (" break;\n\n");
|
||
}
|
||
|
||
printf (" default:\n");
|
||
printf (" gcc_unreachable ();\n");
|
||
printf (" }\n");
|
||
printf ("}\n");
|
||
}
|
||
|
||
/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code
|
||
number that will have clobbers added (as indicated by `recog') and returns
|
||
1 if those include a clobber of a hard reg or 0 if all of them just clobber
|
||
SCRATCH. */
|
||
|
||
static void
|
||
output_added_clobbers_hard_reg_p (void)
|
||
{
|
||
struct clobber_pat *clobber;
|
||
struct clobber_ent *ent;
|
||
int clobber_p, used;
|
||
|
||
printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
|
||
printf ("{\n");
|
||
printf (" switch (insn_code_number)\n");
|
||
printf (" {\n");
|
||
|
||
for (clobber_p = 0; clobber_p <= 1; clobber_p++)
|
||
{
|
||
used = 0;
|
||
for (clobber = clobber_list; clobber; clobber = clobber->next)
|
||
if (clobber->has_hard_reg == clobber_p)
|
||
for (ent = clobber->insns; ent; ent = ent->next)
|
||
{
|
||
printf (" case %d:\n", ent->code_number);
|
||
used++;
|
||
}
|
||
|
||
if (used)
|
||
printf (" return %d;\n\n", clobber_p);
|
||
}
|
||
|
||
printf (" default:\n");
|
||
printf (" gcc_unreachable ();\n");
|
||
printf (" }\n");
|
||
printf ("}\n");
|
||
}
|
||
|
||
/* Generate code to invoke find_free_register () as needed for the
|
||
scratch registers used by the peephole2 pattern in SPLIT. */
|
||
|
||
static void
|
||
output_peephole2_scratches (rtx split)
|
||
{
|
||
int i;
|
||
int insn_nr = 0;
|
||
bool first = true;
|
||
|
||
for (i = 0; i < XVECLEN (split, 0); i++)
|
||
{
|
||
rtx elt = XVECEXP (split, 0, i);
|
||
if (GET_CODE (elt) == MATCH_SCRATCH)
|
||
{
|
||
int last_insn_nr = insn_nr;
|
||
int cur_insn_nr = insn_nr;
|
||
int j;
|
||
for (j = i + 1; j < XVECLEN (split, 0); j++)
|
||
if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
|
||
{
|
||
if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
|
||
last_insn_nr = cur_insn_nr;
|
||
}
|
||
else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
|
||
cur_insn_nr++;
|
||
|
||
if (first)
|
||
{
|
||
printf (" HARD_REG_SET _regs_allocated;\n");
|
||
printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
|
||
first = false;
|
||
}
|
||
|
||
printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
|
||
return NULL;\n",
|
||
XINT (elt, 0),
|
||
insn_nr, last_insn_nr,
|
||
XSTR (elt, 1),
|
||
GET_MODE_NAME (GET_MODE (elt)));
|
||
|
||
}
|
||
else if (GET_CODE (elt) != MATCH_DUP)
|
||
insn_nr++;
|
||
}
|
||
}
|
||
|
||
int
|
||
main (int argc, char **argv)
|
||
{
|
||
rtx desc;
|
||
|
||
progname = "genemit";
|
||
|
||
if (!init_rtx_reader_args (argc, argv))
|
||
return (FATAL_EXIT_CODE);
|
||
|
||
/* Assign sequential codes to all entries in the machine description
|
||
in parallel with the tables in insn-output.c. */
|
||
|
||
insn_code_number = 0;
|
||
insn_index_number = 0;
|
||
|
||
printf ("/* Generated automatically by the program `genemit'\n\
|
||
from the machine description file `md'. */\n\n");
|
||
|
||
printf ("#include \"config.h\"\n");
|
||
printf ("#include \"system.h\"\n");
|
||
printf ("#include \"coretypes.h\"\n");
|
||
printf ("#include \"tm.h\"\n");
|
||
printf ("#include \"tree.h\"\n");
|
||
printf ("#include \"varasm.h\"\n");
|
||
printf ("#include \"stor-layout.h\"\n");
|
||
printf ("#include \"calls.h\"\n");
|
||
printf ("#include \"rtl.h\"\n");
|
||
printf ("#include \"tm_p.h\"\n");
|
||
printf ("#include \"function.h\"\n");
|
||
printf ("#include \"expr.h\"\n");
|
||
printf ("#include \"optabs.h\"\n");
|
||
printf ("#include \"dfp.h\"\n");
|
||
printf ("#include \"flags.h\"\n");
|
||
printf ("#include \"output.h\"\n");
|
||
printf ("#include \"insn-config.h\"\n");
|
||
printf ("#include \"hard-reg-set.h\"\n");
|
||
printf ("#include \"recog.h\"\n");
|
||
printf ("#include \"resource.h\"\n");
|
||
printf ("#include \"reload.h\"\n");
|
||
printf ("#include \"diagnostic-core.h\"\n");
|
||
printf ("#include \"regs.h\"\n");
|
||
printf ("#include \"tm-constrs.h\"\n");
|
||
printf ("#include \"ggc.h\"\n");
|
||
printf ("#include \"basic-block.h\"\n");
|
||
printf ("#include \"target.h\"\n\n");
|
||
printf ("#define FAIL return (end_sequence (), _val)\n");
|
||
printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
|
||
|
||
/* Read the machine description. */
|
||
|
||
while (1)
|
||
{
|
||
int line_no;
|
||
|
||
desc = read_md_rtx (&line_no, &insn_code_number);
|
||
if (desc == NULL)
|
||
break;
|
||
|
||
switch (GET_CODE (desc))
|
||
{
|
||
case DEFINE_INSN:
|
||
gen_insn (desc, line_no);
|
||
break;
|
||
|
||
case DEFINE_EXPAND:
|
||
printf ("/* %s:%d */\n", read_md_filename, line_no);
|
||
gen_expand (desc);
|
||
break;
|
||
|
||
case DEFINE_SPLIT:
|
||
printf ("/* %s:%d */\n", read_md_filename, line_no);
|
||
gen_split (desc);
|
||
break;
|
||
|
||
case DEFINE_PEEPHOLE2:
|
||
printf ("/* %s:%d */\n", read_md_filename, line_no);
|
||
gen_split (desc);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
++insn_index_number;
|
||
}
|
||
|
||
/* Write out the routines to add CLOBBERs to a pattern and say whether they
|
||
clobber a hard reg. */
|
||
output_add_clobbers ();
|
||
output_added_clobbers_hard_reg_p ();
|
||
|
||
fflush (stdout);
|
||
return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
|
||
}
|