OSDN Git Service

2010-03-18 Paolo Carlini <paolo.carlini@oracle.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / repo.c
1 /* Code to maintain a C++ template repository.
2    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
3    2006, 2007, 2008  Free Software Foundation, Inc.
4    Contributed by Jason Merrill (jason@cygnus.com)
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public 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 /* My strategy here is as follows:
23
24    Everything should be emitted in a translation unit where it is used.
25    The results of the automatic process should be easily reproducible with
26    explicit code.  */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32 #include "tree.h"
33 #include "cp-tree.h"
34 #include "input.h"
35 #include "obstack.h"
36 #include "toplev.h"
37 #include "diagnostic.h"
38 #include "flags.h"
39
40 static const char *extract_string (const char **);
41 static const char *get_base_filename (const char *);
42 static FILE *open_repo_file (const char *);
43 static char *afgets (FILE *);
44 static FILE *reopen_repo_file_for_write (void);
45
46 static GTY(()) tree pending_repo;
47 static char *repo_name;
48
49 static const char *old_args, *old_dir, *old_main;
50
51 static struct obstack temporary_obstack;
52 static bool temporary_obstack_initialized_p;
53
54 /* Parse a reasonable subset of shell quoting syntax.  */
55
56 static const char *
57 extract_string (const char **pp)
58 {
59   const char *p = *pp;
60   int backquote = 0;
61   int inside = 0;
62
63   for (;;)
64     {
65       char c = *p;
66       if (c == '\0')
67         break;
68       ++p;
69       if (backquote)
70         {
71           obstack_1grow (&temporary_obstack, c);
72           backquote = 0;
73         }
74       else if (! inside && c == ' ')
75         break;
76       else if (! inside && c == '\\')
77         backquote = 1;
78       else if (c == '\'')
79         inside = !inside;
80       else
81         obstack_1grow (&temporary_obstack, c);
82     }
83
84   obstack_1grow (&temporary_obstack, '\0');
85   *pp = p;
86   return (char *) obstack_finish (&temporary_obstack);
87 }
88
89 static const char *
90 get_base_filename (const char *filename)
91 {
92   const char *p = getenv ("COLLECT_GCC_OPTIONS");
93   const char *output = NULL;
94   int compiling = 0;
95
96   while (p && *p)
97     {
98       const char *q = extract_string (&p);
99
100       if (strcmp (q, "-o") == 0)
101         {
102           if (flag_compare_debug)
103             /* Just in case aux_base_name was based on a name with two
104                or more '.'s, add an arbitrary extension that will be
105                stripped by the caller.  */
106             output = concat (aux_base_name, ".o", NULL);
107           else
108             output = extract_string (&p);
109         }
110       else if (strcmp (q, "-c") == 0)
111         compiling = 1;
112     }
113
114   if (compiling && output)
115     return output;
116
117   if (p && ! compiling)
118     {
119       warning (0, "-frepo must be used with -c");
120       flag_use_repository = 0;
121       return NULL;
122     }
123
124   return lbasename (filename);
125 }
126
127 static FILE *
128 open_repo_file (const char *filename)
129 {
130   const char *p;
131   const char *s = get_base_filename (filename);
132
133   if (s == NULL)
134     return NULL;
135
136   p = lbasename (s);
137   p = strrchr (p, '.');
138   if (! p)
139     p = s + strlen (s);
140
141   repo_name = XNEWVEC (char, p - s + 5);
142   memcpy (repo_name, s, p - s);
143   memcpy (repo_name + (p - s), ".rpo", 5);
144
145   return fopen (repo_name, "r");
146 }
147
148 static char *
149 afgets (FILE *stream)
150 {
151   int c;
152   while ((c = getc (stream)) != EOF && c != '\n')
153     obstack_1grow (&temporary_obstack, c);
154   if (obstack_object_size (&temporary_obstack) == 0)
155     return NULL;
156   obstack_1grow (&temporary_obstack, '\0');
157   return (char *) obstack_finish (&temporary_obstack);
158 }
159
160 void
161 init_repo (void)
162 {
163   char *buf;
164   const char *p;
165   FILE *repo_file;
166
167   if (! flag_use_repository)
168     return;
169
170   /* When a PCH file is loaded, the entire identifier table is
171      replaced, with the result that IDENTIFIER_REPO_CHOSEN is cleared.
172      So, we have to reread the repository file.  */
173   lang_post_pch_load = init_repo;
174
175   if (!temporary_obstack_initialized_p)
176     gcc_obstack_init (&temporary_obstack);
177
178   repo_file = open_repo_file (main_input_filename);
179
180   if (repo_file == 0)
181     return;
182
183   while ((buf = afgets (repo_file)))
184     {
185       switch (buf[0])
186         {
187         case 'A':
188           old_args = ggc_strdup (buf + 2);
189           break;
190         case 'D':
191           old_dir = ggc_strdup (buf + 2);
192           break;
193         case 'M':
194           old_main = ggc_strdup (buf + 2);
195           break;
196         case 'O':
197           /* A symbol that we were able to define the last time this
198              file was compiled.  */
199           break;
200         case 'C':
201           /* A symbol that the prelinker has requested that we
202              define.  */
203           {
204             tree id = get_identifier (buf + 2);
205             IDENTIFIER_REPO_CHOSEN (id) = 1;
206           }
207           break;
208         default:
209           error ("mysterious repository information in %s", repo_name);
210         }
211       obstack_free (&temporary_obstack, buf);
212     }
213   fclose (repo_file);
214
215   if (old_args && !get_random_seed (true)
216       && (p = strstr (old_args, "'-frandom-seed=")))
217     set_random_seed (extract_string (&p) + strlen ("-frandom-seed="));
218 }
219
220 static FILE *
221 reopen_repo_file_for_write (void)
222 {
223   FILE *repo_file = fopen (repo_name, "w");
224
225   if (repo_file == 0)
226     {
227       error ("can't create repository information file %qs", repo_name);
228       flag_use_repository = 0;
229     }
230
231   return repo_file;
232 }
233
234 /* Emit any pending repos.  */
235
236 void
237 finish_repo (void)
238 {
239   tree t;
240   char *dir, *args;
241   FILE *repo_file;
242
243   if (!flag_use_repository || flag_compare_debug)
244     return;
245
246   if (errorcount || sorrycount)
247     return;
248
249   repo_file = reopen_repo_file_for_write ();
250   if (repo_file == 0)
251     goto out;
252
253   fprintf (repo_file, "M %s\n", main_input_filename);
254   dir = getpwd ();
255   fprintf (repo_file, "D %s\n", dir);
256   args = getenv ("COLLECT_GCC_OPTIONS");
257   if (args)
258     {
259       fprintf (repo_file, "A %s", args);
260       /* If -frandom-seed is not among the ARGS, then add the value
261          that we chose.  That will ensure that the names of types from
262          anonymous namespaces will get the same mangling when this
263          file is recompiled.  */
264       if (!strstr (args, "'-frandom-seed="))
265         fprintf (repo_file, " '-frandom-seed=%s'", get_random_seed (false));
266       fprintf (repo_file, "\n");
267     }
268
269   for (t = pending_repo; t; t = TREE_CHAIN (t))
270     {
271       tree val = TREE_VALUE (t);
272       tree name = DECL_ASSEMBLER_NAME (val);
273       char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
274       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
275     }
276
277  out:
278   if (repo_file)
279     fclose (repo_file);
280 }
281
282 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
283    definition is available in this translation unit.  Returns 0 if
284    this definition should not be emitted in this translation unit
285    because it will be emitted elsewhere.  Returns 1 if the repository
286    file indicates that that DECL should be emitted in this translation
287    unit, or 2 if the repository file is not in use.  */
288
289 int
290 repo_emit_p (tree decl)
291 {
292   int ret = 0;
293   gcc_assert (TREE_PUBLIC (decl));
294   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
295               || TREE_CODE (decl) == VAR_DECL);
296   gcc_assert (!DECL_REALLY_EXTERN (decl));
297
298   /* When not using the repository, emit everything.  */
299   if (!flag_use_repository)
300     return 2;
301
302   /* Only template instantiations are managed by the repository.  This
303      is an artificial restriction; the code in the prelinker and here
304      will work fine if all entities with vague linkage are managed by
305      the repository.  */
306   if (TREE_CODE (decl) == VAR_DECL)
307     {
308       tree type = NULL_TREE;
309       if (DECL_VTABLE_OR_VTT_P (decl))
310         type = DECL_CONTEXT (decl);
311       else if (DECL_TINFO_P (decl))
312         type = TREE_TYPE (DECL_NAME (decl));
313       if (!DECL_TEMPLATE_INSTANTIATION (decl)
314           && (!TYPE_LANG_SPECIFIC (type)
315               || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
316         return 2;
317       /* Const static data members initialized by constant expressions must
318          be processed where needed so that their definitions are
319          available.  Still record them into *.rpo files, so if they
320          weren't actually emitted and collect2 requests them, they can
321          be provided.  */
322       if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)
323           && DECL_CLASS_SCOPE_P (decl))
324         ret = 2;
325     }
326   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
327     return 2;
328
329   if (DECL_EXPLICIT_INSTANTIATION (decl))
330     return 2;
331
332   /* For constructors and destructors, the repository contains
333      information about the clones -- not the original function --
334      because only the clones are emitted in the object file.  */
335   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
336       || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
337     {
338       int emit_p = 0;
339       tree clone;
340       /* There is no early exit from this loop because we want to
341          ensure that all of the clones are marked as available in this
342          object file.  */
343       FOR_EACH_CLONE (clone, decl)
344         /* The only possible results from the recursive call to
345            repo_emit_p are 0 or 1.  */
346         if (repo_emit_p (clone))
347           emit_p = 1;
348       return emit_p;
349     }
350
351   /* Keep track of all available entities.  */
352   if (!DECL_REPO_AVAILABLE_P (decl))
353     {
354       DECL_REPO_AVAILABLE_P (decl) = 1;
355       pending_repo = tree_cons (NULL_TREE, decl, pending_repo);
356     }
357
358   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
359 }
360
361 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
362    export from this translation unit.  */
363
364 bool
365 repo_export_class_p (const_tree class_type)
366 {
367   if (!flag_use_repository)
368     return false;
369   if (!CLASSTYPE_VTABLES (class_type))
370     return false;
371   /* If the virtual table has been assigned to this translation unit,
372      export the class.  */
373   return (IDENTIFIER_REPO_CHOSEN
374           (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
375 }
376
377 #include "gt-cp-repo.h"