⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winnt.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Subroutines for insn-output.c for Windows NT.   Contributed by Douglas Rupp (drupp@cs.washington.edu)   Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005   Free Software Foundation, Inc.This file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING.  If not, write to the FreeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA02110-1301, USA.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "output.h"#include "tree.h"#include "flags.h"#include "tm_p.h"#include "toplev.h"#include "hashtab.h"#include "ggc.h"/* i386/PE specific attribute support.   i386/PE has two new attributes:   dllexport - for exporting a function/variable that will live in a dll   dllimport - for importing a function/variable from a dll   Microsoft allows multiple declspecs in one __declspec, separating   them with spaces.  We do NOT support this.  Instead, use __declspec   multiple times.*/static tree associated_type (tree);static tree gen_stdcall_or_fastcall_suffix (tree, bool);static bool i386_pe_dllexport_p (tree);static bool i386_pe_dllimport_p (tree);static void i386_pe_mark_dllexport (tree);static void i386_pe_mark_dllimport (tree);/* This is we how mark internal identifiers with dllimport or dllexport   attributes.  */#ifndef DLL_IMPORT_PREFIX#define DLL_IMPORT_PREFIX "#i."#endif#ifndef DLL_EXPORT_PREFIX#define DLL_EXPORT_PREFIX "#e."#endif/* Handle a "shared" attribute;   arguments as in struct attribute_spec.handler.  */treeix86_handle_shared_attribute (tree *node, tree name,			      tree args ATTRIBUTE_UNUSED,			      int flags ATTRIBUTE_UNUSED, bool *no_add_attrs){  if (TREE_CODE (*node) != VAR_DECL)    {      warning (OPT_Wattributes, "%qs attribute only applies to variables",	       IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}/* Handle a "selectany" attribute;   arguments as in struct attribute_spec.handler.  */treeix86_handle_selectany_attribute (tree *node, tree name,			         tree args ATTRIBUTE_UNUSED,			         int flags ATTRIBUTE_UNUSED,				 bool *no_add_attrs){  /* The attribute applies only to objects that are initialized and have     external linkage,  */	  if (TREE_CODE (*node) == VAR_DECL && TREE_PUBLIC (*node)      && (DECL_INITIAL (*node)          /* If an object is initialized with a ctor, the static	     initialization and destruction code for it is present in	     each unit defining the object.  The code that calls the	     ctor is protected by a link-once guard variable, so that	     the object still has link-once semantics,  */    	  || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (*node))))    make_decl_one_only (*node);  else    {	      error ("%qs attribute applies only to initialized variables"       	     " with external linkage",  IDENTIFIER_POINTER (name));      *no_add_attrs = true;    }  return NULL_TREE;}/* Return the type that we should use to determine if DECL is   imported or exported.  */static treeassociated_type (tree decl){  return  (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))            ?  DECL_CONTEXT (decl) : NULL_TREE;}/* Return true if DECL is a dllexport'd object.  */static booli386_pe_dllexport_p (tree decl){  if (TREE_CODE (decl) != VAR_DECL       && TREE_CODE (decl) != FUNCTION_DECL)    return false;  if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))    return true;  /* Also mark class members of exported classes with dllexport.  */  if (associated_type (decl)      && lookup_attribute ("dllexport",			    TYPE_ATTRIBUTES (associated_type (decl))))    return i386_pe_type_dllexport_p (decl);  return false;}static booli386_pe_dllimport_p (tree decl){  if (TREE_CODE (decl) != VAR_DECL       && TREE_CODE (decl) != FUNCTION_DECL)    return false;  /* Lookup the attribute rather than rely on the DECL_DLLIMPORT_P flag.     We may need to override an earlier decision.  */  if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))    return true;  /* The DECL_DLLIMPORT_P flag was set for decls in the class definition     by  targetm.cxx.adjust_class_at_definition.  Check again to emit     warnings if the class attribute has been overriden by an     out-of-class definition.  */  if (associated_type (decl)      && lookup_attribute ("dllimport",			    TYPE_ATTRIBUTES (associated_type (decl))))    return i386_pe_type_dllimport_p (decl);  return false;}/* Handle the -mno-fun-dllimport target switch.  */booli386_pe_valid_dllimport_attribute_p (tree decl){   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)     return false;   return true;}/* Return nonzero if SYMBOL is marked as being dllexport'd.  */inti386_pe_dllexport_name_p (const char *symbol){  return (strncmp (DLL_EXPORT_PREFIX, symbol,		   strlen (DLL_EXPORT_PREFIX)) == 0);}/* Return nonzero if SYMBOL is marked as being dllimport'd.  */inti386_pe_dllimport_name_p (const char *symbol){  return (strncmp (DLL_IMPORT_PREFIX, symbol,		   strlen (DLL_IMPORT_PREFIX)) == 0);}/* Mark a DECL as being dllexport'd.   Note that we override the previous setting (e.g.: dllimport).  */static voidi386_pe_mark_dllexport (tree decl){  const char *oldname;  char  *newname;  rtx rtlname;  rtx symref;  tree idp;  rtlname = XEXP (DECL_RTL (decl), 0);  if (GET_CODE (rtlname) == MEM)    rtlname = XEXP (rtlname, 0);  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);  oldname = XSTR (rtlname, 0);  if (i386_pe_dllimport_name_p (oldname))    {      warning (0, "inconsistent dll linkage for %q+D, dllexport assumed",	       decl);     /* Remove DLL_IMPORT_PREFIX.  */      oldname += strlen (DLL_IMPORT_PREFIX);    }  else if (i386_pe_dllexport_name_p (oldname))    return;  /*  already done  */  newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);  sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);  /* We pass newname through get_identifier to ensure it has a unique     address.  RTL processing can sometimes peek inside the symbol ref     and compare the string's addresses to see if two symbols are     identical.  */  idp = get_identifier (newname);  symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));  SYMBOL_REF_DECL (symref) = decl;  XEXP (DECL_RTL (decl), 0) = symref;}/* Mark a DECL as being dllimport'd.  */static voidi386_pe_mark_dllimport (tree decl){  const char *oldname;  char  *newname;  tree idp;  rtx rtlname, newrtl;  rtx symref;  rtlname = XEXP (DECL_RTL (decl), 0);  if (GET_CODE (rtlname) == MEM)    rtlname = XEXP (rtlname, 0);  gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);  oldname = XSTR (rtlname, 0);  if (i386_pe_dllexport_name_p (oldname))    {      error ("%qs declared as both exported to and imported from a DLL",             IDENTIFIER_POINTER (DECL_NAME (decl)));      return;    }  else if (i386_pe_dllimport_name_p (oldname))    {      /* Already done, but do a sanity check to prevent assembler	 errors.  */      gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)		  && DECL_DLLIMPORT_P (decl));      return;    }  newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);  sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);  /* We pass newname through get_identifier to ensure it has a unique     address.  RTL processing can sometimes peek inside the symbol ref     and compare the string's addresses to see if two symbols are     identical.  */  idp = get_identifier (newname);  symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));  SYMBOL_REF_DECL (symref) = decl;  newrtl = gen_rtx_MEM (Pmode,symref);  XEXP (DECL_RTL (decl), 0) = newrtl;  DECL_DLLIMPORT_P (decl) = 1;}/* Return string which is the former assembler name modified with a   suffix consisting of an atsign (@) followed by the number of bytes of   arguments.  If FASTCALL is true, also add the FASTCALL_PREFIX.  */static treegen_stdcall_or_fastcall_suffix (tree decl, bool fastcall){  int total = 0;  /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead     of DECL_ASSEMBLER_NAME.  */   const char *asmname =  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));  char *newsym;  char *p;  tree formal_type;  /* Do not change the identifier if a verbatim asmspec or already done. */  if (*asmname == '*' || strchr (asmname, '@'))    return DECL_ASSEMBLER_NAME (decl);  formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));  if (formal_type != NULL_TREE)    {      /* These attributes are ignored for variadic functions in	 i386.c:ix86_return_pops_args. For compatibility with MS         compiler do not add @0 suffix here.  */       if (TREE_VALUE (tree_last (formal_type)) != void_type_node)        return DECL_ASSEMBLER_NAME (decl);      /* Quit if we hit an incomplete type.  Error is reported         by convert_arguments in c-typeck.c or cp/typeck.c.  */      while (TREE_VALUE (formal_type) != void_type_node	     && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))		{	  int parm_size	    = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));	    /* Must round up to include padding.  This is done the same	       way as in store_one_arg.  */	  parm_size = ((parm_size + PARM_BOUNDARY - 1)		       / PARM_BOUNDARY * PARM_BOUNDARY);	  total += parm_size;	  formal_type = TREE_CHAIN (formal_type);\	}     }  /* Assume max of 8 base 10 digits in the suffix.  */  newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);  p = newsym;  if (fastcall)    *p++ = FASTCALL_PREFIX;  sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);  return get_identifier (newsym);}voidi386_pe_encode_section_info (tree decl, rtx rtl, int first){  default_encode_section_info (decl, rtl, first);  if (first && TREE_CODE (decl) == FUNCTION_DECL)    {      tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));      tree newid = NULL_TREE;      if (lookup_attribute ("stdcall", type_attributes))	newid = gen_stdcall_or_fastcall_suffix (decl, false);      else if (lookup_attribute ("fastcall", type_attributes))	newid = gen_stdcall_or_fastcall_suffix (decl, true);      if (newid != NULL_TREE) 		{	  rtx rtlname = XEXP (rtl, 0);	  if (GET_CODE (rtlname) == MEM)	    rtlname = XEXP (rtlname, 0);	  XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);	  /* These attributes must be present on first declaration,	     change_decl_assembler_name will warn if they are added	     later and the decl has been referenced, but duplicate_decls

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -