This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] m68k: Fix a binary compatibility problem with -mno-strict-align.


Hi,

Attached is a patch to fix binary compatibility problem with
-mno-strict-align.

Consider a testcase reduced from
gdb-trunk/gdb/testsuite/gdb.base/structs.c.

struct s {
  char a;
  char b;
} foo2;

struct s
foo (void)
{
  return foo2;
}

-mno-strict-align breaks the ABI compatibility in this testcase.  Here
is how.

-O2 -fomit-frame-pointer

foo:
        move.b foo2,(%a0)
        move.b foo2+1,%d0
        move.b %d0,1(%a0)
        move.l %a0,%d0
        rts

-O2 -fomit-frame-pointer -mno-strict-align

foo:
        move.w foo2,%d0
        rts

Notice that in the first case, GCC stores the return value in a memory
location pointed to by A0.  However, in the second case, GCC stores
the return value in D0.  (FWIW, -mno-strict-align changes code that
calls foo consistently.)

The GCC manual describes -mno-strict-align and -mno-strict-align as

  "Do not (do) assume that unaligned memory references will be handled
  by the system."

The user reading this description would not expect an ABI
incompatibility, so this problem is a bug.

The problem is that the m68k port does not override
TARGET_RETURN_IN_MEMORY.  Thus default_return_in_memory gets to decide
whether a return value is returned in memory, but it just looks at
whether the RTL mode for the return type is BLKmode or not, which is
determined in compute_record_mode.

The patch fixes this problem by introducing m68k_return_in_memory to
immitate what compute_record_mode does as if STRICT_ALIGNMENT were
true.  Specifically, if we are returning an aggregate type, and its
alignment is smaller than the alignment of a mode that would contain
the struct, then we return in memory.

Looking at layout_type in stor-layout.c, I see that ARRAY_TYPE,
RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE are affected by the value
of STRICT_ALIGNMENT, so AGGREGATE_TYPE_P should be appropriate in
m68k_return_in_memory.

Tested on m68k-elf.  Also tested the binary compatibility between code
compiled with -mstrict-align and -mno-strict-align with compat.exp and
struct-layout-1.exp.  OK to apply?

Kazu Hirata

2007-07-16  Kazu Hirata  <kazu@codesourcery.com>

	* config/m68k/m68k.c (TARGET_RETURN_IN_MEMORY): New.
	(m68k_return_in_memory): New.

Index: gcc/config/m68k/m68k.c
===================================================================
--- gcc/config/m68k/m68k.c	(revision 126682)
+++ gcc/config/m68k/m68k.c	(working copy)
@@ -135,6 +135,7 @@ static void m68k_compute_frame_layout (v
 static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
 static bool m68k_ok_for_sibcall_p (tree, tree);
 static bool m68k_rtx_costs (rtx, int, int, int *);
+static bool m68k_return_in_memory (tree, tree);
 
 
 /* Specify the identification number of the library being built */
@@ -206,6 +207,9 @@ int m68k_last_compare_had_fp_operands;
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL m68k_ok_for_sibcall_p
 
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY m68k_return_in_memory
+
 static const struct attribute_spec m68k_attribute_table[] =
 {
   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
@@ -4387,3 +4391,24 @@ m68k_function_value (tree valtype, tree 
   else
     return gen_rtx_REG (mode, D0_REG);
 }
+
+/* Worker function for TARGET_RETURN_IN_MEMORY.  */
+
+static bool
+m68k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+  enum machine_mode mode = TYPE_MODE (type);
+
+  if (mode == BLKmode)
+    return true;
+
+  /* If TYPE's known alignment is less than the alignment of MODE that
+     would contain the structure, then return in memory.  We need to
+     do so to maintain the compatibility between code compiled with
+     -mstrict-align and that compiled with -mno-strict-align.  */
+  if (AGGREGATE_TYPE_P (type)
+      && TYPE_ALIGN (type) < GET_MODE_ALIGNMENT (mode))
+    return true;
+
+  return false;
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]