1d4691e6peter/* Subroutines for insn-output.c for Windows NT.
2d4691e6peter   Contributed by Douglas Rupp (drupp@cs.washington.edu)
31f9ea4dkan   Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
41f9ea4dkan   2005, 2006  Free Software Foundation, Inc.
5d4691e6peter
608db0e4kanThis file is part of GCC.
7d4691e6peter
808db0e4kanGCC is free software; you can redistribute it and/or modify it under
908db0e4kanthe terms of the GNU General Public License as published by the Free
1008db0e4kanSoftware Foundation; either version 2, or (at your option) any later
1108db0e4kanversion.
12d4691e6peter
1308db0e4kanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1408db0e4kanWARRANTY; without even the implied warranty of MERCHANTABILITY or
1508db0e4kanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1608db0e4kanfor more details.
17d4691e6peter
18d4691e6peterYou should have received a copy of the GNU General Public License
1908db0e4kanalong with GCC; see the file COPYING.  If not, write to the Free
201f9ea4dkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
211f9ea4dkan02110-1301, USA.  */
22d4691e6peter
23d4691e6peter#include "config.h"
240bedf4fobrien#include "system.h"
255e00ec7kan#include "coretypes.h"
265e00ec7kan#include "tm.h"
27d4691e6peter#include "rtl.h"
28d4691e6peter#include "regs.h"
29d4691e6peter#include "hard-reg-set.h"
30d4691e6peter#include "output.h"
31d4691e6peter#include "tree.h"
32d4691e6peter#include "flags.h"
33c9ab9aeobrien#include "tm_p.h"
34c9ab9aeobrien#include "toplev.h"
35c9ab9aeobrien#include "hashtab.h"
36b2a8872kan#include "ggc.h"
37d4691e6peter
380bedf4fobrien/* i386/PE specific attribute support.
390bedf4fobrien
400bedf4fobrien   i386/PE has two new attributes:
410bedf4fobrien   dllexport - for exporting a function/variable that will live in a dll
420bedf4fobrien   dllimport - for importing a function/variable from a dll
430bedf4fobrien
440bedf4fobrien   Microsoft allows multiple declspecs in one __declspec, separating
450bedf4fobrien   them with spaces.  We do NOT support this.  Instead, use __declspec
460bedf4fobrien   multiple times.
470bedf4fobrien*/
480bedf4fobrien
495e00ec7kanstatic tree associated_type (tree);
501f9ea4dkanstatic tree gen_stdcall_or_fastcall_suffix (tree, bool);
511f9ea4dkanstatic bool i386_pe_dllexport_p (tree);
521f9ea4dkanstatic bool i386_pe_dllimport_p (tree);
535e00ec7kanstatic void i386_pe_mark_dllexport (tree);
545e00ec7kanstatic void i386_pe_mark_dllimport (tree);
555e00ec7kan
565e00ec7kan/* This is we how mark internal identifiers with dllimport or dllexport
575e00ec7kan   attributes.  */
585e00ec7kan#ifndef DLL_IMPORT_PREFIX
595e00ec7kan#define DLL_IMPORT_PREFIX "#i."
605e00ec7kan#endif
615e00ec7kan#ifndef DLL_EXPORT_PREFIX
625e00ec7kan#define DLL_EXPORT_PREFIX "#e."
635e00ec7kan#endif
640bedf4fobrien
651f9ea4dkan/* Handle a "shared" attribute;
66c9ab9aeobrien   arguments as in struct attribute_spec.handler.  */
67c9ab9aeobrientree
681f9ea4dkanix86_handle_shared_attribute (tree *node, tree name,
691f9ea4dkan			      tree args ATTRIBUTE_UNUSED,
701f9ea4dkan			      int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
710bedf4fobrien{
721f9ea4dkan  if (TREE_CODE (*node) != VAR_DECL)
7392318bckan    {
741f9ea4dkan      warning (OPT_Wattributes, "%qs attribute only applies to variables",
751f9ea4dkan	       IDENTIFIER_POINTER (name));
7608db0e4kan      *no_add_attrs = true;
7792318bckan    }
7892318bckan
79c9ab9aeobrien  return NULL_TREE;
800bedf4fobrien}
810bedf4fobrien
821f9ea4dkan/* Handle a "selectany" attribute;
83c9ab9aeobrien   arguments as in struct attribute_spec.handler.  */
840bedf4fobrientree
851f9ea4dkanix86_handle_selectany_attribute (tree *node, tree name,
861f9ea4dkan			         tree args ATTRIBUTE_UNUSED,
871f9ea4dkan			         int flags ATTRIBUTE_UNUSED,
881f9ea4dkan				 bool *no_add_attrs)
890bedf4fobrien{
901f9ea4dkan  /* The attribute applies only to objects that are initialized and have
911f9ea4dkan     external linkage.  However, we may not know about initialization
921f9ea4dkan     until the language frontend has processed the decl. We'll check for
931f9ea4dkan     initialization later in encode_section_info.  */
941f9ea4dkan  if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node))
951f9ea4dkan    {
961f9ea4dkan      error ("%qs attribute applies only to initialized variables"
971f9ea4dkan       	     " with external linkage",  IDENTIFIER_POINTER (name));
98c9ab9aeobrien      *no_add_attrs = true;
990bedf4fobrien    }
1000bedf4fobrien
101c9ab9aeobrien  return NULL_TREE;
1020bedf4fobrien}
1031f9ea4dkan
1040bedf4fobrien
1050bedf4fobrien/* Return the type that we should use to determine if DECL is
1060bedf4fobrien   imported or exported.  */
1070bedf4fobrien
1080bedf4fobrienstatic tree
1095e00ec7kanassociated_type (tree decl)
1100bedf4fobrien{
1111f9ea4dkan  return  (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
1121f9ea4dkan            ?  DECL_CONTEXT (decl) : NULL_TREE;
1130bedf4fobrien}
1140bedf4fobrien
1150bedf4fobrien
1161f9ea4dkan/* Return true if DECL is a dllexport'd object.  */
1171f9ea4dkan
1181f9ea4dkanstatic bool
1195e00ec7kani386_pe_dllexport_p (tree decl)
1200bedf4fobrien{
1210bedf4fobrien  if (TREE_CODE (decl) != VAR_DECL
1221f9ea4dkan       && TREE_CODE (decl) != FUNCTION_DECL)
1231f9ea4dkan    return false;
1240bedf4fobrien
1251f9ea4dkan  if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
1261f9ea4dkan    return true;
1271f9ea4dkan
1281f9ea4dkan  /* Also mark class members of exported classes with dllexport.  */
1291f9ea4dkan  if (associated_type (decl)
1301f9ea4dkan      && lookup_attribute ("dllexport",
1311f9ea4dkan			    TYPE_ATTRIBUTES (associated_type (decl))))
1321f9ea4dkan    return i386_pe_type_dllexport_p (decl);
1330bedf4fobrien
1341f9ea4dkan  return false;
1351f9ea4dkan}
1360bedf4fobrien
1371f9ea4dkanstatic bool
1385e00ec7kani386_pe_dllimport_p (tree decl)
1390bedf4fobrien{
1400bedf4fobrien  if (TREE_CODE (decl) != VAR_DECL
1411f9ea4dkan       && TREE_CODE (decl) != FUNCTION_DECL)
1421f9ea4dkan    return false;
14308db0e4kan
1441f9ea4dkan  /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag.
1451f9ea4dkan     We may need to override an earlier decision.  */
1461f9ea4dkan  if (DECL_DLLIMPORT_P (decl)
1471f9ea4dkan      && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
14808db0e4kan    {
1491f9ea4dkan       /* Make a final check to see if this is a definition before we generate
1501f9ea4dkan          RTL for an indirect reference.  */
1511f9ea4dkan       if (!DECL_EXTERNAL (decl))
15208db0e4kan	{
1531f9ea4dkan	  error ("%q+D: definition is marked as dllimport", decl);
1541f9ea4dkan	  DECL_DLLIMPORT_P (decl) = 0;
1551f9ea4dkan          return false;
1561f9ea4dkan        }
1571f9ea4dkan      return true;
1580bedf4fobrien    }
1591f9ea4dkan  /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
1601f9ea4dkan     by  targetm.cxx.adjust_class_at_definition.  Check again to emit
1611f9ea4dkan     warnings if the class attribute has been overridden by an
1621f9ea4dkan     out-of-class definition.  */
1631f9ea4dkan  else if (associated_type (decl)
1641f9ea4dkan           && lookup_attribute ("dllimport",
1651f9ea4dkan				TYPE_ATTRIBUTES (associated_type (decl))))
1661f9ea4dkan    return i386_pe_type_dllimport_p (decl);
1671f9ea4dkan
1681f9ea4dkan  return false;
1691f9ea4dkan}
1700bedf4fobrien
1711f9ea4dkan/* Handle the -mno-fun-dllimport target switch.  */
1721f9ea4dkanbool
1731f9ea4dkani386_pe_valid_dllimport_attribute_p (tree decl)
1741f9ea4dkan{
1751f9ea4dkan   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
1761f9ea4dkan     return false;
1771f9ea4dkan   return true;
1780bedf4fobrien}
1790bedf4fobrien
180b2a8872kan/* Return nonzero if SYMBOL is marked as being dllexport'd.  */
1810bedf4fobrien
1820bedf4fobrienint
1835e00ec7kani386_pe_dllexport_name_p (const char *symbol)
1840bedf4fobrien{
1855e00ec7kan  return (strncmp (DLL_EXPORT_PREFIX, symbol,
1865e00ec7kan		   strlen (DLL_EXPORT_PREFIX)) == 0);
1870bedf4fobrien}
1880bedf4fobrien
189b2a8872kan/* Return nonzero if SYMBOL is marked as being dllimport'd.  */
1900bedf4fobrien
1910bedf4fobrienint
1925e00ec7kani386_pe_dllimport_name_p (const char *symbol)
1930bedf4fobrien{
1945e00ec7kan  return (strncmp (DLL_IMPORT_PREFIX, symbol,
1955e00ec7kan		   strlen (DLL_IMPORT_PREFIX)) == 0);
1960bedf4fobrien}
1970bedf4fobrien
1980bedf4fobrien/* Mark a DECL as being dllexport'd.
1991f9ea4dkan   Note that we override the previous setting (e.g.: dllimport).  */
2000bedf4fobrien
2015e00ec7kanstatic void
2025e00ec7kani386_pe_mark_dllexport (tree decl)
2030bedf4fobrien{
204c9ab9aeobrien  const char *oldname;
205c9ab9aeobrien  char  *newname;
2060bedf4fobrien  rtx rtlname;
2071f9ea4dkan  rtx symref;
2080bedf4fobrien  tree idp;
2090bedf4fobrien
2100bedf4fobrien  rtlname = XEXP (DECL_RTL (decl), 0);
2111f9ea4dkan  if (GET_CODE (rtlname) == MEM)
2121f9ea4dkan    rtlname = XEXP (rtlname, 0);
2131f9ea4dkan  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
2141f9ea4dkan  oldname = XSTR (rtlname, 0);
2150bedf4fobrien  if (i386_pe_dllimport_name_p (oldname))
21608db0e4kan    {
2171f9ea4dkan      warning (0, "inconsistent dll linkage for %q+D, dllexport assumed",
2181f9ea4dkan	       decl);
21908db0e4kan     /* Remove DLL_IMPORT_PREFIX.  */
2205e00ec7kan      oldname += strlen (DLL_IMPORT_PREFIX);
22108db0e4kan    }
2220bedf4fobrien  else if (i386_pe_dllexport_name_p (oldname))
2235e00ec7kan    return;  /*  already done  */
2240bedf4fobrien
2255e00ec7kan  newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
2265e00ec7kan  sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
2270bedf4fobrien
2280bedf4fobrien  /* We pass newname through get_identifier to ensure it has a unique
2290bedf4fobrien     address.  RTL processing can sometimes peek inside the symbol ref
2300bedf4fobrien     and compare the string's addresses to see if two symbols are
2310bedf4fobrien     identical.  */
2320bedf4fobrien  idp = get_identifier (newname);
2330bedf4fobrien
2341f9ea4dkan  symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
2351f9ea4dkan  SET_SYMBOL_REF_DECL (symref, decl);
2361f9ea4dkan  XEXP (DECL_RTL (decl), 0) = symref;
2370bedf4fobrien}
2380bedf4fobrien
2390bedf4fobrien/* Mark a DECL as being dllimport'd.  */
2400bedf4fobrien
2415e00ec7kanstatic void
2425e00ec7kani386_pe_mark_dllimport (tree decl)
2430bedf4fobrien{
244c9ab9aeobrien  const char *oldname;
245c9ab9aeobrien  char  *newname;
2460bedf4fobrien  tree idp;
2470bedf4fobrien  rtx rtlname, newrtl;
2481f9ea4dkan  rtx symref;
2490bedf4fobrien
2500bedf4fobrien  rtlname = XEXP (DECL_RTL (decl), 0);
2511f9ea4dkan  if (GET_CODE (rtlname) == MEM)
2521f9ea4dkan    rtlname = XEXP (rtlname, 0);
2531f9ea4dkan  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
2541f9ea4dkan  oldname = XSTR (rtlname, 0);
2550bedf4fobrien  if (i386_pe_dllexport_name_p (oldname))
2560bedf4fobrien    {
2571f9ea4dkan      error ("%qs declared as both exported to and imported from a DLL",
2580bedf4fobrien             IDENTIFIER_POINTER (DECL_NAME (decl)));
2590bedf4fobrien      return;
2600bedf4fobrien    }
2610bedf4fobrien  else if (i386_pe_dllimport_name_p (oldname))
2620bedf4fobrien    {
2631f9ea4dkan      /* Already done, but do a sanity check to prevent assembler
2641f9ea4dkan	 errors.  */
2651f9ea4dkan      gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
2661f9ea4dkan		  && DECL_DLLIMPORT_P (decl));
2675e00ec7kan      return;
2680bedf4fobrien    }
2690bedf4fobrien
2705e00ec7kan  newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
2715e00ec7kan  sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
2720bedf4fobrien
2730bedf4fobrien  /* We pass newname through get_identifier to ensure it has a unique
2740bedf4fobrien     address.  RTL processing can sometimes peek inside the symbol ref
2750bedf4fobrien     and compare the string's addresses to see if two symbols are
2760bedf4fobrien     identical.  */
2770bedf4fobrien  idp = get_identifier (newname);
2780bedf4fobrien
2791f9ea4dkan  symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
2801f9ea4dkan  SET_SYMBOL_REF_DECL (symref, decl);
2811f9ea4dkan  newrtl = gen_rtx_MEM (Pmode,symref);
2820bedf4fobrien  XEXP (DECL_RTL (decl), 0) = newrtl;
2830bedf4fobrien
2841f9ea4dkan  DECL_DLLIMPORT_P (decl) = 1;
2855e00ec7kan}
2865e00ec7kan
2875e00ec7kan/* Return string which is the former assembler name modified with a
2885e00ec7kan   suffix consisting of an atsign (@) followed by the number of bytes of
2891f9ea4dkan   arguments.  If FASTCALL is true, also add the FASTCALL_PREFIX.  */
290d4691e6peter
2911f9ea4dkanstatic tree
2921f9ea4dkangen_stdcall_or_fastcall_suffix (tree decl, bool fastcall)
293d4691e6peter{
294d4691e6peter  int total = 0;
2950bedf4fobrien  /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
2960bedf4fobrien     of DECL_ASSEMBLER_NAME.  */
2971f9ea4dkan   const char *asmname =  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
298d4691e6peter  char *newsym;
2991f9ea4dkan  char *p;
3001f9ea4dkan  tree formal_type;
3011f9ea4dkan
3021f9ea4dkan  /* Do not change the identifier if a verbatim asmspec or already done. */
3031f9ea4dkan  if (*asmname == '*' || strchr (asmname, '@'))
3041f9ea4dkan    return DECL_ASSEMBLER_NAME (decl);
305d4691e6peter
3061f9ea4dkan  formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
3071f9ea4dkan  if (formal_type != NULL_TREE)
3081f9ea4dkan    {
3091f9ea4dkan      /* These attributes are ignored for variadic functions in
3101f9ea4dkan	 i386.c:ix86_return_pops_args. For compatibility with MS
3111f9ea4dkan         compiler do not add @0 suffix here.  */
3121f9ea4dkan      if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
3131f9ea4dkan        return DECL_ASSEMBLER_NAME (decl);
3141f9ea4dkan
3151f9ea4dkan      /* Quit if we hit an incomplete type.  Error is reported
3161f9ea4dkan         by convert_arguments in c-typeck.c or cp/typeck.c.  */
3171f9ea4dkan      while (TREE_VALUE (formal_type) != void_type_node
3181f9ea4dkan	     && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
3191f9ea4dkan	{
3201f9ea4dkan	  int parm_size
3211f9ea4dkan	    = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
3220bedf4fobrien	    /* Must round up to include padding.  This is done the same
3230bedf4fobrien	       way as in store_one_arg.  */
3241f9ea4dkan	  parm_size = ((parm_size + PARM_BOUNDARY - 1)
3251f9ea4dkan		       / PARM_BOUNDARY * PARM_BOUNDARY);
3261f9ea4dkan	  total += parm_size;
3271f9ea4dkan	  formal_type = TREE_CHAIN (formal_type);\
3281f9ea4dkan	}
3291f9ea4dkan     }
330d4691e6peter
3315e00ec7kan  /* Assume max of 8 base 10 digits in the suffix.  */
3321f9ea4dkan  newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
3331f9ea4dkan  p = newsym;
3341f9ea4dkan  if (fastcall)
3351f9ea4dkan    *p++ = FASTCALL_PREFIX;
3361f9ea4dkan  sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);
3371f9ea4dkan  return get_identifier (newsym);
338d4691e6peter}
339d4691e6peter
3400bedf4fobrienvoid
3415e00ec7kani386_pe_encode_section_info (tree decl, rtx rtl, int first)
3420bedf4fobrien{
3435e00ec7kan  default_encode_section_info (decl, rtl, first);
3440bedf4fobrien
3451f9ea4dkan  if (first && TREE_CODE (decl) == FUNCTION_DECL)
3461f9ea4dkan    {
3471f9ea4dkan      tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
3481f9ea4dkan      tree newid = NULL_TREE;
3491f9ea4dkan
3501f9ea4dkan      if (lookup_attribute ("stdcall", type_attributes))
3511f9ea4dkan	newid = gen_stdcall_or_fastcall_suffix (decl, false);
3521f9ea4dkan      else if (lookup_attribute ("fastcall", type_attributes))
3531f9ea4dkan	newid = gen_stdcall_or_fastcall_suffix (decl, true);
3541f9ea4dkan      if (newid != NULL_TREE)
3551f9ea4dkan	{
3561f9ea4dkan	  rtx rtlname = XEXP (rtl, 0);
3571f9ea4dkan	  if (GET_CODE (rtlname) == MEM)
3581f9ea4dkan	    rtlname = XEXP (rtlname, 0);
3591f9ea4dkan	  XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
3601f9ea4dkan	  /* These attributes must be present on first declaration,
3611f9ea4dkan	     change_decl_assembler_name will warn if they are added
3621f9ea4dkan	     later and the decl has been referenced, but duplicate_decls
3631f9ea4dkan	     should catch the mismatch before this is called.  */
3641f9ea4dkan	  change_decl_assembler_name (decl, newid);
3651f9ea4dkan	}
3661f9ea4dkan    }
3671f9ea4dkan
3681f9ea4dkan  else if (TREE_CODE (decl) == VAR_DECL
3691f9ea4dkan           && lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)))
3705e00ec7kan    {
3711f9ea4dkan      if (DECL_INITIAL (decl)
3721f9ea4dkan 	  /* If an object is initialized with a ctor, the static
3731f9ea4dkan	     initialization and destruction code for it is present in
3741f9ea4dkan	     each unit defining the object.  The code that calls the
3751f9ea4dkan	     ctor is protected by a link-once guard variable, so that
3761f9ea4dkan	     the object still has link-once semantics,  */
3771f9ea4dkan    	   || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
3781f9ea4dkan	make_decl_one_only (decl);
3791f9ea4dkan      else
3801f9ea4dkan	error ("%q+D:'selectany' attribute applies only to initialized objects",
3811f9ea4dkan	       decl);
3825e00ec7kan    }
3830bedf4fobrien
3840bedf4fobrien  /* Mark the decl so we can tell from the rtl whether the object is
3851f9ea4dkan     dllexport'd or dllimport'd.  tree.c: merge_dllimport_decl_attributes
3861f9ea4dkan     handles dllexport/dllimport override semantics.  */
3870bedf4fobrien
3880bedf4fobrien  if (i386_pe_dllexport_p (decl))
3890bedf4fobrien    i386_pe_mark_dllexport (decl);
3900bedf4fobrien  else if (i386_pe_dllimport_p (decl))
3910bedf4fobrien    i386_pe_mark_dllimport (decl);
3921f9ea4dkan  /* It might be that DECL has been declared as dllimport, but a
3931f9ea4dkan     subsequent definition nullified that.  Assert that
3941f9ea4dkan     tree.c: merge_dllimport_decl_attributes has removed the attribute
3951f9ea4dkan     before the RTL name was marked with the DLL_IMPORT_PREFIX.  */
3961f9ea4dkan  else
3971f9ea4dkan    gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL
3981f9ea4dkan	    	   || TREE_CODE (decl) == VAR_DECL)
3991f9ea4dkan		  && rtl != NULL_RTX
4001f9ea4dkan		  && GET_CODE (rtl) == MEM
4011f9ea4dkan		  && GET_CODE (XEXP (rtl, 0)) == MEM
4021f9ea4dkan		  && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF
4031f9ea4dkan		  && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0))));
4040bedf4fobrien}
4050bedf4fobrien
4065e00ec7kan/* Strip only the leading encoding, leaving the stdcall suffix and fastcall
4075e00ec7kan   prefix if it exists.  */
408b2a8872kan
409b2a8872kanconst char *
4105e00ec7kani386_pe_strip_name_encoding (const char *str)
411b2a8872kan{
4125e00ec7kan  if (strncmp (str, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
4135e00ec7kan      == 0)
4145e00ec7kan    str += strlen (DLL_IMPORT_PREFIX);
4155e00ec7kan  else if (strncmp (str, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
4165e00ec7kan	   == 0)
4175e00ec7kan    str += strlen (DLL_EXPORT_PREFIX);
418b2a8872kan  if (*str == '*')
419b2a8872kan    str += 1;
420b2a8872kan  return str;
421b2a8872kan}
422b2a8872kan
4231f9ea4dkan/* Also strip the fastcall prefix and stdcall suffix.  */
424b2a8872kan
425b2a8872kanconst char *
4265e00ec7kani386_pe_strip_name_encoding_full (const char *str)
427b2a8872kan{
428b2a8872kan  const char *p;
429b2a8872kan  const char *name = i386_pe_strip_name_encoding (str);
4305e00ec7kan
4311f9ea4dkan  /* Strip leading '@' on fastcall symbols.  */
4321f9ea4dkan  if (*name == '@')
4331f9ea4dkan    name++;
4341f9ea4dkan
4351f9ea4dkan  /* Strip trailing "@n".  */
436b2a8872kan  p = strchr (name, '@');
437b2a8872kan  if (p)
438b2a8872kan    return ggc_alloc_string (name, p - name);
439b2a8872kan
440b2a8872kan  return name;
441b2a8872kan}
4420bedf4fobrien
4435e00ec7kan/* Output a reference to a label. Fastcall symbols are prefixed with @,
4445e00ec7kan   whereas symbols for functions using other calling conventions don't
4455e00ec7kan   have a prefix (unless they are marked dllimport or dllexport).  */
4465e00ec7kan
4475e00ec7kanvoid i386_pe_output_labelref (FILE *stream, const char *name)
4485e00ec7kan{
4495e00ec7kan  if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX))
4505e00ec7kan      == 0)
4515e00ec7kan    /* A dll import */
4525e00ec7kan    {
4535e00ec7kan      if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX)
4545e00ec7kan      /* A dllimport fastcall symbol.  */
4555e00ec7kan        {
4565e00ec7kan          fprintf (stream, "__imp_%s",
4575e00ec7kan                   i386_pe_strip_name_encoding (name));
4585e00ec7kan        }
4595e00ec7kan      else
4605e00ec7kan      /* A dllimport non-fastcall symbol.  */
4615e00ec7kan        {
4625e00ec7kan          fprintf (stream, "__imp__%s",
4635e00ec7kan                   i386_pe_strip_name_encoding (name));
4645e00ec7kan        }
4655e00ec7kan    }
4665e00ec7kan  else if ((name[0] == FASTCALL_PREFIX)
4671f9ea4dkan           || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
4685e00ec7kan	       == 0
4691f9ea4dkan	       && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))
4705e00ec7kan    /* A fastcall symbol.  */
4715e00ec7kan    {
4725e00ec7kan      fprintf (stream, "%s",
4735e00ec7kan               i386_pe_strip_name_encoding (name));
4745e00ec7kan    }
4755e00ec7kan  else
4765e00ec7kan    /* Everything else.  */
4775e00ec7kan    {
4785e00ec7kan      fprintf (stream, "%s%s", USER_LABEL_PREFIX,
4795e00ec7kan               i386_pe_strip_name_encoding (name));
4805e00ec7kan    }
4815e00ec7kan}
4825e00ec7kan
4830bedf4fobrienvoid
4845e00ec7kani386_pe_unique_section (tree decl, int reloc)
4850bedf4fobrien{
4860bedf4fobrien  int len;
487c9ab9aeobrien  const char *name, *prefix;
488c9ab9aeobrien  char *string;
4890bedf4fobrien
4900bedf4fobrien  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
491b2a8872kan  name = i386_pe_strip_name_encoding_full (name);
4920bedf4fobrien
4930bedf4fobrien  /* The object is put in, for example, section .text$foo.
4940bedf4fobrien     The linker will then ultimately place them in .text
4950bedf4fobrien     (everything from the $ on is stripped). Don't put
4965e00ec7kan     read-only data in .rdata section to avoid a PE linker
4970bedf4fobrien     bug when .rdata$* grouped sections are used in code
4980bedf4fobrien     without a .rdata section.  */
4990bedf4fobrien  if (TREE_CODE (decl) == FUNCTION_DECL)
5000bedf4fobrien    prefix = ".text$";
501b2a8872kan  else if (decl_readonly_section (decl, reloc))
5020bedf4fobrien    prefix = ".rdata$";
5030bedf4fobrien  else
5040bedf4fobrien    prefix = ".data$";
5050bedf4fobrien  len = strlen (name) + strlen (prefix);
5060bedf4fobrien  string = alloca (len + 1);
5070bedf4fobrien  sprintf (string, "%s%s", prefix, name);
5080bedf4fobrien
5090bedf4fobrien  DECL_SECTION_NAME (decl) = build_string (len, string);
5100bedf4fobrien}
511c9ab9aeobrien
512c9ab9aeobrien/* Select a set of attributes for section NAME based on the properties
513c9ab9aeobrien   of DECL and whether or not RELOC indicates that DECL's initializer
514c9ab9aeobrien   might contain runtime relocations.
515c9ab9aeobrien
516c9ab9aeobrien   We make the section read-only and executable for a function decl,
517c9ab9aeobrien   read-only for a const data decl, and writable for a non-const data decl.
518c9ab9aeobrien
519c9ab9aeobrien   If the section has already been defined, to not allow it to have
520c9ab9aeobrien   different attributes, as (1) this is ambiguous since we're not seeing
521c9ab9aeobrien   all the declarations up front and (2) some assemblers (e.g. SVR4)
5225e00ec7kan   do not recognize section redefinitions.  */
523c9ab9aeobrien/* ??? This differs from the "standard" PE implementation in that we
524c9ab9aeobrien   handle the SHARED variable attribute.  Should this be done for all
525c9ab9aeobrien   PE targets?  */
526c9ab9aeobrien
527c9ab9aeobrien#define SECTION_PE_SHARED	SECTION_MACH_DEP
528c9ab9aeobrien
529c9ab9aeobrienunsigned int
5305e00ec7kani386_pe_section_type_flags (tree decl, const char *name, int reloc)
531c9ab9aeobrien{
532c9ab9aeobrien  static htab_t htab;
533c9ab9aeobrien  unsigned int flags;
534c9ab9aeobrien  unsigned int **slot;
535c9ab9aeobrien
536c9ab9aeobrien  /* The names we put in the hashtable will always be the unique
5371f9ea4dkan     versions given to us by the stringtable, so we can just use
538c9ab9aeobrien     their addresses as the keys.  */
539c9ab9aeobrien  if (!htab)
540c9ab9aeobrien    htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
541c9ab9aeobrien
542c9ab9aeobrien  if (decl && TREE_CODE (decl) == FUNCTION_DECL)
543c9ab9aeobrien    flags = SECTION_CODE;
544b2a8872kan  else if (decl && decl_readonly_section (decl, reloc))
545c9ab9aeobrien    flags = 0;
546c9ab9aeobrien  else
547c9ab9aeobrien    {
548c9ab9aeobrien      flags = SECTION_WRITE;
549c9ab9aeobrien
550c9ab9aeobrien      if (decl && TREE_CODE (decl) == VAR_DECL
551c9ab9aeobrien	  && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
552c9ab9aeobrien	flags |= SECTION_PE_SHARED;
553c9ab9aeobrien    }
554c9ab9aeobrien
555c9ab9aeobrien  if (decl && DECL_ONE_ONLY (decl))
556c9ab9aeobrien    flags |= SECTION_LINKONCE;
557c9ab9aeobrien
558c9ab9aeobrien  /* See if we already have an entry for this section.  */
559c9ab9aeobrien  slot = (unsigned int **) htab_find_slot (htab, name, INSERT);
560c9ab9aeobrien  if (!*slot)
561c9ab9aeobrien    {
562c9ab9aeobrien      *slot = (unsigned int *) xmalloc (sizeof (unsigned int));
563c9ab9aeobrien      **slot = flags;
564c9ab9aeobrien    }
565c9ab9aeobrien  else
566c9ab9aeobrien    {
567c9ab9aeobrien      if (decl && **slot != flags)
5681f9ea4dkan	error ("%q+D causes a section type conflict", decl);
569c9ab9aeobrien    }
570c9ab9aeobrien
571c9ab9aeobrien  return flags;
572c9ab9aeobrien}
573c9ab9aeobrien
574c9ab9aeobrienvoid
5751f9ea4dkani386_pe_asm_named_section (const char *name, unsigned int flags,
5761f9ea4dkan			   tree decl)
577c9ab9aeobrien{
578c9ab9aeobrien  char flagchars[8], *f = flagchars;
579c9ab9aeobrien
5805e00ec7kan  if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
5815e00ec7kan    /* readonly data */
5825e00ec7kan    {
5835e00ec7kan      *f++ ='d';  /* This is necessary for older versions of gas.  */
5845e00ec7kan      *f++ ='r';
5855e00ec7kan    }
5865e00ec7kan  else
5875e00ec7kan    {
5885e00ec7kan      if (flags & SECTION_CODE)
5895e00ec7kan        *f++ = 'x';
5905e00ec7kan      if (flags & SECTION_WRITE)
5915e00ec7kan        *f++ = 'w';
5925e00ec7kan      if (flags & SECTION_PE_SHARED)
5935e00ec7kan        *f++ = 's';
5945e00ec7kan    }
5955e00ec7kan
596c9ab9aeobrien  *f = '\0';
597c9ab9aeobrien
598c9ab9aeobrien  fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
599c9ab9aeobrien
600c9ab9aeobrien  if (flags & SECTION_LINKONCE)
601c9ab9aeobrien    {
602c9ab9aeobrien      /* Functions may have been compiled at various levels of
6031f9ea4dkan	 optimization so we can't use `same_size' here.
6041f9ea4dkan	 Instead, have the linker pick one, without warning.
6051f9ea4dkan	 If 'selectany' attribute has been specified,  MS compiler
6061f9ea4dkan	 sets 'discard' characteristic, rather than telling linker
6071f9ea4dkan	 to warn of size or content mismatch, so do the same.  */
6081f9ea4dkan      bool discard = (flags & SECTION_CODE)
6091f9ea4dkan		      || lookup_attribute ("selectany",
6101f9ea4dkan					   DECL_ATTRIBUTES (decl));
611c9ab9aeobrien      fprintf (asm_out_file, "\t.linkonce %s\n",
6121f9ea4dkan	       (discard  ? "discard" : "same_size"));
613c9ab9aeobrien    }
614c9ab9aeobrien}
6150bedf4fobrien
6160bedf4fobrien/* The Microsoft linker requires that every function be marked as
617cae8fa8obrien   DT_FCN.  When using gas on cygwin, we must emit appropriate .type
6180bedf4fobrien   directives.  */
6190bedf4fobrien
6200bedf4fobrien#include "gsyms.h"
6210bedf4fobrien
6220bedf4fobrien/* Mark a function appropriately.  This should only be called for
6230bedf4fobrien   functions for which we are not emitting COFF debugging information.
6240bedf4fobrien   FILE is the assembler output file, NAME is the name of the
625b2a8872kan   function, and PUBLIC is nonzero if the function is globally
6260bedf4fobrien   visible.  */
6270bedf4fobrien
6280bedf4fobrienvoid
6295e00ec7kani386_pe_declare_function_type (FILE *file, const char *name, int public)
6300bedf4fobrien{
6310bedf4fobrien  fprintf (file, "\t.def\t");
6320bedf4fobrien  assemble_name (file, name);
6330bedf4fobrien  fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
6340bedf4fobrien	   public ? (int) C_EXT : (int) C_STAT,
6350bedf4fobrien	   (int) DT_FCN << N_BTSHFT);
6360bedf4fobrien}
6370bedf4fobrien
6380bedf4fobrien/* Keep a list of external functions.  */
6390bedf4fobrien
6401f9ea4dkanstruct extern_list GTY(())
6410bedf4fobrien{
6420bedf4fobrien  struct extern_list *next;
6431f9ea4dkan  tree decl;
644c9ab9aeobrien  const char *name;
6450bedf4fobrien};
6460bedf4fobrien
6471f9ea4dkanstatic GTY(()) struct extern_list *extern_head;
6480bedf4fobrien
6490bedf4fobrien/* Assemble an external function reference.  We need to keep a list of
6500bedf4fobrien   these, so that we can output the function types at the end of the
6510bedf4fobrien   assembly.  We can't output the types now, because we might see a
6520bedf4fobrien   definition of the function later on and emit debugging information
6530bedf4fobrien   for it then.  */
6540bedf4fobrien
6550bedf4fobrienvoid
6561f9ea4dkani386_pe_record_external_function (tree decl, const char *name)
6570bedf4fobrien{
6580bedf4fobrien  struct extern_list *p;
6590bedf4fobrien
6601f9ea4dkan  p = (struct extern_list *) ggc_alloc (sizeof *p);
6610bedf4fobrien  p->next = extern_head;
6621f9ea4dkan  p->decl = decl;
6630bedf4fobrien  p->name = name;
6640bedf4fobrien  extern_head = p;
6650bedf4fobrien}
6660bedf4fobrien
667c9ab9aeobrien/* Keep a list of exported symbols.  */
668c9ab9aeobrien
6691f9ea4dkanstruct export_list GTY(())
670c9ab9aeobrien{
671c9ab9aeobrien  struct export_list *next;
672c9ab9aeobrien  const char *name;
673c9ab9aeobrien  int is_data;		/* used to type tag exported symbols.  */
674c9ab9aeobrien};
675c9ab9aeobrien
6761f9ea4dkanstatic GTY(()) struct export_list *export_head;
677cae8fa8obrien
678cae8fa8obrien/* Assemble an export symbol entry.  We need to keep a list of
679cae8fa8obrien   these, so that we can output the export list at the end of the
680cae8fa8obrien   assembly.  We used to output these export symbols in each function,
6815e00ec7kan   but that causes problems with GNU ld when the sections are
682cae8fa8obrien   linkonce.  */
683cae8fa8obrien
684cae8fa8obrienvoid
6855e00ec7kani386_pe_record_exported_symbol (const char *name, int is_data)
686cae8fa8obrien{
687c9ab9aeobrien  struct export_list *p;
688cae8fa8obrien
6891f9ea4dkan  p = (struct export_list *) ggc_alloc (sizeof *p);
690c9ab9aeobrien  p->next = export_head;
691cae8fa8obrien  p->name = name;
692c9ab9aeobrien  p->is_data = is_data;
693c9ab9aeobrien  export_head = p;
694cae8fa8obrien}
695cae8fa8obrien
6960bedf4fobrien/* This is called at the end of assembly.  For each external function
697cae8fa8obrien   which has not been defined, we output a declaration now.  We also
698cae8fa8obrien   output the .drectve section.  */
6990bedf4fobrien
7000bedf4fobrienvoid
7015e00ec7kani386_pe_file_end (void)
7020bedf4fobrien{
7030bedf4fobrien  struct extern_list *p;
7040bedf4fobrien
7055e00ec7kan  ix86_file_end ();
706c9ab9aeobrien
7070bedf4fobrien  for (p = extern_head; p != NULL; p = p->next)
7080bedf4fobrien    {
7090bedf4fobrien      tree decl;
7100bedf4fobrien
7111f9ea4dkan      decl = p->decl;
7120bedf4fobrien
7130bedf4fobrien      /* Positively ensure only one declaration for any given symbol.  */
7141f9ea4dkan      if (! TREE_ASM_WRITTEN (decl)
7151f9ea4dkan	  && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
7160bedf4fobrien	{
7170bedf4fobrien	  TREE_ASM_WRITTEN (decl) = 1;
7185e00ec7kan	  i386_pe_declare_function_type (asm_out_file, p->name,
7195e00ec7kan					 TREE_PUBLIC (decl));
7200bedf4fobrien	}
7210bedf4fobrien    }
722cae8fa8obrien
723c9ab9aeobrien  if (export_head)
724cae8fa8obrien    {
725c9ab9aeobrien      struct export_list *q;
726c9ab9aeobrien      drectve_section ();
727c9ab9aeobrien      for (q = export_head; q != NULL; q = q->next)
728c9ab9aeobrien	{
7295e00ec7kan	  fprintf (asm_out_file, "\t.ascii \" -export:%s%s\"\n",
730b2a8872kan		   i386_pe_strip_name_encoding (q->name),
731c9ab9aeobrien		   (q->is_data) ? ",data" : "");
732c9ab9aeobrien	}
733cae8fa8obrien    }
7340bedf4fobrien}
7351f9ea4dkan
7361f9ea4dkan#include "gt-winnt.h"
737