OSDN Git Service

* config.gcc: Add sh-*-symbianelf target.
authornickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Jul 2004 08:45:00 +0000 (08:45 +0000)
committernickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 12 Jul 2004 08:45:00 +0000 (08:45 +0000)
* config/sh/sh.c: Add new target macros:
  TARGET_ENCODE_SECTION_INFO, TARGET_STRIP_NAME_ENCODING,
  TARGET_CXX_IMPORT_EXPORT_CLASS.
  (sh_file_start): Create a definition of the .directive section.
  (sh_attribute): Add dllimport and dllexport attributes.
* config/sh/symbian-pre.h: New file.
* config/sh/symbian-post.h: New file.
* config/sh/symbian.c: New file. Contains Symbian specific functions.
* config/sh/sh-protos.h: Add prototypes for new functions provided by symbian.c.
* config/sh/t-symbian: New file.
* doc/extend.texi: Document support for dllimport and dllexport attributes by
  the sh-symbianelf target.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84551 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config.gcc
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/symbian-post.h [new file with mode: 0644]
gcc/config/sh/symbian-pre.h [new file with mode: 0644]
gcc/config/sh/symbian.c [new file with mode: 0644]
gcc/config/sh/t-symbian [new file with mode: 0644]
gcc/doc/extend.texi

index bc8fa23..26b4897 100644 (file)
@@ -1671,6 +1671,7 @@ s390x-ibm-tpf*)
        tmake_file="t-slibgcc-elf-ver s390/t-crtstuff s390/t-tpf"
        ;;
 sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
        tmake_file="t-slibgcc-elf-ver s390/t-crtstuff s390/t-tpf"
        ;;
 sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
+sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
   sh-*-linux* | sh[346lbe]*-*-linux* | \
   sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
    sh64-*-netbsd* | sh64l*-*-netbsd*)
   sh-*-linux* | sh[346lbe]*-*-linux* | \
   sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
    sh64-*-netbsd* | sh64l*-*-netbsd*)
@@ -1730,6 +1731,12 @@ sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
                tm_file="${tm_file} sh/sh64.h"
                extra_headers="shmedia.h ushmedia.h sshmedia.h"
                ;;
                tm_file="${tm_file} sh/sh64.h"
                extra_headers="shmedia.h ushmedia.h sshmedia.h"
                ;;
+       *-*-symbianelf*)
+               tmake_file="sh/t-symbian"
+               tm_file="sh/symbian-pre.h sh/little.h ${tm_file} sh/symbian-post.h"
+               extra_objs="symbian.o"
+               extra_parts="crt1.o crti.o crtn.o crtbegin.o crtend.o crtbeginS.o crtendS.o"
+               ;;      
        esac
        # sed el/eb endian suffixes away to avoid confusion with sh[23]e
        case `echo ${target} | sed 's/e[lb]-/-/'` in
        esac
        # sed el/eb endian suffixes away to avoid confusion with sh[23]e
        case `echo ${target} | sed 's/e[lb]-/-/'` in
index 05d694d..0d1733c 100644 (file)
@@ -143,3 +143,17 @@ extern const char *sh_pch_valid_p (const void *data_p, size_t sz);
 extern bool sh_promote_prototypes (tree);
 
 #endif /* ! GCC_SH_PROTOS_H */
 extern bool sh_promote_prototypes (tree);
 
 #endif /* ! GCC_SH_PROTOS_H */
+
+#ifdef SYMBIAN
+extern bool         sh_symbian_dllimport_name_p       (const char *);
+extern const char * sh_symbian_strip_name_encoding    (const char *);
+extern bool         sh_symbian_dllexport_name_p       (const char *);
+extern int          symbian_import_export_class       (tree, int);
+#ifdef TREE_CODE
+extern bool         sh_symbian_dllexport_p            (tree);
+extern tree         sh_symbian_handle_dll_attribute   (tree *, tree, tree, int, bool *);
+#ifdef RTX_CODE
+extern void         sh_symbian_encode_section_info    (tree, rtx, int);
+#endif
+#endif
+#endif /* SYMBIAN */
index 11882dd..dc16c61 100644 (file)
@@ -451,6 +451,17 @@ static tree sh_gimplify_va_arg_expr (tree, tree, tree *, tree *);
 /* Return current register pressure for regmode.  */
 #define CURR_REGMODE_PRESSURE(MODE)    curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
 
 /* Return current register pressure for regmode.  */
 #define CURR_REGMODE_PRESSURE(MODE)    curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
 
