This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: RFA: Add SH Symbian port
- From: Nick Clifton <nickc at redhat dot com>
- To: Joern Rennecke <joern dot rennecke at superh dot com>
- Cc: Joern Rennecke <amylaar at spamcop dot net>, amylaar at onetel dot net dot uk, aoliva at redhat dot com, gcc-patches at gcc dot gnu dot org
- Date: Fri, 09 Jul 2004 13:58:47 +0100
- Subject: Re: RFA: Add SH Symbian port
- References: <200407071402.i67E2QQ06100@chloe.uk.w2k.superh.com>
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.
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;
/* 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."
+
+
+ /* 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. */
+
+ /* 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: