[cft] rewrite i386 dllimport/dllexport

Richard Henderson rth@redhat.com
Sat Mar 24 08:21:00 GMT 2007


(1) Converted to use SYMBOL_REF_FLAGS, instead of mangling the string
    inside the SYMBOL_REF.  This is just general tidiness.

(2) No longer mangle the original DECL_RTL; the expansion to __imp__foo
    happens during code generation instead.  This can make 
    -mno-fun-dllimport redundant, since the decl for foo still contains
    the original symbol.

(3) There appeared to be a whole lot of magic checks and whatnot, that
    ought not ever be generated by the dllimport code in tree.c.

(4) No attempt is made, at this time, to handle 

	extern int __declspec(dllimport) imp;
	int *p = &imp;

    The best way to handle this, I would think, would be to hook
    into TARGET_ASM_INTEGER, like rs6000_assemble_integer, notice
    that a SYMBOL_REF_DLLIMPORT_P symbol is being emitted, and
    generate:

	L1:
		.long	addend
	.section .some.reloc.section
		.rva	L1
		.rva	__imp__symbol
	.previous

    where some bit of the runtime can interpret that table and
    apply the results:

	struct some_reloc_section_entry {
	  DWORD reloc_off;
	  DWORD imp_sym_off;
	};

	DWORD *reloc = __image_base__ + entry->reloc_off;
	DWORD *imp_sym = __image_base__ + entry->imp_sym_off;
	*reloc += *imp_sym;

    I was disappointed to find that none of the existing gnu dll
    relocation mechanisms appear to handle this kind of situation.
    The closest I could find was make_import_fixup_entry in
    ld/pe-dll.c, which appears to generate one entire .idata$2
    entry (5+2 words) for each occurrence of an imported symbol,
    which seems a bit wasteful.  But, since we don't have the
    import symbol numbers, we couldn't even pretend to do that from
    within the compiler.

    Perhaps I'm mistaken about how _pei386_runtime_relocator works,
    but I don't see how it could handle what's needed, as implemeted.
    Though the scheme described above would seem to be a superset of
    what it handles.


Anyway, testing this properly is beyond what I'm set up to do
at present, so assistance is greatly appreciated.


r~


	* config/i386/cygming.h: Remove all function declarations.
	(TARGET_STRIP_NAME_ENCODING, ASM_OUTPUT_LABELREF): Remove.
	(COMMON_ASM_OP, ASM_OUTPUT_COMMON): Remove.
	(ASM_OUTPUT_ALIGNED_DECL_COMMON): New.
	(ASM_DECLARE_OBJECT_NAME): Use i386_pe_maybe_record_exported_symbol.
	(ASM_DECLARE_FUNCTION_NAME): Likewise.
	* config/i386/uwin.h (ASM_DECLARE_FUNCTION_NAME): Likewise.
	* config/i386/i386-interix.h (SUBTARGET_ENCODE_SECTION_INFO): 
	Rename from TARGET_ENCODE_SECTION_INFO.
	* config/i386/netware.h: Likewise.
	* config/i386/i386-protos.h: Update.
	* config/i386/i386.c (ix86_function_ok_for_sibcall): Turn the
	ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES into a straight test.
	(legitimate_constant_p): Deny DLLIMPORT symbols.
	(dllimport_map, get_dllimport_decl): New.
	(legitimize_dllimport_symbol): New.
	(legitimize_address, ix86_expand_move): Use it.
	(TARGET_BINDS_LOCAL_P): New definition for PE.
	* config/i386/i386.h (DLL_IMPORT_EXPORT_PREFIX): Remove.
	(SYMBOL_FLAG_DLLIMPORT, SYMBOL_REF_DLLIMPORT_P): New.
	(SYMBOL_FLAG_DLLEXPORT, SYMBOL_REF_DLLEXPORT_P): New.
	* config/i386/predicates.md (constant_call_address_operand): Deny
	DLLIMPORT symbols.
	* config/i386/winnt.c (DLL_IMPORT_PREFIX, DLL_EXPORT_PREFIX): Remove.
	(i386_pe_determine_dllexport_p): Rename from i386_pe_dllexport_p.
	(i386_pe_determine_dllimport_p): Rename from i386_pe_dllimport_p,
	trust DECL_DLLIMPORT_P setting.
	(i386_pe_dllexport_name_p, i386_pe_dllimport_name_p): Remove.
	(i386_pe_mark_dllexport, i386_pe_mark_dllimport): Remove.
	(gen_stdcall_or_fastcall_suffix): Return NULL when no change is
	required; tidy argument scanning loop.
	(i386_pe_encode_section_info): Set SYMBOL_REF_FLAGS for import/export.
	(i386_pe_strip_name_encoding): Remove.
	(i386_pe_binds_local_p): New.
	(i386_pe_strip_name_encoding_full): Use default_strip_name_encoding.
	(i386_pe_output_labelref): Remove.
	(i386_pe_asm_output_aligned_decl_common): New.
	(i386_pe_maybe_record_exported_symbol): Rename from
	i386_pe_record_exported_symbol; check for dllexported decl first.

	* varasm.c (initializer_constant_valid_p): Don't deny DLLIMPORT
	functions.

