X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fconfig%2Frs6000%2Frs6000.c;h=dd41f62a59c068e697633478b8fec977acd4e50e;hp=2ca1b3027fe5921fb6a2342150d40225709297b7;hb=f13da317dd6b47dda5beac471ffe04cad10c06d3;hpb=1d15adaa22a1f772c0485675970a5468b37ca3ab diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 2ca1b3027fe..dd41f62a59c 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -56,6 +56,7 @@ #include "tree-gimple.h" #include "intl.h" #include "params.h" +#include "tm-constrs.h" #if TARGET_XCOFF #include "xcoffout.h" /* get declarations of xcoff_*_section_name */ #endif @@ -248,11 +249,12 @@ int rs6000_alignment_flags; struct { bool aix_struct_ret; /* True if -maix-struct-ret was used. */ bool alignment; /* True if -malign- was used. */ - bool abi; /* True if -mabi= was used. */ + bool abi; /* True if -mabi=spe/nospe was used. */ bool spe; /* True if -mspe= was used. */ bool float_gprs; /* True if -mfloat-gprs= was used. */ bool isel; /* True if -misel was used. */ bool long_double; /* True if -mlong-double- was used. */ + bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */ } rs6000_explicit_options; struct builtin_description @@ -588,6 +590,7 @@ static unsigned toc_hash_function (const void *); static int toc_hash_eq (const void *, const void *); static int constant_pool_expr_1 (rtx, int *, int *); static bool constant_pool_expr_p (rtx); +static bool legitimate_small_data_p (enum machine_mode, rtx); static bool legitimate_indexed_address_p (rtx, int); static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int); static struct machine_function * rs6000_init_machine_status (void); @@ -599,6 +602,8 @@ static void rs6000_assemble_visibility (tree, int); static int rs6000_ra_ever_killed (void); static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *); +static bool rs6000_ms_bitfield_layout_p (tree); +static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *); static void rs6000_eliminate_indexed_memrefs (rtx operands[2]); static const char *rs6000_mangle_fundamental_type (tree); extern const struct attribute_spec rs6000_attribute_table[]; @@ -929,6 +934,9 @@ static const char alt_reg_names[][8] = #define TARGET_BINDS_LOCAL_P darwin_binds_local_p #endif +#undef TARGET_MS_BITFIELD_LAYOUT_P +#define TARGET_MS_BITFIELD_LAYOUT_P rs6000_ms_bitfield_layout_p + #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk @@ -1002,7 +1010,7 @@ static const char alt_reg_names[][8] = #undef TARGET_DEFAULT_TARGET_FLAGS #define TARGET_DEFAULT_TARGET_FLAGS \ - (TARGET_DEFAULT | MASK_SCHED_PROLOG) + (TARGET_DEFAULT) #undef TARGET_STACK_PROTECT_FAIL #define TARGET_STACK_PROTECT_FAIL rs6000_stack_protect_fail @@ -1135,11 +1143,13 @@ rs6000_override_options (const char *default_cpu) {"403", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN}, {"405", PROCESSOR_PPC405, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW}, - {"405fp", PROCESSOR_PPC405, POWERPC_BASE_MASK | MASK_MULHW}, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, + {"405fp", PROCESSOR_PPC405, + POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, {"440", PROCESSOR_PPC440, - POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW}, - {"440fp", PROCESSOR_PPC440, POWERPC_BASE_MASK | MASK_MULHW}, + POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB}, + {"440fp", PROCESSOR_PPC440, + POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB}, {"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK}, {"601", PROCESSOR_PPC601, MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING}, @@ -1184,6 +1194,9 @@ rs6000_override_options (const char *default_cpu) {"power5+", PROCESSOR_POWER5, POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND}, + {"power6", PROCESSOR_POWER5, + POWERPC_7400_MASK | MASK_POWERPC64 | MASK_MFCRF | MASK_POPCNTB + | MASK_FPRND}, {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK}, {"powerpc64", PROCESSOR_POWERPC64, POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, @@ -1209,7 +1222,8 @@ rs6000_override_options (const char *default_cpu) POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING, POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC - | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW) + | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW + | MASK_DLMZB) }; rs6000_init_hard_regno_mode_ok (); @@ -1317,7 +1331,7 @@ rs6000_override_options (const char *default_cpu) rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE; #ifndef POWERPC_LINUX - if (!rs6000_explicit_options.abi) + if (!rs6000_explicit_options.ieee) rs6000_ieeequad = 1; #endif @@ -1339,6 +1353,11 @@ rs6000_override_options (const char *default_cpu) rs6000_alignment_flags = MASK_ALIGN_NATURAL; } + /* Place FP constants in the constant pool instead of TOC + if section anchors enabled. */ + if (flag_section_anchors) + TARGET_NO_FP_IN_TOC = 1; + /* Handle -mtls-size option. */ rs6000_parse_tls_size_option (); @@ -1610,6 +1629,12 @@ optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED) /* Double growth factor to counter reduced min jump length. */ set_param_value ("max-grow-copy-bb-insns", 16); + + /* Enable section anchors by default. + Skip section anchors for Objective C and Objective C++ + until front-ends fixed. */ + if (!TARGET_MACHO && lang_hooks.name[4] != 'O') + flag_section_anchors = 1; } /* Implement TARGET_HANDLE_OPTION. */ @@ -1632,10 +1657,10 @@ rs6000_handle_option (size_t code, const char *arg, int value) | MASK_PPC_GFXOPT | MASK_POWERPC64); break; case OPT_mfull_toc: - target_flags &= ~(MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC - | MASK_NO_SUM_IN_TOC); - target_flags_explicit |= (MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC - | MASK_NO_SUM_IN_TOC); + target_flags &= ~MASK_MINIMAL_TOC; + TARGET_NO_FP_IN_TOC = 0; + TARGET_NO_SUM_IN_TOC = 0; + target_flags_explicit |= MASK_MINIMAL_TOC; #ifdef TARGET_USES_SYSV4_OPT /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be just the same as -mminimal-toc. */ @@ -1678,8 +1703,8 @@ rs6000_handle_option (size_t code, const char *arg, int value) case OPT_mminimal_toc: if (value == 1) { - target_flags &= ~(MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC); - target_flags_explicit |= (MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC); + TARGET_NO_FP_IN_TOC = 0; + TARGET_NO_SUM_IN_TOC = 0; } break; @@ -1750,18 +1775,18 @@ rs6000_handle_option (size_t code, const char *arg, int value) case OPT_mrelocatable: if (value == 1) { - target_flags |= MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC; - target_flags_explicit |= MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC; + target_flags |= MASK_MINIMAL_TOC; + target_flags_explicit |= MASK_MINIMAL_TOC; + TARGET_NO_FP_IN_TOC = 1; } break; case OPT_mrelocatable_lib: if (value == 1) { - target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC - | MASK_NO_FP_IN_TOC; - target_flags_explicit |= MASK_RELOCATABLE | MASK_MINIMAL_TOC - | MASK_NO_FP_IN_TOC; + target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC; + target_flags_explicit |= MASK_RELOCATABLE | MASK_MINIMAL_TOC; + TARGET_NO_FP_IN_TOC = 1; } else { @@ -1772,23 +1797,31 @@ rs6000_handle_option (size_t code, const char *arg, int value) #endif case OPT_mabi_: - rs6000_explicit_options.abi = true; if (!strcmp (arg, "altivec")) { + rs6000_explicit_options.abi = true; rs6000_altivec_abi = 1; rs6000_spe_abi = 0; } else if (! strcmp (arg, "no-altivec")) - rs6000_altivec_abi = 0; + { + /* ??? Don't set rs6000_explicit_options.abi here, to allow + the default for rs6000_spe_abi to be chosen later. */ + rs6000_altivec_abi = 0; + } else if (! strcmp (arg, "spe")) { + rs6000_explicit_options.abi = true; rs6000_spe_abi = 1; rs6000_altivec_abi = 0; if (!TARGET_SPE_ABI) error ("not configured for ABI: '%s'", arg); } else if (! strcmp (arg, "no-spe")) - rs6000_spe_abi = 0; + { + rs6000_explicit_options.abi = true; + rs6000_spe_abi = 0; + } /* These are here for testing during development only, do not document in the manual please. */ @@ -1805,11 +1838,13 @@ rs6000_handle_option (size_t code, const char *arg, int value) else if (! strcmp (arg, "ibmlongdouble")) { + rs6000_explicit_options.ieee = true; rs6000_ieeequad = 0; warning (0, "Using IBM extended precision long double"); } else if (! strcmp (arg, "ieeelongdouble")) { + rs6000_explicit_options.ieee = true; rs6000_ieeequad = 1; warning (0, "Using IEEE extended precision long double"); } @@ -1988,11 +2023,12 @@ int num_insns_constant_wide (HOST_WIDE_INT value) { /* signed constant loadable with {cal|addi} */ - if (CONST_OK_FOR_LETTER_P (value, 'I')) + if ((unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000) return 1; /* constant loadable with {cau|addis} */ - else if (CONST_OK_FOR_LETTER_P (value, 'L')) + else if ((value & 0xffff) == 0 + && (value >> 31 == -1 || value >> 31 == 0)) return 1; #if HOST_BITS_PER_WIDE_INT == 64 @@ -2087,7 +2123,7 @@ num_insns_constant (rtx op, enum machine_mode mode) } -/* Return true if OP can be synthesized with a particular vspltisb, vspltish +/* Return true if OP can be synthesized with a particular vspltisb, vspltish or vspltisw instruction. OP is a CONST_VECTOR. Which instruction is used depends on STEP and COPIES, one of which will be 1. If COPIES > 1, all items are set to the same value and contain COPIES replicas of the @@ -2154,7 +2190,7 @@ vspltis_constant (rtx op, unsigned step, unsigned copies) } -/* Return true if OP is of the given MODE and can be synthesized +/* Return true if OP is of the given MODE and can be synthesized with a vspltisb, vspltish or vspltisw. */ bool @@ -2689,8 +2725,8 @@ legitimate_constant_pool_address_p (rtx x) && constant_pool_expr_p (XEXP (x, 1))); } -bool -rs6000_legitimate_small_data_p (enum machine_mode mode, rtx x) +static bool +legitimate_small_data_p (enum machine_mode mode, rtx x) { return (DEFAULT_ABI == ABI_V4 && !flag_pic && !TARGET_TOC @@ -3380,9 +3416,12 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, && !flag_pic #endif /* Don't do this for TFmode, since the result isn't offsettable. - The same goes for DImode without 64-bit gprs. */ + The same goes for DImode without 64-bit gprs and DFmode + without fprs. */ && mode != TFmode - && (mode != DImode || TARGET_POWERPC64)) + && (mode != DImode || TARGET_POWERPC64) + && (mode != DFmode || TARGET_POWERPC64 + || (TARGET_FPRS && TARGET_HARD_FLOAT))) { #if TARGET_MACHO if (flag_pic) @@ -3427,7 +3466,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode, && constant_pool_expr_p (x) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode)) { - (x) = create_TOC_reference (x); + x = create_TOC_reference (x); *win = 1; return x; } @@ -3475,7 +3514,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) && TARGET_UPDATE && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)) return 1; - if (rs6000_legitimate_small_data_p (mode, x)) + if (legitimate_small_data_p (mode, x)) return 1; if (legitimate_constant_pool_address_p (x)) return 1; @@ -3540,6 +3579,33 @@ rs6000_mode_dependent_address (rtx addr) return false; } +/* More elaborate version of recog's offsettable_memref_p predicate + that works around the ??? note of rs6000_mode_dependent_address. + In particular it accepts + + (mem:DI (plus:SI (reg/f:SI 31 31) (const_int 32760 [0x7ff8]))) + + in 32-bit mode, that the recog predicate rejects. */ + +bool +rs6000_offsettable_memref_p (rtx op) +{ + if (!MEM_P (op)) + return false; + + /* First mimic offsettable_memref_p. */ + if (offsettable_address_p (1, GET_MODE (op), XEXP (op, 0))) + return true; + + /* offsettable_address_p invokes rs6000_mode_dependent_address, but + the latter predicate knows nothing about the mode of the memory + reference and, therefore, assumes that it is the largest supported + mode (TFmode). As a consequence, legitimate offsettable memory + references are rejected. rs6000_legitimate_offset_address_p contains + the correct logic for the PLUS case of rs6000_mode_dependent_address. */ + return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1); +} + /* Return number of consecutive hard regs needed starting at reg REGNO to hold something of mode MODE. This is ordinarily the length in words of a value of mode MODE @@ -5009,17 +5075,13 @@ rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words) if (align_words + n_units > GP_ARG_NUM_REG) /* Not all of the arg fits in gprs. Say that it goes in memory too, using a magic NULL_RTX component. - FIXME: This is not strictly correct. Only some of the arg - belongs in memory, not all of it. However, there isn't any way - to do this currently, apart from building rtx descriptions for - the pieces of memory we want stored. Due to bugs in the generic - code we can't use the normal function_arg_partial_nregs scheme - with the PARALLEL arg description we emit here. - In any case, the code to store the whole arg to memory is often - more efficient than code to store pieces, and we know that space - is available in the right place for the whole arg. */ - /* FIXME: This should be fixed since the conversion to - TARGET_ARG_PARTIAL_BYTES. */ + This is not strictly correct. Only some of the arg belongs in + memory, not all of it. However, the normal scheme using + function_arg_partial_nregs can result in unusual subregs, eg. + (subreg:SI (reg:DF) 4), which are not handled well. The code to + store the whole arg to memory is often more efficient than code + to store pieces, and we know that space is available in the right + place for the whole arg. */ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx); i = 0; @@ -5261,9 +5323,8 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, include the portion actually in registers here. */ enum machine_mode rmode = TARGET_32BIT ? SImode : DImode; rtx off; - int i=0; - if (align_words + n_words > GP_ARG_NUM_REG - && (TARGET_32BIT && TARGET_POWERPC64)) + int i = 0; + if (align_words + n_words > GP_ARG_NUM_REG) /* Not all of the arg fits in gprs. Say that it goes in memory too, using a magic NULL_RTX component. Also see comment in @@ -5342,18 +5403,20 @@ rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, align_words = rs6000_parm_start (mode, type, cum->words); - if (USE_FP_FOR_ARG_P (cum, mode, type) + if (USE_FP_FOR_ARG_P (cum, mode, type)) + { /* If we are passing this arg in the fixed parameter save area (gprs or memory) as well as fprs, then this function should - return the number of bytes passed in the parameter save area - rather than bytes passed in fprs. */ - && !(type - && (cum->nargs_prototype <= 0 - || (DEFAULT_ABI == ABI_AIX - && TARGET_XL_COMPAT - && align_words >= GP_ARG_NUM_REG)))) - { - if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1) + return the number of partial bytes passed in the parameter + save area rather than partial bytes passed in fprs. */ + if (type + && (cum->nargs_prototype <= 0 + || (DEFAULT_ABI == ABI_AIX + && TARGET_XL_COMPAT + && align_words >= GP_ARG_NUM_REG))) + return 0; + else if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) + > FP_ARG_MAX_REG + 1) ret = (FP_ARG_MAX_REG + 1 - cum->fregno) * 8; else if (cum->nargs_prototype >= 0) return 0; @@ -5911,10 +5974,10 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) t = build1 (LABEL_EXPR, void_type_node, lab_false); append_to_statement_list (t, pre_p); - if (n_reg > 2) + if ((n_reg == 2 && reg != gpr) || n_reg > 2) { /* Ensure that we don't find any more args in regs. - Alignment has taken care of the n_reg == 2 case. */ + Alignment has taken care of the n_reg == 2 gpr case. */ t = build2 (MODIFY_EXPR, TREE_TYPE (reg), reg, size_int (8)); gimplify_and_add (t, pre_p); } @@ -7966,6 +8029,12 @@ rs6000_init_builtins (void) altivec_init_builtins (); if (TARGET_ALTIVEC || TARGET_SPE) rs6000_common_init_builtins (); + +#if TARGET_XCOFF + /* AIX libm provides clog as __clog. */ + if (built_in_decls [BUILT_IN_CLOG]) + set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog"); +#endif } /* Search through a set of builtins and enable the mask bits. @@ -12479,7 +12548,7 @@ rs6000_split_multireg_move (rtx dst, rtx src) : gen_adddi3 (breg, breg, delta_rtx)); src = replace_equiv_address (src, breg); } - else if (! offsettable_memref_p (src)) + else if (! rs6000_offsettable_memref_p (src)) { rtx basereg; basereg = gen_rtx_REG (Pmode, reg); @@ -12532,7 +12601,7 @@ rs6000_split_multireg_move (rtx dst, rtx src) dst = replace_equiv_address (dst, breg); } else - gcc_assert (offsettable_memref_p (dst)); + gcc_assert (rs6000_offsettable_memref_p (dst)); } for (i = 0; i < nregs; i++) @@ -15271,7 +15340,8 @@ rs6000_output_function_epilogue (FILE *file, official way to discover the language being compiled, so we use language_string. C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. - Java is 13. Objective-C is 14. */ + Java is 13. Objective-C is 14. Objective-C++ isn't assigned + a number, so for now use 9. */ if (! strcmp (language_string, "GNU C")) i = 0; else if (! strcmp (language_string, "GNU F77") @@ -15281,7 +15351,8 @@ rs6000_output_function_epilogue (FILE *file, i = 2; else if (! strcmp (language_string, "GNU Ada")) i = 3; - else if (! strcmp (language_string, "GNU C++")) + else if (! strcmp (language_string, "GNU C++") + || ! strcmp (language_string, "GNU Objective-C++")) i = 9; else if (! strcmp (language_string, "GNU Java")) i = 13; @@ -17248,9 +17319,8 @@ rs6000_trampoline_size (void) void rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt) { - enum machine_mode pmode = Pmode; int regsize = (TARGET_32BIT) ? 4 : 8; - rtx ctx_reg = force_reg (pmode, cxt); + rtx ctx_reg = force_reg (Pmode, cxt); switch (DEFAULT_ABI) { @@ -17258,15 +17328,15 @@ rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt) gcc_unreachable (); /* Macros to shorten the code expansions below. */ -#define MEM_DEREF(addr) gen_rtx_MEM (pmode, memory_address (pmode, addr)) +#define MEM_DEREF(addr) gen_rtx_MEM (Pmode, memory_address (Pmode, addr)) #define MEM_PLUS(addr,offset) \ - gen_rtx_MEM (pmode, memory_address (pmode, plus_constant (addr, offset))) + gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (addr, offset))) /* Under AIX, just build the 3 word function descriptor */ case ABI_AIX: { - rtx fn_reg = gen_reg_rtx (pmode); - rtx toc_reg = gen_reg_rtx (pmode); + rtx fn_reg = gen_reg_rtx (Pmode); + rtx toc_reg = gen_reg_rtx (Pmode); emit_move_insn (fn_reg, MEM_DEREF (fnaddr)); emit_move_insn (toc_reg, MEM_PLUS (fnaddr, regsize)); emit_move_insn (MEM_DEREF (addr), fn_reg); @@ -17278,12 +17348,12 @@ rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt) /* Under V.4/eabi/darwin, __trampoline_setup does the real work. */ case ABI_DARWIN: case ABI_V4: - emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"), + emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"), FALSE, VOIDmode, 4, - addr, pmode, + addr, Pmode, GEN_INT (rs6000_trampoline_size ()), SImode, - fnaddr, pmode, - ctx_reg, pmode); + fnaddr, Pmode, + ctx_reg, Pmode); break; } @@ -17299,6 +17369,8 @@ const struct attribute_spec rs6000_attribute_table[] = { "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute }, { "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute }, { "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute }, + { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute }, + { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute }, #ifdef SUBTARGET_ATTRIBUTE_TABLE SUBTARGET_ATTRIBUTE_TABLE, #endif @@ -17469,6 +17541,10 @@ rs6000_set_default_type_attributes (tree type) TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"), NULL_TREE, TYPE_ATTRIBUTES (type)); + +#if TARGET_MACHO + darwin_set_default_type_attributes (type); +#endif } /* Return a reference suitable for calling a function with the @@ -17497,6 +17573,54 @@ rs6000_longcall_ref (rtx call_ref) return force_reg (Pmode, call_ref); } +#ifndef TARGET_USE_MS_BITFIELD_LAYOUT +#define TARGET_USE_MS_BITFIELD_LAYOUT 0 +#endif + +/* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in + struct attribute_spec.handler. */ +static tree +rs6000_handle_struct_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + tree *type = NULL; + if (DECL_P (*node)) + { + if (TREE_CODE (*node) == TYPE_DECL) + type = &TREE_TYPE (*node); + } + else + type = node; + + if (!(type && (TREE_CODE (*type) == RECORD_TYPE + || TREE_CODE (*type) == UNION_TYPE))) + { + warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + else if ((is_attribute_p ("ms_struct", name) + && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type))) + || ((is_attribute_p ("gcc_struct", name) + && lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type))))) + { + warning (OPT_Wattributes, "%qs incompatible attribute ignored", + IDENTIFIER_POINTER (name)); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +static bool +rs6000_ms_bitfield_layout_p (tree record_type) +{ + return (TARGET_USE_MS_BITFIELD_LAYOUT && + !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type))) + || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type)); +} + #ifdef USING_ELFOS_H /* A get_unnamed_section callback, used for switching to toc_section. */ @@ -18039,6 +18163,7 @@ rs6000_darwin_file_start (void) size_t i; rs6000_file_start (); + darwin_file_start (); /* Determine the argument to -mcpu=. Default to G3 if not specified. */ for (i = 0; i < ARRAY_SIZE (rs6000_select); i++) @@ -18477,19 +18602,21 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total) if (((outer_code == SET || outer_code == PLUS || outer_code == MINUS) - && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') - || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L'))) + && (satisfies_constraint_I (x) + || satisfies_constraint_L (x))) || (outer_code == AND - && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K') - || (CONST_OK_FOR_LETTER_P (INTVAL (x), - mode == SImode ? 'L' : 'J')) + && (satisfies_constraint_K (x) + || (mode == SImode + ? satisfies_constraint_L (x) + : satisfies_constraint_J (x)) || mask_operand (x, mode) || (mode == DImode && mask64_operand (x, DImode)))) || ((outer_code == IOR || outer_code == XOR) - && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K') - || (CONST_OK_FOR_LETTER_P (INTVAL (x), - mode == SImode ? 'L' : 'J')))) + && (satisfies_constraint_K (x) + || (mode == SImode + ? satisfies_constraint_L (x) + : satisfies_constraint_J (x)))) || outer_code == ASHIFT || outer_code == ASHIFTRT || outer_code == LSHIFTRT @@ -18497,22 +18624,23 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total) || outer_code == ROTATERT || outer_code == ZERO_EXTRACT || (outer_code == MULT - && CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')) + && satisfies_constraint_I (x)) || ((outer_code == DIV || outer_code == UDIV || outer_code == MOD || outer_code == UMOD) && exact_log2 (INTVAL (x)) >= 0) || (outer_code == COMPARE - && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') - || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K'))) + && (satisfies_constraint_I (x) + || satisfies_constraint_K (x))) || (outer_code == EQ - && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I') - || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K') - || (CONST_OK_FOR_LETTER_P (INTVAL (x), - mode == SImode ? 'L' : 'J')))) + && (satisfies_constraint_I (x) + || satisfies_constraint_K (x) + || (mode == SImode + ? satisfies_constraint_L (x) + : satisfies_constraint_J (x)))) || (outer_code == GTU - && CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')) + && satisfies_constraint_I (x)) || (outer_code == LTU - && CONST_OK_FOR_LETTER_P (INTVAL (x), 'P'))) + && satisfies_constraint_P (x))) { *total = 0; return true; @@ -18533,28 +18661,25 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total) /* FALLTHRU */ case CONST_DOUBLE: - if (mode == DImode - && ((outer_code == AND - && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K') - || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L') - || mask_operand (x, DImode) - || mask64_operand (x, DImode))) - || ((outer_code == IOR || outer_code == XOR) - && CONST_DOUBLE_HIGH (x) == 0 - && (CONST_DOUBLE_LOW (x) - & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0))) - { - *total = 0; - return true; - } - else if (mode == DImode - && (outer_code == SET - || outer_code == IOR - || outer_code == XOR) - && CONST_DOUBLE_HIGH (x) == 0) + if (mode == DImode && code == CONST_DOUBLE) { - *total = COSTS_N_INSNS (1); - return true; + if ((outer_code == IOR || outer_code == XOR) + && CONST_DOUBLE_HIGH (x) == 0 + && (CONST_DOUBLE_LOW (x) + & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0) + { + *total = 0; + return true; + } + else if ((outer_code == AND && and64_2_operand (x, DImode)) + || ((outer_code == SET + || outer_code == IOR + || outer_code == XOR) + && CONST_DOUBLE_HIGH (x) == 0)) + { + *total = COSTS_N_INSNS (1); + return true; + } } /* FALLTHRU */ @@ -18626,7 +18751,7 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total) case MULT: if (GET_CODE (XEXP (x, 1)) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'I')) + && satisfies_constraint_I (XEXP (x, 1))) { if (INTVAL (XEXP (x, 1)) >= -256 && INTVAL (XEXP (x, 1)) <= 255)