PATCH: ARM va_list

Joseph S. Myers joseph@codesourcery.com
Thu Feb 19 23:44:00 GMT 2009


This patch version gives a warning for the mangling change under the
same -Wpsabi option (on by default for C++) as used for the x86_64 ABI
change - it seems appropriate to be consistent among ABI changes in
4.4.

Tested with no regressions with cross to arm-none-linux-gnueabi.  OK
to commit?

2009-02-19  Mark Mitchell  <mark@codesourcery.com>
            Joseph Myers  <joseph@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.

testsuite:
2009-02-19  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.
	* g++.dg/cpp0x/temp-va-arg-bug.C, g++.dg/other/stdarg1.C,
	g++.dg/warn/miss-format-1.C, g++.dg/warn/miss-format-3.C,
	g++.dg/warn/miss-format-4.C, g++.dg/warn/miss-format-5.C,
	g++.dg/warn/miss-format-6.C, g++.old-deja/g++.other/vaarg2.C,
	g++.old-deja/g++.other/vaarg3.C, g++.old-deja/g++.other/vaarg4.C,
	g++.old-deja/g++.pt/builtin.C: Use -Wno-abi on ARM EABI targets.

Index: testsuite/gcc.target/arm/va_list.c
===================================================================
--- testsuite/gcc.target/arm/va_list.c	(revision 0)
+++ 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: testsuite/g++.old-deja/g++.other/vaarg2.C
===================================================================
--- testsuite/g++.old-deja/g++.other/vaarg2.C	(revision 144265)
+++ testsuite/g++.old-deja/g++.other/vaarg2.C	(working copy)
@@ -1,4 +1,5 @@
 // { dg-do run  }
+// { dg-options "-Wno-abi" { target arm_eabi } }
 // Copyright (C) 1999, 2000 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 4 Oct 1999 <nathan@acm.org>
 
Index: testsuite/g++.old-deja/g++.other/vaarg3.C
===================================================================
--- testsuite/g++.old-deja/g++.other/vaarg3.C	(revision 144265)
+++ testsuite/g++.old-deja/g++.other/vaarg3.C	(working copy)
@@ -1,4 +1,5 @@
 // { dg-do assemble  }
+// { dg-options "-Wno-abi" { target arm_eabi } }
 
 // Copyright (C) 1999 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 4 Oct 1999 <nathan@acm.org>
@@ -21,10 +22,10 @@
   const Z &z2 = va_arg (args, Z);       // { dg-error "incomplete" } 
 
   va_arg (args, char);    // { dg-warning "promote" } 
-  // { dg-message "should pass" "pass" { target *-*-* } 23 }
-  // { dg-message "abort" "abort" { target *-*-* } 23 }
+  // { dg-message "should pass" "pass" { target *-*-* } 24 }
+  // { dg-message "abort" "abort" { target *-*-* } 24 }
   va_arg (args, int []);  // { dg-error "array with unspecified bounds" } promote
   va_arg (args, int ());  // { dg-warning "non-POD" } promote
   va_arg (args, bool);    // { dg-warning "promote" "promote" } 
-  // { dg-message "abort" "abort" { target *-*-* } 28 }
+  // { dg-message "abort" "abort" { target *-*-* } 29 }
 }
Index: testsuite/g++.old-deja/g++.other/vaarg4.C
===================================================================
--- testsuite/g++.old-deja/g++.other/vaarg4.C	(revision 144265)
+++ testsuite/g++.old-deja/g++.other/vaarg4.C	(working copy)
@@ -1,4 +1,5 @@
 // { dg-do assemble  }
+// { dg-options "-Wno-abi" { target arm_eabi } }
 
 // Bug 845. We were treating __builtin_va_arg as a unary expr, not a primary,
 // and hence getting parse errors.
Index: testsuite/g++.old-deja/g++.pt/builtin.C
===================================================================
--- testsuite/g++.old-deja/g++.pt/builtin.C	(revision 144265)
+++ testsuite/g++.old-deja/g++.pt/builtin.C	(working copy)
@@ -1,4 +1,5 @@
 // { dg-do assemble  }
+// { dg-options "-Wno-abi" { target arm_eabi } }
 // Bug: Checking whether A depends on template parms, we crash because
 // __builtin_va_list lacks TYPE_LANG_SPECIFIC.
 
Index: testsuite/g++.dg/other/stdarg1.C
===================================================================
--- testsuite/g++.dg/other/stdarg1.C	(revision 144265)
+++ testsuite/g++.dg/other/stdarg1.C	(working copy)
@@ -1,5 +1,6 @@
 // Test stdarg function with anonymous argument
 // { dg-do run }
+// { dg-options "-Wno-abi" { target arm_eabi } }
 
 #include <stdarg.h>
 
Index: testsuite/g++.dg/warn/miss-format-1.C
===================================================================
--- testsuite/g++.dg/warn/miss-format-1.C	(revision 144265)
+++ testsuite/g++.dg/warn/miss-format-1.C	(working copy)
@@ -2,6 +2,7 @@
 /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
 /* { dg-do compile } */
 /* { dg-options "-Wmissing-format-attribute" } */
