From patchwork Tue Jul 27 20:10:40 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [Darwin,3/2] fix PPC64 ABI. From: IainS X-Patchwork-Id: 60044 Message-Id: To: gcc patches Cc: mrs@gcc.gnu.org, David Edelsohn Date: Tue, 27 Jul 2010 21:10:40 +0100 Yeah, part 3 of 2... ... which fixes ABI issues that are not evident in the gcc test-suite... ... but are shown up by "darwin64-abi.c" from LLVM or the apple 4.2.1 local tree. with this the abi check passes and so do the compat and struct- layout-1 tests (with 160947 reverted because of PR45054) on powerpc64- apple-darwin9. I am about to start a full bootstrap/check on powerpc-apple-darwin9. OK for trunk (and 4.5 when re-open) assuming that the m32 bootstrap/ check passes? Iain gcc * config/rs6000/rs6000.c (rs6000_override_options): Use TARGET_MACHO inline. (rs6000_return_in_memory): Update preceding comment for darwin 64 bit ABI. Use TARGET_MACHO inline. (rs6000_darwin64_struct_check_p): New. (function_arg_advance): Use rs6000_darwin64_struct_check_p. (function_arg): Likewise. (rs6000_arg_partial_bytes): Likewise. (rs6000_function_value): Likewise. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 162570) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -2795,13 +2795,14 @@ rs6000_override_options (const char *default_cpu) TARGET_ALTIVEC_VRSAVE = rs6000_altivec_abi; } - /* Set the Darwin64 ABI as default for 64-bit Darwin. */ - if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT) + /* Set the Darwin64 ABI as default for 64-bit Darwin. + So far, the only darwin64 targets are also MACH-O. */ + if (TARGET_MACHO + && DEFAULT_ABI == ABI_DARWIN + && TARGET_64BIT) { rs6000_darwin64_abi = 1; -#if TARGET_MACHO darwin_one_byte_bool = 1; -#endif /* Default to natural alignment, for better performance. */ rs6000_alignment_flags = MASK_ALIGN_NATURAL; } @@ -7264,8 +7265,15 @@ rs6000_emit_move (rtx dest, rtx source, enum machi The AIX ABI for the RS/6000 specifies that all structures are returned in memory. The Darwin ABI does the same. The SVR4 ABI - specifies that structures <= 8 bytes are returned in r3/r4, but a - draft put them in memory, and GCC used to implement the draft + + For the Darwin 64 Bit ABI, a function result can be returned in registers + or in memory, depending on the data type of the function’s return value. + The value is returned in registers (and the same registers) if it would + fit in registers as a function argument. Otherwise, the function places + its result in memory at the location pointed to by GPR3. + + The SVR4 ABI specifies that structures <= 8 bytes are returned in r3/r4, + but a draft put them in memory, and GCC used to implement the draft instead of the final standard. Therefore, aix_struct_return controls this instead of DEFAULT_ABI; V.4 targets needing backward compatibility can change DRAFT_V4_STRUCT_RET to override the @@ -7281,9 +7289,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machi static bool rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) { - /* In the darwin64 abi, try to use registers for larger structs - if possible. */ - if (rs6000_darwin64_abi + /* For the Darwin64 ABI, test if we can fit the return value in regs. */ + if (TARGET_MACHO + && rs6000_darwin64_abi && TREE_CODE (type) == RECORD_TYPE && int_size_in_bytes (type) > 0) { @@ -7499,7 +7507,9 @@ function_arg_boundary (enum machine_mode mode, tre || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) >= 16)) return 128; - else if (rs6000_darwin64_abi && mode == BLKmode + else if (TARGET_MACHO + && rs6000_darwin64_abi + && mode == BLKmode && type && TYPE_ALIGN (type) > 64) return 128; else @@ -7675,6 +7685,20 @@ rs6000_darwin64_record_arg_advance_recurse (CUMULA } } +/* Check for an item that needs to be considered specially under the darwin 64 + bit ABI. These are record types where the mode is BLK or the structure is + 8 bytes in size. */ +static int +rs6000_darwin64_struct_check_p (enum machine_mode mode, const_tree type) +{ + return rs6000_darwin64_abi + && ((mode == BLKmode + && TREE_CODE (type) == RECORD_TYPE + && int_size_in_bytes (type) > 0) + || (type && TREE_CODE (type) == RECORD_TYPE + && int_size_in_bytes (type) == 8)) ? 1 : 0; +} + /* Update the data in CUM to advance over an argument of mode MODE and data type TYPE. (TYPE is null for libcalls where that information may not be available.) @@ -7687,7 +7711,6 @@ void function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named, int depth) { - int size; /* Only tick off an argument if we're not recursing. */ if (depth == 0) @@ -7751,11 +7774,9 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum m && cum->sysv_gregno <= GP_ARG_MAX_REG) cum->sysv_gregno++; - else if (rs6000_darwin64_abi - && mode == BLKmode - && TREE_CODE (type) == RECORD_TYPE - && (size = int_size_in_bytes (type)) > 0) + else if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) { + int size = int_size_in_bytes (type); /* Variable sized types have size == -1 and are treated as if consisting entirely of ints. Pad to 16 byte boundary if needed. */ @@ -7782,7 +7803,7 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum m fprintf (stderr, "function_adv: words = %2d, align=%d, size=%d", cum->words, TYPE_ALIGN (type), size); fprintf (stderr, - "nargs = %4d, proto = %d, mode = %4s (darwin64 abi BLK)\n", + "nargs = %4d, proto = %d, mode = %4s (darwin64 abi)\n", cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode)); } @@ -8262,8 +8283,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_m return GEN_INT (cum->call_cookie); } - if (rs6000_darwin64_abi && mode == BLKmode - && TREE_CODE (type) == RECORD_TYPE) + if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) { rtx rslt = rs6000_darwin64_record_arg (cum, type, named, false); if (rslt != NULL_RTX) @@ -8520,9 +8540,7 @@ rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, en return 0; /* In this complicated case we just disable the partial_nregs code. */ - if (rs6000_darwin64_abi && mode == BLKmode - && TREE_CODE (type) == RECORD_TYPE - && int_size_in_bytes (type) > 0) + if (TARGET_MACHO && rs6000_darwin64_struct_check_p (mode, type)) return 0; align_words = rs6000_parm_start (mode, type, cum->words); @@ -26240,10 +26258,8 @@ rs6000_function_value (const_tree valtype, unsigned int regno; /* Special handling for structs in darwin64. */ - if (rs6000_darwin64_abi - && TYPE_MODE (valtype) == BLKmode - && TREE_CODE (valtype) == RECORD_TYPE - && int_size_in_bytes (valtype) > 0) + if (TARGET_MACHO + && rs6000_darwin64_struct_check_p (TYPE_MODE (valtype), valtype)) { CUMULATIVE_ARGS valcum; rtx valret;