1 /* Routines for GCC for a Symbian OS targeted SH backend, shared by
2 both the C and C++ compilers.
3 Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
5 Most of this code is stolen from i386/winnt.c.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published
11 by the Free Software Foundation; either version 3, or (at your
12 option) any later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
33 #include "diagnostic-core.h"
34 #include "sh-symbian.h"
36 /* Return nonzero if SYMBOL is marked as being dllexport'd. */
39 sh_symbian_is_dllexported_name (const char *symbol)
41 return strncmp (DLL_EXPORT_PREFIX, symbol,
42 strlen (DLL_EXPORT_PREFIX)) == 0;
45 /* Return nonzero if SYMBOL is marked as being dllimport'd. */
48 sh_symbian_is_dllimported_name (const char *symbol)
50 return strncmp (DLL_IMPORT_PREFIX, symbol,
51 strlen (DLL_IMPORT_PREFIX)) == 0;
54 /* Return nonzero if DECL is a dllexport'd object. */
57 sh_symbian_is_dllexported (tree decl)
61 if ( TREE_CODE (decl) != VAR_DECL
62 && TREE_CODE (decl) != FUNCTION_DECL)
65 exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
67 /* Class members get the dllexport status of their class. */
70 tree class = sh_symbian_associated_type (decl);
73 exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
78 print_node_brief (stderr, "dllexport:", decl, 0);
79 fprintf (stderr, "\n");
83 if (TREE_CODE (decl) != FUNCTION_DECL)
86 print_node_brief (stderr, "no dllexport:", decl, 0);
87 fprintf (stderr, "\n");
90 return exp ? true : false;
93 /* Mark a DECL as being dllimport'd. */
96 sh_symbian_mark_dllimport (tree decl)
104 rtlname = XEXP (DECL_RTL (decl), 0);
106 rtlname = XEXP (rtlname, 0);
107 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
108 oldname = XSTR (rtlname, 0);
110 if (sh_symbian_is_dllexported_name (oldname))
112 error ("%qE declared as both exported to and imported from a DLL",
115 else if (sh_symbian_is_dllimported_name (oldname))
117 /* Already done, but do a sanity check to prevent assembler errors. */
118 if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
119 error ("failure in redeclaration of %q+D: dllimport%'d symbol lacks external linkage",
124 newname = (char *) alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
125 sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
127 /* We pass newname through get_identifier to ensure it has a unique
128 address. RTL processing can sometimes peek inside the symbol ref
129 and compare the string's addresses to see if two symbols are
131 idp = get_identifier (newname);
132 newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
133 XEXP (DECL_RTL (decl), 0) = newrtl;
137 /* Mark a DECL as being dllexport'd.
138 Note that we override the previous setting (e.g.: dllimport). */
141 sh_symbian_mark_dllexport (tree decl)
148 rtlname = XEXP (DECL_RTL (decl), 0);
150 rtlname = XEXP (rtlname, 0);
151 gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
152 oldname = XSTR (rtlname, 0);
154 if (sh_symbian_is_dllimported_name (oldname))
156 /* Remove DLL_IMPORT_PREFIX.
157 Note - we do not issue a warning here. In Symbian's environment it
158 is legitimate for a prototype to be marked as dllimport and the
159 corresponding definition to be marked as dllexport. The prototypes
160 are in headers used everywhere and the definition is in a translation
161 unit which has included the header in order to ensure argument
163 oldname += strlen (DLL_IMPORT_PREFIX);
164 DECL_DLLIMPORT_P (decl) = 0;
166 else if (sh_symbian_is_dllexported_name (oldname))
167 return; /* Already done. */
169 newname = (char *) alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
170 sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
172 /* We pass newname through get_identifier to ensure it has a unique
173 address. RTL processing can sometimes peek inside the symbol ref
174 and compare the string's addresses to see if two symbols are
176 idp = get_identifier (newname);
178 XEXP (DECL_RTL (decl), 0) =
179 gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
183 sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
185 default_encode_section_info (decl, rtl, first);
187 /* Mark the decl so we can tell from the rtl whether
188 the object is dllexport'd or dllimport'd. */
189 if (sh_symbian_is_dllexported (decl))
190 sh_symbian_mark_dllexport (decl);
191 else if (sh_symbian_is_dllimported (decl))
192 sh_symbian_mark_dllimport (decl);
193 /* It might be that DECL has already been marked as dllimport, but a
194 subsequent definition nullified that. The attribute is gone but
195 DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
196 that. Ditto for the DECL_DLLIMPORT_P flag. */
197 else if ( (TREE_CODE (decl) == FUNCTION_DECL
198 || TREE_CODE (decl) == VAR_DECL)
199 && DECL_RTL (decl) != NULL_RTX
200 && MEM_P (DECL_RTL (decl))
201 && MEM_P (XEXP (DECL_RTL (decl), 0))
202 && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
203 && sh_symbian_is_dllimported_name (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
205 const char * oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
206 /* Remove DLL_IMPORT_PREFIX. */
207 tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
208 rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
210 warning (0, "%s %q+D %s after being referenced with dllimport linkage",
211 TREE_CODE (decl) == VAR_DECL ? "variable" : "function",
212 decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
213 ? "defined locally" : "redeclared without dllimport attribute");
215 XEXP (DECL_RTL (decl), 0) = newrtl;
217 DECL_DLLIMPORT_P (decl) = 0;
221 /* Return the length of a function name prefix
222 that starts with the character 'c'. */
225 sh_symbian_get_strip_length (int c)
227 /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX). */
228 return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
231 /* Return a pointer to a function's name with any
232 and all prefix encodings stripped from it. */
235 sh_symbian_strip_name_encoding (const char *name)
239 while ((skip = sh_symbian_get_strip_length (*name)))