+/* { dg-options "-Wmissing-format-attribute -Wno-abi" { target arm_eabi } } */
 /* VxWorks does not provide vscanf, either in kernel or RTP mode.  */
 /* { dg-error "not declared" "" { target *-*-solaris2.[7-8] *-*-vxworks* } 25 } */
 
Index: testsuite/g++.dg/warn/miss-format-3.C
===================================================================
--- testsuite/g++.dg/warn/miss-format-3.C	(revision 144265)
+++ testsuite/g++.dg/warn/miss-format-3.C	(working copy)
@@ -2,6 +2,7 @@
 /* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
 /* { dg-do compile } */
 /* { dg-options "-Wmissing-format-attribute" } */
+/* { dg-options "-Wmissing-format-attribute -Wno-abi" { target arm_eabi } } */
 
 #include <stdarg.h>
 
Index: testsuite/g++.dg/warn/miss-format-4.C
===================================================================
--- testsuite/g++.dg/warn/miss-format-4.C	(revision 144265)
+++ testsuite/g++.dg/warn/miss-format-4.C	(working copy)
@@ -2,6 +2,7 @@
 /* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
 /* { dg-do compile } */
 /* { dg-options "-Wmissing-format-attribute" } */
+/* { dg-options "-Wmissing-format-attribute -Wno-abi" { target arm_eabi } } */
 
 #include <stdarg.h>
 
Index: testsuite/g++.dg/warn/miss-format-5.C
===================================================================
--- testsuite/g++.dg/warn/miss-format-5.C	(revision 144265)
+++ testsuite/g++.dg/warn/miss-format-5.C	(working copy)
@@ -2,6 +2,7 @@
 /* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
 /* { dg-do compile } */
 /* { dg-options "-Wmissing-format-attribute" } */
+/* { dg-options "-Wmissing-format-attribute -Wno-abi" { target arm_eabi } } */
 
 #include <stdarg.h>
 
Index: testsuite/g++.dg/warn/miss-format-6.C
===================================================================
--- testsuite/g++.dg/warn/miss-format-6.C	(revision 144265)
+++ testsuite/g++.dg/warn/miss-format-6.C	(working copy)
@@ -2,6 +2,7 @@
 /* Origin: Kaveh Ghazi <ghazi@caip.rutgers.edu> */
 /* { dg-do compile } */
 /* { dg-options "-Wmissing-format-attribute" } */
+/* { dg-options "-Wmissing-format-attribute -Wno-abi" { target arm_eabi } } */
 
 #include <stdarg.h>
 
Index: testsuite/g++.dg/cpp0x/temp-va-arg-bug.C
===================================================================
--- testsuite/g++.dg/cpp0x/temp-va-arg-bug.C	(revision 144265)
+++ testsuite/g++.dg/cpp0x/temp-va-arg-bug.C	(working copy)
@@ -1,4 +1,5 @@
 // { dg-options "--std=c++0x" }
+// { dg-options "-Wno-abi --std=c++0x" { target arm_eabi } }
 #include <stdarg.h>
 
 struct S { };
Index: testsuite/g++.dg/abi/arm_va_list.C
===================================================================
--- testsuite/g++.dg/abi/arm_va_list.C	(revision 0)
+++ testsuite/g++.dg/abi/arm_va_list.C	(revision 0)
@@ -0,0 +1,14 @@
+// { dg-do compile }
+// { dg-options "-Wno-abi" }
+// { dg-require-effective-target arm_eabi }
+
+// AAPCS \S 7.1.4 requires that va_list be a typedef for "struct
+// __va_list".  The mangling 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: testsuite/lib/target-supports.exp
===================================================================
--- testsuite/lib/target-supports.exp	(revision 144265)
+++ testsuite/lib/target-supports.exp	(working copy)
@@ -1451,6 +1451,19 @@
     }]
 }
 
+# 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: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 144265)
+++ config/arm/arm.c	(working copy)
@@ -186,6 +186,9 @@
 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 @@
 #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
@@ -914,6 +924,93 @@
   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
@@ -19506,6 +19603,21 @@
 {
   arm_mangle_map_entry *pos = arm_mangle_map;
 
+  /* The ARM ABI documents (10th October 2008) say that "__va_list"
+     has to be managled as if it is in the "std" namespace.  */
+  if (TARGET_AAPCS_BASED 
+      && lang_hooks.types_compatible_p (type, va_list_type))
+    {
+      static bool warned;
+      if (!warned && warn_psabi)
+	{
+	  warned = true;
+	  inform (input_location,
+		  "the mangling of %<va_list%> has changed in GCC 4.4");
+	}
+      return "St9__va_list";
+    }
+
   if (TREE_CODE (type) != VECTOR_TYPE)
     return NULL;
 

-- 
Joseph S. Myers
joseph@codesourcery.com



More information about the Gcc-patches mailing list