Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/fr30/fr30.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* FR30 specific functions. | 1 /* FR30 specific functions. |
2 Copyright (C) 1998-2018 Free Software Foundation, Inc. | 2 Copyright (C) 1998-2020 Free Software Foundation, Inc. |
3 Contributed by Cygnus Solutions. | 3 Contributed by Cygnus Solutions. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify | 7 GCC is free software; you can redistribute it and/or modify |
37 #include "stor-layout.h" | 37 #include "stor-layout.h" |
38 #include "varasm.h" | 38 #include "varasm.h" |
39 #include "output.h" | 39 #include "output.h" |
40 #include "expr.h" | 40 #include "expr.h" |
41 #include "builtins.h" | 41 #include "builtins.h" |
42 #include "calls.h" | |
42 | 43 |
43 /* This file should be included last. */ | 44 /* This file should be included last. */ |
44 #include "target-def.h" | 45 #include "target-def.h" |
45 | 46 |
46 /*}}}*/ | 47 /*}}}*/ |
110 static struct fr30_frame_info current_frame_info; | 111 static struct fr30_frame_info current_frame_info; |
111 | 112 |
112 /* Zero structure to initialize current_frame_info. */ | 113 /* Zero structure to initialize current_frame_info. */ |
113 static struct fr30_frame_info zero_frame_info; | 114 static struct fr30_frame_info zero_frame_info; |
114 | 115 |
115 static void fr30_setup_incoming_varargs (cumulative_args_t, machine_mode, | 116 static void fr30_setup_incoming_varargs (cumulative_args_t, |
116 tree, int *, int); | 117 const function_arg_info &, |
117 static bool fr30_must_pass_in_stack (machine_mode, const_tree); | 118 int *, int); |
118 static int fr30_arg_partial_bytes (cumulative_args_t, machine_mode, | 119 static bool fr30_must_pass_in_stack (const function_arg_info &); |
119 tree, bool); | 120 static int fr30_arg_partial_bytes (cumulative_args_t, |
120 static rtx fr30_function_arg (cumulative_args_t, machine_mode, | 121 const function_arg_info &); |
121 const_tree, bool); | 122 static rtx fr30_function_arg (cumulative_args_t, const function_arg_info &); |
122 static void fr30_function_arg_advance (cumulative_args_t, machine_mode, | 123 static void fr30_function_arg_advance (cumulative_args_t, |
123 const_tree, bool); | 124 const function_arg_info &); |
124 static bool fr30_frame_pointer_required (void); | 125 static bool fr30_frame_pointer_required (void); |
125 static rtx fr30_function_value (const_tree, const_tree, bool); | 126 static rtx fr30_function_value (const_tree, const_tree, bool); |
126 static rtx fr30_libcall_value (machine_mode, const_rtx); | 127 static rtx fr30_libcall_value (machine_mode, const_rtx); |
127 static bool fr30_function_value_regno_p (const unsigned int); | 128 static bool fr30_function_value_regno_p (const unsigned int); |
128 static bool fr30_can_eliminate (const int, const int); | 129 static bool fr30_can_eliminate (const int, const int); |
129 static void fr30_asm_trampoline_template (FILE *); | 130 static void fr30_asm_trampoline_template (FILE *); |
130 static void fr30_trampoline_init (rtx, tree, rtx); | 131 static void fr30_trampoline_init (rtx, tree, rtx); |
131 static int fr30_num_arg_regs (machine_mode, const_tree); | 132 static int fr30_num_arg_regs (const function_arg_info &); |
132 | 133 |
133 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) | 134 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) |
134 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM)) | 135 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM)) |
135 | 136 |
136 /* Tell prologue and epilogue if register REGNO should be saved / restored. | 137 /* Tell prologue and epilogue if register REGNO should be saved / restored. |
138 Don't consider them here. */ | 139 Don't consider them here. */ |
139 #define MUST_SAVE_REGISTER(regno) \ | 140 #define MUST_SAVE_REGISTER(regno) \ |
140 ( (regno) != RETURN_POINTER_REGNUM \ | 141 ( (regno) != RETURN_POINTER_REGNUM \ |
141 && (regno) != FRAME_POINTER_REGNUM \ | 142 && (regno) != FRAME_POINTER_REGNUM \ |
142 && df_regs_ever_live_p (regno) \ | 143 && df_regs_ever_live_p (regno) \ |
143 && ! call_used_regs [regno] ) | 144 && ! call_used_or_fixed_reg_p (regno)) |
144 | 145 |
145 #define MUST_SAVE_FRAME_POINTER (df_regs_ever_live_p (FRAME_POINTER_REGNUM) || frame_pointer_needed) | 146 #define MUST_SAVE_FRAME_POINTER (df_regs_ever_live_p (FRAME_POINTER_REGNUM) || frame_pointer_needed) |
146 #define MUST_SAVE_RETURN_POINTER (df_regs_ever_live_p (RETURN_POINTER_REGNUM) || crtl->profile) | 147 #define MUST_SAVE_RETURN_POINTER (df_regs_ever_live_p (RETURN_POINTER_REGNUM) || crtl->profile) |
147 | 148 |
148 #if UNITS_PER_WORD == 4 | 149 #if UNITS_PER_WORD == 4 |
456 /* Do any needed setup for a variadic function. We must create a register | 457 /* Do any needed setup for a variadic function. We must create a register |
457 parameter block, and then copy any anonymous arguments, plus the last | 458 parameter block, and then copy any anonymous arguments, plus the last |
458 named argument, from registers into memory. * copying actually done in | 459 named argument, from registers into memory. * copying actually done in |
459 fr30_expand_prologue(). | 460 fr30_expand_prologue(). |
460 | 461 |
461 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument | 462 CUM has not been updated for the last named argument which has type TYPE |
462 which has type TYPE and mode MODE, and we rely on this fact. */ | 463 and mode MODE, and we rely on this fact. */ |
463 void | 464 void |
464 fr30_setup_incoming_varargs (cumulative_args_t arg_regs_used_so_far_v, | 465 fr30_setup_incoming_varargs (cumulative_args_t arg_regs_used_so_far_v, |
465 machine_mode mode, | 466 const function_arg_info &arg, |
466 tree type ATTRIBUTE_UNUSED, | |
467 int *pretend_size, | 467 int *pretend_size, |
468 int second_time ATTRIBUTE_UNUSED) | 468 int second_time ATTRIBUTE_UNUSED) |
469 { | 469 { |
470 CUMULATIVE_ARGS *arg_regs_used_so_far | 470 CUMULATIVE_ARGS *arg_regs_used_so_far |
471 = get_cumulative_args (arg_regs_used_so_far_v); | 471 = get_cumulative_args (arg_regs_used_so_far_v); |
472 int size; | 472 int size; |
473 | 473 |
474 /* All BLKmode values are passed by reference. */ | 474 /* All BLKmode values are passed by reference. */ |
475 gcc_assert (mode != BLKmode); | 475 gcc_assert (arg.mode != BLKmode); |
476 | 476 |
477 /* ??? This run-time test as well as the code inside the if | 477 /* ??? This run-time test as well as the code inside the if |
478 statement is probably unnecessary. */ | 478 statement is probably unnecessary. */ |
479 if (targetm.calls.strict_argument_naming (arg_regs_used_so_far_v)) | 479 if (targetm.calls.strict_argument_naming (arg_regs_used_so_far_v)) |
480 /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named | 480 /* If TARGET_STRICT_ARGUMENT_NAMING returns true, then the last named |
481 arg must not be treated as an anonymous arg. */ | 481 arg must not be treated as an anonymous arg. */ |
482 /* ??? This is a pointer increment, which makes no sense. */ | 482 /* ??? This is a pointer increment, which makes no sense. */ |
483 arg_regs_used_so_far += fr30_num_arg_regs (mode, type); | 483 arg_regs_used_so_far += fr30_num_arg_regs (arg); |
484 | 484 |
485 size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far); | 485 size = FR30_NUM_ARG_REGS - (* arg_regs_used_so_far); |
486 | 486 |
487 if (size <= 0) | 487 if (size <= 0) |
488 return; | 488 return; |
741 | 741 |
742 /* Return true if we should pass an argument on the stack rather than | 742 /* Return true if we should pass an argument on the stack rather than |
743 in registers. */ | 743 in registers. */ |
744 | 744 |
745 static bool | 745 static bool |
746 fr30_must_pass_in_stack (machine_mode mode, const_tree type) | 746 fr30_must_pass_in_stack (const function_arg_info &arg) |
747 { | 747 { |
748 if (mode == BLKmode) | 748 return arg.mode == BLKmode || arg.aggregate_type_p (); |
749 return true; | 749 } |
750 if (type == NULL) | 750 |
751 return false; | 751 /* Compute the number of word sized registers needed to hold function |
752 return AGGREGATE_TYPE_P (type); | 752 argument ARG. */ |
753 } | |
754 | |
755 /* Compute the number of word sized registers needed to hold a | |
756 function argument of mode INT_MODE and tree type TYPE. */ | |
757 static int | 753 static int |
758 fr30_num_arg_regs (machine_mode mode, const_tree type) | 754 fr30_num_arg_regs (const function_arg_info &arg) |
759 { | 755 { |
760 int size; | 756 if (targetm.calls.must_pass_in_stack (arg)) |
761 | |
762 if (targetm.calls.must_pass_in_stack (mode, type)) | |
763 return 0; | 757 return 0; |
764 | 758 |
765 if (type && mode == BLKmode) | 759 int size = arg.promoted_size_in_bytes (); |
766 size = int_size_in_bytes (type); | |
767 else | |
768 size = GET_MODE_SIZE (mode); | |
769 | |
770 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; | 760 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; |
771 } | 761 } |
772 | 762 |
773 /* Returns the number of bytes in which *part* of a parameter of machine | 763 /* Returns the number of bytes of argument registers required to hold *part* |
774 mode MODE and tree type TYPE (which may be NULL if the type is not known). | 764 of argument ARG. If the argument fits entirely in the argument registers, |
775 If the argument fits entirely in the argument registers, or entirely on | 765 or entirely on the stack, then 0 is returned. CUM is the number of |
776 the stack, then 0 is returned. | 766 argument registers already used by earlier parameters to the function. */ |
777 CUM is the number of argument registers already used by earlier | |
778 parameters to the function. */ | |
779 | 767 |
780 static int | 768 static int |
781 fr30_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, | 769 fr30_arg_partial_bytes (cumulative_args_t cum_v, const function_arg_info &arg) |
782 tree type, bool named) | |
783 { | 770 { |
784 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | 771 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
785 | 772 |
786 /* Unnamed arguments, i.e. those that are prototyped as ... | 773 /* Unnamed arguments, i.e. those that are prototyped as ... |
787 are always passed on the stack. | 774 are always passed on the stack. |
788 Also check here to see if all the argument registers are full. */ | 775 Also check here to see if all the argument registers are full. */ |
789 if (named == 0 || *cum >= FR30_NUM_ARG_REGS) | 776 if (!arg.named || *cum >= FR30_NUM_ARG_REGS) |
790 return 0; | 777 return 0; |
791 | 778 |
792 /* Work out how many argument registers would be needed if this | 779 /* Work out how many argument registers would be needed if this |
793 parameter were to be passed entirely in registers. If there | 780 parameter were to be passed entirely in registers. If there |
794 are sufficient argument registers available (or if no registers | 781 are sufficient argument registers available (or if no registers |
795 are needed because the parameter must be passed on the stack) | 782 are needed because the parameter must be passed on the stack) |
796 then return zero, as this parameter does not require partial | 783 then return zero, as this parameter does not require partial |
797 register, partial stack stack space. */ | 784 register, partial stack stack space. */ |
798 if (*cum + fr30_num_arg_regs (mode, type) <= FR30_NUM_ARG_REGS) | 785 if (*cum + fr30_num_arg_regs (arg) <= FR30_NUM_ARG_REGS) |
799 return 0; | 786 return 0; |
800 | 787 |
801 return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD; | 788 return (FR30_NUM_ARG_REGS - *cum) * UNITS_PER_WORD; |
802 } | 789 } |
803 | 790 |
804 static rtx | 791 static rtx |
805 fr30_function_arg (cumulative_args_t cum_v, machine_mode mode, | 792 fr30_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) |
806 const_tree type, bool named) | |
807 { | 793 { |
808 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | 794 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
809 | 795 |
810 if (!named | 796 if (!arg.named |
811 || fr30_must_pass_in_stack (mode, type) | 797 || fr30_must_pass_in_stack (arg) |
812 || *cum >= FR30_NUM_ARG_REGS) | 798 || *cum >= FR30_NUM_ARG_REGS) |
813 return NULL_RTX; | 799 return NULL_RTX; |
814 else | 800 else |
815 return gen_rtx_REG (mode, *cum + FIRST_ARG_REGNUM); | 801 return gen_rtx_REG (arg.mode, *cum + FIRST_ARG_REGNUM); |
816 } | 802 } |
817 | 803 |
818 /* A C statement (sans semicolon) to update the summarizer variable CUM to | 804 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */ |
819 advance past an argument in the argument list. The values MODE, TYPE and | |
820 NAMED describe that argument. Once this is done, the variable CUM is | |
821 suitable for analyzing the *following* argument with `FUNCTION_ARG', etc. | |
822 | |
823 This macro need not do anything if the argument in question was passed on | |
824 the stack. The compiler knows how to track the amount of stack space used | |
825 for arguments without any special help. */ | |
826 static void | 805 static void |
827 fr30_function_arg_advance (cumulative_args_t cum, machine_mode mode, | 806 fr30_function_arg_advance (cumulative_args_t cum, |
828 const_tree type, bool named) | 807 const function_arg_info &arg) |
829 { | 808 { |
830 *get_cumulative_args (cum) += named * fr30_num_arg_regs (mode, type); | 809 if (arg.named) |
810 *get_cumulative_args (cum) += fr30_num_arg_regs (arg); | |
831 } | 811 } |
832 | 812 |
833 /*}}}*/ | 813 /*}}}*/ |
834 /*{{{ Operand predicates */ | 814 /*{{{ Operand predicates */ |
835 | 815 |