xref: /dragonfly/contrib/gcc-4.7/gcc/cp/repo.c (revision 0fe46dc6)
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, 2009, 2010  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-core.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(()) VEC(tree,gc) *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 val;
240   char *dir, *args;
241   FILE *repo_file;
242   unsigned ix;
243 
244   if (!flag_use_repository || flag_compare_debug)
245     return;
246 
247   if (seen_error ())
248     return;
249 
250   repo_file = reopen_repo_file_for_write ();
251   if (repo_file == 0)
252     goto out;
253 
254   fprintf (repo_file, "M %s\n", main_input_filename);
255   dir = getpwd ();
256   fprintf (repo_file, "D %s\n", dir);
257   args = getenv ("COLLECT_GCC_OPTIONS");
258   if (args)
259     {
260       fprintf (repo_file, "A %s", args);
261       /* If -frandom-seed is not among the ARGS, then add the value
262 	 that we chose.  That will ensure that the names of types from
263 	 anonymous namespaces will get the same mangling when this
264 	 file is recompiled.  */
265       if (!strstr (args, "'-frandom-seed="))
266 	fprintf (repo_file, " '-frandom-seed=" HOST_WIDE_INT_PRINT_HEX_PURE "'",
267 		 get_random_seed (false));
268       fprintf (repo_file, "\n");
269     }
270 
271   FOR_EACH_VEC_ELT_REVERSE (tree, pending_repo, ix, val)
272     {
273       tree name = DECL_ASSEMBLER_NAME (val);
274       char type = IDENTIFIER_REPO_CHOSEN (name) ? 'C' : 'O';
275       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (name));
276     }
277 
278  out:
279   if (repo_file)
280     fclose (repo_file);
281 }
282 
283 /* DECL is a FUNCTION_DECL or VAR_DECL with vague linkage whose
284    definition is available in this translation unit.  Returns 0 if
285    this definition should not be emitted in this translation unit
286    because it will be emitted elsewhere.  Returns 1 if the repository
287    file indicates that that DECL should be emitted in this translation
288    unit, or 2 if the repository file is not in use.  */
289 
290 int
291 repo_emit_p (tree decl)
292 {
293   int ret = 0;
294   gcc_assert (TREE_PUBLIC (decl));
295   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
296 	      || TREE_CODE (decl) == VAR_DECL);
297   gcc_assert (!DECL_REALLY_EXTERN (decl));
298 
299   /* When not using the repository, emit everything.  */
300   if (!flag_use_repository)
301     return 2;
302 
303   /* Only template instantiations are managed by the repository.  This
304      is an artificial restriction; the code in the prelinker and here
305      will work fine if all entities with vague linkage are managed by
306      the repository.  */
307   if (TREE_CODE (decl) == VAR_DECL)
308     {
309       tree type = NULL_TREE;
310       if (DECL_VTABLE_OR_VTT_P (decl))
311 	type = DECL_CONTEXT (decl);
312       else if (DECL_TINFO_P (decl))
313 	type = TREE_TYPE (DECL_NAME (decl));
314       if (!DECL_TEMPLATE_INSTANTIATION (decl)
315 	  && (!TYPE_LANG_SPECIFIC (type)
316 	      || !CLASSTYPE_TEMPLATE_INSTANTIATION (type)))
317 	return 2;
318       /* Const static data members initialized by constant expressions must
319 	 be processed where needed so that their definitions are
320 	 available.  Still record them into *.rpo files, so if they
321 	 weren't actually emitted and collect2 requests them, they can
322 	 be provided.  */
323       if (decl_maybe_constant_var_p (decl)
324 	  && DECL_CLASS_SCOPE_P (decl))
325 	ret = 2;
326     }
327   else if (!DECL_TEMPLATE_INSTANTIATION (decl))
328     return 2;
329 
330   if (DECL_EXPLICIT_INSTANTIATION (decl))
331     return 2;
332 
333   /* For constructors and destructors, the repository contains
334      information about the clones -- not the original function --
335      because only the clones are emitted in the object file.  */
336   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
337       || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
338     {
339       int emit_p = 0;
340       tree clone;
341       /* There is no early exit from this loop because we want to
342 	 ensure that all of the clones are marked as available in this
343 	 object file.  */
344       FOR_EACH_CLONE (clone, decl)
345 	/* The only possible results from the recursive call to
346 	   repo_emit_p are 0 or 1.  */
347 	if (repo_emit_p (clone))
348 	  emit_p = 1;
349       return emit_p;
350     }
351 
352   /* Keep track of all available entities.  */
353   if (!DECL_REPO_AVAILABLE_P (decl))
354     {
355       DECL_REPO_AVAILABLE_P (decl) = 1;
356       VEC_safe_push (tree, gc, pending_repo, decl);
357     }
358 
359   return IDENTIFIER_REPO_CHOSEN (DECL_ASSEMBLER_NAME (decl)) ? 1 : ret;
360 }
361 
362 /* Returns true iff the prelinker has explicitly marked CLASS_TYPE for
363    export from this translation unit.  */
364 
365 bool
366 repo_export_class_p (const_tree class_type)
367 {
368   if (!flag_use_repository)
369     return false;
370   if (!CLASSTYPE_VTABLES (class_type))
371     return false;
372   /* If the virtual table has been assigned to this translation unit,
373      export the class.  */
374   return (IDENTIFIER_REPO_CHOSEN
375 	  (DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (class_type))));
376 }
377 
378 #include "gt-cp-repo.h"
379