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

📄 winnt.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 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   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, 59 Temple Place - Suite 330, Boston, MA02111-1307, 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 int i386_pe_dllexport_p (tree);static int 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 ("%qs attribute only applies to variables",	       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){  tree t = NULL_TREE;  /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer     to the containing class.  So we look at the 'this' arg.  */  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)    {      /* Artificial methods are not affected by the import/export status	 of their class unless they are COMDAT.  Implicit copy ctor's and	 dtor's are not affected by class status but virtual and	 non-virtual thunks are.  */      if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl))	t = TYPE_MAIN_VARIANT	  (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));    }  else if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))    t = DECL_CONTEXT (decl);  return t;}/* Return nonzero if DECL is a dllexport'd object.  */static inti386_pe_dllexport_p (tree decl){  tree exp;  if (TREE_CODE (decl) != VAR_DECL      && TREE_CODE (decl) != FUNCTION_DECL)    return 0;  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));  if (exp)    return 1;  /* Class members get the dllexport status of their class.  */  if (associated_type (decl))    {      exp = lookup_attribute ("dllexport",			      TYPE_ATTRIBUTES (associated_type (decl)));      if (exp)	return 1;    }  return 0;}/* Return nonzero if DECL is a dllimport'd object.  */static inti386_pe_dllimport_p (tree decl){  tree imp;  int context_imp = 0;  if (TREE_CODE (decl) == FUNCTION_DECL      && TARGET_NOP_FUN_DLLIMPORT)    return 0;  if (TREE_CODE (decl) != VAR_DECL      && TREE_CODE (decl) != FUNCTION_DECL)    return 0;  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));  /* Class members get the dllimport status of their class.  */  if (!imp && associated_type (decl))    {      imp = lookup_attribute ("dllimport",			      TYPE_ATTRIBUTES (associated_type (decl)));      if (imp)	context_imp = 1;    }  if (imp)    {      /* Don't mark defined functions as dllimport.  If the definition	 itself was marked with dllimport, than ix86_handle_dll_attribute	 reports an error. This handles the case when the definition	 overrides an earlier declaration.  */      if (TREE_CODE (decl) ==  FUNCTION_DECL && DECL_INITIAL (decl)	  && !DECL_INLINE (decl))	{	   /* Don't warn about artificial methods.  */	  if (!DECL_ARTIFICIAL (decl))	    warning ("%Jfunction '%D' is defined after prior declaration "		     "as dllimport: attribute ignored", decl, decl);	  return 0;	}      /* We ignore the dllimport attribute for inline member functions.	 This differs from MSVC behavior which treats it like GNUC	 'extern inline' extension.  */      else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))        {	  if (extra_warnings)	    warning ("%Jinline function '%D' is declared as dllimport: "		     "attribute ignored.", decl, decl);	  return 0;	}      /*  Don't allow definitions of static data members in dllimport class,	  Just ignore attribute for vtable data.  */      else if (TREE_CODE (decl) == VAR_DECL	       && TREE_STATIC (decl) && TREE_PUBLIC (decl)	       && !DECL_EXTERNAL (decl) && context_imp)	{	  if (!DECL_VIRTUAL_P (decl))            error ("%Jdefinition of static data member '%D' of "		   "dllimport'd class.", decl, decl);	  return 0;	}      /* Since we can't treat a pointer to a dllimport'd symbol as a	 constant address, we turn off the attribute on C++ virtual	 methods to allow creation of vtables using thunks.  Don't mark	 artificial methods either (in associated_type, only COMDAT	 artificial method get import status from class context).  */      else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE	       && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))	return 0;      return 1;    }  return 0;}/* 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) == SYMBOL_REF)    oldname = XSTR (rtlname, 0);  else if (GET_CODE (rtlname) == MEM	   && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)    oldname = XSTR (XEXP (rtlname, 0), 0);  else    abort ();  if (i386_pe_dllimport_name_p (oldname))    {      warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.",	       decl, decl);     /* Remove DLL_IMPORT_PREFIX.  */      oldname += strlen (DLL_IMPORT_PREFIX);      DECL_NON_ADDR_CONST_P (decl) = 0;    }  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) == SYMBOL_REF)    oldname = XSTR (rtlname, 0);  else if (GET_CODE (rtlname) == MEM	   && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)    oldname = XSTR (XEXP (rtlname, 0), 0);  else    abort ();  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.  */      if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))	{	  error ("%Jfailure in redeclaration of '%D': dllimport'd "		 "symbol lacks external linkage.", decl, decl);	  abort();	}      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;  /* Can't treat a pointer to this as a constant address */  DECL_NON_ADDR_CONST_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);

⌨️ 快捷键说明

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