--- config/i386/cygming.h	(revision 123169)
+++ config/i386/cygming.h	(local)
@@ -148,39 +148,18 @@ do {									\
    section and we need to set DECL_SECTION_NAME so we do that here.
    Note that we can be called twice on the same decl.  */
 
-#undef SUBTARGET_ENCODE_SECTION_INFO
-#define SUBTARGET_ENCODE_SECTION_INFO  i386_pe_encode_section_info
-#undef  TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING  i386_pe_strip_name_encoding_full
-
-/* Output a reference to a label.  */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF  i386_pe_output_labelref
-
-#undef  COMMON_ASM_OP
-#define COMMON_ASM_OP	"\t.comm\t"
+#define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
 
 /* Output a common block.  */
-#undef ASM_OUTPUT_COMMON
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)	\
-do {							\
-  if (i386_pe_dllexport_name_p (NAME))			\
-    i386_pe_record_exported_symbol (NAME, 1);		\
-  if (! i386_pe_dllimport_name_p (NAME))		\
-    {							\
-      fprintf ((STREAM), "\t.comm\t");			\
-      assemble_name ((STREAM), (NAME));			\
-      fprintf ((STREAM), ", %d\t%s %d\n",		\
-	       (int)(ROUNDED), ASM_COMMENT_START, (int)(SIZE));	\
-    }							\
-} while (0)
+#undef ASM_OUTPUT_ALIGNED_DECL_COMMON
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON \
+  i386_pe_asm_output_aligned_decl_common
 
 /* Output the label for an initialized variable.  */
 #undef ASM_DECLARE_OBJECT_NAME
 #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL)	\
 do {							\
-  if (i386_pe_dllexport_name_p (NAME))			\
-    i386_pe_record_exported_symbol (NAME, 1);		\
+  i386_pe_maybe_record_exported_symbol (DECL, NAME, 1);	\
   ASM_OUTPUT_LABEL ((STREAM), (NAME));			\
 } while (0)
 
@@ -210,7 +189,6 @@ do {							\
 /* Windows uses explicit import from shared libraries.  */
 #define MULTIPLE_SYMBOL_SPACES 1
 
-extern void i386_pe_unique_section (TREE, int);
 #define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
 
@@ -229,8 +207,7 @@ extern void i386_pe_unique_section (TREE
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)			\
   do									\
     {									\
-      if (i386_pe_dllexport_name_p (NAME))				\
-	i386_pe_record_exported_symbol (NAME, 0);			\
+      i386_pe_maybe_record_exported_symbol (DECL, NAME, 0);		\
       if (write_symbols != SDB_DEBUG)					\
 	i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL));	\
       ASM_OUTPUT_LABEL (FILE, NAME);					\
@@ -289,15 +266,6 @@ extern void i386_pe_unique_section (TREE
 			       build_tree_list (get_identifier ("stdcall"),   \
 						NULL))
 
-/* External function declarations.  */
-
-extern void i386_pe_record_external_function (tree, const char *);
-extern void i386_pe_declare_function_type (FILE *, const char *, int);
-extern void i386_pe_record_exported_symbol (const char *, int);
-extern void i386_pe_file_end (void);
-extern int i386_pe_dllexport_name_p (const char *);
-extern int i386_pe_dllimport_name_p (const char *);
-
 /* For Win32 ABI compatibility */
 #undef DEFAULT_PCC_STRUCT_RETURN
 #define DEFAULT_PCC_STRUCT_RETURN 0
@@ -315,10 +283,10 @@ extern int i386_pe_dllimport_name_p (con
    machine.  Use this macro to limit the alignment which can be
    specified using the `__attribute__ ((aligned (N)))' construct.  If
    not defined, the default value is `BIGGEST_ALIGNMENT'.  */
-#undef MAX_OFILE_ALIGNMENT
 /* IMAGE_SCN_ALIGN_8192BYTES is the largest section alignment flag
    specified in the PECOFF60 spec.  Native MS compiler also limits
    user-specified alignment to 8192 bytes.  */
+#undef MAX_OFILE_ALIGNMENT
 #define MAX_OFILE_ALIGNMENT (8192 * 8)
 
 /* Native complier aligns internal doubles in structures on dword boundaries.  */
@@ -334,6 +302,7 @@ extern int i386_pe_dllimport_name_p (con
 #ifndef SET_ASM_OP
 #define SET_ASM_OP "\t.set\t"
 #endif
+
 /* This implements the `alias' attribute, keeping any stdcall or
    fastcall decoration.  */
 #undef	ASM_OUTPUT_DEF_FROM_DECLS
--- config/i386/i386-interix.h	(revision 123169)
+++ config/i386/i386-interix.h	(local)
@@ -326,8 +326,7 @@ while (0)
    differently depending on something about the variable or
    function named by the symbol (such as what section it is in).  */
 
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
+#define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
 #undef  TARGET_STRIP_NAME_ENCODING
 #define TARGET_STRIP_NAME_ENCODING  i386_pe_strip_name_encoding_full
 
--- config/i386/i386-protos.h	(revision 123169)
+++ config/i386/i386-protos.h	(local)
@@ -191,9 +191,6 @@ extern int ix86_local_alignment (tree, i
 extern int ix86_constant_alignment (tree, int);
 extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
 extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
-
-extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
-extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
 extern int x86_field_alignment (tree, int);
 #endif
 
@@ -206,18 +203,23 @@ extern void ix86_expand_vector_extract (
 extern void ix86_expand_reduc_v4sf (rtx (*)(rtx, rtx, rtx), rtx, rtx);
 
 /* In winnt.c  */
-extern int i386_pe_dllexport_name_p (const char *);
-extern int i386_pe_dllimport_name_p (const char *);
 extern void i386_pe_unique_section (tree, int);
 extern void i386_pe_declare_function_type (FILE *, const char *, int);
 extern void i386_pe_record_external_function (tree, const char *);
-extern void i386_pe_record_exported_symbol (const char *, int);
+extern void i386_pe_maybe_record_exported_symbol (tree, const char *, int);
 extern void i386_pe_asm_file_end (FILE *);
 extern void i386_pe_encode_section_info (tree, rtx, int);
-extern const char *i386_pe_strip_name_encoding (const char *);
+extern bool i386_pe_binds_local_p (tree);
 extern const char *i386_pe_strip_name_encoding_full (const char *);
 extern void i386_pe_output_labelref (FILE *, const char *);
 extern bool i386_pe_valid_dllimport_attribute_p (tree);
+extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
+extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
+extern void i386_pe_asm_output_aligned_decl_common (FILE *, tree,
+						    const char *,
+						    HOST_WIDE_INT,
+						    HOST_WIDE_INT);
+extern void i386_pe_file_end (void);
 
 /* In winnt-cxx.c and winnt-stubs.c  */
 extern void i386_pe_adjust_class_at_definition (tree);
--- config/i386/i386.c	(revision 123169)
+++ config/i386/i386.c	(local)
@@ -2561,12 +2561,11 @@ ix86_function_ok_for_sibcall (tree decl,
 	}
     }
 
-#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
   /* Dllimport'd functions are also called indirectly.  */
-  if (decl && DECL_DLLIMPORT_P (decl)
+  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+      && decl && DECL_DLLIMPORT_P (decl)
       && ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
     return false;
-#endif
 
   /* If we forced aligned the stack, then sibcalling would unalign the
      stack, which may break the called function.  */
@@ -6324,6 +6323,11 @@ legitimate_constant_p (rtx x)
       /* TLS symbols are never valid.  */
       if (SYMBOL_REF_TLS_MODEL (x))
 	return false;
+
+      /* DLLIMPORT symbols are never valid.  */
+      if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+	  && SYMBOL_REF_DLLIMPORT_P (x))
+	return false;
       break;
 
     case CONST_DOUBLE:
@@ -7181,6 +7185,82 @@ legitimize_tls_address (rtx x, enum tls_
   return dest;
 }
 
+/* Expand SYMBOL to (MEM __imp_SYMBOL) for dllimport'ed variables.  */
+
+static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+  htab_t dllimport_map;
+
+static tree
+get_dllimport_decl (tree decl)
+{
+  struct tree_map *h, in;
+  void **loc;
+  const char *name;
+  const char *prefix;
+  size_t namelen, prefixlen;
+  char *imp_name;
+  tree to;
+  rtx rtl;
+
+  if (!dllimport_map)
+    dllimport_map = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0);
+
+  in.hash = htab_hash_pointer (decl);
+  in.base.from = decl;
+  loc = htab_find_slot_with_hash (dllimport_map, &in, in.hash, INSERT);
+  h = *loc;
+  if (h)
+    return h->to;
+
+  *loc = h = ggc_alloc (sizeof (struct tree_map));
+  h->hash = in.hash;
+  h->base.from = decl;
+  h->to = to = build_decl (VAR_DECL, NULL, ptr_type_node);
+  DECL_ARTIFICIAL (to) = 1;
+  DECL_IGNORED_P (to) = 1;
+  DECL_EXTERNAL (to) = 1;
+  TREE_READONLY (to) = 1;
+
+  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  name = targetm.strip_name_encoding (name);
+  if (name[0] == FASTCALL_PREFIX)
+    {
+      name++;
+      prefix = "*__imp_";
+    }
+  else
+    prefix = "*__imp__";
+
+  namelen = strlen (name);
+  prefixlen = strlen (prefix);
+  imp_name = alloca (namelen + prefixlen + 1);
+  memcpy (imp_name, prefix, prefixlen);
+  memcpy (imp_name + prefixlen, name, namelen + 1);
+
+  name = ggc_alloc_string (imp_name, namelen + prefixlen);
+  rtl = gen_rtx_SYMBOL_REF (Pmode, name);
+  SET_SYMBOL_REF_DECL (rtl, to);
+  SYMBOL_REF_FLAGS (rtl) = SYMBOL_FLAG_LOCAL;
+
+  rtl = gen_const_mem (Pmode, rtl);
+  set_mem_alias_set (rtl, ix86_GOT_alias_set ());
+
+  SET_DECL_RTL (to, rtl);
+
+  return to;
+}
+
+static rtx
+legitimize_dllimport_symbol (rtx symbol)
+{
+  tree imp_decl;
+
+  gcc_assert (SYMBOL_REF_DECL (symbol));
+  imp_decl = get_dllimport_decl (SYMBOL_REF_DECL (symbol));
+
+  return force_reg (Pmode, DECL_RTL (imp_decl));
+}
+
 /* Try machine-dependent ways of modifying an illegitimate address
    to be legitimate.  If we find one, return the new, valid address.
    This macro is used in only one place: `memory_address' in explow.c.
@@ -7223,6 +7303,20 @@ legitimize_address (rtx x, rtx oldx ATTR
   if (flag_pic && SYMBOLIC_CONST (x))
     return legitimize_pic_address (x, 0);
 
+  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES)
+    {
+      if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_DLLIMPORT_P (x))
+	return legitimize_dllimport_symbol (x);
+      if (GET_CODE (x) == CONST
+	  && GET_CODE (XEXP (x, 0)) == PLUS
+	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
+	  && SYMBOL_REF_DLLIMPORT_P (XEXP (XEXP (x, 0), 0)))
+	{
+	  rtx t = legitimize_dllimport_symbol (XEXP (XEXP (x, 0), 0));
+	  return gen_rtx_PLUS (Pmode, t, XEXP (XEXP (x, 0), 1));
+	}
+    }
+
   /* Canonicalize shifts by 0, 1, 2, 3 into multiply */
   if (GET_CODE (x) == ASHIFT
       && CONST_INT_P (XEXP (x, 1))
@@ -9228,20 +9322,31 @@ ix86_expand_move (enum machine_mode mode
 	  if (op1 == op0)
 	    return;
 	}
+      else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+	       && SYMBOL_REF_DLLIMPORT_P (op1))
+	op1 = legitimize_dllimport_symbol (op1);
     }
   else if (GET_CODE (op1) == CONST
 	   && GET_CODE (XEXP (op1, 0)) == PLUS
 	   && GET_CODE (XEXP (XEXP (op1, 0), 0)) == SYMBOL_REF)
     {
-      model = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (op1, 0), 0));
+      rtx addend = XEXP (XEXP (op1, 0), 1);
+      rtx symbol = XEXP (XEXP (op1, 0), 0);
+      rtx tmp = NULL;
+
+      model = SYMBOL_REF_TLS_MODEL (symbol);
       if (model)
