[Patch] Fix PR 27067 by adding a targetm.mangle_decl_assembler_name

dannysmith@users.sourceforge.net dannysmith@users.sourceforge.net
Wed May 16 11:02:00 GMT 2007


Hello

The attached patch adds a target hook that allows target to
mangle/decorate decl assembler names.     

It is use by windows32 targets to add '@nn' suffix to the external
assembler name of stdcall/fastcall functions. Currently, that is done in
encode_section_info, but sometimes that is too late.

It fixes PR target/27067 where the DECL_ASSEMBLER_NAME of a method does
not get its target-specific encoding  soon enough.

The assembler name is the same as in earlier (3.0 and later) versions of
GCC, so ABI breakage is not a problem.

A C testcase does not appear necesssary since the target will not build
without correct naming of stdcall symbols.  A C++ testcase could be
easily extracted from PR target/27067  

Bootstrapped (c, objc, c++, fortran) and regtested on i686-pc-mingw32.

OK for trunk?

:ADDPATCH target:

ChangeLog
	
	PR target/27067
	* doc/tm.texi (TARGET_MANGLE_DECL_ASSEMBLER_NAME): Document.
	* targhooks.h (default_mangle_decl_assembler_name): Declare
	default hook.
	* targhooks.c (default_mangle_decl_assembler_name): Define
	default hook.
	* target-def.h (TARGET_MANGLE_DECL_ASSEMBLER_NAME) New. Set to
	default hook.
	* target.h (struct gcc_target): Add mangle_decl_assembler_name
field.
	* langhooks.c (lhd_set_decl_assembler_name): Call
	targetm.mangle_decl_assembler_name for names with global scope.

	* config/i386/cygming.h (TARGET_MANGLE_DECL_ASSEMBLER_NAME)
Override
	default.
	(ASM_OUTPUT_DEF_FROM_DECLS): Simplify to use
DECL_ASSEMBLER_NAME.
	* config/i386/i386-protos.h
(i386_pe_mangle_decl_assembler_name):
	Declare.
	* config/i386/winnt.c
(i386_pe_maybe_mangle_decl_assembler_name):
	New. Factored out of i386_pe_encode_section_info.
	(gen_stdcall_or_fastcall_suffix): Get name identifier as
argument.
	Move check for prior decoration of stdcall
	symbols to i386_pe_encode_section_info.
	(i386_pe_encode_section_info): Adjust call to
	gen_stdcall_or_fastcall_suffix.  Use
	i386_pe_maybe_mangle_decl_assembler_name, if needed.
	(i386_pe_mangle_decl_assembler_name): New. Wrap
	i386_pe_maybe_mangle_decl_assembler_name.


cp/ChangeLog

        * mangle.c (mangle_decl): Call
targetm.mangle_decl_assembler_name.


Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 124651)
+++ doc/tm.texi	(working copy)
@@ -6465,6 +6465,14 @@
 else in @code{readonly_data_section}.
 @end deftypefn
 
+@deftypefn {Target Hook} void TARGET_MANGLE_DECL_ASSEMBLER_NAME (tree
@var{decl}, tree @var{id})
+Define this hook if the DECL_ASSEMBLER_NAME of a symbol may
+differ from the language-independent default, DECL_NAME  (the symbol
+name as it appears in source code).  This is the case, for example,
+on MS windows32 targets where stdcall and fastcall function assembler
+names are decorated with an @@nn suffix. 
+@end deftypefn
+
 @deftypefn {Target Hook} void TARGET_ENCODE_SECTION_INFO (tree
@var{decl}, rtx @var{rtl}, int @var{new_decl_p})
 Define this hook if references to a symbol or a constant must be
 treated differently depending on something about the variable or
Index: targhooks.c
===================================================================
--- targhooks.c	(revision 124651)
+++ targhooks.c	(working copy)
@@ -631,4 +631,11 @@
   return flag_pic ? 3 : 0;
 }
 
+/* By default, do no modification. */
+tree default_mangle_decl_assembler_name (tree decl ATTRIBUTE_UNUSED,
+					 tree id)
+{
+   return id;
+}
+
 #include "gt-targhooks.h"
Index: targhooks.h
===================================================================
--- targhooks.h	(revision 124651)
+++ targhooks.h	(working copy)
@@ -84,3 +84,6 @@
 extern void hook_void_bitmap (bitmap);
 extern bool default_handle_c_option (size_t, const char *, int);
 extern int default_reloc_rw_mask (void);
+
+extern tree default_mangle_decl_assembler_name (tree, tree);
+
Index: target.h
===================================================================
--- target.h	(revision 124651)
+++ target.h	(working copy)
@@ -544,6 +544,12 @@
      to the current module.  */
   bool (* binds_local_p) (tree);
 
