OSDN Git Service

* config/arm/arm-protos.h (arm_print_operand): Delete.
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / pe.c
1 /* Routines for GCC for ARM/pe.
2    Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004, 2005, 2007, 2008
3    Free Software Foundation, Inc.
4    Contributed by Doug Evans (dje@cygnus.com).
5
6    This file is part of GCC.
7
8    GCC is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published
10    by the Free Software Foundation; either version 3, or (at your
11    option) any later version.
12
13    GCC is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GCC; see the file COPYING3.  If not see
20    <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "output.h"
28 #include "flags.h"
29 #include "tree.h"
30 #include "expr.h"
31 #include "toplev.h"
32 #include "tm_p.h"
33
34 extern int current_function_anonymous_args;
35
36 \f
37 /* Return nonzero if DECL is a dllexport'd object.  */
38
39 tree current_class_type; /* FIXME */
40
41 int
42 arm_dllexport_p (tree decl)
43 {
44   tree exp;
45
46   if (TREE_CODE (decl) != VAR_DECL
47       && TREE_CODE (decl) != FUNCTION_DECL)
48     return 0;
49   exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
50   if (exp)
51     return 1;
52
53   return 0;
54 }
55
56 /* Return nonzero if DECL is a dllimport'd object.  */
57
58 int
59 arm_dllimport_p (tree decl)
60 {
61   tree imp;
62
63   if (TREE_CODE (decl) == FUNCTION_DECL
64       && TARGET_NOP_FUN_DLLIMPORT)
65     return 0;
66
67   if (TREE_CODE (decl) != VAR_DECL
68       && TREE_CODE (decl) != FUNCTION_DECL)
69     return 0;
70   imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
71   if (imp)
72     return 1;
73
74   return 0;
75 }
76
77 /* Return nonzero if SYMBOL is marked as being dllexport'd.  */
78
79 int
80 arm_dllexport_name_p (const char *symbol)
81 {
82   return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.';
83 }
84
85 /* Return nonzero if SYMBOL is marked as being dllimport'd.  */
86
87 int
88 arm_dllimport_name_p (const char *symbol)
89 {
90   return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.';
91 }
92
93 /* Mark a DECL as being dllexport'd.
94    Note that we override the previous setting (e.g.: dllimport).  */
95
96 void
97 arm_mark_dllexport (tree decl)
98 {
99   const char * oldname;
100   char * newname;
101   rtx rtlname;
102   tree idp;
103
104   rtlname = XEXP (DECL_RTL (decl), 0);
105   if (GET_CODE (rtlname) == MEM)
106     rtlname = XEXP (rtlname, 0);
107   gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
108   oldname = XSTR (rtlname, 0);
109   
110   if (arm_dllimport_name_p (oldname))
111     oldname += 9;
112   else if (arm_dllexport_name_p (oldname))
113     return; /* already done */
114
115   newname = XALLOCAVEC (char, strlen (oldname) + 4);
116   sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname);
117
118   /* We pass newname through get_identifier to ensure it has a unique
119      address.  RTL processing can sometimes peek inside the symbol ref
120      and compare the string's addresses to see if two symbols are
121      identical.  */
122   /* ??? At least I think that's why we do this.  */
123   idp = get_identifier (newname);
124
125   XEXP (DECL_RTL (decl), 0) =
126     gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
127 }
128
129 /* Mark a DECL as being dllimport'd.  */
130
131 void
132 arm_mark_dllimport (tree decl)
133 {
134   const char * oldname;
135   char * newname;
136   tree idp;
137   rtx rtlname, newrtl;
138
139   rtlname = XEXP (DECL_RTL (decl), 0);
140   
141   if (GET_CODE (rtlname) == MEM)
142     rtlname = XEXP (rtlname, 0);
143   gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
144   oldname = XSTR (rtlname, 0);
145   
146   gcc_assert (!arm_dllexport_name_p (oldname));
147   if (arm_dllimport_name_p (oldname))
148     return; /* already done */
149
150   /* ??? One can well ask why we're making these checks here,
151      and that would be a good question.  */
152
153   /* Imported variables can't be initialized.  */
154   if (TREE_CODE (decl) == VAR_DECL
155       && !DECL_VIRTUAL_P (decl)
156       && DECL_INITIAL (decl))
157     {
158       error ("initialized variable %q+D is marked dllimport", decl);
159       return;
160     }
161   /* Nor can they be static.  */
162   if (TREE_CODE (decl) == VAR_DECL
163       /* ??? Is this test for vtables needed?  */
164       && !DECL_VIRTUAL_P (decl)
165       && 0 /*???*/)
166     {
167       error ("static variable %q+D is marked dllimport", decl);
168       return;
169     }
170
171   /* `extern' needn't be specified with dllimport.
172      Specify `extern' now and hope for the best.  Sigh.  */
173   if (TREE_CODE (decl) == VAR_DECL
174       /* ??? Is this test for vtables needed?  */
175       && !DECL_VIRTUAL_P (decl))
176     {
177       DECL_EXTERNAL (decl) = 1;
178       TREE_PUBLIC (decl) = 1;
179     }
180
181   newname = XALLOCAVEC (char, strlen (oldname) + 11);
182   sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname);
183
184   /* We pass newname through get_identifier to ensure it has a unique
185      address.  RTL processing can sometimes peek inside the symbol ref
186      and compare the string's addresses to see if two symbols are
187      identical.  */
188   /* ??? At least I think that's why we do this.  */
189   idp = get_identifier (newname);
190
191   newrtl = gen_rtx_MEM (Pmode,
192                         gen_rtx_SYMBOL_REF (Pmode,
193                                             IDENTIFIER_POINTER (idp)));
194   XEXP (DECL_RTL (decl), 0) = newrtl;
195 }
196
197 void
198 arm_pe_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
199 {
200   /* This bit is copied from arm_encode_section_info.  */
201   if (optimize > 0 && TREE_CONSTANT (decl))
202     SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
203
204   /* Mark the decl so we can tell from the rtl whether the object is
205      dllexport'd or dllimport'd.  */
206   if (arm_dllexport_p (decl))
207     arm_mark_dllexport (decl);
208   else if (arm_dllimport_p (decl))
209     arm_mark_dllimport (decl);
210   /* It might be that DECL has already been marked as dllimport, but a
211      subsequent definition nullified that.  The attribute is gone but
212      DECL_RTL still has @i.__imp_foo.  We need to remove that.  */
213   else if ((TREE_CODE (decl) == FUNCTION_DECL
214             || TREE_CODE (decl) == VAR_DECL)
215            && DECL_RTL (decl) != NULL_RTX
216            && GET_CODE (DECL_RTL (decl)) == MEM
217            && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
218            && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
219            && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
220     {
221       const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
222       tree idp = get_identifier (oldname + 9);
223       rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
224
225       XEXP (DECL_RTL (decl), 0) = newrtl;
226
227       /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
228          ??? We leave these alone for now.  */
229     }
230 }
231
232 void
233 arm_pe_unique_section (tree decl, int reloc)
234 {
235   int len;
236   const char * name;
237   char * string;
238   const char * prefix;
239
240   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
241   name = arm_strip_name_encoding (name);
242
243   /* The object is put in, for example, section .text$foo.
244      The linker will then ultimately place them in .text
245      (everything from the $ on is stripped).  */
246   if (TREE_CODE (decl) == FUNCTION_DECL)
247     prefix = ".text$";
248   else if (decl_readonly_section (decl, reloc))
249     prefix = ".rdata$";
250   else
251     prefix = ".data$";
252   len = strlen (name) + strlen (prefix);
253   string = XALLOCAVEC (char, len + 1);
254   sprintf (string, "%s%s", prefix, name);
255
256   DECL_SECTION_NAME (decl) = build_string (len, string);
257 }