public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* RFA: Add SH Symbian port
@ 2004-07-06 15:26 Nick Clifton
  2004-07-07  3:27 ` Joern Rennecke
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Clifton @ 2004-07-06 15:26 UTC (permalink / raw)
  To: amylaar, aoliva; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1799 bytes --]

Hi Joern, Hi Alex,

  Please could I have approval to apply the patch below.  It adds
  support for an SH port targeted at the Symbian OS.  This work was
  done by Red Hat under contract to Symbian and Renesas and they would
  now like the code contributed.

  The patch makes use of the recently accepted patch to add an
  import_export_class field to the gcc_target structure and it also
  needs a binutils patch which I will be submitting shortly.  All of
  the changes to the normal parts of the SH backend are protected by
  the definition of a macro called SYMBIAN.

Cheers
  Nick

gcc/ChangeLog
2004-07-06  Nick Clifton  <nickc@redhat.com>

	* config.gcc: Add *-symbian-elf support to the general SH
	target.
        * config/sh/sh.c: Add gcc_target structure initialisers for
	use by the sh-symbian-elf target.
        (print_operand): Add support for the naked attribute.
        (sh_expand_prologue): Likewise.
        (sh_expand_epilogue): Likewise.
        (sh_need_epilogue): Likewise.
        (sh_attribute): Add naked, dllimport and dllexport
	attributes.
        (sh_file_start): Create a .directive section.
        (sh_reorg): Call sh_symbian_reorg.
        * config/sh/symbian-post.h: New header file.  Contains
	definitions of macros that override definitions provided in
	earlier headers.
        * config/sh/symbian-pre.h: New header file.  Define SYMBIAN
	and other macros necessary to set up the Symbian environment.
        * config/sh/t-symbian: New makefile fragment.  Define the
	build rules for the support files used by the Symbian target.
        * config/sh/symbian.c: New source file.  Contains all of the
	SH backend functions necessary to support the sh-symbian-elf
	target.
        * config/sh/sh-protos.h: Add prototypes for the functions
	defined in symbian.c


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Add Symbian OS targeted SH port to GCC --]
[-- Type: text/x-patch, Size: 44485 bytes --]

Index: config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.464
diff -c -3 -p -r1.464 config.gcc
*** config.gcc	5 Jul 2004 19:49:10 -0000	1.464
--- config.gcc	6 Jul 2004 15:04:42 -0000
*************** sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-k
*** 1730,1735 ****
--- 1730,1741 ----
  		tm_file="${tm_file} sh/sh64.h"
  		extra_headers="shmedia.h ushmedia.h sshmedia.h"
  		;;
+ 	*-symbian-elf)
+ 		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
Index: config/sh/sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.55
diff -c -3 -p -r1.55 sh-protos.h
*** config/sh/sh-protos.h	10 May 2004 23:25:13 -0000	1.55
--- config/sh/sh-protos.h	6 Jul 2004 15:04:42 -0000
*************** extern const char *sh_pch_valid_p (const
*** 144,146 ****
--- 144,163 ----
  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 void         sh_symbian_reorg                  (void);
+ extern int          symbian_import_export_class       (tree, int);
+ #ifdef TREE_CODE
+ extern bool         sh_symbian_dllexport_p            (tree);
+ extern bool         sh_symbian_naked_function_p       (tree);
+ extern tree         sh_symbian_handle_naked_attribute (tree *, tree, tree, int, bool *);
+ 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: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.275
diff -c -3 -p -r1.275 sh.c
*** config/sh/sh.c	3 Jul 2004 11:56:43 -0000	1.275
--- config/sh/sh.c	6 Jul 2004 15:04:52 -0000
*************** static tree sh_build_builtin_va_list (vo
*** 446,451 ****
--- 446,462 ----
  /* 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.  */
*************** print_operand_address (FILE *stream, rtx
*** 526,531 ****
--- 537,546 ----
  void
  print_operand (FILE *stream, rtx x, int code)
  {
+ #ifdef SYMBIAN
+   static int skip_nop = 0;
+ #endif
+ 
    switch (code)
      {
      case '.':
*************** print_operand (FILE *stream, rtx x, int 
*** 542,551 ****
--- 557,577 ----
  	fprintf (stream, "trapa #%d", trap_exit);
        else if (sh_cfun_interrupt_handler_p ())
  	fprintf (stream, "rte");
+ #ifdef SYMBIAN
+       else if (sh_symbian_naked_function_p (current_function_decl))
+ 	/* We know that a %# is about to come,
+ 	   and we do not want it to emit an nop.  */
+ 	skip_nop = 1;
+ #endif
        else
  	fprintf (stream, "rts");
        break;
      case '#':
+ #ifdef SYMBIAN
+       if (skip_nop)
+ 	skip_nop = 0;
+       else
+ #endif
        /* Output a nop if there's nothing in the delay slot.  */
        if (dbr_sequence_length () == 0)
  	fprintf (stream, "\n\tnop");
*************** sh_file_start (void)
*** 1426,1431 ****
--- 1452,1463 ----
  {
    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
*************** sh_reorg (void)
*** 3902,3907 ****
--- 3934,3943 ----
    rtx r0_rtx = gen_rtx_REG (Pmode, 0);
    rtx r0_inc_rtx = gen_rtx_POST_INC (Pmode, r0_rtx);
  
+ #ifdef SYMBIAN
+   sh_symbian_reorg ();
+ #endif
+ 
    first = get_insns ();
  
    /* We must split call insns before introducing `mova's.  If we're