+	tmp = legitimize_tls_address (symbol, model, true);
+      else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
+	       && SYMBOL_REF_DLLIMPORT_P (symbol))
+	tmp = legitimize_dllimport_symbol (symbol);
+
+      if (tmp)
 	{
-	  rtx addend = XEXP (XEXP (op1, 0), 1);
-	  op1 = legitimize_tls_address (XEXP (XEXP (op1, 0), 0), model, true);
-	  op1 = force_operand (op1, NULL);
-	  op1 = expand_simple_binop (Pmode, PLUS, op1, addend,
+	  tmp = force_operand (tmp, NULL);
+	  tmp = expand_simple_binop (Pmode, PLUS, tmp, addend,
 				     op0, 1, OPTAB_DIRECT);
-	  if (op1 == op0)
+	  if (tmp == op0)
 	    return;
 	}
     }
@@ -21551,6 +21656,10 @@ static const struct attribute_spec ix86_
 #undef TARGET_BINDS_LOCAL_P
 #define TARGET_BINDS_LOCAL_P darwin_binds_local_p
 #endif
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#undef TARGET_BINDS_LOCAL_P
+#define TARGET_BINDS_LOCAL_P i386_pe_binds_local_p
+#endif
 
 #undef TARGET_ASM_OUTPUT_MI_THUNK
 #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
--- config/i386/i386.h	(revision 123169)
+++ config/i386/i386.h	(local)
@@ -2344,8 +2344,6 @@ enum ix86_stack_slot
   (! IN_RANGE ((SRC), FIRST_STACK_REG, LAST_STACK_REG))
 
 
-#define DLL_IMPORT_EXPORT_PREFIX '#'
-
 #define FASTCALL_PREFIX '@'
 
 struct machine_function GTY(())
@@ -2395,6 +2393,17 @@ struct machine_function GTY(())
 #define SYMBOL_FLAG_FAR_ADDR		(SYMBOL_FLAG_MACH_DEP << 0)
 #define SYMBOL_REF_FAR_ADDR_P(X)	\
 	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_FAR_ADDR) != 0)
+
+/* Flags to mark dllimport/dllexport.  Used by PE ports, but handy to
+   have defined always, to avoid ifdefing.  */
+#define SYMBOL_FLAG_DLLIMPORT		(SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_REF_DLLIMPORT_P(X) \
+	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLIMPORT) != 0)
+
+#define SYMBOL_FLAG_DLLEXPORT		(SYMBOL_FLAG_MACH_DEP << 2)
+#define SYMBOL_REF_DLLEXPORT_P(X) \
+	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLEXPORT) != 0)
+
 /*
 Local variables:
 version-control: t
--- config/i386/netware.h	(revision 123169)
+++ config/i386/netware.h	(local)
@@ -150,7 +150,6 @@ Boston, MA 02110-1301, USA.  */
    the number of registers used, and an atsign (@). */
 void i386_nlm_encode_section_info (tree, rtx, int);
 const char *i386_nlm_strip_name_encoding (const char *);
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO  i386_nlm_encode_section_info
+#define SUBTARGET_ENCODE_SECTION_INFO  i386_nlm_encode_section_info
 #undef  TARGET_STRIP_NAME_ENCODING
 #define TARGET_STRIP_NAME_ENCODING  i386_nlm_strip_name_encoding
