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