From a5c76ee6e2c613ac4c3e309e562d51bea137c73a Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Sat, 11 May 2002 16:25:05 +0000 Subject: [PATCH] rs6000.c (rs6000_default_long_calls, [...]): New. * config/rs6000/rs6000.c (rs6000_default_long_calls, rs6000_longcall_switch, rs6000_set_default_type_attributes): New. (TARGET_SET_DEFAULT_TYPE_ATTRIBUTES): Set it. (rs6000_override_options): Handle -m(no-)longcall. (init_cumulative_args, output_mi_thunk): Check for both longcall and shortcall attributes on the function. (rs6000_attribute_table): Add "shortcall". (rs6000_handle_longcall_attribute): Update comment. (altivec_expand_unop_builtin, altivec_expand_binop_builtin, altivec_expand_ternop_builtin): Add default clauses to switches to silence warnings. * config/rs6000/rs6000.h: Declare rs6000_longcall_switch and rs6000_default_long_calls. Define REGISTER_TARGET_PRAGMAS. (TARGET_OPTIONS): Add longcall and no-longcall. * config/rs6000/rs6000.md (call_nonlocal_sysv, call_value_nonlocal_sysv): Split by alternatives. One pair accepts only SYMBOL_REFs and rejects if CALL_LONG is set in the call cookie. The other pair accepts only LR/CTR and has no restriction. * config.gcc (rs6000-*-* | powerpc*-*-* trailer stanza): Set c_target_objs, cxx_target_objs; add t-rs6000-c-rule to tmake_file. * config/rs6000/rs6000-c.c: New file. * config/rs6000/t-rs6000-c-rule: New file. * config/rs6000/rs6000-protos.c: Add multiple-include guard. Prototype rs6000_pragma_longcall. * doc/extend.texi: Document shortcall attribute. * doc/invoke.texi: Document -mlongcall, -mno-longcall. From-SVN: r53382 --- gcc/ChangeLog | 95 ++++++++++++++++++-------- gcc/config.gcc | 3 + gcc/config/rs6000/rs6000-c.c | 71 +++++++++++++++++++ gcc/config/rs6000/rs6000-protos.h | 9 +++ gcc/config/rs6000/rs6000.c | 68 ++++++++++++++++--- gcc/config/rs6000/rs6000.h | 10 +++ gcc/config/rs6000/rs6000.md | 109 ++++++++++++++++++------------ gcc/config/rs6000/t-rs6000-c-rule | 4 ++ gcc/doc/extend.texi | 35 ++++++++-- gcc/doc/invoke.texi | 18 +++++ 10 files changed, 336 insertions(+), 86 deletions(-) create mode 100644 gcc/config/rs6000/rs6000-c.c create mode 100644 gcc/config/rs6000/t-rs6000-c-rule diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 019c96dd901..093d96947e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2002-05-11 Zack Weinberg + + * config/rs6000/rs6000.c (rs6000_default_long_calls, + rs6000_longcall_switch, rs6000_set_default_type_attributes): New. + (TARGET_SET_DEFAULT_TYPE_ATTRIBUTES): Set it. + (rs6000_override_options): Handle -m(no-)longcall. + (init_cumulative_args, output_mi_thunk): Check for both + longcall and shortcall attributes on the function. + (rs6000_attribute_table): Add "shortcall". + (rs6000_handle_longcall_attribute): Update comment. + (altivec_expand_unop_builtin, altivec_expand_binop_builtin, + altivec_expand_ternop_builtin): Add default clauses to switches + to silence warnings. + + * config/rs6000/rs6000.h: Declare rs6000_longcall_switch and + rs6000_default_long_calls. Define REGISTER_TARGET_PRAGMAS. + (TARGET_OPTIONS): Add longcall and no-longcall. + + * config/rs6000/rs6000.md (call_nonlocal_sysv, + call_value_nonlocal_sysv): Split by alternatives. One pair + accepts only SYMBOL_REFs and rejects if CALL_LONG is set in + the call cookie. The other pair accepts only LR/CTR and has + no restriction. + + * config.gcc (rs6000-*-* | powerpc*-*-* trailer stanza): + Set c_target_objs, cxx_target_objs; add t-rs6000-c-rule to + tmake_file. + * config/rs6000/rs6000-c.c: New file. + * config/rs6000/t-rs6000-c-rule: New file. + * config/rs6000/rs6000-protos.c: Add multiple-include guard. + Prototype rs6000_pragma_longcall. + + * doc/extend.texi: Document shortcall attribute. + * doc/invoke.texi: Document -mlongcall, -mno-longcall. + 2002-05-12 Marek Michalkiewicz * config/avr/avr.c (avr_mcu_types): Update supported devices. @@ -205,38 +240,38 @@ Thu May 9 14:52:45 CEST 2002 Jan Hubicka * final.c (end_final): Use C trees to output data structures for profiling. * Makefile.in (LIBGCC_DEPS): Added missing dependency on gcov-io.h - (profile.o): New dependency profile.h - (final.o): New dependency profile.h - * profile.h: New file. New global structure profile_info. - * final.h (count_edges_instrumented_now): Declare. - (current_function_cfg_checksum): Declare. - (function_list): New structure. - (functions_head, functions_tail): New static variables. - (end_final): Emits more data, removed some -ax stuff. - (final): Stores function names and chcksums. - * gcov-io.h (__write_gcov_string): New function. - (__read_gcov_string): New function. - * gcov.c (read_profile): New function. - (create_program_flow_graph): Uses read_profile instead of reading + (profile.o): New dependency profile.h + (final.o): New dependency profile.h + * profile.h: New file. New global structure profile_info. + * final.h (count_edges_instrumented_now): Declare. + (current_function_cfg_checksum): Declare. + (function_list): New structure. + (functions_head, functions_tail): New static variables. + (end_final): Emits more data, removed some -ax stuff. + (final): Stores function names and chcksums. + * gcov-io.h (__write_gcov_string): New function. + (__read_gcov_string): New function. + * gcov.c (read_profile): New function. + (create_program_flow_graph): Uses read_profile instead of reading da_file. - (read_files): Removed da_file checking, it's done by read_profile now. - * libgcc2.c (bb_function_info): New structure. - (bb): New field in structure, removed some -ax stuff. - (__bb_exit_func): Changed structure of da_file. - * profile.c (count_edges_instrumented_now): New global variable. - (current_function_cfg_checksum): New global variable. - (max_counter_in_program): New global variable. - (get_exec_counts): New function. - (compute_checksum): New function. - (instrument_edges): Sets count_edges_instrumented_now. - (compute_branch_probabilities): Uses get_exec_counts instead of + (read_files): Removed da_file checking, it's done by read_profile now. + * libgcc2.c (bb_function_info): New structure. + (bb): New field in structure, removed some -ax stuff. + (__bb_exit_func): Changed structure of da_file. + * profile.c (count_edges_instrumented_now): New global variable. + (current_function_cfg_checksum): New global variable. + (max_counter_in_program): New global variable. + (get_exec_counts): New function. + (compute_checksum): New function. + (instrument_edges): Sets count_edges_instrumented_now. + (compute_branch_probabilities): Uses get_exec_counts instead of reading da_file. - (branch_prob): Calls compute_checksum and writes extra data to bbg_file. - (init_branch_prob): Removed da_file checking, done in get_exec_counts + (branch_prob): Calls compute_checksum and writes extra data to bbg_file. + (init_branch_prob): Removed da_file checking, done in get_exec_counts now. - (end_branch_prob): Removed da_file checking, done in get_exec_counts + (end_branch_prob): Removed da_file checking, done in get_exec_counts now. - * gcov.texi: Updated information about gcov file format. + * gcov.texi: Updated information about gcov file format. 2002-05-09 Kazu Hirata @@ -347,7 +382,7 @@ doc: * config/arm/t-arm-elf (MULTILIB): Do not allow big-endian/ little-endian multilibs to override arm/thumb multilibs. - Do not build hardware floating point multilibs, nor apcs-26 + Do not build hardware floating point multilibs, nor apcs-26 multilibs for the Thumb. 2002-05-08 Mark Mitchell @@ -496,7 +531,7 @@ Tue May 7 10:06:22 2002 Jeffrey A Law (law@redhat.com) 2002-05-07 Aldy Hernandez - * config/rs6000/rs6000.c (bdesc_2arg): Fix vmax typos. + * config/rs6000/rs6000.c (bdesc_2arg): Fix vmax typos. 2002-05-06 David S. Miller diff --git a/gcc/config.gcc b/gcc/config.gcc index 15038c54769..e6c268c1aec 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -3650,6 +3650,9 @@ powerpc*-*-* | rs6000-*-*) fi ;; esac + c_target_objs="rs6000-c.o" + cxx_target_objs="rs6000-c.o" + tmake_file="${tmake_file} rs6000/t-rs6000-c-rule" ;; sparc*-*-*) case ".$with_cpu" in diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c new file mode 100644 index 00000000000..33ce2a1420d --- /dev/null +++ b/gcc/config/rs6000/rs6000-c.c @@ -0,0 +1,71 @@ +/* Subroutines for the C front end on the POWER and PowerPC architectures. + Copyright (C) 2002 + Free Software Foundation, Inc. + + Contributed by Zack Weinberg + +This file is part of GNU CC. + +GNU CC 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 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" +#include "system.h" +#include "cpplib.h" +#include "tree.h" +#include "c-lex.h" +#include "errors.h" +#include "tm_p.h" + +/* Handle the machine specific pragma longcall. Its syntax is + + # pragma longcall ( TOGGLE ) + + where TOGGLE is either 0 or 1. + + rs6000_default_long_calls is set to the value of TOGGLE, changing + whether or not new function declarations receive a longcall + attribute by default. */ + +#define SYNTAX_ERROR(msgid) do { \ + warning (msgid); \ + warning ("ignoring malformed #pragma longcall"); \ + return; \ +} while (0) + +void +rs6000_pragma_longcall (pfile) + cpp_reader *pfile ATTRIBUTE_UNUSED; +{ + tree x, n; + + /* If we get here, generic code has already scanned the directive + leader and the word "longcall". */ + + if (c_lex (&x) != CPP_OPEN_PAREN) + SYNTAX_ERROR ("missing open paren"); + if (c_lex (&n) != CPP_NUMBER) + SYNTAX_ERROR ("missing number"); + if (c_lex (&x) != CPP_CLOSE_PAREN) + SYNTAX_ERROR ("missing close paren"); + + if (n != integer_zero_node && n != integer_one_node) + SYNTAX_ERROR ("number must be 0 or 1"); + + if (c_lex (&x) != CPP_EOF) + warning ("junk at end of #pragma longcall"); + + rs6000_default_long_calls = (n == integer_one_node); +} diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 50367e35e25..26bb1e6cd13 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -19,6 +19,9 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef GCC_RS6000_PROTOS_H +#define GCC_RS6000_PROTOS_H + /* Declare functions in rs6000.c */ #ifdef RTX_CODE @@ -186,3 +189,9 @@ extern void rs6000_emit_epilogue PARAMS ((int)); extern void debug_stack_info PARAMS ((rs6000_stack_t *)); extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *)); + +#ifdef GCC_CPPLIB_H +extern void rs6000_pragma_longcall PARAMS ((cpp_reader *)); +#endif + +#endif /* rs6000-protos.h */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index e40340b7a06..c6b703bcc8a 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -124,6 +124,13 @@ char toc_label_name[10]; /* Alias set for saves and restores from the rs6000 stack. */ static int rs6000_sr_alias_set; +/* Call distance, overridden by -mlongcall and #pragma longcall(1). + The only place that looks at this is rs6000_set_default_type_attributes; + everywhere else should rely on the presence or absence of a longcall + attribute on the function declaration. */ +int rs6000_default_long_calls; +const char *rs6000_longcall_switch; + static void rs6000_add_gc_roots PARAMS ((void)); static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT)); static rtx expand_block_move_mem PARAMS ((enum machine_mode, rtx, rtx)); @@ -146,6 +153,7 @@ static bool rs6000_assemble_integer PARAMS ((rtx, unsigned int, int)); static int rs6000_ra_ever_killed PARAMS ((void)); static tree rs6000_handle_longcall_attribute PARAMS ((tree *, tree, tree, int, bool *)); const struct attribute_spec rs6000_attribute_table[]; +static void rs6000_set_default_type_attributes PARAMS ((tree)); static void rs6000_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT)); static void rs6000_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT)); static rtx rs6000_emit_set_long_const PARAMS ((rtx, @@ -235,6 +243,8 @@ static const char alt_reg_names[][8] = /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table +#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES +#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES rs6000_set_default_type_attributes #undef TARGET_ASM_ALIGNED_DI_OP #define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP @@ -546,6 +556,22 @@ rs6000_override_options (default_cpu) /* Handle -mvrsave= option. */ rs6000_parse_vrsave_option (); + /* Handle -m(no-)longcall option. This is a bit of a cheap hack, + using TARGET_OPTIONS to handle a toggle switch, but we're out of + bits in target_flags so TARGET_SWITCHES cannot be used. + Assumption here is that rs6000_longcall_switch points into the + text of the complete option, rather than being a copy, so we can + scan back for the presence or absence of the no- modifier. */ + if (rs6000_longcall_switch) + { + const char *base = rs6000_longcall_switch; + while (base[-1] != 'm') base--; + + if (*rs6000_longcall_switch != '\0') + error ("invalid option `%s'", base); + rs6000_default_long_calls = (base[0] != 'n'); + } + #ifdef TARGET_REGNAMES /* If the user desires alternate register names, copy in the alternate names now. */ @@ -2541,8 +2567,10 @@ init_cumulative_args (cum, fntype, libname, incoming) cum->orig_nargs = cum->nargs_prototype; - /* Check for longcall's */ - if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype))) + /* Check for a longcall attribute. */ + if (fntype + && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)) + && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype))) cum->call_cookie = CALL_LONG; if (TARGET_DEBUG_ARG) @@ -3565,6 +3593,8 @@ altivec_expand_unop_builtin (icode, arglist, target) return NULL_RTX; } break; + default: + break; } if (target == 0 @@ -3654,6 +3684,8 @@ altivec_expand_binop_builtin (icode, arglist, target) return NULL_RTX; } break; + default: + break; } if (target == 0 @@ -3828,6 +3860,8 @@ altivec_expand_ternop_builtin (icode, arglist, target) return NULL_RTX; } break; + default: + break; } if (target == 0 @@ -9871,8 +9905,11 @@ output_mi_thunk (file, thunk_fndecl, delta, function) fname = XSTR (XEXP (DECL_RTL (function), 0), 0); if (current_file_function_operand (XEXP (DECL_RTL (function), 0), VOIDmode) - && ! lookup_attribute ("longcall", - TYPE_ATTRIBUTES (TREE_TYPE (function)))) + && (! lookup_attribute ("longcall", + TYPE_ATTRIBUTES (TREE_TYPE (function))) + || lookup_attribute ("shortcall", + TYPE_ATTRIBUTES (TREE_TYPE (function))))) + { fprintf (file, "\tb %s", prefix); assemble_name (file, fname); @@ -10852,12 +10889,13 @@ rs6000_initialize_trampoline (addr, fnaddr, cxt) const struct attribute_spec rs6000_attribute_table[] = { /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute }, - { NULL, 0, 0, false, false, false, NULL } + { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute }, + { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute }, + { NULL, 0, 0, false, false, false, NULL } }; -/* Handle a "longcall" attribute; arguments as in struct - attribute_spec.handler. */ +/* Handle a "longcall" or "shortcall" attribute; arguments as in + struct attribute_spec.handler. */ static tree rs6000_handle_longcall_attribute (node, name, args, flags, no_add_attrs) @@ -10879,6 +10917,20 @@ rs6000_handle_longcall_attribute (node, name, args, flags, no_add_attrs) return NULL_TREE; } +/* Set longcall attributes on all functions declared when + rs6000_default_long_calls is true. */ +static void +rs6000_set_default_type_attributes (type) + tree type; +{ + if (rs6000_default_long_calls + && (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE)) + TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"), + NULL_TREE, + TYPE_ATTRIBUTES (type)); +} + /* Return a reference suitable for calling a function with the longcall attribute. */ diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f5bfbfe7add..91627a289b0 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -432,6 +432,9 @@ extern enum processor_type rs6000_cpu; N_("Specify size of long double (64 or 128 bits)") }, \ {"vrsave=", &rs6000_altivec_vrsave_string, \ N_("Specify yes/no if VRSAVE instructions should be generated for AltiVec") }, \ + {"longcall", &rs6000_longcall_switch, \ + N_("Avoid all range limits on call instructions") }, \ + {"no-longcall", &rs6000_longcall_switch, "" }, \ SUBTARGET_OPTIONS \ } @@ -462,6 +465,8 @@ extern int rs6000_long_double_type_size; extern int rs6000_altivec_abi; extern const char *rs6000_altivec_vrsave_string; extern int rs6000_altivec_vrsave; +extern const char *rs6000_longcall_switch; +extern int rs6000_default_long_calls; #define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128) #define TARGET_ALTIVEC_ABI rs6000_altivec_abi @@ -483,6 +488,11 @@ extern int rs6000_altivec_vrsave; /* Define this to change the optimizations performed by default. */ #define OPTIMIZATION_OPTIONS(LEVEL,SIZE) optimization_options(LEVEL,SIZE) +/* Target pragma. */ +#define REGISTER_TARGET_PRAGMAS(PFILE) do { \ + cpp_register_pragma (PFILE, 0, "longcall", rs6000_pragma_longcall); \ +} while (0) + /* Show we can debug even without a frame pointer. */ #define CAN_DEBUG_WITHOUT_FP diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 7b2cd6e7163..6b66c42e088 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10036,68 +10036,89 @@ ;; operands[2] is the value FUNCTION_ARG returns for the VOID argument ;; which indicates how to set cr1 -(define_insn "*call_nonlocal_sysv" - [(call (mem:SI (match_operand:SI 0 "call_operand" "cl,cl,s,s")) - (match_operand 1 "" "g,g,g,g")) - (use (match_operand:SI 2 "immediate_operand" "O,n,O,n")) - (clobber (match_scratch:SI 3 "=l,l,l,l"))] +(define_insn "*call_indirect_nonlocal_sysv" + [(call (mem:SI (match_operand:SI 0 "register_operand" "cl,cl")) + (match_operand 1 "" "g,g")) + (use (match_operand:SI 2 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 3 "=l,l"))] "DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN" - "* { if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); + output_asm_insn ("creqv 6,6,6", operands); - switch (which_alternative) - { - default: - abort (); - case 0: - case 1: - return \"b%T0l\"; - case 2: - case 3: - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z0@plt\" : \"bl %z0\"; - } -}" - [(set_attr "type" "jmpreg,jmpreg,branch,branch") - (set_attr "length" "4,8,4,8")]) + return "b%T0l"; +} + [(set_attr "type" "jmpreg,jmpreg") + (set_attr "length" "4,8")]) -(define_insn "*call_value_nonlocal_sysv" +(define_insn "*call_nonlocal_sysv" + [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s")) + (match_operand 1 "" "g,g")) + (use (match_operand:SI 2 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 3 "=l,l"))] + "(DEFAULT_ABI == ABI_AIX_NODESC + || DEFAULT_ABI == ABI_V4 + || DEFAULT_ABI == ABI_DARWIN) + && (INTVAL (operands[2]) & CALL_LONG) == 0" +{ + if (INTVAL (operands[2]) & CALL_V4_SET_FP_ARGS) + output_asm_insn ("crxor 6,6,6", operands); + + else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0"; +} + [(set_attr "type" "branch,branch") + (set_attr "length" "4,8")]) + +(define_insn "*call_value_indirect_nonlocal_sysv" [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:SI 1 "call_operand" "cl,cl,s,s")) - (match_operand 2 "" "g,g,g,g"))) - (use (match_operand:SI 3 "immediate_operand" "O,n,O,n")) - (clobber (match_scratch:SI 4 "=l,l,l,l"))] + (call (mem:SI (match_operand:SI 1 "register_operand" "cl,cl")) + (match_operand 2 "" "g,g"))) + (use (match_operand:SI 3 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 4 "=l,l"))] "DEFAULT_ABI == ABI_AIX_NODESC || DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN" - "* { if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) - output_asm_insn (\"crxor 6,6,6\", operands); + output_asm_insn ("crxor 6,6,6", operands); else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) - output_asm_insn (\"creqv 6,6,6\", operands); + output_asm_insn ("creqv 6,6,6", operands); - switch (which_alternative) - { - default: - abort (); - case 0: - case 1: - return \"b%T1l\"; - case 2: - case 3: - return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"bl %z1@plt\" : \"bl %z1\"; - } -}" - [(set_attr "type" "jmpreg,jmpreg,branch,branch") - (set_attr "length" "4,8,4,8")]) + return "b%T1l"; +} + [(set_attr "type" "jmpreg,jmpreg") + (set_attr "length" "4,8")]) + +(define_insn "*call_value_nonlocal_sysv" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s")) + (match_operand 2 "" "g,g"))) + (use (match_operand:SI 3 "immediate_operand" "O,n")) + (clobber (match_scratch:SI 4 "=l,l"))] + "(DEFAULT_ABI == ABI_AIX_NODESC + || DEFAULT_ABI == ABI_V4 + || DEFAULT_ABI == ABI_DARWIN) + && (INTVAL (operands[3]) & CALL_LONG) == 0" +{ + if (INTVAL (operands[3]) & CALL_V4_SET_FP_ARGS) + output_asm_insn ("crxor 6,6,6", operands); + + else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) + output_asm_insn ("creqv 6,6,6", operands); + + return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1"; +} + [(set_attr "type" "branch,branch") + (set_attr "length" "4,8")]) ;; Call subroutine returning any type. (define_expand "untyped_call" diff --git a/gcc/config/rs6000/t-rs6000-c-rule b/gcc/config/rs6000/t-rs6000-c-rule new file mode 100644 index 00000000000..3be9d67304d --- /dev/null +++ b/gcc/config/rs6000/t-rs6000-c-rule @@ -0,0 +1,4 @@ +rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \ + $(srcdir)/config/rs6000/rs6000-protos.h \ + $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) $(TM_P_H) c-lex.h errors.h + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 2545acfa23b..b27bec4c3bf 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2273,12 +2273,17 @@ useful to override the effects of the @option{-mrtd} switch. The PowerPC compiler for Windows NT currently ignores the @code{cdecl} attribute. -@item longcall +@item longcall/shortcall @cindex functions called via pointer on the RS/6000 and PowerPC On the RS/6000 and PowerPC, the @code{longcall} attribute causes the -compiler to always call the function via a pointer, so that functions -which reside further than 64 megabytes (67,108,864 bytes) from the -current location can be called. +compiler to always call this function via a pointer, just as it would if +the @option{-mlongcall} option had been specified. The @code{shortcall} +attribute causes the compiler not to do this. These attributes override +both the @option{-mlongcall} switch and the @code{#pragma longcall} +setting. + +@xref{RS/6000 and PowerPC Options}, for more information on when long +calls are and are not necessary. @item long_call/short_call @cindex indirect calls on ARM @@ -5992,6 +5997,7 @@ for further explanation. @menu * ARM Pragmas:: +* RS/6000 and PowerPC Pragmas:: * Darwin Pragmas:: * Solaris Pragmas:: * Tru64 Pragmas:: @@ -6020,6 +6026,27 @@ Do not affect the @code{long_call} or @code{short_call} attributes of subsequent functions. @end table +@node RS/6000 and PowerPC Pragmas +@subsection RS/6000 and PowerPC Pragmas + +The RS/6000 and PowerPC targets define one pragma for controlling +whether or not the @code{longcall} attribute is added to function +declarations by default. This pragma overrides the @option{-mlongcall} +option, but not the @code{longcall} and @code{shortcall} attributes. +@xref{RS/6000 and PowerPC Options}, for more information about when long +calls are and are not necessary. + +@table @code +@item longcall (1) +@cindex pragma, longcall +Apply the @code{longcall} attribute to all subsequent function +declarations. + +@item longcall (0) +Do not apply the @code{longcall} attribute to subsequent function +declarations. +@end table + @c Describe c4x pragmas here. @c Describe h8300 pragmas here. @c Describe i370 pragmas here. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d422bf2ecbf..68b888fca94 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6817,6 +6817,24 @@ All modules should be compiled with the same @option{-G @var{num}} value. On System V.4 and embedded PowerPC systems do (do not) emit register names in the assembly language output using symbolic forms. +@item -mlongcall +@itemx -mno-longcall +@opindex mlongcall +@opindex mno-longcall +Default to making all function calls via pointers, so that functions +which reside further than 64 megabytes (67,108,864 bytes) from the +current location can be called. This setting can be overridden by the +@code{shortcall} function attribute, or by @code{#pragma longcall(0)}. + +Some linkers are capable of detecting out-of-range calls and generating +glue code on the fly. On these systems, long calls are unnecessary and +generate slower code. As of this writing, the AIX linker can do this, +as can the GNU linker for PowerPC/64. It is planned to add this feature +to the GNU linker for 32-bit PowerPC systems as well. + +In the future, we may cause GCC to ignore all longcall specifications +when the linker is known to generate glue. + @item -pthread @opindex pthread Adds support for multithreading with the @dfn{pthreads} library. -- 2.30.2