--- config/i386/predicates.md	(revision 123169)
+++ config/i386/predicates.md	(local)
@@ -484,9 +484,13 @@
 
 ;; Test for a pc-relative call operand
 (define_predicate "constant_call_address_operand"
-  (and (ior (match_code "symbol_ref")
-            (match_operand 0 "local_symbolic_operand"))
-       (match_test "ix86_cmodel != CM_LARGE && ix86_cmodel != CM_LARGE_PIC")))
+  (match_code "symbol_ref")
+{
+  if (ix86_cmodel == CM_LARGE || ix86_cmodel == CM_LARGE_PIC)
+    return false;
+  if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && SYMBOL_REF_DLLIMPORT_P (op))
+    return false;
+})
 
 ;; True for any non-virtual or eliminable register.  Used in places where
 ;; instantiation of such a register may cause the pattern to not be recognized.
--- config/i386/uwin.h	(revision 123169)
+++ config/i386/uwin.h	(local)
@@ -77,8 +77,7 @@ Boston, MA 02110-1301, USA.  */
 #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)			\
   do									\
     {									\
-      if (i386_pe_dllexport_name_p (NAME))				\
-	i386_pe_record_exported_symbol (NAME, 0);			\
+      i386_pe_maybe_record_exported_symbol (DECL, NAME, 0);		\
       /* UWIN binutils bug workaround.  */				\
       if (0 && write_symbols != SDB_DEBUG)				\
 	i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL));	\
--- config/i386/winnt.c	(revision 123169)
+++ config/i386/winnt.c	(local)
@@ -34,6 +34,7 @@ Software Foundation, 51 Franklin Street,
 #include "toplev.h"
 #include "hashtab.h"
 #include "ggc.h"
+#include "target.h"
 
 /* i386/PE specific attribute support.
 
@@ -46,22 +47,6 @@ Software Foundation, 51 Franklin Street,
    multiple times.
 */
 
-static tree associated_type (tree);
-static tree gen_stdcall_or_fastcall_suffix (tree, bool);
-static bool i386_pe_dllexport_p (tree);
-static bool i386_pe_dllimport_p (tree);
-static void i386_pe_mark_dllexport (tree);
-static void i386_pe_mark_dllimport (tree);
-
-/* This is we how mark internal identifiers with dllimport or dllexport
-   attributes.  */
-#ifndef DLL_IMPORT_PREFIX
-#define DLL_IMPORT_PREFIX "#i."
-#endif
-#ifndef DLL_EXPORT_PREFIX
-#define DLL_EXPORT_PREFIX "#e."
-#endif
-
 /* Handle a "shared" attribute;
    arguments as in struct attribute_spec.handler.  */
 tree
@@ -108,67 +93,59 @@ ix86_handle_selectany_attribute (tree *n
 static tree
 associated_type (tree decl)
 {
-  return  (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
-            ?  DECL_CONTEXT (decl) : NULL_TREE;
+  return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
+          ?  DECL_CONTEXT (decl) : NULL_TREE);
 }
 
-
-/* Return true if DECL is a dllexport'd object.  */
+/* Return true if DECL should be a dllexport'd object.  */
 
 static bool
-i386_pe_dllexport_p (tree decl)
+i386_pe_determine_dllexport_p (tree decl)
 {
-  if (TREE_CODE (decl) != VAR_DECL
-       && TREE_CODE (decl) != FUNCTION_DECL)
+  tree assoc;
+
+  if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
     return false;
 
   if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
     return true;
 
   /* Also mark class members of exported classes with dllexport.  */
-  if (associated_type (decl)
-      && lookup_attribute ("dllexport",
-			    TYPE_ATTRIBUTES (associated_type (decl))))
+  assoc = associated_type (decl);
+  if (assoc && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (assoc)))
     return i386_pe_type_dllexport_p (decl);
 
   return false;
 }
 
+/* Return true if DECL should be a dllimport'd object.  */
+
 static bool
-i386_pe_dllimport_p (tree decl)
+i386_pe_determine_dllimport_p (tree decl)
 {
-  if (TREE_CODE (decl) != VAR_DECL
-       && TREE_CODE (decl) != FUNCTION_DECL)
+  tree assoc;
+
+  if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
     return false;
 
   /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag.
      We may need to override an earlier decision.  */
-  if (DECL_DLLIMPORT_P (decl)
-      && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
-    {
-       /* Make a final check to see if this is a definition before we generate
-          RTL for an indirect reference.  */   
-       if (!DECL_EXTERNAL (decl))
-	{
-	  error ("%q+D: definition is marked as dllimport", decl);
-	  DECL_DLLIMPORT_P (decl) = 0;
-          return false;
-        }
-      return true;
-    }
+  if (DECL_DLLIMPORT_P (decl))
+    return true;
+
   /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
      by  targetm.cxx.adjust_class_at_definition.  Check again to emit
      warnings if the class attribute has been overridden by an
      out-of-class definition.  */
-  else if (associated_type (decl)
-           && lookup_attribute ("dllimport",
-				TYPE_ATTRIBUTES (associated_type (decl))))
+  assoc = associated_type (decl);
+  if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)))
     return i386_pe_type_dllimport_p (decl);
 
   return false;
 }
 
 /* Handle the -mno-fun-dllimport target switch.  */
