diff options
-rw-r--r-- | gcc/ChangeLog | 36 | ||||
-rw-r--r-- | gcc/config.in | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/predicates.md | 18 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 359 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 4 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 247 | ||||
-rwxr-xr-x | gcc/configure | 48 | ||||
-rw-r--r-- | gcc/configure.ac | 6 |
9 files changed, 602 insertions, 124 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 50148302f19..56dd30f9b3e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,41 @@ 2018-11-29 Alan Modra <amodra@gmail.com> + * config.in (HAVE_AS_PLTSEQ): Add. + * config/rs6000/predicates.md (indirect_call_operand): New. + * config/rs6000/rs6000-protos.h (rs6000_pltseq_template), + (rs6000_sibcall_sysv): Declare. + * config/rs6000/rs6000.c (init_cumulative_args): Set cookie + CALL_LONG for -fno-plt. + (print_operand <T, z, 0>): Handle UNSPEC_PLTSEQ. + (rs6000_indirect_call_template_1): Emit .reloc directives for + UNSPEC_PLTSEQ calls. + (rs6000_pltseq_template): New function. + (rs6000_longcall_ref): Add arg parameter. Use PLT16 insns if + relocs supported by assembler. Move SYMBOL_REF test to callers. + (rs6000_call_aix): Adjust rs6000_longcall_ref call. Package + insns in UNSPEC_PLTSEQ, preserving original func_desc. + (rs6000_call_sysv): Likewise. + (rs6000_sibcall_sysv): New function. + * config/rs6000/rs6000.h (HAVE_AS_PLTSEQ): Provide default. + * config/rs6000/rs6000.md (UNSPEC_PLTSEQ, UNSPEC_PLT16_HA, + UNSPEC_PLT16_LO): New. + (pltseq_tocsave, pltseq_plt16_ha, pltseq_plt16_lo, pltseq_mtctr): New. + (call_indirect_nonlocal_sysv): Don't differentiate zero from non-zero + cookie in constraints. Test explicitly for flags in length attr. + Handle unspec operand 1. + (call_value_indirect_nonlocal_sysv): Likewise. + (call_indirect_aix, call_value_indirect_aix): Handle unspec operand 1. + (call_indirect_elfv2, call_value_indirect_elfv2): Likewise. + (sibcall, sibcall_value): Use rs6000_sibcall_sysv. + (sibcall_indirect_nonlocal_sysv): New pattern. + (sibcall_value_indirect_nonlocal_sysv): Likewise. + (sibcall_nonlocal_sysv, sibcall_value_nonlocal_sysv): Remove indirect + call alternatives. + * configure.ac: Check for gas plt sequence marker support. + * configure: Regenerate. + +2018-11-29 Alan Modra <amodra@gmail.com> + * config/rs6000/predicates.md (unspec_tls): New. * config/rs6000/rs6000-protos.h (rs6000_call_template), (rs6000_sibcall_template): Update prototype. diff --git a/gcc/config.in b/gcc/config.in index 999ade4154c..48a533bf208 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -577,6 +577,12 @@ #endif +/* Define if your assembler supports R_PPC*_PLTSEQ relocations. */ +#ifndef USED_FOR_TARGET +#undef HAVE_AS_PLTSEQ +#endif + + /* Define if your assembler supports .ref */ #ifndef USED_FOR_TARGET #undef HAVE_AS_REF diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 2c297fc45e8..e98b00dec5d 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1013,6 +1013,24 @@ || REGNO (op) >= FIRST_PSEUDO_REGISTER") (match_code "symbol_ref"))) +;; Return 1 if the operand, used inside a MEM, is a valid first argument +;; to an indirect CALL. This is LR, CTR, or a PLTSEQ unspec using CTR. +(define_predicate "indirect_call_operand" + (match_code "reg,unspec") +{ + if (REG_P (op)) + return (REGNO (op) == LR_REGNO + || REGNO (op) == CTR_REGNO); + if (GET_CODE (op) == UNSPEC) + { + if (XINT (op, 1) != UNSPEC_PLTSEQ) + return false; + op = XVECEXP (op, 0, 0); + return REG_P (op) && REGNO (op) == CTR_REGNO; + } + return false; +}) + ;; Return 1 if the operand is a SYMBOL_REF for a function known to be in ;; this file. (define_predicate "current_file_function_operand" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index dd930bb2da6..1dfe7995ff1 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -109,6 +109,7 @@ extern const char *rs6000_call_template (rtx *, unsigned int); extern const char *rs6000_sibcall_template (rtx *, unsigned int); extern const char *rs6000_indirect_call_template (rtx *, unsigned int); extern const char *rs6000_indirect_sibcall_template (rtx *, unsigned int); +extern const char *rs6000_pltseq_template (rtx *, int); extern enum rtx_code rs6000_reverse_condition (machine_mode, enum rtx_code); extern rtx rs6000_emit_eqne (machine_mode, rtx, rtx, rtx); @@ -198,6 +199,7 @@ extern void rs6000_emit_eh_reg_restore (rtx, rtx); extern void rs6000_call_aix (rtx, rtx, rtx, rtx); extern void rs6000_sibcall_aix (rtx, rtx, rtx, rtx); extern void rs6000_call_sysv (rtx, rtx, rtx, rtx); +extern void rs6000_sibcall_sysv (rtx, rtx, rtx, rtx); extern void rs6000_aix_asm_output_dwarf_table_ref (char *); extern void get_ppc476_thunk_name (char name[32]); extern bool rs6000_overloaded_builtin_p (enum rs6000_builtins); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index f3376065ee1..1c4bdb0cfd6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -10689,7 +10689,7 @@ void init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname ATTRIBUTE_UNUSED, int incoming, int libcall, int n_named_args, - tree fndecl ATTRIBUTE_UNUSED, + tree fndecl, machine_mode return_mode ATTRIBUTE_UNUSED) { static CUMULATIVE_ARGS zero_cumulative; @@ -10715,6 +10715,27 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)) && !lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))) cum->call_cookie |= CALL_LONG; + else if (DEFAULT_ABI != ABI_DARWIN) + { + bool is_local = (fndecl + && !DECL_EXTERNAL (fndecl) + && !DECL_WEAK (fndecl) + && (*targetm.binds_local_p) (fndecl)); + if (is_local) + ; + else if (flag_plt) + { + if (fntype + && lookup_attribute ("noplt", TYPE_ATTRIBUTES (fntype))) + cum->call_cookie |= CALL_LONG; + } + else + { + if (!(fntype + && lookup_attribute ("plt", TYPE_ATTRIBUTES (fntype)))) + cum->call_cookie |= CALL_LONG; + } + } if (TARGET_DEBUG_ARG) { @@ -20946,6 +20967,8 @@ print_operand (FILE *file, rtx x, int code) case 'T': /* Print the symbolic name of a branch target register. */ + if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PLTSEQ) + x = XVECEXP (x, 0, 0); if (GET_CODE (x) != REG || (REGNO (x) != LR_REGNO && REGNO (x) != CTR_REGNO)) output_operand_lossage ("invalid %%T value"); @@ -21089,6 +21112,8 @@ print_operand (FILE *file, rtx x, int code) return; case 'z': + if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PLTSEQ) + x = XVECEXP (x, 0, 1); /* X is a SYMBOL_REF. Write out the name preceded by a period and without any trailing data in brackets. Used for function names. If we are configured for System V (or the embedded ABI) on @@ -21208,6 +21233,8 @@ print_operand (FILE *file, rtx x, int code) output_addr_const (file, CONST_CAST_RTX (tocrel_base_oac)); else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD) output_addr_const (file, XVECEXP (x, 0, 0)); + else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PLTSEQ) + output_addr_const (file, XVECEXP (x, 0, 1)); else output_addr_const (file, x); return; @@ -21457,9 +21484,15 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop, might produce 10 digits. */ gcc_assert (funop <= MAX_RECOG_OPERANDS); - static char str[144]; + static char str[144]; /* 1 spare */ + char *s = str; const char *ptrload = TARGET_64BIT ? "d" : "wz"; + if (DEFAULT_ABI == ABI_AIX) + s += sprintf (s, + "l%s 2,%%%u\n\t", + ptrload, funop + 2); + /* We don't need the extra code to stop indirect call speculation if calling via LR. */ bool speculate = (TARGET_MACHO @@ -21467,32 +21500,61 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop, || (REG_P (operands[funop]) && REGNO (operands[funop]) == LR_REGNO)); + if (!TARGET_MACHO && HAVE_AS_PLTSEQ && GET_CODE (operands[funop]) == UNSPEC) + { + const char *rel64 = TARGET_64BIT ? "64" : ""; + char tls[29]; + tls[0] = 0; + if (GET_CODE (operands[funop + 1]) == UNSPEC) + { + if (XINT (operands[funop + 1], 1) == UNSPEC_TLSGD) + sprintf (tls, ".reloc .,R_PPC%s_TLSGD,%%%u\n\t", + rel64, funop + 1); + else if (XINT (operands[funop + 1], 1) == UNSPEC_TLSLD) + sprintf (tls, ".reloc .,R_PPC%s_TLSLD,%%&\n\t", + rel64); + else + gcc_unreachable (); + } + + const char *addend = (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT + && flag_pic == 2 ? "+32768" : ""); + if (!speculate) + { + s += sprintf (s, + "%s.reloc .,R_PPC%s_PLTSEQ,%%z%u%s\n\t", + tls, rel64, funop, addend); + s += sprintf (s, "crset 2\n\t"); + } + s += sprintf (s, + "%s.reloc .,R_PPC%s_PLTCALL,%%z%u%s\n\t", + tls, rel64, funop, addend); + } + else if (!speculate) + s += sprintf (s, "crset 2\n\t"); + if (DEFAULT_ABI == ABI_AIX) { if (speculate) - sprintf (str, - "l%s 2,%%%u\n\t" + sprintf (s, "b%%T%ul\n\t" "l%s 2,%%%u(1)", - ptrload, funop + 2, funop, ptrload, funop + 3); + funop, ptrload, funop + 3); else - sprintf (str, - "crset 2\n\t" - "l%s 2,%%%u\n\t" + sprintf (s, "beq%%T%ul-\n\t" "l%s 2,%%%u(1)", - ptrload, funop + 2, funop, ptrload, funop + 3); + funop, ptrload, funop + 3); } else if (DEFAULT_ABI == ABI_ELFv2) { if (speculate) - sprintf (str, + sprintf (s, "b%%T%ul\n\t" "l%s 2,%%%u(1)", funop, ptrload, funop + 2); else - sprintf (str, - "crset 2\n\t" + sprintf (s, "beq%%T%ul-\n\t" "l%s 2,%%%u(1)", funop, ptrload, funop + 2); @@ -21500,12 +21562,11 @@ rs6000_indirect_call_template_1 (rtx *operands, unsigned int funop, else { if (speculate) - sprintf (str, + sprintf (s, "b%%T%u%s", funop, sibcall ? "" : "l"); else - sprintf (str, - "crset 2\n\t" + sprintf (s, "beq%%T%u%s-%s", funop, sibcall ? "" : "l", sibcall ? "\n\tb $" : ""); } @@ -21524,6 +21585,72 @@ rs6000_indirect_sibcall_template (rtx *operands, unsigned int funop) return rs6000_indirect_call_template_1 (operands, funop, true); } +#if HAVE_AS_PLTSEQ +/* Output indirect call insns. + WHICH is 0 for tocsave, 1 for plt16_ha, 2 for plt16_lo, 3 for mtctr. */ +const char * +rs6000_pltseq_template (rtx *operands, int which) +{ + const char *rel64 = TARGET_64BIT ? "64" : ""; + char tls[28]; + tls[0] = 0; + if (GET_CODE (operands[3]) == UNSPEC) + { + if (XINT (operands[3], 1) == UNSPEC_TLSGD) + sprintf (tls, ".reloc .,R_PPC%s_TLSGD,%%3\n\t", + rel64); + else if (XINT (operands[3], 1) == UNSPEC_TLSLD) + sprintf (tls, ".reloc .,R_PPC%s_TLSLD,%%&\n\t", + rel64); + else + gcc_unreachable (); + } + + gcc_assert (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4); + static char str[96]; /* 15 spare */ + const char *off = WORDS_BIG_ENDIAN ? "+2" : ""; + const char *addend = (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT + && flag_pic == 2 ? "+32768" : ""); + switch (which) + { + case 0: + sprintf (str, + "%s.reloc .,R_PPC%s_PLTSEQ,%%z2\n\t" + "st%s", + tls, rel64, TARGET_64BIT ? "d 2,24(1)" : "w 2,12(1)"); + break; + case 1: + if (DEFAULT_ABI == ABI_V4 && !flag_pic) + sprintf (str, + "%s.reloc .%s,R_PPC%s_PLT16_HA,%%z2\n\t" + "lis %%0,0", + tls, off, rel64); + else + sprintf (str, + "%s.reloc .%s,R_PPC%s_PLT16_HA,%%z2%s\n\t" + "addis %%0,%%1,0", + tls, off, rel64, addend); + break; + case 2: + sprintf (str, + "%s.reloc .%s,R_PPC%s_PLT16_LO%s,%%z2%s\n\t" + "l%s %%0,0(%%1)", + tls, off, rel64, TARGET_64BIT ? "_DS" : "", addend, + TARGET_64BIT ? "d" : "wz"); + break; + case 3: + sprintf (str, + "%s.reloc .,R_PPC%s_PLTSEQ,%%z2%s\n\t" + "mtctr %%1", + tls, rel64, addend); + break; + default: + gcc_unreachable (); + } + return str; +} +#endif + #if defined (HAVE_GAS_HIDDEN) && !TARGET_MACHO /* Emit an assembler directive to set symbol visibility for DECL to VISIBILITY_TYPE. */ @@ -32535,11 +32662,8 @@ rs6000_set_default_type_attributes (tree type) longcall attribute. */ static rtx -rs6000_longcall_ref (rtx call_ref) +rs6000_longcall_ref (rtx call_ref, rtx arg) { - if (GET_CODE (call_ref) != SYMBOL_REF) - return call_ref; - /* System V adds '.' to the internal name, so skip them. */ const char *call_name = XSTR (call_ref, 0); if (*call_name == '.') @@ -32551,6 +32675,36 @@ rs6000_longcall_ref (rtx call_ref) call_ref = gen_rtx_SYMBOL_REF (VOIDmode, IDENTIFIER_POINTER (node)); } + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS + && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)) + { + rtx base = const0_rtx; + int regno; + if (DEFAULT_ABI == ABI_ELFv2) + { + base = gen_rtx_REG (Pmode, TOC_REGISTER); + regno = 12; + } + else + { + if (flag_pic) + base = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM); + regno = 11; + } + /* Reg must match that used by linker PLT stubs. For ELFv2, r12 + may be used by a function global entry point. For SysV4, r11 + is used by __glink_PLTresolve lazy resolver entry. */ + rtx reg = gen_rtx_REG (Pmode, regno); + rtx hi = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, base, call_ref, arg), + UNSPEC_PLT16_HA); + rtx lo = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, reg, call_ref, arg), + UNSPEC_PLT16_LO); + emit_insn (gen_rtx_SET (reg, hi)); + emit_insn (gen_rtx_SET (reg, lo)); + return reg; + } + return force_reg (Pmode, call_ref); } @@ -37520,8 +37674,7 @@ chain_already_loaded (rtx_insn *last) void rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) { - const bool direct_call_p - = GET_CODE (func_desc) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (func_desc); + rtx func = func_desc; rtx toc_reg = gen_rtx_REG (Pmode, TOC_REGNUM); rtx toc_load = NULL_RTX; rtx toc_restore = NULL_RTX; @@ -37535,12 +37688,13 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) tlsarg = global_tlsarg; /* Handle longcall attributes. */ - if (INTVAL (cookie) & CALL_LONG) - func_desc = rs6000_longcall_ref (func_desc); + if ((INTVAL (cookie) & CALL_LONG) != 0 + && GET_CODE (func_desc) == SYMBOL_REF) + func = rs6000_longcall_ref (func_desc, tlsarg); /* Handle indirect calls. */ - if (GET_CODE (func_desc) != SYMBOL_REF - || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func_desc))) + if (GET_CODE (func) != SYMBOL_REF + || (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (func))) { /* Save the TOC into its reserved slot before the call, and prepare to restore it after the call. */ @@ -37561,7 +37715,17 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) gen_rtx_PLUS (Pmode, stack_ptr, stack_toc_offset)); MEM_VOLATILE_P (stack_toc_mem) = 1; - emit_move_insn (stack_toc_mem, toc_reg); + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS + && DEFAULT_ABI == ABI_ELFv2 + && GET_CODE (func_desc) == SYMBOL_REF) + { + rtvec v = gen_rtvec (3, toc_reg, func_desc, tlsarg); + rtx mark_toc_reg = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + emit_insn (gen_rtx_SET (stack_toc_mem, mark_toc_reg)); + } + else + emit_move_insn (stack_toc_mem, toc_reg); } if (DEFAULT_ABI == ABI_ELFv2) @@ -37569,9 +37733,25 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) /* A function pointer in the ELFv2 ABI is just a plain address, but the ABI requires it to be loaded into r12 before the call. */ func_addr = gen_rtx_REG (Pmode, 12); - if (!rtx_equal_p (func_addr, func_desc)) - emit_move_insn (func_addr, func_desc); + if (!rtx_equal_p (func_addr, func)) + emit_move_insn (func_addr, func); abi_reg = func_addr; + /* Indirect calls via CTR are strongly preferred over indirect + calls via LR, so move the address there. Needed to mark + this insn for linker plt sequence editing too. */ + func_addr = gen_rtx_REG (Pmode, CTR_REGNO); + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS + && GET_CODE (func_desc) == SYMBOL_REF) + { + rtvec v = gen_rtvec (3, abi_reg, func_desc, tlsarg); + rtx mark_func = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + emit_insn (gen_rtx_SET (func_addr, mark_func)); + v = gen_rtvec (2, func_addr, func_desc); + func_addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + } + else + emit_move_insn (func_addr, abi_reg); } else { @@ -37583,9 +37763,15 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) not have any executable code. */ /* Load up address of the actual function. */ - func_desc = force_reg (Pmode, func_desc); + func = force_reg (Pmode, func); func_addr = gen_reg_rtx (Pmode); - emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func_desc)); + emit_move_insn (func_addr, gen_rtx_MEM (Pmode, func)); + + /* Indirect calls via CTR are strongly preferred over indirect + calls via LR, so move the address there. */ + rtx ctr_reg = gen_rtx_REG (Pmode, CTR_REGNO); + emit_move_insn (ctr_reg, func_addr); + func_addr = ctr_reg; /* Prepare to load the TOC of the called function. Note that the TOC load must happen immediately before the actual call so @@ -37593,7 +37779,7 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) comment in frob_update_context. */ rtx func_toc_offset = GEN_INT (GET_MODE_SIZE (Pmode)); rtx func_toc_mem = gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, func_desc, + gen_rtx_PLUS (Pmode, func, func_toc_offset)); toc_load = gen_rtx_USE (VOIDmode, func_toc_mem); @@ -37601,14 +37787,15 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) originally direct, the 3rd word has not been written since no trampoline has been built, so we ought not to load it, lest we override a static chain value. */ - if (!direct_call_p + if (!(GET_CODE (func_desc) == SYMBOL_REF + && SYMBOL_REF_FUNCTION_P (func_desc)) && TARGET_POINTERS_TO_NESTED_FUNCTIONS && !chain_already_loaded (get_current_sequence ()->next->last)) { rtx sc_reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); rtx func_sc_offset = GEN_INT (2 * GET_MODE_SIZE (Pmode)); rtx func_sc_mem = gen_rtx_MEM (Pmode, - gen_rtx_PLUS (Pmode, func_desc, + gen_rtx_PLUS (Pmode, func, func_sc_offset)); emit_move_insn (sc_reg, func_sc_mem); abi_reg = sc_reg; @@ -37621,7 +37808,7 @@ rs6000_call_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) assume the TOC register is set; for non-local calls, the PLT stub needs the TOC register. */ abi_reg = toc_reg; - func_addr = func_desc; + func_addr = func; } /* Create the call. */ @@ -37676,22 +37863,51 @@ rs6000_sibcall_aix (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) /* Expand code to perform a call under the SYSV4 ABI. */ void -rs6000_call_sysv (rtx value, rtx func, rtx tlsarg, rtx cookie) +rs6000_call_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) { + rtx func = func_desc; rtx func_addr; rtx call[3]; rtx insn; + rtx abi_reg = NULL_RTX; if (global_tlsarg) tlsarg = global_tlsarg; /* Handle longcall attributes. */ - if (INTVAL (cookie) & CALL_LONG) - func = rs6000_longcall_ref (func); + if ((INTVAL (cookie) & CALL_LONG) != 0 + && GET_CODE (func_desc) == SYMBOL_REF) + { + func = rs6000_longcall_ref (func_desc, tlsarg); + /* If the longcall was implemented using PLT16 relocs, then r11 + needs to be valid at the call for lazy linking. */ + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS) + abi_reg = func; + } /* Handle indirect calls. */ if (GET_CODE (func) != SYMBOL_REF) - func_addr = force_reg (Pmode, func); + { + func = force_reg (Pmode, func); + + /* Indirect calls via CTR are strongly preferred over indirect + calls via LR, so move the address there. Needed to mark + this insn for linker plt sequence editing too. */ + func_addr = gen_rtx_REG (Pmode, CTR_REGNO); + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS + && GET_CODE (func_desc) == SYMBOL_REF) + { + rtvec v = gen_rtvec (3, func, func_desc, tlsarg); + rtx mark_func = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + emit_insn (gen_rtx_SET (func_addr, mark_func)); + v = gen_rtvec (2, func_addr, func_desc); + func_addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + } + else + emit_move_insn (func_addr, func); + } else func_addr = func; @@ -37707,6 +37923,73 @@ rs6000_call_sysv (rtx value, rtx func, rtx tlsarg, rtx cookie) insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call)); insn = emit_call_insn (insn); + if (abi_reg) + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg); +} + +/* Expand code to perform a sibling call under the SysV4 ABI. */ + +void +rs6000_sibcall_sysv (rtx value, rtx func_desc, rtx tlsarg, rtx cookie) +{ + rtx func = func_desc; + rtx func_addr; + rtx call[3]; + rtx insn; + rtx abi_reg = NULL_RTX; + + if (global_tlsarg) + tlsarg = global_tlsarg; + + /* Handle longcall attributes. */ + if ((INTVAL (cookie) & CALL_LONG) != 0 + && GET_CODE (func_desc) == SYMBOL_REF) + { + func = rs6000_longcall_ref (func_desc, tlsarg); + /* If the longcall was implemented using PLT16 relocs, then r11 + needs to be valid at the call for lazy linking. */ + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS) + abi_reg = func; + } + + /* Handle indirect calls. */ + if (GET_CODE (func) != SYMBOL_REF) + { + func = force_reg (Pmode, func); + + /* Indirect sibcalls must go via CTR. Needed to mark + this insn for linker plt sequence editing too. */ + func_addr = gen_rtx_REG (Pmode, CTR_REGNO); + if (HAVE_AS_PLTSEQ + && TARGET_TLS_MARKERS + && GET_CODE (func_desc) == SYMBOL_REF) + { + rtvec v = gen_rtvec (3, func, func_desc, tlsarg); + rtx mark_func = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + emit_insn (gen_rtx_SET (func_addr, mark_func)); + v = gen_rtvec (2, func_addr, func_desc); + func_addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_PLTSEQ); + } + else + emit_move_insn (func_addr, func); + } + else + func_addr = func; + + /* Create the call. */ + call[0] = gen_rtx_CALL (VOIDmode, gen_rtx_MEM (SImode, func_addr), tlsarg); + if (value != NULL_RTX) + call[0] = gen_rtx_SET (value, call[0]); + + unsigned int mask = CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS; + call[1] = gen_rtx_USE (VOIDmode, GEN_INT (INTVAL (cookie) & mask)); + call[2] = simple_return_rtx; + + insn = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (3, call)); + insn = emit_call_insn (insn); + if (abi_reg) + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), abi_reg); } /* Return whether we need to always update the saved TOC pointer when we update diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index e62664fe2fb..2a62679bdb8 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -220,6 +220,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define HAVE_AS_TLS 0 #endif +#ifndef HAVE_AS_PLTSEQ +#define HAVE_AS_PLTSEQ 0 +#endif + #ifndef TARGET_LINK_STACK #define TARGET_LINK_STACK 0 #endif diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index ac87bb96436..8427a5e55bb 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -146,6 +146,9 @@ UNSPEC_SIGNBIT UNSPEC_SF_FROM_SI UNSPEC_SI_FROM_SF + UNSPEC_PLTSEQ + UNSPEC_PLT16_HA + UNSPEC_PLT16_LO ]) ;; @@ -10195,6 +10198,55 @@ (match_operand 2 "" "")))] "TARGET_ELF && !TARGET_64BIT && !flag_pic" "la %0,%2@l(%1)") + +(define_insn "*pltseq_tocsave_<mode>" + [(set (match_operand:P 0 "memory_operand" "=m") + (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "symbol_ref_operand" "s") + (match_operand:P 3 "" "")] + UNSPEC_PLTSEQ))] + "HAVE_AS_PLTSEQ && TARGET_TLS_MARKERS + && DEFAULT_ABI == ABI_ELFv2" +{ + return rs6000_pltseq_template (operands, 0); +}) + +(define_insn "*pltseq_plt16_ha_<mode>" + [(set (match_operand:P 0 "gpc_reg_operand" "=r") + (unspec:P [(match_operand:P 1 "" "") + (match_operand:P 2 "symbol_ref_operand" "s") + (match_operand:P 3 "" "")] + UNSPEC_PLT16_HA))] + "HAVE_AS_PLTSEQ && TARGET_TLS_MARKERS + && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)" +{ + return rs6000_pltseq_template (operands, 1); +}) + +(define_insn "*pltseq_plt16_lo_<mode>" + [(set (match_operand:P 0 "gpc_reg_operand" "=r") + (unspec:P [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "symbol_ref_operand" "s") + (match_operand:P 3 "" "")] + UNSPEC_PLT16_LO))] + "HAVE_AS_PLTSEQ && TARGET_TLS_MARKERS + && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)" +{ + return rs6000_pltseq_template (operands, 2); +} + [(set_attr "type" "load")]) + +(define_insn "*pltseq_mtctr_<mode>" + [(set (match_operand:P 0 "register_operand" "=c") + (unspec:P [(match_operand:P 1 "gpc_reg_operand" "r") + (match_operand:P 2 "symbol_ref_operand" "s") + (match_operand:P 3 "" "")] + UNSPEC_PLTSEQ))] + "HAVE_AS_PLTSEQ && TARGET_TLS_MARKERS + && (DEFAULT_ABI == ABI_ELFv2 || DEFAULT_ABI == ABI_V4)" +{ + return rs6000_pltseq_template (operands, 3); +}) ;; Call and call_value insns (define_expand "call" @@ -10351,9 +10403,9 @@ ;; which indicates how to set cr1 (define_insn "*call_indirect_nonlocal_sysv<mode>" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l,c,*l")) + [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X")) (match_operand 1)) - (use (match_operand:SI 2 "immediate_operand" "O,O,n,n")) + (use (match_operand:SI 2 "immediate_operand" "n,n,n")) (clobber (reg:SI LR_REGNO))] "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN" @@ -10366,18 +10418,17 @@ return rs6000_indirect_call_template (operands, 0); } - [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg") - (set_attr_alternative "length" - [(if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "8") - (const_string "4")) - (const_string "4") - (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "12") - (const_string "8")) - (const_string "8")])]) + [(set_attr "type" "jmpreg") + (set (attr "length") + (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[2]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "12") + (ior (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[2]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "8")] + (const_string "4")))]) (define_insn_and_split "*call_nonlocal_sysv<mode>" [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s")) @@ -10437,9 +10488,9 @@ (define_insn "*call_value_indirect_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l,c,*l")) + (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X")) (match_operand 2))) - (use (match_operand:SI 3 "immediate_operand" "O,O,n,n")) + (use (match_operand:SI 3 "immediate_operand" "n,n,n")) (clobber (reg:SI LR_REGNO))] "DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_DARWIN" @@ -10452,18 +10503,17 @@ return rs6000_indirect_call_template (operands, 1); } - [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg") - (set_attr_alternative "length" - [(if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "8") - (const_string "4")) - (const_string "4") - (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "12") - (const_string "8")) - (const_string "8")])]) + [(set_attr "type" "jmpreg") + (set (attr "length") + (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[3]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "12") + (ior (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[3]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "8")] + (const_string "4")))]) (define_insn_and_split "*call_value_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") @@ -10576,10 +10626,10 @@ ;; Operand3 is the offset of the stack location holding the current TOC pointer (define_insn "*call_indirect_aix<mode>" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X")) (match_operand 1)) - (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>")) - (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (use (match_operand:P 2 "memory_operand" "<ptrm>,<ptrm>,<ptrm>")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] "DEFAULT_ABI == ABI_AIX" { @@ -10594,10 +10644,10 @@ (define_insn "*call_value_indirect_aix<mode>" [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X")) (match_operand 2))) - (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>")) - (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 4 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (use (match_operand:P 3 "memory_operand" "<ptrm>,<ptrm>,<ptrm>")) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 4 "const_int_operand" "n,n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] "DEFAULT_ABI == ABI_AIX" { @@ -10615,9 +10665,9 @@ ;; Operand2 is the offset of the stack location holding the current TOC pointer (define_insn "*call_indirect_elfv2<mode>" - [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l")) + [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X")) (match_operand 1)) - (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] "DEFAULT_ABI == ABI_ELFv2" { @@ -10632,9 +10682,9 @@ (define_insn "*call_value_indirect_elfv2<mode>" [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "register_operand" "c,*l")) + (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X")) (match_operand 2))) - (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT)) + (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n,n")] UNSPEC_TOCSLOT)) (clobber (reg:P LR_REGNO))] "DEFAULT_ABI == ABI_ELFv2" { @@ -10697,6 +10747,12 @@ rs6000_sibcall_aix (NULL_RTX, operands[0], operands[1], operands[2]); DONE; } + + if (DEFAULT_ABI == ABI_V4) + { + rs6000_sibcall_sysv (NULL_RTX, operands[0], operands[1], operands[2]); + DONE; + } }) (define_expand "sibcall_value" @@ -10722,6 +10778,12 @@ rs6000_sibcall_aix (operands[0], operands[1], operands[2], operands[3]); DONE; } + + if (DEFAULT_ABI == ABI_V4) + { + rs6000_sibcall_sysv (operands[0], operands[1], operands[2], operands[3]); + DONE; + } }) (define_insn "*sibcall_local32" @@ -10798,10 +10860,38 @@ [(set_attr "type" "branch") (set_attr "length" "4,8")]) +(define_insn "*sibcall_indirect_nonlocal_sysv<mode>" + [(call (mem:SI (match_operand:P 0 "indirect_call_operand" "c,*l,X")) + (match_operand 1)) + (use (match_operand:SI 2 "immediate_operand" "n,n,n")) + (simple_return)] + "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); + + else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) + output_asm_insn ("creqv 6,6,6", operands); + + return rs6000_indirect_sibcall_template (operands, 0); +} + [(set_attr "type" "jmpreg") + (set (attr "length") + (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[2]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "12") + (ior (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[2]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "8")] + (const_string "4")))]) + (define_insn "*sibcall_nonlocal_sysv<mode>" - [(call (mem:SI (match_operand:P 0 "call_operand" "s,s,c,c")) - (match_operand 1 "" "")) - (use (match_operand 2 "immediate_operand" "O,n,O,n")) + [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s")) + (match_operand 1)) + (use (match_operand 2 "immediate_operand" "O,n")) (simple_return)] "(DEFAULT_ABI == ABI_DARWIN || DEFAULT_ABI == ABI_V4) @@ -10813,29 +10903,45 @@ else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS) output_asm_insn ("creqv 6,6,6", operands); - if (which_alternative >= 2) - return rs6000_indirect_sibcall_template (operands, 0); - else - return rs6000_sibcall_template (operands, 0); + return rs6000_sibcall_template (operands, 0); } [(set_attr "type" "branch") - (set_attr_alternative "length" - [(const_string "4") - (const_string "8") - (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "12") - (const_string "4")) - (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "16") - (const_string "8"))])]) + (set_attr "length" "4,8")]) + +(define_insn "*sibcall_value_indirect_nonlocal_sysv<mode>" + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:P 1 "indirect_call_operand" "c,*l,X")) + (match_operand 2))) + (use (match_operand:SI 3 "immediate_operand" "n,n,n")) + (simple_return)] + "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); + + else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) + output_asm_insn ("creqv 6,6,6", operands); + + return rs6000_indirect_sibcall_template (operands, 1); +} + [(set_attr "type" "jmpreg") + (set (attr "length") + (cond [(and (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[3]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "12") + (ior (and (match_test "!rs6000_speculate_indirect_jumps") + (match_test "which_alternative != 1")) + (match_test "(INTVAL (operands[3]) & (CALL_V4_SET_FP_ARGS | CALL_V4_CLEAR_FP_ARGS))")) + (const_string "8")] + (const_string "4")))]) (define_insn "*sibcall_value_nonlocal_sysv<mode>" [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:P 1 "call_operand" "s,s,c,c")) - (match_operand 2 "" ""))) - (use (match_operand:SI 3 "immediate_operand" "O,n,O,n")) + (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s")) + (match_operand 2))) + (use (match_operand:SI 3 "immediate_operand" "O,n")) (simple_return)] "(DEFAULT_ABI == ABI_DARWIN || DEFAULT_ABI == ABI_V4) @@ -10847,29 +10953,10 @@ else if (INTVAL (operands[3]) & CALL_V4_CLEAR_FP_ARGS) output_asm_insn ("creqv 6,6,6", operands); - if (which_alternative >= 2) - { - if (rs6000_speculate_indirect_jumps) - return "b%T1"; - else - /* Can use CR0 since it is volatile across sibcalls. */ - return "crset 2\;beq%T1-\;b $"; - } - else - return rs6000_sibcall_template (operands, 1); + return rs6000_sibcall_template (operands, 1); } [(set_attr "type" "branch") - (set_attr_alternative "length" - [(const_string "4") - (const_string "8") - (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "12") - (const_string "4")) - (if_then_else (eq (symbol_ref "rs6000_speculate_indirect_jumps") - (const_int 0)) - (const_string "16") - (const_string "8"))])]) + (set_attr "length" "4,8")]) ;; AIX ABI sibling call patterns. diff --git a/gcc/configure b/gcc/configure index 3a20399adba..bdaa6fa0c3e 100755 --- a/gcc/configure +++ b/gcc/configure @@ -24393,12 +24393,12 @@ foo: .long 25 ;; or1k*-*-*) conftest_s=' - .section ".tdata","awT",@progbits -foo: .long 25 - .text - l.movhi r3, tpoffha(foo) - l.add r3, r3, r10 - l.lwz r4, tpofflo(foo)(r3)' + .section ".tdata","awT",@progbits +foo: .long 25 + .text + l.movhi r3, tpoffha(foo) + l.add r3, r3, r10 + l.lwz r4, tpofflo(foo)(r3)' tls_first_major=2 tls_first_minor=30 tls_as_opt=--fatal-warnings @@ -26942,6 +26942,42 @@ $as_echo "#define HAVE_AS_ENTRY_MARKERS 1" >>confdefs.h fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for plt sequence marker support" >&5 +$as_echo_n "checking assembler for plt sequence marker support... " >&6; } +if ${gcc_cv_as_powerpc_pltseq_markers+:} false; then : + $as_echo_n "(cached) " >&6 +else + gcc_cv_as_powerpc_pltseq_markers=no + if test $in_tree_gas = yes; then + if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 31 \) \* 1000 + 0` + then gcc_cv_as_powerpc_pltseq_markers=yes +fi + elif test x$gcc_cv_as != x; then + $as_echo ' .reloc .,R_PPC_PLTSEQ; nop' > conftest.s + if { ac_try='$gcc_cv_as $gcc_cv_as_flags -a32 --fatal-warnings -o conftest.o conftest.s >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + gcc_cv_as_powerpc_pltseq_markers=yes + else + echo "configure: failed program was" >&5 + cat conftest.s >&5 + fi + rm -f conftest.o conftest.s + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_powerpc_pltseq_markers" >&5 +$as_echo "$gcc_cv_as_powerpc_pltseq_markers" >&6; } +if test $gcc_cv_as_powerpc_pltseq_markers = yes; then + +$as_echo "#define HAVE_AS_PLTSEQ 1" >>confdefs.h + +fi + + case $target in *-*-aix*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for AIX .ref support" >&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index 2a1f3bb39a4..2673f80af96 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -4648,6 +4648,12 @@ LCF0: [AC_DEFINE(HAVE_AS_ENTRY_MARKERS, 1, [Define if your assembler supports the R_PPC64_ENTRY relocation.])]) + gcc_GAS_CHECK_FEATURE([plt sequence marker support], + gcc_cv_as_powerpc_pltseq_markers, [2,31,0],-a32 --fatal-warnings, + [ .reloc .,R_PPC_PLTSEQ; nop],, + [AC_DEFINE(HAVE_AS_PLTSEQ, 1, + [Define if your assembler supports R_PPC*_PLTSEQ relocations.])]) + case $target in *-*-aix*) gcc_GAS_CHECK_FEATURE([AIX .ref support], |