This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: ARM va_list
- From: mitchell at codesourcery dot com (Mark Mitchell)
- To: gcc-patches at gcc dot gnu dot org
- Cc: paul at codesourcery dot com, janis187 at us dot ibm dot com
- Date: Tue, 13 Jan 2009 16:22:02 -0800 (PST)
- Subject: PATCH: ARM va_list
- Reply-to: mark at codesourcery dot com
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;