*************** sh_expand_prologue (void)
*** 5321,5326 ****
--- 5357,5367 ----
    int save_flags = target_flags;
    int pretend_args;
  
+ #ifdef SYMBIAN
+   if (sh_symbian_naked_function_p (current_function_decl))
+     return;
+ #endif
+ 
    current_function_interrupt = sh_cfun_interrupt_handler_p ();
  
    /* We have pretend args if we had an object sent partially in registers
*************** sh_expand_epilogue (bool sibcall_p)
*** 5684,5689 ****
--- 5725,5735 ----
    int fpscr_deferred = 0;
    int e = sibcall_p ? -1 : 1;
  
+ #ifdef SYMBIAN
+   if (sh_symbian_naked_function_p (current_function_decl))
+     return;
+ #endif
+ 
    d = calc_live_regs (&live_regs_mask);
  
    save_size = d;
*************** static int sh_need_epilogue_known = 0;
*** 5929,5934 ****
--- 5975,5985 ----
  int
  sh_need_epilogue (void)
  {
+ #ifdef SYMBIAN
+   if (sh_symbian_naked_function_p (current_function_decl))
+     return sh_need_epilogue_known = 0;
+ #endif
+ 
    if (! sh_need_epilogue_known)
      {
        rtx epilogue;
*************** const struct attribute_spec sh_attribute
*** 6965,6970 ****
--- 7016,7034 ----
    { "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
+      naked     - functions without a prologue or epilogue.
+      
+      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 },
+   { "naked",             0, 0, true,  false, false, sh_symbian_handle_naked_attribute },
+ #endif
    { NULL,                0, 0, false, false, false, NULL }
  };
  
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- config/sh/symbian-post.h	2004-07-06 12:46:35.000000000 +0100
***************
*** 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)
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- config/sh/symbian-pre.h	2004-07-02 13:00:33.000000000 +0100
***************
*** 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"
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- config/sh/t-symbian	2004-07-02 12:40:10.000000000 +0100
***************
*** 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:
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- config/sh/symbian.c	2004-07-06 13:19:42.000000000 +0100
***************
*** 0 ****
--- 1,963 ----
+ /* 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
+ 
+ extern int current_function_anonymous_args;
+ 
+ /* 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;
+ }
+ 
+ /* Return nonzero if FUNC is a naked function.  */
+ 
+ bool
+ sh_symbian_naked_function_p (tree func)
+ {
+   tree a;
+ 
+   if (TREE_CODE (func) != FUNCTION_DECL)
+     abort ();
+ 
+   a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
+   return a != NULL_TREE;
+ }
+ 
+ /* This is part of a nasty hack to suppress the generation of
+    "control reaches end of non-void function" warning messages
+    (eg when ebaled by with -Wall) for naked functions.  */
+ 
+ static int saved_warn_return_type = 0;
+ static int warn_return_type_saved = 0;
+ 
+ /* Handle the naked attribute - make sure that
+    it is only applied to a function decl.  */
+ 
+ tree
+ sh_symbian_handle_naked_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+ 				   int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ {
+   if (TREE_CODE (*node) != FUNCTION_DECL)
+     {
+       warning ("`%s' attribute only applies to functions",
+ 	       IDENTIFIER_POINTER (name));
+       *no_add_attrs = true;
+     }
+ 
+   if (! warn_return_type_saved)
+     {
+       saved_warn_return_type = warn_return_type;
+       warn_return_type = 0;
+       warn_return_type_saved = 1;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ void
+ sh_symbian_reorg (void)
+ {
+   if (warn_return_type_saved)
+     {
+       warn_return_type = saved_warn_return_type;
+       warn_return_type_saved = 0;
+     }
+ }
+ 
+ /* 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 = TYPE_BINFO_BASETYPES (ctype);
+   len = CLASSTYPE_N_BASECLASSES (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 */

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFA: Add SH Symbian port
  2004-07-06 15:26 RFA: Add SH Symbian port Nick Clifton
@ 2004-07-07  3:27 ` Joern Rennecke
  2004-07-07  8:26   ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Joern Rennecke @ 2004-07-07  3:27 UTC (permalink / raw)
  To: Nick Clifton; +Cc: amylaar, aoliva, gcc-patches

What for would you want to use a naked function?
How does this attribute interact with inlinning, sibcall optimizations,
c++ thunking, instrumentation, and nested functions?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFA: Add SH Symbian port
  2004-07-07  3:27 ` Joern Rennecke
@ 2004-07-07  8:26   ` Nick Clifton
  2004-07-07 14:52     ` Joern Rennecke
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Clifton @ 2004-07-07  8:26 UTC (permalink / raw)
  To: Joern Rennecke; +Cc: amylaar, aoliva, gcc-patches

Hi Joern,

> What for would you want to use a naked function?

Personally I wouldn't want to use one, but the Symbian OS uses them for 
various different things, including device drivers and interrupt handlers.

> How does this attribute interact with inlinning, sibcall optimizations,
> c++ thunking, instrumentation, and nested functions?

It interacts badly with inlining, sibcalls and nesting.  Or at least I 
assume that it will, it has not been tested with these optimisations. 
Symbian explicitly disable all optimisations when compiling a naked 
function.

It should not affect instrumentation which can still occur during the 
function's prologue, it is just that there will be no compiler-generated 
  function setup.  The instrumentation code will have to rely upon the 
assembly code provided by the programmer writing the naked function to 
correctly setup the prologue.

I have no idea about C++ thunking.  To date I have only seen naked 
attributes applied to C code.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFA: Add SH Symbian port
  2004-07-07  8:26   ` Nick Clifton
@ 2004-07-07 14:52     ` Joern Rennecke
  2004-07-09 14:31       ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Joern Rennecke @ 2004-07-07 14:52 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Joern Rennecke, amylaar, aoliva, gcc-patches

> > What for would you want to use a naked function?
> 
> Personally I wouldn't want to use one, but the Symbian OS uses them for 
> various different things, including device drivers and interrupt handlers.

We already have the interrupt, trapa and sp_switch attributes for interrupt
functions.  I know we have some issues with the use of static variables,
but you are welcome to submit patches to fix them.

> > How does this attribute interact with inlinning, sibcall optimizations,
> > c++ thunking, instrumentation, and nested functions?
> 
> It interacts badly with inlining, sibcalls and nesting.  Or at least I 
> assume that it will, it has not been tested with these optimisations. 
> Symbian explicitly disable all optimisations when compiling a naked 
> function.

As I'm sure you are aware, that is not actually possible anymore - we
do some minimal optimization all the time.  There might be more such
changes in the future.

That they try to disable optimizations to make this work is just one
more indication that this attribute is ill-conceived.
Prologues and epilogues are an implementation detail of gcc.  What goes into
them, or not, can change from time to time.
Gcc extensions should have a defined meaning in terms of the semantics of
the program.  The naked function attribute does not have any such meaning,
instead it changes the internals of the compiler, getting you completely
undefined results.
Please define the attributes that ou need in terms of semantics of
the program.

Let's look at what your patch would do to the code generation with a
current snapshot:

- Variadic function handling is suppressed.  That is just daft.  If the
  function is declared variadic, it should better work.  If the attribute
  is incompatible with a particular function signature so that you can't
  emit valid code, generate an error.
- Register saving and restoring is omitted, except that FPSCR is set back
  to the normal mode if you don't also use the interrupt attribute.
  Changing the set of registers that are saved is OK, but you should look
  closely at what you want to do with FPSCR.
- Setting up the frame (i.e. allocating static space on the stack) and
  deallocating it (uncluding deynamic allocations) is disabled.
  This does not make sense, either.  You ask the compiler to allocate
  variables and temporaries on the stack, so you should also leave it to
  the compiler to adjust the stack pointer accordingly.
  If you have some pre-allocated space on the stack that the function may
  reuse, you should specify the size of that space (in an attribute
  argument), and then the prologue can allocate more space if it needs to.
  Regardless, if alloca is being used, a frame pointer is needed, and the
  epilogue must deallocate the frame.
- The return instruction is omitted.  That doesn't make sense, as then
  the program can drop through into a switch table or constant pool.
  Inserting random assembler afterwards is also unsfe, becasue the
  compiler has to know about the distance between the switch table /
  constant pools from the sites where they are used, and the debug
  information also is emitted assuming that the compiler emits the whole
  function.
  What we could do is have some alternate return sequence.
  If you just want jump to a specific symbol at the end, that would be
  a tail call to a nonreturn function with void argument list.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFA: Add SH Symbian port
  2004-07-07 14:52     ` Joern Rennecke
@ 2004-07-09 14:31       ` Nick Clifton
  2004-07-10  2:27         ` Joern Rennecke
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Clifton @ 2004-07-09 14:31 UTC (permalink / raw)
  To: Joern Rennecke; +Cc: Joern Rennecke, amylaar, aoliva, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 856 bytes --]

Hi Joern,

   OK - will you accept this revised patch with the use/support of naked 
functions removed ?  (The patch also renames the target to 
sh-*-symbianelf in line with the change made to the binutils sources).

Cheers  Nick

gcc/ChangeLog

2004-07-09  Nick Clifton  <nickc@redhat.com>

	* config.gcc: Add sh-*-symbianelf target.
	* 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.


[-- Attachment #2: gcc.symbian.patch --]
[-- Type: text/plain, Size: 40893 bytes --]

Index: gcc/config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.465
diff -c -3 -p -r1.465 config.gcc
*** gcc/config.gcc	8 Jul 2004 01:28:53 -0000	1.465
--- gcc/config.gcc	9 Jul 2004 12:42:41 -0000
*************** s390x-ibm-tpf*)
*** 1671,1676 ****
--- 1671,1677 ----
  	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-*-elf* | sh[12346l]*-*-elf* | sh*-*-k
*** 1730,1735 ****
--- 1731,1742 ----
  		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
Index: gcc/config/sh/sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.55
diff -c -3 -p -r1.55 sh-protos.h
*** gcc/config/sh/sh-protos.h	10 May 2004 23:25:13 -0000	1.55
--- gcc/config/sh/sh-protos.h	9 Jul 2004 12:42:47 -0000
*************** extern const char *sh_pch_valid_p (const
*** 144,146 ****
--- 144,160 ----
  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: gcc/config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.277
diff -c -3 -p -r1.277 sh.c
*** gcc/config/sh/sh.c	9 Jul 2004 00:47:46 -0000	1.277
--- gcc/config/sh/sh.c	9 Jul 2004 12:42:57 -0000
*************** static tree sh_build_builtin_va_list (vo
*** 446,451 ****
--- 446,462 ----
  /* 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.  */
*************** sh_file_start (void)
*** 1426,1431 ****
--- 1437,1448 ----
  {
    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
*************** const struct attribute_spec sh_attribute
*** 6965,6970 ****
--- 6982,6998 ----
    { "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 }
  };
  
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- gcc/config/sh/symbian-pre.h	2004-07-02 13:00:33.000000000 +0100
***************
*** 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"
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- gcc/config/sh/symbian-post.h	2004-07-06 12:46:35.000000000 +0100
***************
*** 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)
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- gcc/config/sh/symbian.c	2004-07-09 13:49:38.000000000 +0100
***************
*** 0 ****
--- 1,908 ----
+ /* 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
+ 
+ extern int current_function_anonymous_args;
+ 
+ /* 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 */
*** /dev/null	2004-02-18 15:26:44.000000000 +0000
--- gcc/config/sh/t-symbian	2004-07-02 12:40:10.000000000 +0100
***************
*** 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:

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFA: Add SH Symbian port
  2004-07-09 14:31       ` Nick Clifton
@ 2004-07-10  2:27         ` Joern Rennecke
  2004-07-12 12:11           ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Joern Rennecke @ 2004-07-10  2:27 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Joern Rennecke, Joern Rennecke, amylaar, aoliva, gcc-patches

>    OK - will you accept this revised patch with the use/support of naked 
> functions removed ?  (The patch also renames the target to 
> sh-*-symbianelf in line with the change made to the binutils sources).
> 
> Cheers  Nick
> 
> gcc/ChangeLog
> 
> 2004-07-09  Nick Clifton  <nickc@redhat.com>
> 
> 	* config.gcc: Add sh-*-symbianelf target.
> 	* 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.

mostly OK, except for two things.

First:
> + extern int current_function_anonymous_args;
> + 

I think you can loose this.  In fact, this variable in sh.c is dead.
The varargs handling was changed to do without this static function because
this never worked for nested functions.

If someone wants to clean this up, a patch to remove this variable from
sh.c is preapproved, if properly tested.

Second: the new attributes should be described in extend.texi.
If they do exactly the same as the attributes of the same name do for
other targets, just fixing the description to refer to the new targets
that support them is fine, but if theyt are different, you should
describe either the differences, or from scratch what they do for
sh-*-symbianelf, or both.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFA: Add SH Symbian port
  2004-07-10  2:27         ` Joern Rennecke
@ 2004-07-12 12:11           ` Nick Clifton
  0 siblings, 0 replies; 7+ messages in thread
From: Nick Clifton @ 2004-07-12 12:11 UTC (permalink / raw)
  To: Joern Rennecke; +Cc: Joern Rennecke, amylaar, aoliva, gcc-patches

Hi Joern,

> mostly OK, except for two things.

Thanks - I have checked the patch in with the two changes you requested.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-07-12  8:45 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-06 15:26 RFA: Add SH Symbian port Nick Clifton
2004-07-07  3:27 ` Joern Rennecke
2004-07-07  8:26   ` Nick Clifton
2004-07-07 14:52     ` Joern Rennecke
2004-07-09 14:31       ` Nick Clifton
2004-07-10  2:27         ` Joern Rennecke
2004-07-12 12:11           ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).