config.gcc: Add sh-*-symbianelf target.
* 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. * doc/extend.texi: Document support for dllimport and dllexport attributes by the sh-symbianelf target. From-SVN: r84551
This commit is contained in:
parent
55e99d5226
commit
b55e3aad63
@ -1671,6 +1671,7 @@ s390x-ibm-tpf*)
|
||||
tmake_file="t-slibgcc-elf-ver s390/t-crtstuff s390/t-tpf"
|
||||
;;
|
||||
sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
|
||||
sh-*-symbianelf* | sh[12346l]*-*-symbianelf* | \
|
||||
sh-*-linux* | sh[346lbe]*-*-linux* | \
|
||||
sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
|
||||
sh64-*-netbsd* | sh64l*-*-netbsd*)
|
||||
@ -1730,6 +1731,12 @@ sh-*-elf* | sh[12346l]*-*-elf* | sh*-*-kaos* | \
|
||||
tm_file="${tm_file} sh/sh64.h"
|
||||
extra_headers="shmedia.h ushmedia.h sshmedia.h"
|
||||
;;
|
||||
*-*-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
|
||||
|
@ -143,3 +143,17 @@ extern const char *sh_pch_valid_p (const void *data_p, size_t sz);
|
||||
extern bool sh_promote_prototypes (tree);
|
||||
|
||||
#endif /* ! GCC_SH_PROTOS_H */
|
||||
|
||||
#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 */
|
||||
|
@ -451,6 +451,17 @@ static tree sh_gimplify_va_arg_expr (tree, tree, tree *, tree *);
|
||||
/* Return current register pressure for regmode. */
|
||||
#define CURR_REGMODE_PRESSURE(MODE) curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
|
||||
|
||||
#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. */
|
||||
@ -1431,6 +1442,12 @@ sh_file_start (void)
|
||||
{
|
||||
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
|
||||
@ -6950,6 +6967,17 @@ const struct attribute_spec sh_attribute_table[] =
|
||||
{ "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
|
||||
{ "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
|
||||
{ "renesas", 0, 0, false, true, false, sh_handle_renesas_attribute },
|
||||
#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 }
|
||||
};
|
||||
|
||||
|
89
gcc/config/sh/symbian-post.h
Normal file
89
gcc/config/sh/symbian-post.h
Normal file
@ -0,0 +1,89 @@
|
||||
/* Definitions for the Symbian OS running on an SH part.
|
||||
This file is included after all the other target specific headers.
|
||||
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
Contributed by Red Hat.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION \
|
||||
fputs (" (Renesas SH for Symbian OS)", stderr);
|
||||
|
||||
#undef LINK_EMUL_PREFIX
|
||||
#define LINK_EMUL_PREFIX "shlsymbian"
|
||||
|
||||
|
||||
#define SYMBIAN_EXPORT_NAME(NAME,FILE,DECL) \
|
||||
do \
|
||||
{ \
|
||||
if ((DECL && sh_symbian_dllexport_p (DECL)) \
|
||||
|| sh_symbian_dllexport_name_p (NAME)) \
|
||||
{ \
|
||||
fprintf ((FILE), "\t.pushsection .directive\n"); \
|
||||
fprintf ((FILE), "\t.asciz \"EXPORT %s\\n\"\n", \
|
||||
sh_symbian_strip_name_encoding (NAME)); \
|
||||
fprintf ((FILE), "\t.popsection\n"); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output a function definition label. */
|
||||
#undef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "function"); \
|
||||
ASM_DECLARE_RESULT ((FILE), DECL_RESULT (DECL)); \
|
||||
ASM_OUTPUT_LABEL ((FILE), (NAME)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output the label for an initialized variable. */
|
||||
#undef ASM_DECLARE_OBJECT_NAME
|
||||
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
HOST_WIDE_INT size; \
|
||||
\
|
||||
SYMBIAN_EXPORT_NAME ((NAME), (FILE), (DECL)); \
|
||||
ASM_OUTPUT_TYPE_DIRECTIVE ((FILE), (NAME), "object"); \
|
||||
\
|
||||
size_directive_output = 0; \
|
||||
if (!flag_inhibit_size_directive \
|
||||
&& (DECL) \
|
||||
&& DECL_SIZE (DECL)) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
size = int_size_in_bytes (TREE_TYPE (DECL)); \
|
||||
ASM_OUTPUT_SIZE_DIRECTIVE ((FILE), (NAME), size); \
|
||||
} \
|
||||
\
|
||||
ASM_OUTPUT_LABEL ((FILE), (NAME)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#undef ASM_OUTPUT_LABELREF
|
||||
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
|
||||
do \
|
||||
{ \
|
||||
asm_fprintf ((FILE), "%U%s", \
|
||||
sh_symbian_strip_name_encoding (NAME)); \
|
||||
} \
|
||||
while (0)
|
48
gcc/config/sh/symbian-pre.h
Normal file
48
gcc/config/sh/symbian-pre.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Definitions for the Symbian OS running on an SH part.
|
||||
This file is included before any other target specific headers.
|
||||
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
Contributed by Red Hat.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Enable Symbian specific code. */
|
||||
#define SYMBIAN 1
|
||||
|
||||
/* Default to using the Renesas ABI. */
|
||||
#define TARGET_ABI_DEFAULT RENESAS_BIT
|
||||
|
||||
/* Support the __declspec keyword by turning them into attributes.
|
||||
We currently only support: naked, dllimport, and dllexport.
|
||||
Note that the current way we do this may result in a collision with
|
||||
predefined attributes later on. This can be solved by using one attribute,
|
||||
say __declspec__, and passing args to it. The problem with that approach
|
||||
is that args are not accumulated: each new appearance would clobber any
|
||||
existing args. */
|
||||
#define SUBTARGET_CPP_SPEC "-D__declspec(x)=__attribute__((x))"
|
||||
|
||||
/* Get tree.c to declare merge_dllimport_decl_attributes(). */
|
||||
#define TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||
|
||||
/* The Symbian OS currently does not support exception handling. */
|
||||
#define SUBTARGET_CC1PLUS_SPEC "-fno-exceptions"
|
||||
|
||||
/* Create constructor/destructor sections without the writable flag.
|
||||
Symbian puts them into the text segment and munges them later on. */
|
||||
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"ax\",@progbits"
|
||||
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"ax\",@progbits"
|
906
gcc/config/sh/symbian.c
Normal file
906
gcc/config/sh/symbian.c
Normal file
@ -0,0 +1,906 @@
|
||||
/* Routines for GCC for a Symbian OS targeted SH backend.
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
Contributed by RedHat.
|
||||
Most of this code is stolen from i386/winnt.c.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; either version 2, or (at your
|
||||
option) any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "rtl.h"
|
||||
#include "output.h"
|
||||
#include "flags.h"
|
||||
#include "tree.h"
|
||||
#include "expr.h"
|
||||
#include "tm_p.h"
|
||||
#include "cp/cp-tree.h" /* We need access to the OVL_... macros. */
|
||||
#include "toplev.h"
|
||||
|
||||
/* Select the level of debugging information to display.
|
||||
0 for no debugging.
|
||||
1 for informative messages about decisions to add attributes
|
||||
2 for verbose information about what is being done. */
|
||||
#define SYMBIAN_DEBUG 0
|
||||
//#define SYMBIAN_DEBUG 1
|
||||
//#define SYMBIAN_DEBUG 2
|
||||
|
||||
/* A unique character to encode declspec encoded objects. */
|
||||
#define SH_SYMBIAN_FLAG_CHAR "$"
|
||||
|
||||
/* Unique strings to prefix exported and imported objects. */
|
||||
#define DLL_IMPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "i."
|
||||
#define DLL_EXPORT_PREFIX SH_SYMBIAN_FLAG_CHAR "e."
|
||||
|
||||
|
||||
/* 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 */
|
35
gcc/config/sh/t-symbian
Normal file
35
gcc/config/sh/t-symbian
Normal file
@ -0,0 +1,35 @@
|
||||
LIB1ASMSRC = sh/lib1funcs.asm
|
||||
LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
|
||||
_movstr_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
|
||||
$(LIB1ASMFUNCS_CACHE)
|
||||
|
||||
# We want fine grained libraries, so use the new code to build the
|
||||
# floating point emulation libraries.
|
||||
FPBIT = fp-bit.c
|
||||
DPBIT = dp-bit.c
|
||||
|
||||
dp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
|
||||
|
||||
fp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
echo '#define FLOAT' > fp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
|
||||
|
||||
$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
|
||||
$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
|
||||
$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
|
||||
$(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
|
||||
|
||||
$(out_object_file): gt-sh.h
|
||||
gt-sh.h : s-gtype ; @true
|
||||
|
||||
symbian.o: $(srcdir)/config/sh/symbian.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/symbian.c
|
||||
|
||||
|
||||
# Local Variables:
|
||||
# mode: Makefile
|
||||
# End:
|
@ -2009,10 +2009,11 @@ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
|
||||
|
||||
@item dllexport
|
||||
@cindex @code{__declspec(dllexport)}
|
||||
On Microsoft Windows targets the @code{dllexport} attribute causes the
|
||||
compiler to provide a global pointer to a pointer in a dll, so that it
|
||||
can be referenced with the @code{dllimport} attribute. The pointer name
|
||||
is formed by combining @code{_imp__} and the function or variable name.
|
||||
On Microsoft Windows targets and Symbian targets the @code{dllexport}
|
||||
attribute causes the compiler to provide a global pointer to a pointer
|
||||
in a dll, so that it can be referenced with the @code{dllimport}
|
||||
attribute. The pointer name is formed by combining @code{_imp__} and
|
||||
the function or variable name.
|
||||
|
||||
Currently, the @code{dllexport}attribute is ignored for inlined
|
||||
functions, but export can be forced by using the
|
||||
@ -2024,21 +2025,24 @@ member functions and static data members as exports. Static consts
|
||||
initialized in-class are not marked unless they are also defined
|
||||
out-of-class.
|
||||
|
||||
On cygwin, mingw and arm-pe targets, @code{__declspec(dllexport)} is
|
||||
recognized as a synonym for @code{__attribute__ ((dllexport))} for
|
||||
compatibility with other Microsoft Windows compilers.
|
||||
On cygwin, mingw, arm-pe and sh-symbianelf targets,
|
||||
@code{__declspec(dllexport)} is recognized as a synonym for
|
||||
@code{__attribute__ ((dllexport))} for compatibility with other
|
||||
Microsoft Windows and Symbian compilers.
|
||||
|
||||
Alternative methods for including the symbol in the dll's export table
|
||||
are to use a .def file with an @code{EXPORTS} section or, with GNU ld,
|
||||
using the @option{--export-all} linker flag.
|
||||
For Microsoft Windows targets there are alternative methods for
|
||||
including the symbol in the dll's export table such as using a
|
||||
@file{.def} file with an @code{EXPORTS} section or, with GNU ld, using
|
||||
the @option{--export-all} linker flag.
|
||||
|
||||
@item dllimport
|
||||
@cindex @code{__declspec(dllimport)}
|
||||
On Microsoft Windows targets, the @code{dllimport} attribute causes the
|
||||
compiler to reference a function or variable via a global pointer to a
|
||||
pointer that is set up by the Microsoft Windows dll library. The pointer
|
||||
name is formed by combining @code{_imp__} and the function or variable
|
||||
name. The attribute implies @code{extern} storage.
|
||||
On Microsoft Windows and Symbian targets, the @code{dllimport}
|
||||
attribute causes the compiler to reference a function or variable via
|
||||
a global pointer to a pointer that is set up by the Microsoft Windows
|
||||
dll library. The pointer name is formed by combining @code{_imp__} and
|
||||
the function or variable name. The attribute implies @code{extern}
|
||||
storage.
|
||||
|
||||
Currently, the attribute is ignored for inlined functions. If the
|
||||
attribute is applied to a symbol @emph{definition}, an error is reported.
|
||||
@ -2052,15 +2056,25 @@ member functions and static data members as imports. However, the
|
||||
attribute is ignored for virtual methods to allow creation of vtables
|
||||
using thunks.
|
||||
|
||||
On cygwin, mingw and arm-pe targets, @code{__declspec(dllimport)} is
|
||||
recognized as a synonym for @code{__attribute__ ((dllimport))} for
|
||||
compatibility with other Microsoft Windows compilers.
|
||||
For Symbian targets the @code{dllimport} attribute also has another
|
||||
affect - it can cause the vtable and run-time type information for a
|
||||
class to be exported. This happens when the class has a dllimport'ed
|
||||
constructor or a non-inline, non-pure virtual function and, for either
|
||||
of those two conditions, the class also has a inline constructor or
|
||||
destructor and has a key function that is defined in the current
|
||||
translation unit.
|
||||
|
||||
The use of the @code{dllimport} attribute on functions is not necessary,
|
||||
but provides a small performance benefit by eliminating a thunk in the
|
||||
dll. The use of the @code{dllimport} attribute on imported variables was
|
||||
required on older versions of GNU ld, but can now be avoided by passing
|
||||
the @option{--enable-auto-import} switch to ld. As with functions, using
|
||||
On cygwin, mingw, arm-pe sh-symbianelf targets,
|
||||
@code{__declspec(dllimport)} is recognized as a synonym for
|
||||
@code{__attribute__ ((dllimport))} for compatibility with other
|
||||
Microsoft Windows and Symbian compilers.
|
||||
|
||||
For Microsoft Windows based targets the use of the @code{dllimport}
|
||||
attribute on functions is not necessary, but provides a small
|
||||
performance benefit by eliminating a thunk in the dll. The use of the
|
||||
@code{dllimport} attribute on imported variables was required on older
|
||||
versions of GNU ld, but can now be avoided by passing the
|
||||
@option{--enable-auto-import} switch to ld. As with functions, using
|
||||
the attribute for a variable eliminates a thunk in the dll.
|
||||
|
||||
One drawback to using this attribute is that a pointer to a function or
|
||||
|
Loading…
Reference in New Issue
Block a user