+#ifdef SYMBIAN
+
+#undef  TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO     sh_symbian_encode_section_info
+#undef  TARGET_STRIP_NAME_ENCODING
+#define TARGET_STRIP_NAME_ENCODING     sh_symbian_strip_name_encoding
+#undef  TARGET_CXX_IMPORT_EXPORT_CLASS
+#define TARGET_CXX_IMPORT_EXPORT_CLASS  symbian_import_export_class
+
+#endif /* SYMBIAN */
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Print the operand address in x to the stream.  */
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Print the operand address in x to the stream.  */
@@ -1431,6 +1442,12 @@ sh_file_start (void)
 {
   default_file_start ();
 
 {
   default_file_start ();
 
+#ifdef SYMBIAN
+  /* Declare the .directive section before it is used.  */
+  fputs ("\t.section .directive, \"SM\", @progbits, 1\n", asm_out_file);
+  fputs ("\t.asciz \"#<SYMEDIT>#\\n\"\n", asm_out_file);
+#endif
+  
   if (TARGET_ELF)
     /* We need to show the text section with the proper
        attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
   if (TARGET_ELF)
     /* We need to show the text section with the proper
        attributes as in TEXT_SECTION_ASM_OP, before dwarf2out
@@ -6950,6 +6967,17 @@ const struct attribute_spec sh_attribute_table[] =
   { "sp_switch",         1, 1, true,  false, false, sh_handle_sp_switch_attribute },
   { "trap_exit",         1, 1, true,  false, false, sh_handle_trap_exit_attribute },
   { "renesas",           0, 0, false, true, false, sh_handle_renesas_attribute },
   { "sp_switch",         1, 1, true,  false, false, sh_handle_sp_switch_attribute },
   { "trap_exit",         1, 1, true,  false, false, sh_handle_trap_exit_attribute },
   { "renesas",           0, 0, false, true, false, sh_handle_renesas_attribute },
+#ifdef SYMBIAN
+  /* Symbian support adds three 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.  */
+  { "dllimport",         0, 0, true,  false, false, sh_symbian_handle_dll_attribute },
+  { "dllexport",         0, 0, true,  false, false, sh_symbian_handle_dll_attribute },
+#endif
   { NULL,                0, 0, false, false, false, NULL }
 };
 
   { NULL,                0, 0, false, false, false, NULL }
 };
 
