OSDN Git Service

* config/sh/elf.h (LIB_SPEC): Define.
[pf3gnuchains/gcc-fork.git] / gcc / config / sh / symbian-base.c
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.
4    Contributed by RedHat.
5    Most of this code is stolen from i386/winnt.c.
6
7    This file is part of GCC.
8
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.
13
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.
18
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/>.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "output.h"
29 #include "flags.h"
30 #include "tree.h"
31 #include "expr.h"
32 #include "tm_p.h"
33 #include "diagnostic-core.h"
34 #include "sh-symbian.h"
35
36 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
37
38 bool
39 sh_symbian_is_dllexported_name (const char *symbol)
40 {
41   return strncmp (DLL_EXPORT_PREFIX, symbol,
42                   strlen (DLL_EXPORT_PREFIX)) == 0;
43 }
44
45 /* Return nonzero if SYMBOL is marked as being dllimport'd.  */
46
47 static bool
48 sh_symbian_is_dllimported_name (const char *symbol)
49 {
50   return strncmp (DLL_IMPORT_PREFIX, symbol,
51                   strlen (DLL_IMPORT_PREFIX)) == 0;
52 }
53
54 /* Return nonzero if DECL is a dllexport'd object.  */
55
56 bool
57 sh_symbian_is_dllexported (tree decl)
58 {
59   tree exp;
60
61   if (   TREE_CODE (decl) != VAR_DECL
62       && TREE_CODE (decl) != FUNCTION_DECL)
63     return false;
64
65   exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
66
67   /* Class members get the dllexport status of their class.  */
68   if (exp == NULL)
69     {
70       tree class = sh_symbian_associated_type (decl);
71
72       if (class)
73         exp = lookup_attribute ("dllexport", TYPE_ATTRIBUTES (class));
74     }
75 #if SYMBIAN_DEBUG
76   if (exp)
77     {
78       print_node_brief (stderr, "dllexport:", decl, 0);
79       fprintf (stderr, "\n");
80     }
81   else
82 #if SYMBIAN_DEBUG < 2
83     if (TREE_CODE (decl) != FUNCTION_DECL)
84 #endif
85     {
86       print_node_brief (stderr, "no dllexport:", decl, 0);
87       fprintf (stderr, "\n");
88     }
89 #endif
90   return exp ? true : false;
91 }
92
93 /* Mark a DECL as being dllimport'd.  */
94
95 static void
96 sh_symbian_mark_dllimport (tree decl)
97 {
98   const char *oldname;
99   char *newname;
100   tree idp;
101   rtx rtlname;
102   rtx newrtl;
103
104   rtlname = XEXP (DECL_RTL (decl), 0);
105   if (MEM_P (rtlname))
106     rtlname = XEXP (rtlname, 0);
107   gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
108   oldname = XSTR (rtlname, 0);
109
110   if (sh_symbian_is_dllexported_name (oldname))
111     {
112       error ("%qE declared as both exported to and imported from a DLL",
113              DECL_NAME (decl));
114     }
115   else if (sh_symbian_is_dllimported_name (oldname))
116     {
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",
120                decl);
121     }
122   else
123     {
124       newname = (char *) alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
125       sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
126
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
130          identical.  */
131       idp = get_identifier (newname);
132       newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
133       XEXP (DECL_RTL (decl), 0) = newrtl;
134     }
135 }
136
137 /* Mark a DECL as being dllexport'd.
138    Note that we override the previous setting (e.g.: dllimport).  */
139
140 static void
141 sh_symbian_mark_dllexport (tree decl)
142 {
143   const char *oldname;
144   char *newname;
145   rtx rtlname;
146   tree idp;
147
148   rtlname = XEXP (DECL_RTL (decl), 0);
149   if (MEM_P (rtlname))
150     rtlname = XEXP (rtlname, 0);
151   gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
152   oldname = XSTR (rtlname, 0);
153
154   if (sh_symbian_is_dllimported_name (oldname))
155     {
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
162         correctness.  */
163       oldname += strlen (DLL_IMPORT_PREFIX);
164       DECL_DLLIMPORT_P (decl) = 0;
165     }
166   else if (sh_symbian_is_dllexported_name (oldname))
167     return; /* Already done.  */
168
169   newname = (char *) alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1);
170   sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname);
171
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
175      identical.  */
176   idp = get_identifier (newname);
177
178   XEXP (DECL_RTL (decl), 0) =
179     gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
180 }
181
182 void
183 sh_symbian_encode_section_info (tree decl, rtx rtl, int first)
184 {
185   default_encode_section_info (decl, rtl, first);
186
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)))
204     {
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));
209
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");
214
215       XEXP (DECL_RTL (decl), 0) = newrtl;
216
217       DECL_DLLIMPORT_P (decl) = 0;
218     }
219 }
220
221 /* Return the length of a function name prefix
222     that starts with the character 'c'.  */
223
224 static int
225 sh_symbian_get_strip_length (int c)
226 {
227   /* XXX Assumes strlen (DLL_EXPORT_PREFIX) == strlen (DLL_IMPORT_PREFIX).  */
228   return (c == SH_SYMBIAN_FLAG_CHAR[0]) ? strlen (DLL_EXPORT_PREFIX) : 0;
229 }
230
231 /* Return a pointer to a function's name with any
232    and all prefix encodings stripped from it.  */
233
234 const char *
235 sh_symbian_strip_name_encoding (const char *name)
236 {
237   int skip;
238
239   while ((skip = sh_symbian_get_strip_length (*name)))
240     name += skip;
241
242   return name;
243 }
244