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

📄 symbian.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Routines for GCC for a Symbian OS targeted SH backend.   Copyright (C) 2004, 2005 Free Software Foundation, Inc.   Contributed by RedHat.   Most of this code is stolen from i386/winnt.c.   This file is part of GCC.   GCC is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published   by the Free Software Foundation; either version 2, or (at your   option) any later version.   GCC is distributed in the hope that it will be useful, but WITHOUT   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public   License for more details.   You should have received a copy of the GNU General Public License   along with GCC; see the file COPYING.  If not, write to   the Free Software Foundation, 51 Franklin Street, Fifth Floor,   Boston, MA 02110-1301, USA.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tm.h"#include "rtl.h"#include "output.h"#include "flags.h"#include "tree.h"#include "expr.h"#include "tm_p.h"#include "cp/cp-tree.h"	/* We need access to the OVL_... macros.  */#include "toplev.h"/* Select the level of debugging information to display.   0 for no debugging.   1 for informative messages about decisions to add attributes   2 for verbose information about what is being done.  */#define SYMBIAN_DEBUG 0/* #define SYMBIAN_DEBUG 1 *//* #define SYMBIAN_DEBUG 2 *//* A unique character to encode declspec encoded objects.  */#define SH_SYMBIAN_FLAG_CHAR "$"/* Unique strings to prefix exported and imported objects.  */#define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."#define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."/* Return the type that we should use to determine if DECL is   imported or exported.  */static treesh_symbian_associated_type (tree decl){  tree t = NULL_TREE;  if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)  /* Methods now inherit their dllimport/dllexport attributes correctly     so there is no need to check their class.  In fact it is wrong to     check their class since a method can remain unexported from an     exported class.  */    return t;  /* Otherwise we can just take the DECL_CONTEXT as normal.  */  if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))    t = DECL_CONTEXT (decl);  return t;}/* Return nonzero if DECL is a dllexport'd object.  */boolsh_symbian_dllexport_p (tree decl){  tree exp;  if (   TREE_CODE (decl) != VAR_DECL      && TREE_CODE (decl) != FUNCTION_DECL)    return false;  exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));  /* Class members get the dllexport status of their class.  */  if (exp == NULL)    {      tree class = sh_symbian_associated_type (decl);      if (class)	exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));    }#if SYMBIAN_DEBUG  if (exp)    {      print_node_brief (stderr, "dllexport:", decl, 0);      fprintf (stderr, "\n");    }  else#if SYMBIAN_DEBUG < 2    if (TREE_CODE (decl) != FUNCTION_DECL)#endif    {      print_node_brief (stderr, "no dllexport:", decl, 0);      fprintf (stderr, "\n");    }#endif  return exp ? true : false;}/* Return nonzero if DECL is a dllimport'd object.  */static boolsh_symbian_dllimport_p (tree decl){  tree imp;  if (   TREE_CODE (decl) != VAR_DECL      && TREE_CODE (decl) != FUNCTION_DECL)    return false;  imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));  if (imp)    return true;  /* Class members get the dllimport status of their class.  */  imp = sh_symbian_associated_type (decl);  if (! imp)    return false;  imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (imp));  if (!imp)    return false;  /* Don't mark defined functions as dllimport.  If the definition itself     was marked with dllimport, then sh_symbian_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 (OPT_Wattributes, "function %q+D is defined after prior "		 "declaration as dllimport: attribute ignored",		 decl);      return false;    }  /* 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 (OPT_Wattributes, "inline function %q+D is declared as "		 "dllimport: attribute ignored",		 decl);      return false;    }  /*  Don't allow definitions of static data members in dllimport      class.  Just ignore the attribute for vtable data.  */  else if (TREE_CODE (decl) == VAR_DECL	   && TREE_STATIC (decl)	   && TREE_PUBLIC (decl)	   && !DECL_EXTERNAL (decl))    {      if (!DECL_VIRTUAL_P (decl))	error ("definition of static data member %q+D of dllimport'd class",	       decl);      return false;    }  /* 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 sh_symbian_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 false;  return true;}/* Return nonzero if SYMBOL is marked as being dllexport'd.  */boolsh_symbian_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.  */boolsh_symbian_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 voidsh_symbian_mark_dllexport (tree decl){  const char *oldname;  char *newname;  rtx rtlname;  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 (sh_symbian_dllimport_name_p (oldname))    {     /* Remove DLL_IMPORT_PREFIX.	Note - we do not issue a warning here.  In Symbian's environment it	is legitimate for a prototype to be marked as dllimport and the	corresponding definition to be marked as dllexport.  The prototypes	are in headers used everywhere and the definition is in a translation	unit which has included the header in order to ensure argument	correctness.  */      oldname += strlen (DLL_IMPORT_PREFIX);      DECL_NON_ADDR_CONST_P (decl) = 0;    }  else if (sh_symbian_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);  XEXP (DECL_RTL (decl), 0) =    gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));}/* Mark a DECL as being dllimport'd.  */static voidsh_symbian_mark_dllimport (tree decl){  const char *oldname;  char *newname;  tree idp;  rtx rtlname;  rtx newrtl;  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 (sh_symbian_dllexport_name_p (oldname))    {      error ("%qs declared as both exported to and imported from a DLL",             IDENTIFIER_POINTER (DECL_NAME (decl)));    }  else if (sh_symbian_dllimport_name_p (oldname))    {      /* Already done, but do a sanity check to prevent assembler errors.  */      if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))	error ("failure in redeclaration of %q+D: dllimport'd symbol lacks external linkage",	       decl);    }  else    {      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);      newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));      XEXP (DECL_RTL (decl), 0) = newrtl;    }}voidsh_symbian_encode_section_info (tree decl, rtx rtl, int first){  default_encode_section_info (decl, rtl, first);  /* Mark the decl so we can tell from the rtl whether     the object is dllexport'd or dllimport'd.  */  if (sh_symbian_dllexport_p (decl))    sh_symbian_mark_dllexport (decl);  else if (sh_symbian_dllimport_p (decl))    sh_symbian_mark_dllimport (decl);  /* It might be that DECL has already been marked as dllimport, but a     subsequent definition nullified that.  The attribute is gone but     DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove     that. Ditto for the DECL_NON_ADDR_CONST_P flag.  */  else if (  (TREE_CODE (decl) == FUNCTION_DECL	   || TREE_CODE (decl) == VAR_DECL)	   && DECL_RTL (decl) != NULL_RTX	   && GET_CODE (DECL_RTL (decl)) == MEM	   && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM	   && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF	   && sh_symbian_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))    {      const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);      /* Remove DLL_IMPORT_PREFIX.  */      tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));      rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));      warning (0, "%s %q+D %s after being referenced with dllimport linkage",	       TREE_CODE (decl) == VAR_DECL ? "variable" : "function",	       decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))	       ? "defined locally" : "redeclared without dllimport attribute");      XEXP (DECL_RTL (decl), 0) = newrtl;      DECL_NON_ADDR_CONST_P (decl) = 0;    }}/* Return the length of a function name prefix    that starts with the character 'c'.  */static intsh_symbian_get_strip_length (int c){  /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX).  */  return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;}/* Return a pointer to a function's name with any   and all prefix encodings stripped from it.  */const char *sh_symbian_strip_name_encoding (const char *name){  int skip;  while ((skip = sh_symbian_get_strip_length (*name)))    name += skip;  return name;}/* Add the named attribute to the given node.  Copes with both DECLs and   TYPEs.  Will only add the attribute if it is not already present.  */static voidsymbian_add_attribute (tree node, const char *attr_name){  tree attrs;  tree attr;  attrs = DECL_P (node) ? DECL_ATTRIBUTES (node) : TYPE_ATTRIBUTES (node);  if (lookup_attribute (attr_name, attrs) != NULL_TREE)    return;  attr = get_identifier (attr_name);  if (DECL_P (node))    DECL_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);  else    TYPE_ATTRIBUTES (node) = tree_cons (attr, NULL_TREE, attrs);#if SYMBIAN_DEBUG  fprintf (stderr, "propogate %s attribute", attr_name);  print_node_brief (stderr, " to", node, 0);  fprintf (stderr, "\n");#endif}/* Handle a "dllimport" or "dllexport" attribute;   arguments as in struct attribute_spec.handler.  */treesh_symbian_handle_dll_attribute (tree *pnode, tree name, tree args,				 int flags, bool *no_add_attrs){  tree thunk;  tree node = *pnode;  const char *attr = IDENTIFIER_POINTER (name);  /* These attributes may apply to structure and union types being     created, but otherwise should pass to the declaration involved.  */  if (!DECL_P (node))    {      if (flags & ((int) ATTR_FLAG_DECL_NEXT		   | (int) ATTR_FLAG_FUNCTION_NEXT		   | (int) ATTR_FLAG_ARRAY_NEXT))	{	  warning (OPT_Wattributes, "%qs attribute ignored", attr);	  *no_add_attrs = true;	  return tree_cons (name, args, NULL_TREE);	}      if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)	{	  warning (OPT_Wattributes, "%qs attribute ignored", attr);	  *no_add_attrs = true;	}      return NULL_TREE;    }  /* Report error on dllimport ambiguities     seen now before they cause any damage.  */  else if (is_attribute_p ("dllimport", name))    {      if (TREE_CODE (node) == VAR_DECL)	{	  if (DECL_INITIAL (node))	    {	      error ("variable %q+D definition is marked dllimport",		     node);	      *no_add_attrs = true;	    }	  /* `extern' needn't be specified with dllimport.	     Specify `extern' now and hope for the best.  Sigh.  */	  DECL_EXTERNAL (node) = 1;	  /* Also, implicitly give dllimport'd variables declared within	     a function global scope, unless declared static.  */	  if (current_function_decl != NULL_TREE && ! TREE_STATIC (node))  	    TREE_PUBLIC (node) = 1;	}    }  /* If the node is an overloaded constructor or destructor, then we must     make sure that the attribute is propagated along the overload chain,     as it is these overloaded functions which will be emitted, rather than

⌨️ 快捷键说明

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