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: ARM va_list


This patch improves conformance to the ABI for the ARM Architecture.
In particular, va_list has a defined layout in the ABI, including the
name of the members of the structure, and its mangling in C++.  At the
binary level, other than the mangling issue, we were already
conformant, but this patch gets the member naming and mangling
correct.

I guess it's hard to call this a regression, but the sooner we fix
this ABI breakage, the less pain we'll have, and this is an
ARM-specific fix.  Is an ARM maintainers willing to grant
dispensation?

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2009-01-13  Mark Mitchell  <mark@codesourcery.com>

	* config/arm/arm.c (arm_builtin_va_list): New function.
	(arm_expand_builtin_va_start): Likewise.
	(arm_gimplify_va_arg_expr): Likewise.
	(TARGET_BUILD_BUILTIN_VA_LIST): Define.
	(TARGET_BUILD_BUILTIN_VA_START): Likewise.
	(TARGET_BUILD_BUILTIN_VA_ARG_EXPR): Likewise.
	(va_list_type): New variable.
	(arm_mangle_type): Mangle va_list_type appropriately.

2009-01-13  Mark Mitchell  <mark@codesourcery.com>
	    Joseph Myers  <joseph@codesourcery.com>

	* gcc.target/arm/va_list.c: New test.
	* g++.dg/abi/arm_va_list.C: Likewise.
	* lib/target-supports.exp (check_effective_target_arm_eabi): New
	function.

Index: gcc/testsuite/gcc.target/arm/va_list.c
===================================================================
--- gcc/testsuite/gcc.target/arm/va_list.c	(revision 0)
+++ gcc/testsuite/gcc.target/arm/va_list.c	(revision 0)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target arm_eabi } */
+
+#include <stdarg.h>
+#include <stddef.h>
+
+/* AAPCS \S 7.1.4 requires that va_list match the structure shown
+   here */
+typedef struct my_va_list 
+{
+  void *ap;
+} my_va_list;
+
+int 
+main () {
+  if (sizeof (va_list) != sizeof (my_va_list))
+    return 1;
+  /* This check confirms both that "va_list" has a member named "__ap"
+     and that it is located at the correct position.  */
+  if (offsetof (va_list, __ap) 
+      != offsetof (my_va_list, ap))
+    return 2;
+
+  return 0;
+}
Index: gcc/testsuite/g++.dg/abi/arm_va_list.C
===================================================================
--- gcc/testsuite/g++.dg/abi/arm_va_list.C	(revision 0)
+++ gcc/testsuite/g++.dg/abi/arm_va_list.C	(revision 0)
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-require-effective-target arm_eabi }
+
+// AAPCS \S 7.1.4 requires that va_list be a typedef for "struct
+// __va_list".  The mangling (to match RealView) is as if it were
+// "std::__va_list".
+// #include <stdarg.h>
+typedef __builtin_va_list va_list;
+
+// { dg-final { scan-assembler "\n_Z1fPSt9__va_list:" } }
+void f(va_list*) {}
+
+// { dg-final { scan-assembler "\n_Z1gSt9__va_listS_:" } }
+void g(va_list, va_list) {}
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp	(revision 143326)
+++ gcc/testsuite/lib/target-supports.exp	(working copy)
@@ -1417,6 +1417,19 @@ proc check_effective_target_mips_loongso
     }]
 }
 
+# Return 1 if this is an ARM target that adheres to the ABI for the ARM
+# Architecture.
+
+proc check_effective_target_arm_eabi { } {
+    return [check_no_compiler_messages arm_eabi object {
+	#ifndef __ARM_EABI__
+	#error not EABI
+	#else
+	int dummy;
+	#endif
+    }]
+}
+
 # Return 1 if this is a PowerPC target with floating-point registers.
 
 proc check_effective_target_powerpc_fprs { } {
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c	(revision 143326)
+++ gcc/config/arm/arm.c	(working copy)
@@ -186,6 +186,9 @@ static void arm_cxx_determine_class_data
 static bool arm_cxx_class_data_always_comdat (void);
 static bool arm_cxx_use_aeabi_atexit (void);
 static void arm_init_libfuncs (void);
+static tree arm_build_builtin_va_list (void);
+static void arm_expand_builtin_va_start (tree, rtx);
+static tree arm_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 static bool arm_handle_option (size_t, const char *, int);
 static void arm_target_help (void);
 static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
@@ -383,6 +386,13 @@ static bool arm_allocate_stack_slots_for
 #undef TARGET_MANGLE_TYPE
 #define TARGET_MANGLE_TYPE arm_mangle_type
 
+#undef TARGET_BUILD_BUILTIN_VA_LIST
+#define TARGET_BUILD_BUILTIN_VA_LIST arm_build_builtin_va_list
+#undef TARGET_EXPAND_BUILTIN_VA_START
+#define TARGET_EXPAND_BUILTIN_VA_START arm_expand_builtin_va_start
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR arm_gimplify_va_arg_expr
+
 #ifdef HAVE_AS_TLS
 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL
 #define TARGET_ASM_OUTPUT_DWARF_DTPREL arm_output_dwarf_dtprel
@@ -913,6 +923,93 @@ arm_init_libfuncs (void)
   set_optab_libfunc (umod_optab, SImode, NULL);
 }
 
+/* On AAPCS systems, this is the "struct __va_list".  */
+static GTY(()) tree va_list_type;
+
+/* Return the type to use as __builtin_va_list.  */
+static tree
+arm_build_builtin_va_list (void)
+{
+  tree va_list_name;
+  tree ap_field;
+  
+  if (!TARGET_AAPCS_BASED)
+    return std_build_builtin_va_list ();
+
+  /* AAPCS \S 7.1.4 requires that va_list be a typedef for a type
+     defined as:
+
+       struct __va_list 
+       {
+	 void *__ap;
+       };
+
+     The C Library ABI further reinforces this definition in \S
+     4.1.
+
+     We must follow this definition exactly.  The structure tag
+     name is visible in C++ mangled names, and thus forms a part
+     of the ABI.  The field name may be used by people who
+     #include <stdarg.h>.  */
+  /* Create the type.  */
+  va_list_type = lang_hooks.types.make_type (RECORD_TYPE);
+  /* Give it the required name.  */
+  va_list_name = build_decl (TYPE_DECL,
+			     get_identifier ("__va_list"),
+			     va_list_type);
+  DECL_ARTIFICIAL (va_list_name) = 1;
+  TYPE_NAME (va_list_type) = va_list_name;
+  /* Create the __ap field.  */
+  ap_field = build_decl (FIELD_DECL, 
+			 get_identifier ("__ap"),
+			 ptr_type_node);
+  DECL_ARTIFICIAL (ap_field) = 1;
+  DECL_FIELD_CONTEXT (ap_field) = va_list_type;
+  TYPE_FIELDS (va_list_type) = ap_field;
+  /* Compute its layout.  */
+  layout_type (va_list_type);
+
+  return va_list_type;
+}
+
+/* Return an expression of type "void *" pointing to the next
+   available argument in a variable-argument list.  VALIST is the
+   user-level va_list object, of type __builtin_va_list.  */
+static tree
+arm_extract_valist_ptr (tree valist)
+{
+  if (TREE_TYPE (valist) == error_mark_node)
+    return error_mark_node;
+
+  /* On an AAPCS target, the pointer is stored within "struct
+     va_list".  */
+  if (TARGET_AAPCS_BASED)
+    {
+      tree ap_field = TYPE_FIELDS (TREE_TYPE (valist));
+      valist = build3 (COMPONENT_REF, TREE_TYPE (ap_field), 
+		       valist, ap_field, NULL_TREE);
+    }
+
+  return valist;
+}
+
+/* Implement TARGET_EXPAND_BUILTIN_VA_START.  */
+static void
+arm_expand_builtin_va_start (tree valist, rtx nextarg)
+{
+  valist = arm_extract_valist_ptr (valist);
+  std_expand_builtin_va_start (valist, nextarg);
+}
+
+/* Implement TARGET_GIMPLIFY_VA_ARG_EXPR.  */
+static tree
+arm_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, 
+			  tree *post_p)
+{
+  valist = arm_extract_valist_ptr (valist);
+  return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
+}
+
 /* Implement TARGET_HANDLE_OPTION.  */
 
 static bool
@@ -19168,6 +19265,13 @@ arm_mangle_type (const_tree type)
 {
   arm_mangle_map_entry *pos = arm_mangle_map;
 
+  /* Although the ARM ABI documents do not specifically say that
+     "__va_list" has to be managled as if it is in the "std"
+     namespace, that is what RealView does.  */
+  if (TARGET_AAPCS_BASED 
+      && lang_hooks.types_compatible_p (type, va_list_type))
+    return "St9__va_list";
+
   if (TREE_CODE (type) != VECTOR_TYPE)
     return NULL;
 


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