Home | History | Annotate | Line # | Download | only in i386
winnt.cc revision 1.1
      1 /* Subroutines for insn-output.cc for Windows NT.
      2    Contributed by Douglas Rupp (drupp (at) cs.washington.edu)
      3    Copyright (C) 1995-2022 Free Software Foundation, Inc.
      4 
      5 This file is part of GCC.
      6 
      7 GCC is free software; you can redistribute it and/or modify it under
      8 the terms of the GNU General Public License as published by the Free
      9 Software Foundation; either version 3, or (at your option) any later
     10 version.
     11 
     12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15 for more details.
     16 
     17 You should have received a copy of the GNU General Public License
     18 along with GCC; see the file COPYING3.  If not see
     19 <http://www.gnu.org/licenses/>.  */
     20 
     21 #define IN_TARGET_CODE 1
     22 
     23 #include "config.h"
     24 #include "system.h"
     25 #include "coretypes.h"
     26 #include "target.h"
     27 #include "function.h"
     28 #include "basic-block.h"
     29 #include "rtl.h"
     30 #include "tree.h"
     31 #include "gimple.h"
     32 #include "memmodel.h"
     33 #include "tm_p.h"
     34 #include "stringpool.h"
     35 #include "attribs.h"
     36 #include "emit-rtl.h"
     37 #include "cgraph.h"
     38 #include "lto-streamer.h"
     39 #include "except.h"
     40 #include "output.h"
     41 #include "varasm.h"
     42 #include "lto-section-names.h"
     43 
     44 /* i386/PE specific attribute support.
     45 
     46    i386/PE has two new attributes:
     47    dllexport - for exporting a function/variable that will live in a dll
     48    dllimport - for importing a function/variable from a dll
     49 
     50    Microsoft allows multiple declspecs in one __declspec, separating
     51    them with spaces.  We do NOT support this.  Instead, use __declspec
     52    multiple times.
     53 */
     54 
     55 /* Handle a "shared" attribute;
     56    arguments as in struct attribute_spec.handler.  */
     57 tree
     58 ix86_handle_shared_attribute (tree *node, tree name, tree, int,
     59 			      bool *no_add_attrs)
     60 {
     61   if (TREE_CODE (*node) != VAR_DECL)
     62     {
     63       warning (OPT_Wattributes, "%qE attribute only applies to variables",
     64 	       name);
     65       *no_add_attrs = true;
     66     }
     67 
     68   return NULL_TREE;
     69 }
     70 
     71 /* Handle a "selectany" attribute;
     72    arguments as in struct attribute_spec.handler.  */
     73 tree
     74 ix86_handle_selectany_attribute (tree *node, tree name, tree, int,
     75 				 bool *no_add_attrs)
     76 {
     77   tree decl = *node;
     78   /* The attribute applies only to objects that are initialized and have
     79      external linkage.  However, we may not know about initialization
     80      until the language frontend has processed the decl.   Therefore
     81      we make sure that variable isn't initialized as common.  */
     82   if (TREE_CODE (decl) != VAR_DECL || !TREE_PUBLIC (decl))
     83     error ("%qE attribute applies only to initialized variables"
     84        	   " with external linkage", name);
     85   else
     86     {
     87       make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl));
     88       /* A variable with attribute selectany never can be common.  */
     89       DECL_COMMON (decl) = 0;
     90     }
     91 
     92   /* We don't need to keep attribute itself.  */
     93   *no_add_attrs = true;
     94   return NULL_TREE;
     95 }
     96 
     97 
     98 /* Return the type that we should use to determine if DECL is
    100    imported or exported.  */
    101 
    102 static tree
    103 associated_type (tree decl)
    104 {
    105   return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))
    106           ?  DECL_CONTEXT (decl) : NULL_TREE);
    107 }
    108 
    109 /* Return true if DECL should be a dllexport'd object.  */
    110 
    111 static bool
    112 i386_pe_determine_dllexport_p (tree decl)
    113 {
    114   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
    115     return false;
    116 
    117   /* Don't export local clones of dllexports.  */
    118   if (!TREE_PUBLIC (decl))
    119     return false;
    120 
    121   if (TREE_CODE (decl) == FUNCTION_DECL
    122       && DECL_DECLARED_INLINE_P (decl)
    123       && !flag_keep_inline_dllexport)
    124     return false;
    125 
    126   if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
    127     return true;
    128 
    129   return false;
    130 }
    131 
    132 /* Return true if DECL should be a dllimport'd object.  */
    133 
    134 static bool
    135 i386_pe_determine_dllimport_p (tree decl)
    136 {
    137   tree assoc;
    138 
    139   if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
    140     return false;
    141 
    142   if (DECL_DLLIMPORT_P (decl))
    143     return true;
    144 
    145   /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
    146      by  targetm.cxx.adjust_class_at_definition.  Check again to emit
    147      error message if the class attribute has been overridden by an
    148      out-of-class definition of static data.  */
    149   assoc = associated_type (decl);
    150   if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc))
    151       && TREE_CODE (decl) == VAR_DECL
    152       && TREE_STATIC (decl) && TREE_PUBLIC (decl)
    153       && !DECL_EXTERNAL (decl)
    154       /* vtable's are linkonce constants, so defining a vtable is not
    155 	 an error as long as we don't try to import it too.  */
    156       && !DECL_VIRTUAL_P (decl))
    157 	error ("definition of static data member %q+D of "
    158 	       "dllimport%'d class", decl);
    159 
    160   return false;
    161 }
    162 
    163 /* Handle the -mno-fun-dllimport target switch.  */
    164 
    165 bool
    166 i386_pe_valid_dllimport_attribute_p (const_tree decl)
    167 {
    168    if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
    169      return false;
    170    return true;
    171 }
    172 
    173 /* Return string which is the function name, identified by ID, modified
    174    with a suffix consisting of an atsign (@) followed by the number of
    175    bytes of arguments.  If ID is NULL use the DECL_NAME as base. If
    176    FASTCALL is true, also add the FASTCALL_PREFIX.
    177    Return NULL if no change required.  */
    178 
    179 static tree
    180 gen_stdcall_or_fastcall_suffix (tree decl, tree id, bool fastcall)
    181 {
    182   HOST_WIDE_INT total = 0;
    183   const char *old_str = IDENTIFIER_POINTER (id != NULL_TREE ? id : DECL_NAME (decl));
    184   char *new_str, *p;
    185   tree type = TREE_TYPE (DECL_ORIGIN (decl));
    186   tree arg;
    187   function_args_iterator args_iter;
    188 
    189   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
    190 
    191   if (prototype_p (type))
    192     {
    193       /* This attribute is ignored for variadic functions.  */
    194       if (stdarg_p (type))
    195 	return NULL_TREE;
    196 
    197       /* Quit if we hit an incomplete type.  Error is reported
    198 	 by convert_arguments in c-typeck.cc or cp/typeck.cc.  */
    199       FOREACH_FUNCTION_ARGS(type, arg, args_iter)
    200 	{
    201 	  HOST_WIDE_INT parm_size;
    202 	  HOST_WIDE_INT parm_boundary_bytes = PARM_BOUNDARY / BITS_PER_UNIT;
    203 
    204 	  if (! COMPLETE_TYPE_P (arg))
    205 	    break;
    206 
    207 	  parm_size = int_size_in_bytes (arg);
    208 	  if (parm_size < 0)
    209 	    break;
    210 
    211 	  /* Must round up to include padding.  This is done the same
    212 	     way as in store_one_arg.  */
    213 	  parm_size = ((parm_size + parm_boundary_bytes - 1)
    214 		       / parm_boundary_bytes * parm_boundary_bytes);
    215 	  total += parm_size;
    216 	}
    217     }
    218 
    219   /* Assume max of 8 base 10 digits in the suffix.  */
    220   p = new_str = XALLOCAVEC (char, 1 + strlen (old_str) + 1 + 8 + 1);
    221   if (fastcall)
    222     *p++ = FASTCALL_PREFIX;
    223   sprintf (p, "%s@" HOST_WIDE_INT_PRINT_DEC, old_str, total);
    224 
    225   return get_identifier (new_str);
    226 }
    227 
    228 /* Maybe decorate and get a new identifier for the DECL of a stdcall or
    229    fastcall function. The original identifier is supplied in ID. */
    230 
    231 static tree
    232 i386_pe_maybe_mangle_decl_assembler_name (tree decl, tree id)
    233 {
    234   tree new_id = NULL_TREE;
    235 
    236   if (TREE_CODE (decl) == FUNCTION_DECL)
    237     {
    238       unsigned int ccvt = ix86_get_callcvt (TREE_TYPE (decl));
    239       if ((ccvt & IX86_CALLCVT_STDCALL) != 0)
    240         {
    241 	  if (TARGET_RTD)
    242 	    /* If we are using -mrtd emit undecorated symbol and let linker
    243 	       do the proper resolving.  */
    244 	    return NULL_TREE;
    245 	  new_id = gen_stdcall_or_fastcall_suffix (decl, id, false);
    246 	}
    247       else if ((ccvt & IX86_CALLCVT_FASTCALL) != 0)
    248 	new_id = gen_stdcall_or_fastcall_suffix (decl, id, true);
    249     }
    250 
    251   return new_id;
    252 }
    253 
    254 /* Emit an assembler directive to set symbol for DECL visibility to
    255    the visibility type VIS, which must not be VISIBILITY_DEFAULT.
    256    As for PE there is no hidden support in gas, we just warn for
    257    user-specified visibility attributes.  */
    258 
    259 void
    260 i386_pe_assemble_visibility (tree decl, int)
    261 {
    262   if (!decl
    263       || !lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)))
    264     return;
    265   if (!DECL_ARTIFICIAL (decl))
    266     warning (OPT_Wattributes, "visibility attribute not supported "
    267 			      "in this configuration; ignored");
    268 }
    269 
    270 /* This is used as a target hook to modify the DECL_ASSEMBLER_NAME
    271    in the language-independent default hook
    272    langhooks,c:lhd_set_decl_assembler_name ()
    273    and in cp/mangle,c:mangle_decl ().  */
    274 tree
    275 i386_pe_mangle_decl_assembler_name (tree decl, tree id)
    276 {
    277   tree new_id = i386_pe_maybe_mangle_decl_assembler_name (decl, id);
    278 
    279   return (new_id ? new_id : id);
    280 }
    281 
    282 /* This hook behaves the same as varasm.cc/assemble_name(), but
    283    generates the name into memory rather than outputting it to
    284    a file stream.  */
    285 
    286 tree
    287 i386_pe_mangle_assembler_name (const char *name)
    288 {
    289   const char *skipped = name + (*name == '*' ? 1 : 0);
    290   const char *stripped = targetm.strip_name_encoding (skipped);
    291   if (*name != '*' && *user_label_prefix && *stripped != FASTCALL_PREFIX)
    292     stripped = ACONCAT ((user_label_prefix, stripped, NULL));
    293   return get_identifier (stripped);
    294 }
    295 
    296 void
    297 i386_pe_encode_section_info (tree decl, rtx rtl, int first)
    298 {
    299   rtx symbol;
    300   int flags;
    301 
    302   /* Do this last, due to our frobbing of DECL_DLLIMPORT_P above.  */
    303   default_encode_section_info (decl, rtl, first);
    304 
    305   /* Careful not to prod global register variables.  */
    306   if (!MEM_P (rtl))
    307     return;
    308 
    309   symbol = XEXP (rtl, 0);
    310   gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
    311 
    312   switch (TREE_CODE (decl))
    313     {
    314     case FUNCTION_DECL:
    315     case VAR_DECL:
    316       break;
    317 
    318     default:
    319       return;
    320     }
    321 
    322   /* Mark the decl so we can tell from the rtl whether the object is
    323      dllexport'd or dllimport'd.  tree.cc: merge_dllimport_decl_attributes
    324      handles dllexport/dllimport override semantics.  */
    325   flags = (SYMBOL_REF_FLAGS (symbol) &
    326 	   ~(SYMBOL_FLAG_DLLIMPORT | SYMBOL_FLAG_DLLEXPORT));
    327   if (i386_pe_determine_dllexport_p (decl))
    328     flags |= SYMBOL_FLAG_DLLEXPORT;
    329   else if (i386_pe_determine_dllimport_p (decl))
    330     flags |= SYMBOL_FLAG_DLLIMPORT;
    331 
    332   SYMBOL_REF_FLAGS (symbol) = flags;
    333 }
    334 
    335 
    336 bool
    337 i386_pe_binds_local_p (const_tree exp)
    338 {
    339   if ((TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == FUNCTION_DECL)
    340       && DECL_DLLIMPORT_P (exp))
    341     return false;
    342 
    343   /* External public symbols, which aren't weakref-s,
    344      have local-binding for PE targets.  */
    345   if (DECL_P (exp)
    346       && !lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
    347       && TREE_PUBLIC (exp)
    348       && DECL_EXTERNAL (exp))
    349     return true;
    350 
    351 #ifndef MAKE_DECL_ONE_ONLY
    352   /* PR target/66655: If a function has been marked as DECL_ONE_ONLY
    353      but we do not the means to make it so, then do not allow it to
    354      bind locally.  */
    355   if (DECL_P (exp)
    356       && TREE_CODE (exp) == FUNCTION_DECL
    357       && TREE_PUBLIC (exp)
    358       && DECL_ONE_ONLY (exp)
    359       && ! DECL_EXTERNAL (exp)
    360       && DECL_DECLARED_INLINE_P (exp))
    361     return false;
    362 #endif
    363 
    364   return default_binds_local_p_1 (exp, 0);
    365 }
    366 
    367 /* Also strip the fastcall prefix and stdcall suffix.  */
    368 
    369 const char *
    370 i386_pe_strip_name_encoding_full (const char *str)
    371 {
    372   const char *p;
    373   const char *name = default_strip_name_encoding (str);
    374 
    375   /* Strip leading '@' on fastcall symbols.  */
    376   if (*name == '@')
    377     name++;
    378 
    379   /* Strip trailing "@n".  */
    380   p = strchr (name, '@');
    381   if (p)
    382     return ggc_alloc_string (name, p - name);
    383 
    384   return name;
    385 }
    386 
    387 void
    388 i386_pe_unique_section (tree decl, int reloc)
    389 {
    390   int len;
    391   const char *name, *prefix;
    392   char *string;
    393 
    394   /* Ignore RELOC, if we are allowed to put relocated
    395      const data into read-only section.  */
    396   if (!flag_writable_rel_rdata)
    397     reloc = 0;
    398   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
    399   name = i386_pe_strip_name_encoding_full (name);
    400 
    401   /* The object is put in, for example, section .text$foo.
    402      The linker will then ultimately place them in .text
    403      (everything from the $ on is stripped). Don't put
    404      read-only data in .rdata section to avoid a PE linker
    405      bug when .rdata$* grouped sections are used in code
    406      without a .rdata section.  */
    407   if (TREE_CODE (decl) == FUNCTION_DECL)
    408     prefix = ".text$";
    409   else if (decl_readonly_section (decl, reloc))
    410     prefix = ".rdata$";
    411   else
    412     prefix = ".data$";
    413   len = strlen (name) + strlen (prefix);
    414   string = XALLOCAVEC (char, len + 1);
    415   sprintf (string, "%s%s", prefix, name);
    416 
    417   set_decl_section_name (decl, string);
    418 }
    419 
    420 /* Local and global relocs can be placed always into readonly memory for
    421    memory for PE-COFF targets.  */
    422 int
    423 i386_pe_reloc_rw_mask (void)
    424 {
    425   return 0;
    426 }
    427 
    428 /* Select a set of attributes for section NAME based on the properties
    429    of DECL and whether or not RELOC indicates that DECL's initializer
    430    might contain runtime relocations.
    431 
    432    We make the section read-only and executable for a function decl,
    433    read-only for a const data decl, and writable for a non-const data decl.
    434 
    435    If the section has already been defined, to not allow it to have
    436    different attributes, as (1) this is ambiguous since we're not seeing
    437    all the declarations up front and (2) some assemblers (e.g. SVR4)
    438    do not recognize section redefinitions.  */
    439 /* ??? This differs from the "standard" PE implementation in that we
    440    handle the SHARED variable attribute.  Should this be done for all
    441    PE targets?  */
    442 
    443 #define SECTION_PE_SHARED	SECTION_MACH_DEP
    444 
    445 unsigned int
    446 i386_pe_section_type_flags (tree decl, const char *, int reloc)
    447 {
    448   unsigned int flags;
    449 
    450   /* Ignore RELOC, if we are allowed to put relocated
    451      const data into read-only section.  */
    452   if (!flag_writable_rel_rdata)
    453     reloc = 0;
    454 
    455   if (decl && TREE_CODE (decl) == FUNCTION_DECL)
    456     flags = SECTION_CODE;
    457   else if (decl && decl_readonly_section (decl, reloc))
    458     flags = 0;
    459   else
    460     {
    461       flags = SECTION_WRITE;
    462 
    463       if (decl && TREE_CODE (decl) == VAR_DECL
    464 	  && lookup_attribute ("shared", DECL_ATTRIBUTES (decl)))
    465 	flags |= SECTION_PE_SHARED;
    466     }
    467 
    468   if (decl && DECL_P (decl) && DECL_ONE_ONLY (decl))
    469     flags |= SECTION_LINKONCE;
    470 
    471   return flags;
    472 }
    473 
    474 void
    475 i386_pe_asm_named_section (const char *name, unsigned int flags,
    476 			   tree decl)
    477 {
    478   char flagchars[8], *f = flagchars;
    479 
    480 #if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1
    481   if ((flags & SECTION_EXCLUDE) != 0)
    482     *f++ = 'e';
    483 #endif
    484 
    485   if ((flags & (SECTION_CODE | SECTION_WRITE)) == 0)
    486     /* readonly data */
    487     {
    488       *f++ ='d';  /* This is necessary for older versions of gas.  */
    489       *f++ ='r';
    490     }
    491   else
    492     {
    493       if (flags & SECTION_CODE)
    494         *f++ = 'x';
    495       if (flags & SECTION_WRITE)
    496         *f++ = 'w';
    497       if (flags & SECTION_PE_SHARED)
    498         *f++ = 's';
    499 #if !defined (HAVE_GAS_SECTION_EXCLUDE) || HAVE_GAS_SECTION_EXCLUDE == 0
    500       /* If attribute "e" isn't supported we mark this section as
    501          never-load.  */
    502       if ((flags & SECTION_EXCLUDE) != 0)
    503 	*f++ = 'n';
    504 #endif
    505     }
    506 
    507   /* LTO sections need 1-byte alignment to avoid confusing the
    508      zlib decompression algorithm with trailing zero pad bytes.  */
    509   if (startswith (name, LTO_SECTION_NAME_PREFIX))
    510     *f++ = '0';
    511 
    512   *f = '\0';
    513 
    514   fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
    515 
    516   if (flags & SECTION_LINKONCE)
    517     {
    518       /* Functions may have been compiled at various levels of
    519 	 optimization so we can't use `same_size' here.
    520 	 Instead, have the linker pick one, without warning.
    521 	 If 'selectany' attribute has been specified,  MS compiler
    522 	 sets 'discard' characteristic, rather than telling linker
    523 	 to warn of size or content mismatch, so do the same.  */
    524       bool discard = (flags & SECTION_CODE)
    525 		      || (TREE_CODE (decl) != IDENTIFIER_NODE
    526 			  && lookup_attribute ("selectany",
    527 					       DECL_ATTRIBUTES (decl)));
    528       fprintf (asm_out_file, "\t.linkonce %s\n",
    529 	       (discard  ? "discard" : "same_size"));
    530     }
    531 }
    532 
    533 /* Beware, DECL may be NULL if compile_file() is emitting the LTO marker.  */
    534 
    535 void
    536 i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
    537 					const char *name, HOST_WIDE_INT size,
    538 					HOST_WIDE_INT align)
    539 {
    540   HOST_WIDE_INT rounded;
    541 
    542   /* Compute as in assemble_noswitch_variable, since we don't have
    543      support for aligned common on older binutils.  We must also
    544      avoid emitting a common symbol of size zero, as this is the
    545      overloaded representation that indicates an undefined external
    546      symbol in the PE object file format.  */
    547   rounded = size ? size : 1;
    548   rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
    549   rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
    550 	     * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
    551 
    552   i386_pe_maybe_record_exported_symbol (decl, name, 1);
    553 
    554   fprintf (stream, "\t.comm\t");
    555   assemble_name (stream, name);
    556   if (use_pe_aligned_common)
    557     fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n",
    558 	   size ? size : HOST_WIDE_INT_1,
    559 	   exact_log2 (align) - exact_log2 (CHAR_BIT));
    560   else
    561     fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
    562 	   " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size);
    563 }
    564 
    565 /* The Microsoft linker requires that every function be marked as
    567    DT_FCN.  When using gas on cygwin, we must emit appropriate .type
    568    directives.  */
    569 
    570 #include "gsyms.h"
    571 
    572 /* Mark a function appropriately.  This should only be called for
    573    functions for which we are not emitting COFF debugging information.
    574    FILE is the assembler output file, NAME is the name of the
    575    function, and PUB is nonzero if the function is globally
    576    visible.  */
    577 
    578 void
    579 i386_pe_declare_function_type (FILE *file, const char *name, int pub)
    580 {
    581   fprintf (file, "\t.def\t");
    582   assemble_name (file, name);
    583   fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n",
    584 	   pub ? (int) C_EXT : (int) C_STAT,
    585 	   (int) DT_FCN << N_BTSHFT);
    586 }
    587 
    588 /* Keep a list of external functions.  */
    589 
    590 struct GTY(()) extern_list
    591 {
    592   struct extern_list *next;
    593   tree decl;
    594   const char *name;
    595 };
    596 
    597 static GTY(()) struct extern_list *extern_head;
    598 
    599 /* Assemble an external function reference.  We need to keep a list of
    600    these, so that we can output the function types at the end of the
    601    assembly.  We can't output the types now, because we might see a
    602    definition of the function later on and emit debugging information
    603    for it then.  */
    604 
    605 void
    606 i386_pe_record_external_function (tree decl, const char *name)
    607 {
    608   struct extern_list *p;
    609 
    610   p = ggc_alloc<extern_list> ();
    611   p->next = extern_head;
    612   p->decl = decl;
    613   p->name = name;
    614   extern_head = p;
    615 }
    616 
    617 /* Keep a list of exported symbols.  */
    618 
    619 struct GTY(()) export_list
    620 {
    621   struct export_list *next;
    622   const char *name;
    623   int is_data;		/* used to type tag exported symbols.  */
    624 };
    625 
    626 /* Keep a list of stub symbols.  */
    627 
    628 struct GTY(()) stub_list
    629 {
    630   struct stub_list *next;
    631   const char *name;
    632 };
    633 
    634 static GTY(()) struct export_list *export_head;
    635 
    636 static GTY(()) struct stub_list *stub_head;
    637 
    638 /* Assemble an export symbol entry.  We need to keep a list of
    639    these, so that we can output the export list at the end of the
    640    assembly.  We used to output these export symbols in each function,
    641    but that causes problems with GNU ld when the sections are
    642    linkonce.  Beware, DECL may be NULL if compile_file() is emitting
    643    the LTO marker.  */
    644 
    645 void
    646 i386_pe_maybe_record_exported_symbol (tree decl, const char *name, int is_data)
    647 {
    648   rtx symbol;
    649   struct export_list *p;
    650 
    651   if (!decl)
    652     return;
    653 
    654   symbol = XEXP (DECL_RTL (decl), 0);
    655   gcc_assert (GET_CODE (symbol) == SYMBOL_REF);
    656   if (!SYMBOL_REF_DLLEXPORT_P (symbol))
    657     return;
    658 
    659   gcc_assert (TREE_PUBLIC (decl));
    660 
    661   p = ggc_alloc<export_list> ();
    662   p->next = export_head;
    663   p->name = name;
    664   p->is_data = is_data;
    665   export_head = p;
    666 }
    667 
    668 void
    669 i386_pe_record_stub (const char *name)
    670 {
    671   struct stub_list *p;
    672 
    673   if (!name || *name == 0)
    674     return;
    675 
    676   p = stub_head;
    677   while (p != NULL)
    678     {
    679       if (p->name[0] == *name
    680           && !strcmp (p->name, name))
    681 	return;
    682       p = p->next;
    683     }
    684 
    685   p = ggc_alloc<stub_list> ();
    686   p->next = stub_head;
    687   p->name = name;
    688   stub_head = p;
    689 }
    690 
    691 
    692 #ifdef CXX_WRAP_SPEC_LIST
    693 
    694 /* Search for a function named TARGET in the list of library wrappers
    695    we are using, returning a pointer to it if found or NULL if not.
    696    This function might be called on quite a few symbols, and we only
    697    have the list of names of wrapped functions available to us as a
    698    spec string, so first time round we lazily initialise a hash table
    699    to make things quicker.  */
    700 
    701 static const char *
    702 i386_find_on_wrapper_list (const char *target)
    703 {
    704   static char first_time = 1;
    705   static hash_table<nofree_string_hash> *wrappers;
    706 
    707   if (first_time)
    708     {
    709       /* Beware that this is not a complicated parser, it assumes
    710          that any sequence of non-whitespace beginning with an
    711 	 underscore is one of the wrapped symbols.  For now that's
    712 	 adequate to distinguish symbols from spec substitutions
    713 	 and command-line options.  */
    714       static char wrapper_list_buffer[] = CXX_WRAP_SPEC_LIST;
    715       char *bufptr;
    716       /* Breaks up the char array into separated strings
    717          strings and enter them into the hash table.  */
    718       wrappers = new hash_table<nofree_string_hash> (8);
    719       for (bufptr = wrapper_list_buffer; *bufptr; ++bufptr)
    720 	{
    721 	  char *found = NULL;
    722 	  if (ISSPACE (*bufptr))
    723 	    continue;
    724 	  if (*bufptr == '_')
    725 	    found = bufptr;
    726 	  while (*bufptr && !ISSPACE (*bufptr))
    727 	    ++bufptr;
    728 	  if (*bufptr)
    729 	    *bufptr = 0;
    730 	  if (found)
    731 	    *wrappers->find_slot (found, INSERT) = found;
    732 	}
    733       first_time = 0;
    734     }
    735 
    736   return wrappers->find (target);
    737 }
    738 
    739 #endif /* CXX_WRAP_SPEC_LIST */
    740 
    741 /* This is called at the end of assembly.  For each external function
    742    which has not been defined, we output a declaration now.  We also
    743    output the .drectve section.  */
    744 
    745 void
    746 i386_pe_file_end (void)
    747 {
    748   struct extern_list *p;
    749 
    750   for (p = extern_head; p != NULL; p = p->next)
    751     {
    752       tree decl;
    753 
    754       decl = p->decl;
    755 
    756       /* Positively ensure only one declaration for any given symbol.  */
    757       if (! TREE_ASM_WRITTEN (decl)
    758 	  && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
    759 	{
    760 #ifdef CXX_WRAP_SPEC_LIST
    761 	  /* To ensure the DLL that provides the corresponding real
    762 	     functions is still loaded at runtime, we must reference
    763 	     the real function so that an (unused) import is created.  */
    764 	  const char *realsym = i386_find_on_wrapper_list (p->name);
    765 	  if (realsym)
    766 	    i386_pe_declare_function_type (asm_out_file,
    767 		concat ("__real_", realsym, NULL), TREE_PUBLIC (decl));
    768 #endif /* CXX_WRAP_SPEC_LIST */
    769 	  TREE_ASM_WRITTEN (decl) = 1;
    770 	  i386_pe_declare_function_type (asm_out_file, p->name,
    771 					 TREE_PUBLIC (decl));
    772 	}
    773     }
    774 
    775   if (export_head)
    776     {
    777       struct export_list *q;
    778       drectve_section ();
    779       for (q = export_head; q != NULL; q = q->next)
    780 	{
    781 	  fprintf (asm_out_file, "\t.ascii \" -export:\\\"%s\\\"%s\"\n",
    782 		   default_strip_name_encoding (q->name),
    783 		   (q->is_data ? ",data" : ""));
    784 	}
    785     }
    786 
    787   if (stub_head)
    788     {
    789       struct stub_list *q;
    790 
    791       for (q = stub_head; q != NULL; q = q->next)
    792 	{
    793 	  const char *name = q->name;
    794 	  const char *oname;
    795 
    796 	  if (name[0] == '*')
    797 	    ++name;
    798 	  oname = name;
    799 	  if (name[0] == '.')
    800 	    ++name;
    801 	  if (!startswith (name, "refptr."))
    802 	    continue;
    803 	  name += 7;
    804 	  fprintf (asm_out_file, "\t.section\t.rdata$%s, \"dr\"\n"
    805 	  		   "\t.globl\t%s\n"
    806 			   "\t.linkonce\tdiscard\n", oname, oname);
    807 	  fprintf (asm_out_file, "%s:\n\t.quad\t%s\n", oname, name);
    808 	}
    809     }
    810 }
    811 
    812 /* Kludge because of missing PE-COFF support for early LTO debug.  */
    813 
    814 static enum debug_info_levels saved_debug_info_level;
    815 
    816 void
    817 i386_pe_asm_lto_start (void)
    818 {
    819   saved_debug_info_level = debug_info_level;
    820   debug_info_level = DINFO_LEVEL_NONE;
    821 }
    822 
    823 void
    824 i386_pe_asm_lto_end (void)
    825 {
    826   debug_info_level = saved_debug_info_level;
    827 }
    828 
    829 
    830 /* x64 Structured Exception Handling unwind info.  */
    832 
    833 struct seh_frame_state
    834 {
    835   /* SEH records offsets relative to the lowest address of the fixed stack
    836      allocation.  If there is no frame pointer, these offsets are from the
    837      stack pointer; if there is a frame pointer, these offsets are from the
    838      value of the stack pointer when the frame pointer was established, i.e.
    839      the frame pointer minus the offset in the .seh_setframe directive.
    840 
    841      We do not distinguish these two cases, i.e. we consider that the offsets
    842      are always relative to the "current" stack pointer.  This means that we
    843      need to perform the fixed stack allocation before establishing the frame
    844      pointer whenever there are registers to be saved, and this is guaranteed
    845      by the prologue provided that we force the frame pointer to point at or
    846      below the lowest used register save area, see ix86_compute_frame_layout.
    847 
    848      This tracks the current stack pointer offset from the CFA.  */
    849   HOST_WIDE_INT sp_offset;
    850 
    851   /* The CFA is located at CFA_REG + CFA_OFFSET.  */
    852   HOST_WIDE_INT cfa_offset;
    853   rtx cfa_reg;
    854 
    855   /* The offset wrt the CFA where register N has been saved.  */
    856   HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
    857 
    858   /* True if we are past the end of the epilogue.  */
    859   bool after_prologue;
    860 
    861   /* True if we are in the cold section.  */
    862   bool in_cold_section;
    863 };
    864 
    865 /* Set up data structures beginning output for SEH.  */
    866 
    867 void
    868 i386_pe_seh_init (FILE *f)
    869 {
    870   struct seh_frame_state *seh;
    871 
    872   if (!TARGET_SEH)
    873     return;
    874   if (cfun->is_thunk)
    875     return;
    876 
    877   /* We cannot support DRAP with SEH.  We turned off support for it by
    878      re-defining MAX_STACK_ALIGNMENT when SEH is enabled.  */
    879   gcc_assert (!stack_realign_drap);
    880 
    881   seh = XCNEW (struct seh_frame_state);
    882   cfun->machine->seh = seh;
    883 
    884   seh->sp_offset = INCOMING_FRAME_SP_OFFSET;
    885   seh->cfa_offset = INCOMING_FRAME_SP_OFFSET;
    886   seh->cfa_reg = stack_pointer_rtx;
    887 
    888   fputs ("\t.seh_proc\t", f);
    889   assemble_name (f, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl)));
    890   fputc ('\n', f);
    891 }
    892 
    893 /* Emit an assembler directive for the end of the prologue.  */
    894 
    895 void
    896 i386_pe_seh_end_prologue (FILE *f)
    897 {
    898   if (!TARGET_SEH)
    899     return;
    900   if (cfun->is_thunk)
    901     return;
    902   cfun->machine->seh->after_prologue = true;
    903   fputs ("\t.seh_endprologue\n", f);
    904 }
    905 
    906 /* Emit assembler directives to reconstruct the SEH state.  */
    907 
    908 void
    909 i386_pe_seh_cold_init (FILE *f, const char *name)
    910 {
    911   struct seh_frame_state *seh;
    912   HOST_WIDE_INT alloc_offset, offset;
    913 
    914   if (!TARGET_SEH)
    915     return;
    916   if (cfun->is_thunk)
    917     return;
    918   seh = cfun->machine->seh;
    919 
    920   fputs ("\t.seh_proc\t", f);
    921   assemble_name (f, name);
    922   fputc ('\n', f);
    923 
    924   /* In the normal case, the frame pointer is near the bottom of the frame
    925      so we can do the full stack allocation and set it afterwards.  There
    926      is an exception if the function overflows the SEH maximum frame size
    927      or accesses prior frames so, in this case, we need to pre-allocate a
    928      small chunk of stack before setting it.  */
    929   offset = seh->sp_offset - INCOMING_FRAME_SP_OFFSET;
    930   if (offset < SEH_MAX_FRAME_SIZE && !crtl->accesses_prior_frames)
    931     alloc_offset = seh->sp_offset;
    932   else
    933     alloc_offset = MIN (seh->cfa_offset + 240, seh->sp_offset);
    934 
    935   offset = alloc_offset - INCOMING_FRAME_SP_OFFSET;
    936   if (offset > 0)
    937     fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
    938 
    939   for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    940     if (seh->reg_offset[regno] > 0 && seh->reg_offset[regno] <= alloc_offset)
    941       {
    942 	if (SSE_REGNO_P (regno))
    943 	  fputs ("\t.seh_savexmm\t", f);
    944 	else if (GENERAL_REGNO_P (regno))
    945 	  fputs ("\t.seh_savereg\t", f);
    946 	else
    947 	  gcc_unreachable ();
    948 	print_reg (gen_rtx_REG (DImode, regno), 0, f);
    949 	fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
    950 		 alloc_offset - seh->reg_offset[regno]);
    951       }
    952 
    953   if (seh->cfa_reg != stack_pointer_rtx)
    954     {
    955       offset = alloc_offset - seh->cfa_offset;
    956 
    957       gcc_assert ((offset & 15) == 0);
    958       gcc_assert (IN_RANGE (offset, 0, 240));
    959 
    960       fputs ("\t.seh_setframe\t", f);
    961       print_reg (seh->cfa_reg, 0, f);
    962       fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
    963     }
    964 
    965   if (alloc_offset != seh->sp_offset)
    966     {
    967       offset = seh->sp_offset - alloc_offset;
    968       if (offset > 0 && offset < SEH_MAX_FRAME_SIZE)
    969 	fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
    970 
    971       for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    972 	if (seh->reg_offset[regno] > alloc_offset)
    973 	  {
    974 	    if (SSE_REGNO_P (regno))
    975 	      fputs ("\t.seh_savexmm\t", f);
    976 	    else if (GENERAL_REGNO_P (regno))
    977 	      fputs ("\t.seh_savereg\t", f);
    978 	    else
    979 	      gcc_unreachable ();
    980 	    print_reg (gen_rtx_REG (DImode, regno), 0, f);
    981 	    fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n",
    982 		     seh->sp_offset - seh->reg_offset[regno]);
    983 	  }
    984     }
    985 
    986   fputs ("\t.seh_endprologue\n", f);
    987 }
    988 
    989 /* Emit an assembler directive for the end of the function.  */
    990 
    991 static void
    992 i386_pe_seh_fini (FILE *f, bool cold)
    993 {
    994   struct seh_frame_state *seh;
    995 
    996   if (!TARGET_SEH)
    997     return;
    998   if (cfun->is_thunk)
    999     return;
   1000   seh = cfun->machine->seh;
   1001   if (cold != seh->in_cold_section)
   1002     return;
   1003   XDELETE (seh);
   1004   cfun->machine->seh = NULL;
   1005   fputs ("\t.seh_endproc\n", f);
   1006 }
   1007 
   1008 /* Emit an assembler directive to save REG via a PUSH.  */
   1009 
   1010 static void
   1011 seh_emit_push (FILE *f, struct seh_frame_state *seh, rtx reg)
   1012 {
   1013   const unsigned int regno = REGNO (reg);
   1014 
   1015   gcc_checking_assert (GENERAL_REGNO_P (regno));
   1016 
   1017   seh->sp_offset += UNITS_PER_WORD;
   1018   seh->reg_offset[regno] = seh->sp_offset;
   1019   if (seh->cfa_reg == stack_pointer_rtx)
   1020     seh->cfa_offset += UNITS_PER_WORD;
   1021 
   1022   fputs ("\t.seh_pushreg\t", f);
   1023   print_reg (reg, 0, f);
   1024   fputc ('\n', f);
   1025 }
   1026 
   1027 /* Emit an assembler directive to save REG at CFA - CFA_OFFSET.  */
   1028 
   1029 static void
   1030 seh_emit_save (FILE *f, struct seh_frame_state *seh,
   1031 	       rtx reg, HOST_WIDE_INT cfa_offset)
   1032 {
   1033   const unsigned int regno = REGNO (reg);
   1034   HOST_WIDE_INT offset;
   1035 
   1036   seh->reg_offset[regno] = cfa_offset;
   1037 
   1038   /* Negative save offsets are of course not supported, since that
   1039      would be a store below the stack pointer and thus clobberable.  */
   1040   gcc_assert (seh->sp_offset >= cfa_offset);
   1041   offset = seh->sp_offset - cfa_offset;
   1042 
   1043   fputs ((SSE_REGNO_P (regno) ? "\t.seh_savexmm\t"
   1044 	 : GENERAL_REGNO_P (regno) ?  "\t.seh_savereg\t"
   1045 	 : (gcc_unreachable (), "")), f);
   1046   print_reg (reg, 0, f);
   1047   fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
   1048 }
   1049 
   1050 /* Emit an assembler directive to adjust RSP by OFFSET.  */
   1051 
   1052 static void
   1053 seh_emit_stackalloc (FILE *f, struct seh_frame_state *seh,
   1054 		     HOST_WIDE_INT offset)
   1055 {
   1056   /* We're only concerned with prologue stack allocations, which all
   1057      are subtractions from the stack pointer.  */
   1058   gcc_assert (offset < 0);
   1059   offset = -offset;
   1060 
   1061   if (seh->cfa_reg == stack_pointer_rtx)
   1062     seh->cfa_offset += offset;
   1063   seh->sp_offset += offset;
   1064 
   1065   /* Do not output the stackalloc in that case (it won't work as there is no
   1066      encoding for very large frame size).  */
   1067   if (offset < SEH_MAX_FRAME_SIZE)
   1068     fprintf (f, "\t.seh_stackalloc\t" HOST_WIDE_INT_PRINT_DEC "\n", offset);
   1069 }
   1070 
   1071 /* Process REG_CFA_ADJUST_CFA for SEH.  */
   1072 
   1073 static void
   1074 seh_cfa_adjust_cfa (FILE *f, struct seh_frame_state *seh, rtx pat)
   1075 {
   1076   rtx dest, src;
   1077   HOST_WIDE_INT reg_offset = 0;
   1078   unsigned int dest_regno;
   1079 
   1080   dest = SET_DEST (pat);
   1081   src = SET_SRC (pat);
   1082 
   1083   if (GET_CODE (src) == PLUS)
   1084     {
   1085       reg_offset = INTVAL (XEXP (src, 1));
   1086       src = XEXP (src, 0);
   1087     }
   1088   else if (GET_CODE (src) == MINUS)
   1089     {
   1090       reg_offset = -INTVAL (XEXP (src, 1));
   1091       src = XEXP (src, 0);
   1092     }
   1093   gcc_assert (src == stack_pointer_rtx);
   1094   gcc_assert (seh->cfa_reg == stack_pointer_rtx);
   1095   dest_regno = REGNO (dest);
   1096 
   1097   if (dest_regno == STACK_POINTER_REGNUM)
   1098     seh_emit_stackalloc (f, seh, reg_offset);
   1099   else if (dest_regno == HARD_FRAME_POINTER_REGNUM)
   1100     {
   1101       HOST_WIDE_INT offset;
   1102 
   1103       seh->cfa_reg = dest;
   1104       seh->cfa_offset -= reg_offset;
   1105 
   1106       offset = seh->sp_offset - seh->cfa_offset;
   1107 
   1108       gcc_assert ((offset & 15) == 0);
   1109       gcc_assert (IN_RANGE (offset, 0, 240));
   1110 
   1111       fputs ("\t.seh_setframe\t", f);
   1112       print_reg (seh->cfa_reg, 0, f);
   1113       fprintf (f, ", " HOST_WIDE_INT_PRINT_DEC "\n", offset);
   1114     }
   1115   else
   1116     gcc_unreachable ();
   1117 }
   1118 
   1119 /* Process REG_CFA_OFFSET for SEH.  */
   1120 
   1121 static void
   1122 seh_cfa_offset (FILE *f, struct seh_frame_state *seh, rtx pat)
   1123 {
   1124   rtx dest, src;
   1125   HOST_WIDE_INT reg_offset;
   1126 
   1127   dest = SET_DEST (pat);
   1128   src = SET_SRC (pat);
   1129 
   1130   gcc_assert (MEM_P (dest));
   1131   dest = XEXP (dest, 0);
   1132   if (REG_P (dest))
   1133     reg_offset = 0;
   1134   else
   1135     {
   1136       gcc_assert (GET_CODE (dest) == PLUS);
   1137       reg_offset = INTVAL (XEXP (dest, 1));
   1138       dest = XEXP (dest, 0);
   1139     }
   1140   gcc_assert (dest == seh->cfa_reg);
   1141 
   1142   seh_emit_save (f, seh, src, seh->cfa_offset - reg_offset);
   1143 }
   1144 
   1145 /* Process a FRAME_RELATED_EXPR for SEH.  */
   1146 
   1147 static void
   1148 seh_frame_related_expr (FILE *f, struct seh_frame_state *seh, rtx pat)
   1149 {
   1150   rtx dest, src;
   1151   HOST_WIDE_INT addend;
   1152 
   1153   /* See the full loop in dwarf2out_frame_debug_expr.  */
   1154   if (GET_CODE (pat) == PARALLEL || GET_CODE (pat) == SEQUENCE)
   1155     {
   1156       int i, n = XVECLEN (pat, 0), pass, npass;
   1157 
   1158       npass = (GET_CODE (pat) == PARALLEL ? 2 : 1);
   1159       for (pass = 0; pass < npass; ++pass)
   1160 	for (i = 0; i < n; ++i)
   1161 	  {
   1162 	    rtx ele = XVECEXP (pat, 0, i);
   1163 
   1164 	    if (GET_CODE (ele) != SET)
   1165 	      continue;
   1166 	    dest = SET_DEST (ele);
   1167 
   1168 	    /* Process each member of the PARALLEL independently.  The first
   1169 	       member is always processed; others only if they are marked.  */
   1170 	    if (i == 0 || RTX_FRAME_RELATED_P (ele))
   1171 	      {
   1172 		/* Evaluate all register saves in the first pass and all
   1173 		   register updates in the second pass.  */
   1174 		if ((MEM_P (dest) ^ pass) || npass == 1)
   1175 		  seh_frame_related_expr (f, seh, ele);
   1176 	      }
   1177 	  }
   1178       return;
   1179     }
   1180 
   1181   dest = SET_DEST (pat);
   1182   src = SET_SRC (pat);
   1183 
   1184   switch (GET_CODE (dest))
   1185     {
   1186     case REG:
   1187       switch (GET_CODE (src))
   1188 	{
   1189 	case REG:
   1190 	  /* REG = REG: This should be establishing a frame pointer.  */
   1191 	  gcc_assert (src == stack_pointer_rtx);
   1192 	  gcc_assert (dest == hard_frame_pointer_rtx);
   1193 	  seh_cfa_adjust_cfa (f, seh, pat);
   1194 	  break;
   1195 
   1196 	case PLUS:
   1197 	  addend = INTVAL (XEXP (src, 1));
   1198 	  src = XEXP (src, 0);
   1199 	  if (dest == hard_frame_pointer_rtx)
   1200 	    seh_cfa_adjust_cfa (f, seh, pat);
   1201 	  else if (dest == stack_pointer_rtx)
   1202 	    {
   1203 	      gcc_assert (src == stack_pointer_rtx);
   1204 	      seh_emit_stackalloc (f, seh, addend);
   1205 	    }
   1206 	  else
   1207 	    gcc_unreachable ();
   1208 	  break;
   1209 
   1210 	default:
   1211 	  gcc_unreachable ();
   1212 	}
   1213       break;
   1214 
   1215     case MEM:
   1216       /* A save of some kind.  */
   1217       dest = XEXP (dest, 0);
   1218       if (GET_CODE (dest) == PRE_DEC)
   1219 	{
   1220 	  gcc_checking_assert (GET_MODE (src) == Pmode);
   1221 	  gcc_checking_assert (REG_P (src));
   1222 	  seh_emit_push (f, seh, src);
   1223 	}
   1224       else
   1225 	seh_cfa_offset (f, seh, pat);
   1226       break;
   1227 
   1228     default:
   1229       gcc_unreachable ();
   1230     }
   1231 }
   1232 
   1233 /* This function looks at a single insn and emits any SEH directives
   1234    required for unwind of this insn.  */
   1235 
   1236 void
   1237 i386_pe_seh_unwind_emit (FILE *out_file, rtx_insn *insn)
   1238 {
   1239   rtx note, pat;
   1240   bool handled_one = false;
   1241   struct seh_frame_state *seh;
   1242 
   1243   if (!TARGET_SEH)
   1244     return;
   1245 
   1246   seh = cfun->machine->seh;
   1247   if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS)
   1248     {
   1249       /* See ix86_output_call_insn/seh_fixup_eh_fallthru for the rationale.  */
   1250       rtx_insn *prev = prev_active_insn (insn);
   1251       if (prev && (CALL_P (prev) || !insn_nothrow_p (prev)))
   1252 	fputs ("\tnop\n", out_file);
   1253       fputs ("\t.seh_endproc\n", out_file);
   1254       seh->in_cold_section = true;
   1255       return;
   1256     }
   1257 
   1258   if (NOTE_P (insn) || !RTX_FRAME_RELATED_P (insn))
   1259     return;
   1260 
   1261   /* Skip RTX_FRAME_RELATED_P insns that are associated with the epilogue.  */
   1262   if (seh->after_prologue)
   1263     return;
   1264 
   1265   for (note = REG_NOTES (insn); note ; note = XEXP (note, 1))
   1266     {
   1267       switch (REG_NOTE_KIND (note))
   1268 	{
   1269 	case REG_FRAME_RELATED_EXPR:
   1270 	  pat = XEXP (note, 0);
   1271 	  goto found;
   1272 
   1273 	case REG_CFA_DEF_CFA:
   1274 	case REG_CFA_EXPRESSION:
   1275 	  /* Only emitted with DRAP and aligned memory access using a
   1276 	     realigned SP, both of which we disable.  */
   1277 	  gcc_unreachable ();
   1278 	  break;
   1279 
   1280 	case REG_CFA_REGISTER:
   1281 	  /* Only emitted in epilogues, which we skip.  */
   1282 	  gcc_unreachable ();
   1283 
   1284 	case REG_CFA_ADJUST_CFA:
   1285 	  pat = XEXP (note, 0);
   1286 	  if (pat == NULL)
   1287 	    {
   1288 	      pat = PATTERN (insn);
   1289 	      if (GET_CODE (pat) == PARALLEL)
   1290 		pat = XVECEXP (pat, 0, 0);
   1291 	    }
   1292 	  seh_cfa_adjust_cfa (out_file, seh, pat);
   1293 	  handled_one = true;
   1294 	  break;
   1295 
   1296 	case REG_CFA_OFFSET:
   1297 	  pat = XEXP (note, 0);
   1298 	  if (pat == NULL)
   1299 	    pat = single_set (insn);
   1300 	  seh_cfa_offset (out_file, seh, pat);
   1301 	  handled_one = true;
   1302 	  break;
   1303 
   1304 	default:
   1305 	  break;
   1306 	}
   1307     }
   1308   if (handled_one)
   1309     return;
   1310   pat = PATTERN (insn);
   1311  found:
   1312   seh_frame_related_expr (out_file, seh, pat);
   1313 }
   1314 
   1315 void
   1316 i386_pe_seh_emit_except_personality (rtx personality)
   1317 {
   1318   int flags = 0;
   1319 
   1320   if (!TARGET_SEH)
   1321     return;
   1322 
   1323   fputs ("\t.seh_handler\t", asm_out_file);
   1324   output_addr_const (asm_out_file, personality);
   1325 
   1326 #if 0
   1327   /* ??? The current implementation of _GCC_specific_handler requires
   1328      both except and unwind handling, regardless of which sorts the
   1329      user-level function requires.  */
   1330   eh_region r;
   1331   FOR_ALL_EH_REGION(r)
   1332     {
   1333       if (r->type == ERT_CLEANUP)
   1334 	flags |= 1;
   1335       else
   1336 	flags |= 2;
   1337     }
   1338 #else
   1339   flags = 3;
   1340 #endif
   1341 
   1342   if (flags & 1)
   1343     fputs (", @unwind", asm_out_file);
   1344   if (flags & 2)
   1345     fputs (", @except", asm_out_file);
   1346   fputc ('\n', asm_out_file);
   1347 }
   1348 
   1349 void
   1350 i386_pe_seh_init_sections (void)
   1351 {
   1352   if (TARGET_SEH)
   1353     exception_section = get_unnamed_section (0, output_section_asm_op,
   1354 					     "\t.seh_handlerdata");
   1355 }
   1356 
   1357 void
   1359 i386_pe_start_function (FILE *f, const char *name, tree decl)
   1360 {
   1361   i386_pe_maybe_record_exported_symbol (decl, name, 0);
   1362   i386_pe_declare_function_type (f, name, TREE_PUBLIC (decl));
   1363   /* In case section was altered by debugging output.  */
   1364   if (decl != NULL_TREE)
   1365     switch_to_section (function_section (decl));
   1366   ASM_OUTPUT_FUNCTION_LABEL (f, name, decl);
   1367 }
   1368 
   1369 void
   1370 i386_pe_end_function (FILE *f, const char *, tree)
   1371 {
   1372   i386_pe_seh_fini (f, false);
   1373 }
   1374 
   1375 void
   1377 i386_pe_end_cold_function (FILE *f, const char *, tree)
   1378 {
   1379   i386_pe_seh_fini (f, true);
   1380 }
   1381 
   1382 #include "gt-winnt.h"
   1383