+
 bool
 i386_pe_valid_dllimport_attribute_p (tree decl)
 {
@@ -177,247 +154,157 @@ i386_pe_valid_dllimport_attribute_p (tre
    return true;
 }
 
-/* Return nonzero if SYMBOL is marked as being dllexport'd.  */
-
-int
-i386_pe_dllexport_name_p (const char *symbol)
-{
-  return (strncmp (DLL_EXPORT_PREFIX, symbol,
-		   strlen (DLL_EXPORT_PREFIX)) == 0);
-}
-
-/* Return nonzero if SYMBOL is marked as being dllimport'd.  */
-
-int
-i386_pe_dllimport_name_p (const char *symbol)
-{
-  return (strncmp (DLL_IMPORT_PREFIX, symbol,
-		   strlen (DLL_IMPORT_PREFIX)) == 0);
-}
-
-/* Mark a DECL as being dllexport'd.
-   Note that we override the previous setting (e.g.: dllimport).  */
-
-static void
-i386_pe_mark_dllexport (tree decl)
-{
-  const char *oldname;
-  char  *newname;
-  rtx rtlname;
-  rtx symref;
-  tree idp;
-
-  rtlname = XEXP (DECL_RTL (decl), 0);
-  if (GET_CODE (rtlname) == MEM)
-    rtlname = XEXP (rtlname, 0);
-  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
-  oldname = XSTR (rtlname, 0);
-  if (i386_pe_dllimport_name_p (oldname))
-    {
-      warning (0, "inconsistent dll linkage for %q+D, dllexport assumed",
-	       decl);
-     /* Remove DLL_IMPORT_PREFIX.  */
-      oldname += strlen (DLL_IMPORT_PREFIX);
-    }
-  else if (i386_pe_dllexport_name_p (oldname))
-    return;  /*  already done  */
-
-  newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
-  sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
-
-  /* We pass newname through get_identifier to ensure it has a unique
-     address.  RTL processing can sometimes peek inside the symbol ref
-     and compare the string's addresses to see if two symbols are
-     identical.  */
-  idp = get_identifier (newname);
-
-  symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-  SET_SYMBOL_REF_DECL (symref, decl);
-  XEXP (DECL_RTL (decl), 0) = symref;
-}
-
-/* Mark a DECL as being dllimport'd.  */
-
-static void
-i386_pe_mark_dllimport (tree decl)
-{
-  const char *oldname;
-  char  *newname;
-  tree idp;
-  rtx rtlname, newrtl;
-  rtx symref;
-
-  rtlname = XEXP (DECL_RTL (decl), 0);
-  if (GET_CODE (rtlname) == MEM)
-    rtlname = XEXP (rtlname, 0);
-  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
-  oldname = XSTR (rtlname, 0);
-  if (i386_pe_dllexport_name_p (oldname))
-    {
-      error ("%qs declared as both exported to and imported from a DLL",
-             IDENTIFIER_POINTER (DECL_NAME (decl)));
-      return;
-    }
-  else if (i386_pe_dllimport_name_p (oldname))
-    {
-      /* Already done, but do a sanity check to prevent assembler
-	 errors.  */
-      gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
-		  && DECL_DLLIMPORT_P (decl));
-      return;
-    }
-
-  newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
-  sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
-
-  /* We pass newname through get_identifier to ensure it has a unique
-     address.  RTL processing can sometimes peek inside the symbol ref
-     and compare the string's addresses to see if two symbols are
-     identical.  */
-  idp = get_identifier (newname);
-
-  symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-  SET_SYMBOL_REF_DECL (symref, decl);
-  newrtl = gen_rtx_MEM (Pmode,symref);
-  XEXP (DECL_RTL (decl), 0) = newrtl;
-
-  DECL_DLLIMPORT_P (decl) = 1;
-}
-
 /* 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.  */
+   arguments.  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)
 {
-  int total = 0;
-  /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
-     of DECL_ASSEMBLER_NAME.  */
-   const char *asmname =  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-  char *newsym;
-  char *p;
+  HOST_WIDE_INT total = 0;
+  const char *asm_str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  char *new_str, *p;
   tree formal_type;
 
   /* Do not change the identifier if a verbatim asmspec or already done. */
-  if (*asmname == '*' || strchr (asmname, '@'))
-    return DECL_ASSEMBLER_NAME (decl);
+  if (*asm_str == '*' || strchr (asm_str, '@'))
+    return NULL_TREE;
 
   formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
   if (formal_type != NULL_TREE)
-    {
-      /* These attributes are ignored for variadic functions in
-	 i386.c:ix86_return_pops_args. For compatibility with MS
-         compiler do not add @0 suffix here.  */ 
-      if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
-        return DECL_ASSEMBLER_NAME (decl);
-
-      /* Quit if we hit an incomplete type.  Error is reported
-         by convert_arguments in c-typeck.c or cp/typeck.c.  */
-      while (TREE_VALUE (formal_type) != void_type_node
-	     && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))	
-	{
-	  int parm_size
-	    = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
-	    /* Must round up to include padding.  This is done the same
-	       way as in store_one_arg.  */
-	  parm_size = ((parm_size + PARM_BOUNDARY - 1)
-		       / PARM_BOUNDARY * PARM_BOUNDARY);
-	  total += parm_size;
-	  formal_type = TREE_CHAIN (formal_type);\
-	}
-     }
+    while (1)
+      {
+	HOST_WIDE_INT parm_size;
+	HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
+
+	/* We got to the end of the list without seeing void_list_node,
+	   which means the function is variadic.  The suffix is to be
+	   ignored in that case.  */
+	if (formal_type == NULL_TREE)
+	  return NULL_TREE;
+
+	/* End of arguments, non-varargs marker.  */
+        if (formal_type == void_list_node)
+	  break;
+
+        /* Quit if we hit an incomplete type.  Error is reported
+	   by convert_arguments in c-typeck.c or cp/typeck.c.  */
+	parm_size = int_size_in_bytes (TREE_VALUE (formal_type));
+	if (parm_size < 0)
+	  break;
+
+	/* Must round up to include padding.  This is done the same
+	   way as in store_one_arg.  */
+	parm_size = ((parm_size + parm_boundary_bytes - 1)
+		     / parm_boundary_bytes * parm_boundary_bytes);
+	total += parm_size;
+
+	formal_type = TREE_CHAIN (formal_type);
+      }
 
   /* Assume max of 8 base 10 digits in the suffix.  */
