This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v2] ARM: __attribute__ ((reg_return))
- From: Zack Weinberg <zack at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org, Paul Brook <paul at codesourcery dot com>, Mark Mitchell <mark at codesourcery dot com>
- Date: Mon, 10 Sep 2007 02:33:30 -0700
- Subject: [PATCH v2] ARM: __attribute__ ((reg_return))
Here is a revised version of my patch from last week [
http://gcc.gnu.org/ml/gcc-patches/2007-09/msg00163.html ] which adds an
ARM-specific type attribute that overrides the ABI and causes an
aggregate to be returned in registers. Aggregates of up to 16 bytes can
be returned this way (in r0-r3).
To reiterate, the primary motivation for this feature is to allow
implementing __aeabi_ldivmod (which is special-cased in the platform
ABI) in C, and as a demonstration, I do just that, removing
__gnu_*divmod_helper and the assembly stubs.
Changes from the previous version: the __gnu_*divmod_helper functions
are altogether gone rather than preserved for binary compatibility (Paul
thought that this was unnecessary) and several constraints on the use of
the attribute are relaxed. You can now apply it to any aggregate type
or complex type. I tested complex types by hand.
Tested with arm-eabi cross compiler (simulator). Can this squeeze into 4.3?
zw
* target.h (member_forces_blkmode, override_record_mode):
New hooks.
* targhooks.c (default_member_forces_blkmode)
(default_override_record_mode): New functions.
* target-def.h, targhooks.h: Update to match.
* stor-layout.c (compute_record_mode): Use
targetm.member_forces_blkmode instead of
MEMBER_TYPE_FORCES_BLK. Call
targetm.override_record_mode at very end.
(layout_type): Use targetm.member_forces_blkmode.
* doc/tm.texi: Document new target hooks; mark
MEMBER_TYPE_FORCES_BLK as obsolete.
* config/arm/arm-protos.h (arm_return_in_memory)
(arm_function_value): Don't declare here.
* config/arm/arm.c (arm_handle_regreturn_attribute)
(arm_override_record_mode): New functions.
(arm_attributes): Add reg_return.
(TARGET_OVERRIDE_RECORD_MODE, TARGET_FUNCTION_VALUE)
(TARGET_RETURN_IN_MEMORY): Define.
(arm_return_in_memory): Now static. Aggregates and
COMPLEX_TYPEs with the reg_return attribute are returned
in registers if their TYPE_SIZE is no more than
4*BITS_PER_WORD. Recursively call this function,
not RETURN_IN_MEMORY.
(arm_function_value): Now static. Abort if structures with the
reg_return attribute do not have the appropriate TYPE_MODE.
* config/arm/arm.h (FUNCTION_VALUE, RETURN_IN_MEMORY):
Don't define.
* config/arm/bpabi.S (__aeabi_ldivmod, __aeabi_uldivmod):
Delete.
* config/arm/bpabi.c: Define them here, using reg_return
structs.
* config/arm/t-bpabi (LIB1ASMFUNCS): Remove _aeabi_ldivmod and
_aeabi_uldivmod.
==================================================================
--- config/arm/arm-protos.h (revision 128380)
+++ config/arm/arm-protos.h (local)
@@ -41,10 +41,6 @@ extern HOST_WIDE_INT thumb_compute_initi
extern unsigned int arm_dbx_register_number (unsigned int);
extern void arm_output_fn_unwind (FILE *, bool);
-
-#ifdef TREE_CODE
-extern int arm_return_in_memory (const_tree);
-#endif
#ifdef RTX_CODE
extern bool arm_vector_mode_supported_p (enum machine_mode);
extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
@@ -159,7 +155,6 @@ extern void arm_init_cumulative_args (CU
extern bool arm_pad_arg_upward (enum machine_mode, const_tree);
extern bool arm_pad_reg_upward (enum machine_mode, tree, int);
extern bool arm_needs_doubleword_align (enum machine_mode, tree);
-extern rtx arm_function_value(const_tree, const_tree);
#endif
extern int arm_apply_result_size (void);
==================================================================
--- config/arm/arm.c (revision 128380)
+++ config/arm/arm.c (local)
@@ -108,6 +108,7 @@ static unsigned long arm_isr_value (tree
static unsigned long arm_compute_func_type (void);
static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
+static tree arm_handle_regreturn_attribute (tree *, tree, tree, int, bool *);
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
#endif
@@ -116,6 +117,7 @@ static void arm_output_function_prologue
static void thumb1_output_function_prologue (FILE *, HOST_WIDE_INT);
static int arm_comp_type_attributes (const_tree, const_tree);
static void arm_set_default_type_attributes (tree);
+static enum machine_mode arm_override_record_mode (const_tree);
static int arm_adjust_cost (rtx, rtx, rtx, int);
static int count_insns_for_constant (HOST_WIDE_INT, int);
static int arm_get_strip_length (int);
@@ -163,6 +165,8 @@ static bool arm_pass_by_reference (CUMUL
static bool arm_promote_prototypes (const_tree);
static bool arm_default_short_enums (void);
static bool arm_align_anon_bitfield (void);
+static rtx arm_function_value (const_tree, const_tree, bool);
+static bool arm_return_in_memory (const_tree, const_tree);
static bool arm_return_in_msb (const_tree);
static bool arm_must_pass_in_stack (enum machine_mode, const_tree);
#ifdef TARGET_UNWIND_INFO
@@ -227,6 +231,9 @@ static void arm_output_dwarf_dtprel (FIL
#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES arm_set_default_type_attributes
+#undef TARGET_OVERRIDE_RECORD_MODE
+#define TARGET_OVERRIDE_RECORD_MODE arm_override_record_mode
+
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
@@ -324,9 +331,15 @@ static void arm_output_dwarf_dtprel (FIL
#undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
+#undef TARGET_FUNCTION_VALUE
+#define TARGET_FUNCTION_VALUE arm_function_value
+
#undef TARGET_RETURN_IN_MSB
#define TARGET_RETURN_IN_MSB arm_return_in_msb
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY arm_return_in_memory
+
#undef TARGET_MUST_PASS_IN_STACK
#define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
@@ -2676,8 +2689,9 @@ arm_canonicalize_comparison (enum rtx_co
/* Define how to find the value returned by a function. */
-rtx
-arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED)
+static rtx
+arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED,
+ bool outgoing ATTRIBUTE_UNUSED)
{
enum machine_mode mode;
int unsignedp ATTRIBUTE_UNUSED;
@@ -2688,6 +2702,12 @@ arm_function_value(const_tree type, cons
if (INTEGRAL_TYPE_P (type))
PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+ /* Structures tagged with reg_return should already have the
+ appropriate integer mode. */
+ if ((AGGREGATE_TYPE_P (type))
+ && lookup_attribute ("reg_return", TYPE_ATTRIBUTES (type)))
+ gcc_assert (mode == mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 0));
+
/* Promotes small structs returned in a register to full-word size
for big-endian AAPCS. */
if (arm_return_in_msb (type))
@@ -2727,10 +2747,9 @@ arm_apply_result_size (void)
}
/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called by the macro
- RETURN_IN_MEMORY. */
-int
-arm_return_in_memory (const_tree type)
+ or in a register (false). */
+static bool
+arm_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
{
HOST_WIDE_INT size;
@@ -2738,8 +2757,13 @@ arm_return_in_memory (const_tree type)
/* Vector values should be returned using ARM registers, not memory (unless
they're over 16 bytes, which will break since we only have four
- call-clobbered registers to play with). */
- if (TREE_CODE (type) == VECTOR_TYPE)
+ call-clobbered registers to play with).
+
+ Structures tagged with the reg_return attribute should also be returned
+ using registers, unless they are too big. */
+ if (TREE_CODE (type) == VECTOR_TYPE
+ || ((AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
+ && lookup_attribute ("reg_return", TYPE_ATTRIBUTES (type))))
return (size < 0 || size > (4 * UNITS_PER_WORD));
if (!AGGREGATE_TYPE_P (type) &&
@@ -2793,7 +2817,7 @@ arm_return_in_memory (const_tree type)
/* ... Aggregates that are not themselves valid for returning in
a register are not allowed. */
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
+ if (arm_return_in_memory (TREE_TYPE (field), fntype))
return 1;
/* Now check the remaining fields, if any. Only bitfields are allowed,
@@ -2828,7 +2852,7 @@ arm_return_in_memory (const_tree type)
if (FLOAT_TYPE_P (TREE_TYPE (field)))
return 1;
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
+ if (arm_return_in_memory (TREE_TYPE (field), fntype))
return 1;
}
@@ -3033,6 +3057,9 @@ const struct attribute_spec arm_attribut
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
{ "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute },
+ /* Return this structure in registers even if the ABI says return it in
+ memory. */
+ { "reg_return", 0, 0, false, true, false, arm_handle_regreturn_attribute },
#ifdef ARM_PE
/* ARM/PE has three new attributes:
interfacearm - ?
@@ -3131,6 +3158,60 @@ arm_handle_isr_attribute (tree *node, tr
return NULL_TREE;
}
+static tree
+arm_handle_regreturn_attribute (tree *node,
+ tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags,
+ bool *no_add_attrs)
+{
+ if (!AGGREGATE_TYPE_P (*node) && TREE_CODE (*node) != COMPLEX_TYPE)
+ {
+ warning (OPT_Wattributes, "the %qs attribute is only meaningful for "
+ "aggregates and complex numbers", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (COMPLETE_TYPE_P (*node))
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (*node);
+
+ if (size == -1)
+ {
+ warning (OPT_Wattributes, "%qT is of variable size, "
+ "so it cannot be returned in registers", *node);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ /* Only r0-r3 can be used for structure returns. */
+ if (size > 4*UNITS_PER_WORD)
+ {
+ warning (OPT_Wattributes,
+ "%qT is too large to return in registers", *node);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ if (!(flags & ATTR_FLAG_TYPE_IN_PLACE))
+ *node = build_variant_type_copy (*node);
+
+ return NULL_TREE;
+}
+
+/* If we're going to return a type in registers, we should keep it in
+ registers too, even if we normally wouldn't. */
+static enum machine_mode
+arm_override_record_mode (const_tree record)
+{
+ if (lookup_attribute ("reg_return", TYPE_ATTRIBUTES (record)))
+ return mode_for_size_tree (TYPE_SIZE (record), MODE_INT, 0);
+ else
+ return TYPE_MODE (record);
+}
+
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
/* Handle the "notshared" attribute. This attribute is another way of
requesting hidden visibility. ARM's compiler supports
==================================================================
--- config/arm/arm.h (revision 128380)
+++ config/arm/arm.h (local)
@@ -1447,13 +1447,6 @@ do { \
? gen_rtx_REG (MODE, FIRST_IWMMXT_REGNUM) \
: gen_rtx_REG (MODE, ARG_REGISTER (1)))
-/* Define how to find the value returned by a function.
- VALTYPE is the data type of the value (as a tree).
- If the precise function being called is known, FUNC is its FUNCTION_DECL;
- otherwise, FUNC is 0. */
-#define FUNCTION_VALUE(VALTYPE, FUNC) \
- arm_function_value (VALTYPE, FUNC);
-
/* 1 if N is a possible register number for a function value.
On the ARM, only r0 and f0 can return results. */
/* On a Cirrus chip, mvf0 can return results. */
@@ -1470,9 +1463,6 @@ do { \
#define APPLY_RESULT_SIZE arm_apply_result_size()
/* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
- in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) arm_return_in_memory (TYPE)
/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
values must be in memory. On the ARM, they need only do so if larger
==================================================================
--- config/arm/bpabi.S (revision 128380)
+++ config/arm/bpabi.S (local)
@@ -80,40 +80,3 @@ ARM_FUNC_START aeabi_ulcmp
FUNC_END aeabi_ulcmp
#endif /* L_aeabi_ulcmp */
-
-#ifdef L_aeabi_ldivmod
-
-ARM_FUNC_START aeabi_ldivmod
- sub sp, sp, #8
-#if defined(__thumb2__)
- mov ip, sp
- push {ip, lr}
-#else
- do_push {sp, lr}
-#endif
- bl SYM(__gnu_ldivmod_helper) __PLT__
- ldr lr, [sp, #4]
- add sp, sp, #8
- do_pop {r2, r3}
- RET
-
-#endif /* L_aeabi_ldivmod */
-
-#ifdef L_aeabi_uldivmod
-
-ARM_FUNC_START aeabi_uldivmod
- sub sp, sp, #8
-#if defined(__thumb2__)
- mov ip, sp
- push {ip, lr}
-#else
- do_push {sp, lr}
-#endif
- bl SYM(__gnu_uldivmod_helper) __PLT__
- ldr lr, [sp, #4]
- add sp, sp, #8
- do_pop {r2, r3}
- RET
-
-#endif /* L_aeabi_divmod */
-
==================================================================
--- config/arm/bpabi.c (revision 128380)
+++ config/arm/bpabi.c (local)
@@ -1,6 +1,6 @@
/* Miscellaneous BPABI functions.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
Contributed by CodeSourcery, LLC.
This file is free software; you can redistribute it and/or modify it
@@ -30,32 +30,36 @@
extern long long __divdi3 (long long, long long);
extern unsigned long long __udivdi3 (unsigned long long,
unsigned long long);
-extern long long __gnu_ldivmod_helper (long long, long long, long long *);
-extern unsigned long long __gnu_uldivmod_helper (unsigned long long,
- unsigned long long,
- unsigned long long *);
+typedef struct __attribute__ ((reg_return))
+{
+ long long quot;
+ long long rem;
+} lldiv_t_rr;
-long long
-__gnu_ldivmod_helper (long long a,
- long long b,
- long long *remainder)
+typedef struct __attribute__ ((reg_return))
{
- long long quotient;
+ unsigned long long quot;
+ unsigned long long rem;
+} ulldiv_t_rr;
- quotient = __divdi3 (a, b);
- *remainder = a - b * quotient;
- return quotient;
-}
+extern lldiv_t_rr __aeabi_ldivmod(long long, long long);
+extern ulldiv_t_rr __aeabi_uldivmod(unsigned long long, unsigned long long);
-unsigned long long
-__gnu_uldivmod_helper (unsigned long long a,
- unsigned long long b,
- unsigned long long *remainder)
+lldiv_t_rr
+__aeabi_ldivmod (long long a, long long b)
{
- unsigned long long quotient;
+ lldiv_t_rr r;
+ r.quot =__divdi3 (a, b);
+ r.rem = a - b * r.quot;
+ return r;
+}
- quotient = __udivdi3 (a, b);
- *remainder = a - b * quotient;
- return quotient;
+ulldiv_t_rr
+__aeabi_uldivmod (unsigned long long a, unsigned long long b)
+{
+ ulldiv_t_rr r;
+ r.quot = __udivdi3 (a, b);
+ r.rem = a - b * r.quot;
+ return r;
}
==================================================================
--- config/arm/t-bpabi (revision 128380)
+++ config/arm/t-bpabi (local)
@@ -1,5 +1,5 @@
# Add the bpabi.S functions.
-LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
+LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp
# Add the BPABI C functions.
LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \
==================================================================
--- doc/tm.texi (revision 128380)
+++ doc/tm.texi (local)
@@ -1278,19 +1278,38 @@ these accesses should use the bitfield c
The default is @code{!TARGET_STRICT_ALIGN}.
@end deftypefn
-@defmac MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode})
-Return 1 if a structure or array containing @var{field} should be accessed using
-@code{BLKMODE}.
+@deftypefn {Target Hook} bool TARGET_MEMBER_FORCES_BLKMODE (@var{field}, @var{mode})
+Return @code{true} if an aggregate type containing @var{field} should
+be assigned @code{BLKmode}, even when it otherwise would not.
+
+If @var{field} is the only field in the aggregate, @var{mode} is its
+mode, otherwise @var{mode} is @code{VOIDmode}. @var{mode} is provided
+for the case where structures of one field would require the
+structure's mode to retain the field's mode. The default always
+returns @code{false}.
-If @var{field} is the only field in the structure, @var{mode} is its
-mode, otherwise @var{mode} is VOIDmode. @var{mode} is provided in the
-case where structures of one field would require the structure's mode to
-retain the field's mode.
-
-Normally, this is not needed. See the file @file{c4x.h} for an example
-of how to use this macro to prevent a structure having a floating point
-field from being accessed in an integer mode.
-@end defmac
+This hook is normally not needed. See the @code{c4x} back end for a
+case where it is.
+@end deftypefn
+
+@defmac MEMBER_TYPE_FORCES_BLK (@var{field}, @var{mode})
+This is an obsolete macro with the same function as the
+@code{TARGET_MEMBER_FORCES_BLKMODE} hook. New ports should define
+that hook instead.
+@end defmac
+
+@deftypefn {Target Hook} {enum machine_mode} TARGET_OVERRIDE_RECORD_MODE (@var{record})
+Return the mode that @var{record} should be assigned. When it is
+called, @code{TYPE_MODE (@var{record})} is the mode that
+@code{compute_record_mode} has just selected; return that mode if the
+machine-independent logic made the right choice, or some other mode if
+not. The default is to accept @code{compute_record_mode}'s choice
+always.
+
+One reason to define this hook is if some @code{RECORD_TYPE}s bigger
+than @code{MAX_FIXED_MODE_SIZE} should be assigned scalar modes
+anyway. See the @code{arm} back end for an example.
+@end deftypefn
@defmac ROUND_TYPE_ALIGN (@var{type}, @var{computed}, @var{specified})
Define this macro as an expression for the alignment of a type (given
==================================================================
--- stor-layout.c (revision 128380)
+++ stor-layout.c (local)
@@ -1363,13 +1363,10 @@ compute_record_mode (tree type)
if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
mode = DECL_MODE (field);
-#ifdef MEMBER_TYPE_FORCES_BLK
/* With some targets, eg. c4x, it is sub-optimal
to access an aligned BLKmode structure as a scalar. */
-
- if (MEMBER_TYPE_FORCES_BLK (field, mode))
+ if (targetm.member_forces_blkmode (field, mode))
return;
-#endif /* MEMBER_TYPE_FORCES_BLK */
}
/* If we only have one real field; use its mode if that mode's size
@@ -1394,6 +1391,10 @@ compute_record_mode (tree type)
TYPE_NO_FORCE_BLK (type) = 1;
TYPE_MODE (type) = BLKmode;
}
+
+ /* As long as we were not forced to use BLKmode for any of the
+ reasons above, targets have a chance to override the decision. */
+ TYPE_MODE (type) = targetm.override_record_mode (type);
}
/* Compute TYPE_SIZE and TYPE_ALIGN for TYPE, once it has been laid
@@ -1812,9 +1813,7 @@ layout_type (tree type)
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
TYPE_MODE (type) = BLKmode;
if (TYPE_SIZE (type) != 0
-#ifdef MEMBER_TYPE_FORCES_BLK
- && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode)
-#endif
+ && ! targetm.member_forces_blkmode (type, VOIDmode)
/* BLKmode elements force BLKmode aggregate;
else extract/store fields may lose. */
&& (TYPE_MODE (TREE_TYPE (type)) != BLKmode
==================================================================
--- target-def.h (revision 128380)
+++ target-def.h (local)
@@ -473,6 +473,8 @@
#define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
#define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_const_tree_false
#define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_const_tree_false
+#define TARGET_MEMBER_FORCES_BLKMODE default_member_forces_blkmode
+#define TARGET_OVERRIDE_RECORD_MODE default_override_record_mode
#define TARGET_ALIGN_ANON_BITFIELD hook_bool_void_false
#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
#define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false
@@ -700,6 +702,8 @@
TARGET_INSERT_ATTRIBUTES, \
TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
TARGET_MS_BITFIELD_LAYOUT_P, \
+ TARGET_MEMBER_FORCES_BLKMODE, \
+ TARGET_OVERRIDE_RECORD_MODE, \
TARGET_DECIMAL_FLOAT_SUPPORTED_P, \
TARGET_FIXED_POINT_SUPPORTED_P, \
TARGET_ALIGN_ANON_BITFIELD, \
==================================================================
--- target.h (revision 128380)
+++ target.h (local)
@@ -483,6 +483,15 @@ struct gcc_target
Microsoft Visual C++ bitfield layout rules. */
bool (* ms_bitfield_layout_p) (const_tree record_type);
+ /* True if the presence of FIELD (a FIELD_DECL) in a structure
+ forces that structure to be given BLKmode. MODE is FIELD's mode
+ if it is the only field, VOIDmode otherwise. */
+ bool (* member_forces_blkmode) (const_tree field, enum machine_mode mode);
+
+ /* Called at the end of compute_record_mode to allow targets to override
+ its choices. RECORD is the record whose mode is being determined. */
+ enum machine_mode (*override_record_mode) (const_tree record);
+
/* True if the target supports decimal floating point. */
bool (* decimal_float_supported_p) (void);
==================================================================
--- targhooks.c (revision 128380)
+++ targhooks.c (local)
@@ -256,6 +256,28 @@ default_unwind_emit (FILE * stream ATTRI
gcc_unreachable ();
}
+/* Return true if a field requires its containing structure to be BLKmode
+ (i.e. to be handled in memory). This is a transitional hook which defers
+ to the old MEMBER_TYPE_FORCES_BLK macro. */
+bool
+default_member_forces_blkmode (const_tree field ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+#ifdef MEMBER_TYPE_FORCES_BLK
+ return MEMBER_TYPE_FORCES_BLK (field, mode);
+#else
+ return false;
+#endif
+}
+
+/* Targets may override the decision made by compute_record_mode, if
+ they wish, by defining this hook. */
+enum machine_mode
+default_override_record_mode (const_tree record)
+{
+ return TYPE_MODE (record);
+}
+
/* True if MODE is valid for the target. By "valid", we mean able to
be manipulated in non-trivial ways. In particular, this means all
the arithmetic is supported.
==================================================================
--- targhooks.h (revision 128380)
+++ targhooks.h (local)
@@ -53,6 +53,9 @@ extern bool hook_callee_copies_named
extern void default_unwind_emit (FILE *, rtx);
+extern bool default_member_forces_blkmode (const_tree, enum machine_mode);
+extern enum machine_mode default_override_record_mode (const_tree);
+
extern bool default_scalar_mode_supported_p (enum machine_mode);
extern bool default_decimal_float_supported_p (void);
extern bool default_fixed_point_supported_p (void);