+  /* Modify and return the identifier of a DECL's external name,
+     originally identified by ID, as required by the target,
+    (eg, append @nn to windows32 stdcall function names).
+     The default is to return ID without modification. */
+   tree (* mangle_decl_assembler_name) (tree decl, tree  id);
+
   /* Do something target-specific to record properties of the DECL into
      the associated SYMBOL_REF.  */
   void (* encode_section_info) (tree, rtx, int);
Index: cp/mangle.c
===================================================================
--- cp/mangle.c	(revision 124651)
+++ cp/mangle.c	(working copy)
@@ -2621,8 +2621,9 @@
 void
 mangle_decl (const tree decl)
 {
-  SET_DECL_ASSEMBLER_NAME (decl,
-			   get_identifier_nocopy (mangle_decl_string
(decl)));
+  tree id = get_identifier_nocopy (mangle_decl_string (decl));
+  id = targetm.mangle_decl_assembler_name (decl, id);
+  SET_DECL_ASSEMBLER_NAME (decl, id);
 }
 
 /* Generate the mangled representation of TYPE.  */
Index: langhooks.c
===================================================================
--- langhooks.c	(revision 124651)
+++ langhooks.c	(working copy)
@@ -34,6 +34,7 @@
 #include "integrate.h"
 #include "flags.h"
 #include "langhooks.h"
+#include "target.h"
 #include "langhooks-def.h"
 #include "ggc.h"
 #include "diagnostic.h"
@@ -147,6 +148,8 @@
 void
 lhd_set_decl_assembler_name (tree decl)
 {
+  tree id;
+
   /* The language-independent code should never use the
      DECL_ASSEMBLER_NAME for lots of DECLs.  Only FUNCTION_DECLs and
      VAR_DECLs for variables with static storage duration need a real
@@ -161,21 +164,26 @@
      as that used in the source language.  (That's correct for C, and
      GCC used to set DECL_ASSEMBLER_NAME to the same value as
      DECL_NAME in build_decl, so this choice provides backwards
-     compatibility with existing front-ends.
-      
+     compatibility with existing front-ends.  This assumption is
wrapped
+     in a target hook, to allow for target-specific modification of the
+     identifier.
+ 
      Can't use just the variable's own name for a variable whose scope
      is less than the whole compilation.  Concatenate a distinguishing
      number - we use the DECL_UID.  */
+
   if (TREE_PUBLIC (decl) || DECL_CONTEXT (decl) == NULL_TREE)
-    SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+    id = targetm.mangle_decl_assembler_name (decl, DECL_NAME (decl));
   else
     {
       const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
       char *label;
       
       ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
+      id = get_identifier (label);
     }
+  SET_DECL_ASSEMBLER_NAME (decl, id);
+
 }
 
 /* Type promotion for variable arguments.  */
Index: config/i386/cygming.h
===================================================================
--- config/i386/cygming.h	(revision 124651)
+++ config/i386/cygming.h	(working copy)
@@ -347,15 +347,11 @@
 /* This implements the `alias' attribute, keeping any stdcall or
    fastcall decoration.  */
 #undef	ASM_OUTPUT_DEF_FROM_DECLS
-#define	ASM_OUTPUT_DEF_FROM_DECLS(STREAM, DECL, TARGET)
\
+#define	ASM_OUTPUT_DEF_FROM_DECLS(STREAM, DECL, TARGET)
\
   do
\
     {
\
-      const char *alias;
\
-      rtx rtlname = XEXP (DECL_RTL (DECL), 0);
\
-      if (GET_CODE (rtlname) == SYMBOL_REF)
\
-	alias = XSTR (rtlname, 0);
\
-      else
\
-	abort ();
\
+      const char *alias
\
+	= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL));
\
       if (TREE_CODE (DECL) == FUNCTION_DECL)
\
 	i386_pe_declare_function_type (STREAM, alias,
\
 				       TREE_PUBLIC (DECL));
\
@@ -395,6 +391,8 @@
 #define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P
i386_pe_valid_dllimport_attribute_p
 #define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
i386_pe_adjust_class_at_definition
 
+#define TARGET_MANGLE_DECL_ASSEMBLER_NAME
i386_pe_mangle_decl_assembler_name
+
 #undef TREE
 
 #ifndef BUFSIZ
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 124651)
+++ config/i386/winnt.c	(working copy)
@@ -75,7 +75,7 @@
   /* The attribute applies only to objects that are initialized and
have
      external linkage.  However, we may not know about initialization
      until the language frontend has processed the decl. We'll check
for
-     initialization later in encode_section_info.  */	
+     initialization later in encode_section_info.  */
   if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node))
     {	
       error ("%qs attribute applies only to initialized variables"
@@ -154,22 +154,21 @@
    return true;
 }
 
-/* Return string which is the former assembler name modified with a
-   suffix consisting of an atsign (@) followed by the number of bytes
of
-   arguments.  If FASTCALL is true, also add the FASTCALL_PREFIX.
+/* Return string which is the function name, identified by ID, modified
+   with a suffix consisting of an atsign (@) followed by the number of
+   bytes of arguments.  If ID is NULL use the DECL_NAME as base. If
+   FASTCALL is true, also add the FASTCALL_PREFIX.
    Return NULL if no change required.  */
 
 static tree
-gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall)
+gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall)
 {
   HOST_WIDE_INT total = 0;
-  const char *asm_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
(decl));
+  const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id :
DECL_NAME (decl));
   char *new_str, *p;
   tree formal_type;
 