-  newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
-  p = newsym;
+  p = new_str = alloca (1 + strlen (asm_str) + 1 + 8 + 1);
   if (fastcall)
     *p++ = FASTCALL_PREFIX;
-  sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);
-  return get_identifier (newsym);
+  sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, asm_str, total);
+
+  return get_identifier (new_str);
 }
 
 void
 i386_pe_encode_section_info (tree decl, rtx rtl, int first)
 {
+  rtx symbol;
+  int flags;
+
+  /* Do this last, due to our frobbing of DECL_DLLIMPORT_P above.  */
   default_encode_section_info (decl, rtl, first);
 
-  if (first && TREE_CODE (decl) == FUNCTION_DECL)
+  switch (TREE_CODE (decl))
     {
-      tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
-      tree newid = NULL_TREE;
+    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) 	
+	    {
+	      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);
+	    }
+	}
+      break;
 
-      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) 	
+    case VAR_DECL:
+      /* Careful not to prod global register variables.  */
+      if (!MEM_P (rtl))
+	return;
+
+      if (lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)))
 	{
-	  rtx rtlname = XEXP (rtl, 0);
-	  if (GET_CODE (rtlname) == MEM)
-	    rtlname = XEXP (rtlname, 0);
-	  XSTR (rtlname, 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);
+	  if (DECL_INITIAL (decl)
+	      /* If an object is initialized with a ctor, the static
+		 initialization and destruction code for it is present in
+		 each unit defining the object.  The code that calls the
+		 ctor is protected by a link-once guard variable, so that
+		 the object still has link-once semantics,  */
+	      || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+	    make_decl_one_only (decl);
+	  else
+	    error ("%q+D:'selectany' attribute applies only to "
+		   "initialized objects", decl);
 	}
-    }
+      break;
 
-  else if (TREE_CODE (decl) == VAR_DECL
-           && lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)))
-    {
-      if (DECL_INITIAL (decl)
- 	  /* If an object is initialized with a ctor, the static
-	     initialization and destruction code for it is present in
-	     each unit defining the object.  The code that calls the
-	     ctor is protected by a link-once guard variable, so that
-	     the object still has link-once semantics,  */
-    	   || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
-	make_decl_one_only (decl);
-      else
-	error ("%q+D:'selectany' attribute applies only to initialized objects",
-	       decl);
+    default:
+      return;
     }
 
+  symbol = XEXP (rtl, 0);
+  gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
+
   /* Mark the decl so we can tell from the rtl whether the object is
      dllexport'd or dllimport'd.  tree.c: merge_dllimport_decl_attributes
      handles dllexport/dllimport override semantics.  */
-
-  if (i386_pe_dllexport_p (decl))
-    i386_pe_mark_dllexport (decl);
-  else if (i386_pe_dllimport_p (decl))
-    i386_pe_mark_dllimport (decl);
-  /* It might be that DECL has been declared as dllimport, but a
-     subsequent definition nullified that.  Assert that
-     tree.c: merge_dllimport_decl_attributes has removed the attribute
-     before the RTL name was marked with the DLL_IMPORT_PREFIX.  */
-  else
-    gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL
-	    	   || TREE_CODE (decl) == VAR_DECL)
-		  && rtl != NULL_RTX
-		  && GET_CODE (rtl) == MEM
-		  && GET_CODE (XEXP (rtl, 0)) == MEM
-		  && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF
-		  && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0))));
+  flags = (SYMBOL_REF_FLAGS (symbol) &
+	   ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT));
+  if (i386_pe_determine_dllexport_p (decl))
+    flags |= SYMBOL_FLAG_DLLEXPORT;
+  else if (i386_pe_determine_dllimport_p (decl))
+    {
+      flags |= SYMBOL_FLAG_DLLIMPORT;
+      /* If we went through the associated_type path, this won't already
+	 be set.  Though, frankly, this seems wrong, and should be fixed
+	 elsewhere.  */
+      if (!DECL_DLLIMPORT_P (decl))
+	{
+	  DECL_DLLIMPORT_P (decl) = 1;
+	  flags &= ~SYMBOL_FLAG_LOCAL;
+	}
+    }
+  SYMBOL_REF_FLAGS (symbol) = flags;
 }
 