diff --git a/gcc/config/sh/symbian-post.h b/gcc/config/sh/symbian-post.h
new file mode 100644 (file)
index 0000000..b39262d
--- /dev/null
@@ -0,0 +1,89 @@
+/* Definitions for the Symbian OS running on an SH part.
+   This file is included after all the other target specific headers.
+
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.  */
+
+#undef  TARGET_VERSION
+#define TARGET_VERSION \
+  fputs (" (Renesas SH for Symbian OS)", stderr);
+
+#undef  LINK_EMUL_PREFIX
+#define LINK_EMUL_PREFIX "shlsymbian"
+
+
+#define SYMBIAN_EXPORT_NAME(NAME,FILE,DECL)                    \
+  do                                                           \
+    {                                                          \
+      if ((DECL && sh_symbian_dllexport_p (DECL))              \
+         || sh_symbian_dllexport_name_p (NAME))                        \
+        {                                                      \
+          fprintf ((FILE), "\t.pushsection .directive\n");     \
+          fprintf ((FILE), "\t.asciz \"EXPORT %s\\n\"\n",      \
+                  sh_symbian_strip_name_encoding (NAME));      \
+          fprintf ((FILE), "\t.popsection\n");                 \
+       }                                                       \
+    }                                                          \
+  while (0)
+
+/* Output a function definition label.  */
+#undef  ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)            \
+  do                                                           \
+    {                                                          \
+      SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL));            \
+      ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "function");  \
+      ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL));         \
+      ASM_OUTPUT_LABEL ((FILE), (NAME));                       \
+    }                                                          \
+  while (0)
+
+/* Output the label for an initialized variable.  */
+#undef  ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL)              \
+  do                                                           \
+    {                                                          \
+      HOST_WIDE_INT size;                                      \
+                                                               \
+      SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL));            \
+      ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "object");    \
+                                                               \
+      size_directive_output = 0;                               \
+      if (!flag_inhibit_size_directive                         \
+         && (DECL)                                             \
+          && DECL_SIZE (DECL))                                 \
+       {                                                       \
+         size_directive_output = 1;                            \
+         size = int_size_in_bytes (TREE_TYPE (DECL));          \
+         ASM_OUTPUT_SIZE_DIRECTIVE ((FILE), (NAME), size);     \
+       }                                                       \
+                                                               \
+      ASM_OUTPUT_LABEL ((FILE), (NAME));                       \
+    }                                                          \
+  while (0)
+
+#undef  ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE, NAME)                                \
+  do                                                           \
+    {                                                          \
+      asm_fprintf ((FILE), "%U%s",                             \
+                  sh_symbian_strip_name_encoding (NAME));      \
+    }                                                          \
+  while (0)
diff --git a/gcc/config/sh/symbian-pre.h b/gcc/config/sh/symbian-pre.h
new file mode 100644 (file)
index 0000000..aa23535
--- /dev/null
@@ -0,0 +1,48 @@
+/* Definitions for the Symbian OS running on an SH part.
+   This file is included before any other target specific headers.
+
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   Contributed by Red Hat.
+
+   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.  */
+
+/* Enable Symbian specific code.  */
+#define SYMBIAN                1
+
+/* Default to using the Renesas ABI.  */
+#define TARGET_ABI_DEFAULT     RENESAS_BIT
+
+/* Support the __declspec keyword by turning them into attributes.
+   We currently only support: naked, dllimport, and dllexport.
+   Note that the current way we do this may result in a collision with
+   predefined attributes later on.  This can be solved by using one attribute,
+   say __declspec__, and passing args to it.  The problem with that approach
+   is that args are not accumulated: each new appearance would clobber any
+   existing args.  */
+#define SUBTARGET_CPP_SPEC "-D__declspec(x)=__attribute__((x))"
+
+/* Get tree.c to declare merge_dllimport_decl_attributes().  */
+#define TARGET_DLLIMPORT_DECL_ATTRIBUTES
+
+/* The Symbian OS currently does not support exception handling.  */
+#define SUBTARGET_CC1PLUS_SPEC "-fno-exceptions"
+
+/* Create constructor/destructor sections without the writable flag.
+   Symbian puts them into the text segment and munges them later on.  */
+#define CTORS_SECTION_ASM_OP   "\t.section\t.ctors,\"ax\",@progbits"
+#define DTORS_SECTION_ASM_OP   "\t.section\t.dtors,\"ax\",@progbits"
diff --git a/gcc/config/sh/symbian.c b/gcc/config/sh/symbian.c
new file mode 100644 (file)
index 0000000..33ab711
--- /dev/null
@@ -0,0 +1,906 @@
+/* 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."
+
+\f
+/* Return the type that we should use to determine if DECL is
+   imported or exported.  */
+
+static tree
+sh_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.  */
+
+bool
+sh_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 bool
+sh_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.  */
+
+bool
+sh_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.  */
+
+
+bool
+sh_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 (eg: dllimport).  */
+
+static void
+sh_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 defintion to be marked as dllexport.  The prototypes
+       are in headers used everywhere and the defintion 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 void
+sh_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 ("`%s' 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;
+    }
+}
+
+void
+sh_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 int
+sh_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 void
+symbian_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.  */
+
+tree
+sh_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 ("`%s' 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 ("`%s' 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 `%D' 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;
+       }
+    }
+
+  /* If the node is an overloaded constructor or desctructor, then we must
+     make sure that the attribute is propogated along the overload chain,
+     as it is these overloaded functions which will be emitted, rather than
+     the user declared constructor itself.  */
+  if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE
+      && (DECL_CONSTRUCTOR_P (node) || DECL_DESTRUCTOR_P (node)))
+    {
+      tree overload;
+
+      for (overload = OVL_CHAIN (node); overload; overload = OVL_CHAIN (overload))
+       {
+         tree node_args;
+         tree func_args;
+         tree function = OVL_CURRENT (overload);
+
+         if (! function
+             || ! DECL_P (function)
+             || (DECL_CONSTRUCTOR_P (node) && ! DECL_CONSTRUCTOR_P (function))
+             || (DECL_DESTRUCTOR_P (node)  && ! DECL_DESTRUCTOR_P (function)))
+           continue;
+
+         /* The arguments must match as well.  */
+         for (node_args = DECL_ARGUMENTS (node), func_args = DECL_ARGUMENTS (function);
+              node_args && func_args;
+              node_args = TREE_CHAIN (node_args), func_args = TREE_CHAIN (func_args))
+           if (TREE_TYPE (node_args) != TREE_TYPE (func_args))
+             break;
+
+         if (node_args || func_args)
+           {
+             /* We can ignore an extraneous __in_chrg arguments in the node.
+                GCC generated destructors, for example, will have this.  */
+             if ((node_args == NULL_TREE
+                  || func_args != NULL_TREE)
+                 && strcmp (IDENTIFIER_POINTER (DECL_NAME (node)), "__in_chrg") != 0)
+               continue;
+           }
+
+         symbian_add_attribute (function, attr);
+
+         /* Propogate the attribute to any function thunks as well.  */
+         for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
+           if (TREE_CODE (thunk) == FUNCTION_DECL)
+             symbian_add_attribute (thunk, attr);
+       }
+    }
+
+  if (TREE_CODE (node) == FUNCTION_DECL && DECL_VIRTUAL_P (node))
+    {
+      /* Propogate the attribute to any thunks of this function.  */
+      for (thunk = DECL_THUNKS (node); thunk; thunk = TREE_CHAIN (thunk))
+       if (TREE_CODE (thunk) == FUNCTION_DECL)
+         symbian_add_attribute (thunk, attr);
+    }
+
+  /*  Report error if symbol is not accessible at global scope.  */
+  if (!TREE_PUBLIC (node)
+      && (   TREE_CODE (node) == VAR_DECL
+         || TREE_CODE (node) == FUNCTION_DECL))
+    {
+      error ("%Hexternal linkage required for symbol '%D' because of '%s' attribute.",
+              & DECL_SOURCE_LOCATION (node), node, IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+#if SYMBIAN_DEBUG
+  print_node_brief (stderr, "mark node", node, 0);
+  fprintf (stderr, " as %s\n", attr);
+#endif
+
+  return NULL_TREE;
+}
+
+/* This code implements a specification for exporting the vtable and rtti of
+   classes that have members with the dllexport or dllexport attributes.
+   This specification is defined here:
+
+     http://www.armdevzone.com/EABI/exported_class.txt
+
+   Basically it says that a class's vtable and rtti should be exported if
+   the following rules apply:
+
+   - If it has any non-inline non-pure virtual functions,
+     at least one of these need to be declared dllimport
+     OR any of the constructors is declared dllimport.
+
+   AND
+
+   - The class has an inline constructor/destructor and
+     a key-function (placement of vtable uniquely defined) that
+     is defined in this translation unit.
+
+   The specification also says that for classes which will have their
+   vtables and rtti exported that their base class(es) might also need a
+   similar exporting if:
+
+   - Every base class needs to have its vtable & rtti exported
+     as well, if the following the conditions hold true:
+     + The base class has a non-inline declared non-pure virtual function
+     + The base class is polymorphic (has or inherits any virtual functions)
+       or the base class has any virtual base classes.  */
+\f
+/* Decide if a base class of a class should
+   also have its vtable and rtti exported.  */
+
+static void
+symbian_possibly_export_base_class (tree base_class)
+{
+  tree methods;
+  int len;
+
+  if (! (TYPE_POLYMORPHIC_P (base_class)
+        || TYPE_USES_VIRTUAL_BASECLASSES (base_class)))
+    return;
+
+  methods = CLASSTYPE_METHOD_VEC (base_class);
+  len = methods ? TREE_VEC_LENGTH (methods) : 0;
+
+  for (;len --;)
+    {
+      tree member = TREE_VEC_ELT (methods, len);
+
+      if (! member)
+       continue;
+
+      for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
+       {
+         if (TREE_CODE (member) != FUNCTION_DECL)
+           continue;
+
+         if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
+           continue;
+
+         if (! DECL_VIRTUAL_P (member))
+           continue;
+
+         if (DECL_PURE_VIRTUAL_P (member))
+           continue;
+
+         if (DECL_INLINE (member))
+           continue;
+
+         break;
+       }
+
+      if (member)
+       break;
+    }
+
+  if (len < 0)
+    return;
+
+  /* FIXME: According to the spec this base class should be exported, but
+     a) how do we do this ? and
+     b) it does not appear to be necessary for compliance with the Symbian
+        OS which so far is the only consumer of this code.  */
+#if SYMBIAN_DEBUG
+  print_node_brief (stderr, "", base_class, 0);
+  fprintf (stderr, " EXPORTed [base class of exported class]\n");
+#endif
+}
+
+/* Decide if a class needs its vtable and rtti exporting.  */
+
+static bool
+symbian_export_vtable_and_rtti_p (tree ctype)
+{
+  bool inline_ctor_dtor;
+  bool dllimport_ctor_dtor;
+  bool dllimport_member;
+  tree binfos;
+  tree methods;
+  tree key;
+  int len;
+
+  /* Make sure that we are examining a class...  */
+  if (TREE_CODE (ctype) != RECORD_TYPE)
+    {
+#if SYMBIAN_DEBUG
+      print_node_brief (stderr, "", ctype, 0);
+      fprintf (stderr, " does NOT need to be EXPORTed [not a class]\n");
+#endif
+      return false;
+    }
+
+  /* If the class does not have a key function it
+     does not need to have its vtable exported.  */
+  if ((key = CLASSTYPE_KEY_METHOD (ctype)) == NULL_TREE)
+    {
+#if SYMBIAN_DEBUG
+      print_node_brief (stderr, "", ctype, 0);
+      fprintf (stderr, " does NOT need to be EXPORTed [no key function]\n");
+#endif
+      return false;
+    }
+
+  /* If the key fn has not been defined
+     then the class should not be exported.  */
+  if (! TREE_ASM_WRITTEN (key))
+    {
+#if SYMBIAN_DEBUG
+      print_node_brief (stderr, "", ctype, 0);
+      fprintf (stderr, " does NOT need to be EXPORTed [key function not defined]\n");
+#endif
+      return false;
+    }
+
+  /* Check the class's member functions.  */
+  inline_ctor_dtor = false;
+  dllimport_ctor_dtor = false;
+  dllimport_member = false;
+
+  methods = CLASSTYPE_METHOD_VEC (ctype);
+  len = methods ? TREE_VEC_LENGTH (methods) : 0;
+
+  for (;len --;)
+    {
+      tree member = TREE_VEC_ELT (methods, len);
+
+      if (! member)
+       continue;
+
+      for (member = OVL_CURRENT (member); member; member = OVL_NEXT (member))
+       {
+         if (TREE_CODE (member) != FUNCTION_DECL)
+           continue;
+
+         if (DECL_CONSTRUCTOR_P (member) || DECL_DESTRUCTOR_P (member))
+           {
+             if (DECL_INLINE (member)
+                 /* Ignore C++ backend created inline ctors/dtors.  */
+                 && (   DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (member)
+                     || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (member)))
+               inline_ctor_dtor = true;
+
+             if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
+               dllimport_ctor_dtor = true;
+           }
+         else
+           {
+             if (DECL_PURE_VIRTUAL_P (member))
+               continue;
+
+             if (! DECL_VIRTUAL_P (member))
+               continue;
+
+             if (DECL_INLINE (member))
+               continue;
+
+             if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (member)))
+               dllimport_member = true;
+           }
+       }
+    }
+
+  if (! dllimport_member && ! dllimport_ctor_dtor)
+    {
+#if SYMBIAN_DEBUG
+      print_node_brief (stderr, "", ctype, 0);
+      fprintf (stderr,
+              " does NOT need to be EXPORTed [no non-pure virtuals or ctors/dtors with dllimport]\n");
+#endif
+      return false;
+    }
+
+  if (! inline_ctor_dtor)
+    {
+#if SYMBIAN_DEBUG
+      print_node_brief (stderr, "", ctype, 0);
+      fprintf (stderr,
+              " does NOT need to be EXPORTed [no inline ctor/dtor]\n");
+#endif
+      return false;
+    }
+
+#if SYMBIAN_DEBUG
+  print_node_brief (stderr, "", ctype, 0);
+  fprintf (stderr, " DOES need to be EXPORTed\n");
+#endif
+
+  /* Now we must check and possibly export the base classes.  */
+  binfos = BINFO_BASE_BINFOS (TYPE_BINFO (ctype));
+  len = BINFO_N_BASE_BINFOS (TYPE_BINFO (ctype));
+
+  for (; len --;)
+    {
+      tree base_binfo;
+      tree basetype;
+
+      /* Figure out which base we're looking at.  */
+      base_binfo = TREE_VEC_ELT (binfos, len);
+      basetype = TREE_TYPE (base_binfo);
+
+      symbian_possibly_export_base_class (basetype);
+    }
+
+  return true;
+}
+
+/* Add the named attribute to a class and its vtable and rtti.  */
+
+static void
+symbian_add_attribute_to_class_vtable_and_rtti (tree ctype, const char *attr_name)
+{
+  symbian_add_attribute (ctype, attr_name);
+
+  /* If the vtable exists then they need annotating as well.  */
+  if (CLASSTYPE_VTABLES (ctype))
+    /* XXX - Do we need to annotate any vtables other than the primary ?  */
+    symbian_add_attribute (CLASSTYPE_VTABLES (ctype), attr_name);
+
+  /* If the rtti exists then it needs annotating as well.  */
+  if (TYPE_MAIN_VARIANT (ctype)
+      && CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))
+    symbian_add_attribute (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)),
+                          attr_name);
+}
+
+/* Decide if a class needs to have an attribute because
+   one of its member functions has the attribute.  */
+
+static bool
+symbian_class_needs_attribute_p (tree ctype, const char *attribute_name)
+{
+  /* If the key function has the attribute then the class needs it too.  */
+  if (TYPE_POLYMORPHIC_P (ctype)
+      && CLASSTYPE_KEY_METHOD (ctype)
+      && lookup_attribute (attribute_name,
+                          DECL_ATTRIBUTES (CLASSTYPE_KEY_METHOD (ctype))))
+    return true;
+
+  /* Check the class's member functions.  */
+  if (TREE_CODE (ctype) == RECORD_TYPE)
+    {
+      tree methods = CLASSTYPE_METHOD_VEC (ctype);
+      unsigned int len = methods ? TREE_VEC_LENGTH (methods) : 0;
+
+      for (;len --;)
+       {
+         tree member = TREE_VEC_ELT (methods, len);
+
+         if (! member)
+           continue;
+
+         for (member = OVL_CURRENT (member);
+              member;
+              member = OVL_NEXT (member))
+           {
+             if (TREE_CODE (member) != FUNCTION_DECL)
+               continue;
+
+             if (DECL_PURE_VIRTUAL_P (member))
+               continue;
+
+             if (! DECL_VIRTUAL_P (member))
+               continue;
+
+             if (lookup_attribute (attribute_name, DECL_ATTRIBUTES (member)))
+               {
+#if SYMBIAN_DEBUG
+                 print_node_brief (stderr, "", ctype, 0);
+                 fprintf (stderr, " inherits %s because", attribute_name);
+                 print_node_brief (stderr, "", member, 0);
+                 fprintf (stderr, " has it.\n");
+#endif
+                 return true;
+               }
+           }
+       }
+    }
+
+#if SYMBIAN_DEBUG
+  print_node_brief (stderr, "", ctype, 0);
+  fprintf (stderr, " does not inherit %s\n", attribute_name);
+#endif
+  return false;
+}
+
+int
+symbian_import_export_class (tree ctype, int import_export)
+{
+  const char *attr_name = NULL;
+
+  /* If we are exporting the class but it does not have the dllexport
+     attribute then we may need to add it.  Similarly imported classes
+     may need the dllimport attribute.  */
+  switch (import_export)
+    {
+    case  1: attr_name = "dllexport"; break;
+    case -1: attr_name = "dllimport"; break;
+    default: break;
+    }
+
+  if (attr_name
+      && ! lookup_attribute (attr_name, TYPE_ATTRIBUTES (ctype)))
+    {
+      if (symbian_class_needs_attribute_p (ctype, attr_name))
+       symbian_add_attribute_to_class_vtable_and_rtti (ctype, attr_name);
+
+      /* Classes can be forced to export their
+        vtable and rtti under certain conditions.  */
+      if (symbian_export_vtable_and_rtti_p (ctype))
+       {
+         symbian_add_attribute_to_class_vtable_and_rtti (ctype, "dllexport");
+
+         /* Make sure that the class and its vtable are exported.  */
+         import_export = 1;
+
+         if (CLASSTYPE_VTABLES (ctype))
+           DECL_EXTERNAL (CLASSTYPE_VTABLES (ctype)) = 1;
+
+         /* Check to make sure that if the class has a key method that
+            it is now on the list of keyed classes.  That way its vtable
+            will be emitted.  */
+         if (CLASSTYPE_KEY_METHOD (ctype))
+           {
+             tree class;
+
+             for (class = keyed_classes; class; class = TREE_CHAIN (class))
+               if (class == ctype)
+                 break;
+
+             if (class == NULL_TREE)
+               {
+#if SYMBIAN_DEBUG
+                 print_node_brief (stderr, "Add node", ctype, 0);
+                 fprintf (stderr, " to the keyed classes list\n");
+#endif
+                 keyed_classes = tree_cons (NULL_TREE, ctype, keyed_classes);
+               }
+           }
+
+         /* Make sure that the typeinfo will be emitted as well.  */
+         if (CLASS_TYPE_P (ctype))
+           TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (CLASSTYPE_TYPEINFO_VAR (TYPE_MAIN_VARIANT (ctype)))) = 1;
+       }
+    }
+
+  return import_export;
+}
+
+/* Dummy defintion of this array for cc1 building purposes.  */
+tree cp_global_trees[CPTI_MAX] __attribute__((weak));
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Dummy version of this G++ function for building cc1.  */
+void lang_check_failed (const char *, int, const char *) __attribute__((weak));
+
+void
+lang_check_failed (const char *file, int line, const char *function)
+{
+  internal_error ("lang_* check: failed in %s, at %s:%d",
+                 function, trim_filename (file), line);
+}
+#endif /* ENABLE_TREE_CHECKING */
diff --git a/gcc/config/sh/t-symbian b/gcc/config/sh/t-symbian
new file mode 100644 (file)
index 0000000..494029f
--- /dev/null
@@ -0,0 +1,35 @@
+LIB1ASMSRC = sh/lib1funcs.asm
+LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
+  _movstr_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
+  $(LIB1ASMFUNCS_CACHE)
+
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+       echo '#define FLOAT' > fp-bit.c
+       cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
+       $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
+$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
+       $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
+$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
+       $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
+
+$(out_object_file): gt-sh.h
+gt-sh.h : s-gtype ; @true
+
+symbian.o: $(srcdir)/config/sh/symbian.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+  $(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
+       $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/symbian.c
+
+
+# Local Variables:
+# mode: Makefile
+# End:
index 4f9b9d9..1df0221 100644 (file)
@@ -2009,10 +2009,11 @@ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
 
 @item dllexport
 @cindex @code{__declspec(dllexport)}
 
 @item dllexport
 @cindex @code{__declspec(dllexport)}
-On Microsoft Windows targets the @code{dllexport} attribute causes the
-compiler to provide a global pointer to a pointer in a dll, so that it
-can be referenced with the @code{dllimport} attribute. The pointer name
-is formed by combining @code{_imp__} and the function or variable name.
+On Microsoft Windows targets and Symbian targets the @code{dllexport}
+attribute causes the compiler to provide a global pointer to a pointer
+in a dll, so that it can be referenced with the @code{dllimport}
+attribute. The pointer name is formed by combining @code{_imp__} and
+the function or variable name.
 
 Currently, the @code{dllexport}attribute is ignored for inlined
 functions, but export can be forced by using the
 
 Currently, the @code{dllexport}attribute is ignored for inlined
 functions, but export can be forced by using the
@@ -2024,21 +2025,24 @@ member functions and static data members as exports. Static consts
 initialized in-class are not marked unless they are also defined
 out-of-class.
 
 initialized in-class are not marked unless they are also defined
 out-of-class.
 
-On cygwin, mingw and arm-pe targets, @code{__declspec(dllexport)} is
-recognized as a synonym for @code{__attribute__ ((dllexport))} for
-compatibility with other Microsoft Windows compilers.
+On cygwin, mingw, arm-pe and sh-symbianelf targets,
+@code{__declspec(dllexport)} is recognized as a synonym for
+@code{__attribute__ ((dllexport))} for compatibility with other
+Microsoft Windows and Symbian compilers. 
 
 
-Alternative methods for including the symbol in the dll's export table
-are to use a .def file with an @code{EXPORTS} section or, with GNU ld,
-using the @option{--export-all} linker flag.
+For Microsoft Windows targets there are alternative methods for
+including the symbol in the dll's export table such as using a
+@file{.def} file with an @code{EXPORTS} section or, with GNU ld, using
+the @option{--export-all} linker flag.
 
 @item dllimport
 @cindex @code{__declspec(dllimport)}
 
 @item dllimport
 @cindex @code{__declspec(dllimport)}
-On Microsoft Windows targets, the @code{dllimport} attribute causes the
-compiler to reference a function or variable via a global pointer to a
-pointer that is set up by the Microsoft Windows dll library. The pointer
-name is formed by combining @code{_imp__} and the function or variable
-name. The attribute implies @code{extern} storage.
+On Microsoft Windows and Symbian targets, the @code{dllimport}
+attribute causes the compiler to reference a function or variable via
+a global pointer to a pointer that is set up by the Microsoft Windows
+dll library. The pointer name is formed by combining @code{_imp__} and
+the function or variable name. The attribute implies @code{extern}
+storage.
 
 Currently, the attribute is ignored for inlined functions. If the
 attribute is applied to a symbol @emph{definition}, an error is reported.
 
 Currently, the attribute is ignored for inlined functions. If the
 attribute is applied to a symbol @emph{definition}, an error is reported.
@@ -2052,15 +2056,25 @@ member functions and static data members as imports.  However, the
 attribute is ignored for virtual methods to allow creation of vtables
 using thunks.
 
 attribute is ignored for virtual methods to allow creation of vtables
 using thunks.
 
-On cygwin, mingw and arm-pe targets, @code{__declspec(dllimport)} is
-recognized as a synonym for @code{__attribute__ ((dllimport))} for
-compatibility with other Microsoft Windows compilers.
+For Symbian targets the @code{dllimport} attribute also has another
+affect - it can cause the vtable and run-time type information for a
+class to be exported.  This happens when the class has a dllimport'ed
+constructor or a non-inline, non-pure virtual function and, for either
+of those two conditions, the class also has a inline constructor or
+destructor and has a key function that is defined in the current
+translation unit.
 
 
-The use of the @code{dllimport} attribute on functions is not necessary,
-but provides a small performance benefit by eliminating a thunk in the
-dll. The use of the @code{dllimport} attribute on imported variables was
-required on older versions of GNU ld, but can now be avoided by passing
-the @option{--enable-auto-import} switch to ld. As with functions, using
+On cygwin, mingw, arm-pe sh-symbianelf targets,
+@code{__declspec(dllimport)} is recognized as a synonym for
+@code{__attribute__ ((dllimport))} for compatibility with other
+Microsoft Windows and Symbian compilers. 
+
+For Microsoft Windows based targets the use of the @code{dllimport}
+attribute on functions is not necessary, but provides a small
+performance benefit by eliminating a thunk in the dll. The use of the
+@code{dllimport} attribute on imported variables was required on older
+versions of GNU ld, but can now be avoided by passing the
+@option{--enable-auto-import} switch to ld. As with functions, using
 the attribute for a variable eliminates a thunk in the dll.
 
 One drawback to using this attribute is that a pointer to a function or
 the attribute for a variable eliminates a thunk in the dll.
 
 One drawback to using this attribute is that a pointer to a function or