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

📄 symbian.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Routines for GCC for a Symbian OS targeted SH backend.   Copyright (C) 2004 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, 59 Temple Place - Suite 330,   Boston, MA 02111-1307, 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 ("%H function '%D' is defined after prior declaration as dllimport: attribute ignored",		 & DECL_SOURCE_LOCATION (decl), 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 ("%Hinline function '%D' is declared as dllimport: attribute ignored.",		 & DECL_SOURCE_LOCATION (decl), 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 ("%Hdefinition of static data member '%D' of dllimport'd class.",	       & DECL_SOURCE_LOCATION (decl), 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) == 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 (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) == 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 (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 ("%Hfailure in redeclaration of '%D': dllimport'd symbol lacks external linkage.",	       &DECL_SOURCE_LOCATION (decl), 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 ("%H%s '%D' %s after being referenced with dllimport linkage.",	       & DECL_SOURCE_LOCATION (decl),	       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);  (DECL_P (node) ? DECL_ATTRIBUTES (node) : 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 ("%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 ("%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 ("%Hvariable %qD definition is marked dllimport.",		     & DECL_SOURCE_LOCATION (node), 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;	}

⌨️ 快捷键说明

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