-/* Strip only the leading encoding, leaving the stdcall suffix and fastcall
-   prefix if it exists.  */
-
-const char *
-i386_pe_strip_name_encoding (const char *str)
+bool
+i386_pe_binds_local_p (tree exp)
 {
-  if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
-      == 0)
-    str += strlen (DLL_IMPORT_PREFIX);
-  else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
-	   == 0)
-    str += strlen (DLL_EXPORT_PREFIX);
-  if (*str == '*')
-    str += 1;
-  return str;
+  /* PE does not do dynamic binding.  Indeed, the only kind of
+     non-local reference comes from a dllimport'd symbol.  */
+  if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
+      && DECL_DLLIMPORT_P (exp))
+    return false;
+
+  return true;
 }
 
 /* Also strip the fastcall prefix and stdcall suffix.  */
@@ -426,7 +313,7 @@ const char *
 i386_pe_strip_name_encoding_full (const char *str)
 {
   const char *p;
-  const char *name = i386_pe_strip_name_encoding (str);
+  const char *name = default_strip_name_encoding (str);
 
   /* Strip leading '@' on fastcall symbols.  */
   if (*name == '@')
@@ -440,46 +327,6 @@ i386_pe_strip_name_encoding_full (const 
   return name;
 }
 
-/* Output a reference to a label. Fastcall symbols are prefixed with @,
-   whereas symbols for functions using other calling conventions don't
-   have a prefix (unless they are marked dllimport or dllexport).  */
-
-void i386_pe_output_labelref (FILE *stream, const char *name)
-{
-  if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
-      == 0)
-    /* A dll import */
-    {
-      if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
-      /* A dllimport fastcall symbol.  */
-        {
-          fprintf (stream, "__imp_%s",
-                   i386_pe_strip_name_encoding (name));
-        }
-      else
-      /* A dllimport non-fastcall symbol.  */
-        {
-          fprintf (stream, "__imp__%s",
-                   i386_pe_strip_name_encoding (name));
-        }
-    }
-  else if ((name[0] == FASTCALL_PREFIX)
-           || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
-	       == 0
-	       && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))
-    /* A fastcall symbol.  */
-    {
-      fprintf (stream, "%s",
-               i386_pe_strip_name_encoding (name));
-    }
-  else
-    /* Everything else.  */
-    {
-      fprintf (stream, "%s%s", USER_LABEL_PREFIX,
-               i386_pe_strip_name_encoding (name));
-    }
-}
-
 void
 i386_pe_unique_section (tree decl, int reloc)
 {
@@ -612,6 +459,32 @@ i386_pe_asm_named_section (const char *n
 	       (discard  ? "discard" : "same_size"));
     }
 }
+
+void
+i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
+					const char *name, HOST_WIDE_INT size,
+					HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+{
+  HOST_WIDE_INT rounded;
+
+  /* Compute as in assemble_noswitch_variable, since we don't actually
+     support aligned common.  */
+  rounded = size ? size : 1;
+  rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
+  rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
+	     * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+  
+  i386_pe_maybe_record_exported_symbol (decl, name, 1);
+
+  /* All of these should have been marked DECL_EXTERNAL.  */
+  gcc_assert (!DECL_DLLIMPORT_P (decl));
+
+  fprintf (stream, "\t.comm\t");
+  assemble_name (stream, name);
+  fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
+	   " " HOST_WIDE_INT_PRINT_DEC "\n",
+	   rounded, size);
+}
 
 /* The Microsoft linker requires that every function be marked as
    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
@@ -682,10 +555,16 @@ static GTY(()) struct export_list *expor
    linkonce.  */
 
 void
-i386_pe_record_exported_symbol (const char *name, int is_data)
+i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
 {
+  rtx symbol;
   struct export_list *p;
 
+  symbol = XEXP (DECL_RTL (decl), 0);
+  gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
+  if (!SYMBOL_REF_DLLEXPORT_P (symbol))
+    return;
+
   p = (struct export_list *) ggc_alloc (sizeof *p);
   p->next = export_head;
   p->name = name;
@@ -727,8 +606,8 @@ i386_pe_file_end (void)
       for (q = export_head; q != NULL; q = q->next)
 	{
 	  fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
-		   i386_pe_strip_name_encoding (q->name),
-		   (q->is_data) ? ",data" : "");
+		   targetm.strip_name_encoding (q->name),
+		   (q->is_data ? ",data" : ""));
 	}
     }
 }
--- varasm.c	(revision 123169)
+++ varasm.c	(local)
@@ -4063,9 +4063,8 @@ initializer_constant_valid_p (tree value
 	    return null_pointer_node;
 	  /* Taking the address of a nested function involves a trampoline.  */
 	  if (TREE_CODE (value) == FUNCTION_DECL
-	      && ((decl_function_context (value)
-		   && !DECL_NO_STATIC_CHAIN (value))
-		  || DECL_DLLIMPORT_P (value)))
+	      && decl_function_context (value)
+	      && !DECL_NO_STATIC_CHAIN (value))
 	    return NULL_TREE;
 	  /* "&{...}" requires a temporary to hold the constructed
 	     object.  */



More information about the Gcc-patches mailing list