Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/sh/symbian-base.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
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 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 "toplev.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 |