-  /* Do not change the identifier if a verbatim asmspec or already
done. */
-  if (*asm_str == '*' || strchr (asm_str, '@'))
-    return NULL_TREE;
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);  
 
   formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
   if (formal_type != NULL_TREE)
@@ -202,16 +201,47 @@
 
 	formal_type = TREE_CHAIN (formal_type);
       }
-
   /* Assume max of 8 base 10 digits in the suffix.  */
-  p = new_str = alloca (1 + strlen (asm_str) + 1 + 8 + 1);
+  p = new_str = alloca (1 + strlen (old_str) + 1 + 8 + 1);
   if (fastcall)
     *p++ = FASTCALL_PREFIX;
-  sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, asm_str, total);
+  sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, old_str, total);
 
   return get_identifier (new_str);
 }
 
+/* Maybe decorate and get a new identifier for the DECL of a stdcall or
+   fastcall function. The original identifier is supplied in ID. */
+
+static tree
+i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id)
+{
+  tree new_id = NULL_TREE;
+
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    { 
+      tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+      if (lookup_attribute ("stdcall", type_attributes))
+	new_id = gen_stdcall_or_fastcall_suffix (decl, id, false);
+      else if (lookup_attribute ("fastcall", type_attributes))
+	new_id = gen_stdcall_or_fastcall_suffix (decl, id, true);
+    }
+
+  return new_id;
+}
+
+/* This is used as a target hook to modify the DECL_ASSEMBLER_NAME
+   in the language-independent default hook
+   langhooks,c:lhd_set_decl_assembler_name ()
+   and in cp/mangle,c:mangle_decl ().  */
+tree
+i386_pe_mangle_decl_assembler_name (tree decl, tree id)
+{
+  tree new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, id);   
+
+  return (new_id ? new_id : id);
+}
+
 void
 i386_pe_encode_section_info (tree decl, rtx rtl, int first)
 {
@@ -233,21 +263,24 @@
     case FUNCTION_DECL:
       if (first)
 	{
-	  tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
-	  tree newid = NULL_TREE;
-
-	  if (lookup_attribute ("stdcall", type_attributes))
-	    newid = gen_stdcall_or_fastcall_suffix (decl, false);
-	  else if (lookup_attribute ("fastcall", type_attributes))
-	    newid = gen_stdcall_or_fastcall_suffix (decl, true);
-	  if (newid != NULL_TREE) 	
+	  /* FIXME: In Ada, and perhaps other language frontends,
+	     imported stdcall names may not yet have been modified.
+	     Check and do it know.  */
+         tree new_id;
+         tree old_id = DECL_ASSEMBLER_NAME (decl);
+     	  const char* asm_str = IDENTIFIER_POINTER (old_id);
+          /* Do not change the identifier if a verbatim asmspec
+	     or if stdcall suffix already added. */
+      	  if (*asm_str == '*' || strchr (asm_str, '@'))
+            break;
+	  if ((new_id = i386_pe_maybe_mangle_decl_assembler_name (decl,
old_id)))
 	    {
-	      XSTR (symbol, 0) = IDENTIFIER_POINTER (newid);
 	      /* These attributes must be present on first declaration,
-	         change_decl_assembler_name will warn if they are added
-	         later and the decl has been referenced, but
duplicate_decls
-	         should catch the mismatch before this is called.  */ 
-	      change_decl_assembler_name (decl, newid);
+		 change_decl_assembler_name will warn if they are added
+		 later and the decl has been referenced, but
duplicate_decls
+		 should catch the mismatch first.  */
+	      change_decl_assembler_name (decl, new_id);
+	      XSTR (symbol, 0) = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
(decl));
 	    }
 	}
       break;
Index: config/i386/i386-protos.h
===================================================================
--- config/i386/i386-protos.h	(revision 124651)
+++ config/i386/i386-protos.h	(working copy)
@@ -220,6 +220,7 @@
 						    HOST_WIDE_INT,
 						    HOST_WIDE_INT);
 extern void i386_pe_file_end (void);
+extern tree i386_pe_mangle_decl_assembler_name (tree, tree);
 
 /* In winnt-cxx.c and winnt-stubs.c  */
 extern void i386_pe_adjust_class_at_definition (tree);



More information about the Gcc-patches mailing list