diff options
Diffstat (limited to 'gcc/config/rs6000/rs6000.c')
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 5d4b889e6d7..e82b6d59581 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2591,7 +2591,7 @@ invalid_e500_subreg (rtx op, enum machine_mode mode) return false; } -/* Darwin, AIX increases natural record alignment to doubleword if the first +/* AIX increases natural record alignment to doubleword if the first field is an FP double while the FP fields remain word aligned. */ unsigned int @@ -2618,6 +2618,37 @@ rs6000_special_round_type_align (tree type, unsigned int computed, return align; } +/* Darwin increases record alignment to the natural alignment of + the first field. */ + +unsigned int +darwin_rs6000_special_round_type_align (tree type, unsigned int computed, + unsigned int specified) +{ + unsigned int align = MAX (computed, specified); + + if (TYPE_PACKED (type)) + return align; + + /* Find the first field, looking down into aggregates. */ + do { + tree field = TYPE_FIELDS (type); + /* Skip all non field decls */ + while (field != NULL && TREE_CODE (field) != FIELD_DECL) + field = TREE_CHAIN (field); + if (! field) + break; + type = TREE_TYPE (field); + while (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + } while (AGGREGATE_TYPE_P (type)); + + if (! AGGREGATE_TYPE_P (type) && type != error_mark_node) + align = MAX (align, TYPE_ALIGN (type)); + + return align; +} + /* Return 1 for an operand in small memory on V.4/eabi. */ int |