OSDN Git Service

(struct function): Make frame_offset be HOST_WIDE_INT.
[pf3gnuchains/gcc-fork.git] / gcc / cp / repo.c
1 /* Code to maintain a C++ template repository.
2    Copyright (C) 1995 Free Software Foundation, Inc.
3    Contributed by Jason Merrill (jason@cygnus.com)
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
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 <stdio.h>
29 #include "config.h"
30 #include "tree.h"
31 #include "cp-tree.h"
32 #include "input.h"
33 #include "obstack.h"
34
35 extern char * rindex ();
36 extern char * getenv ();
37 extern char * getpwd ();
38
39 static tree pending_repo;
40 static tree original_repo;
41 static char *repo_name;
42 static FILE *repo_file;
43
44 extern int flag_use_repository;
45 extern int errorcount, sorrycount;
46 extern struct obstack temporary_obstack;
47 extern struct obstack permanent_obstack;
48
49 #define IDENTIFIER_REPO_USED(NODE)   (TREE_LANG_FLAG_3 (NODE))
50 #define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
51
52 #if 0
53 /* Record the flags used to compile this translation unit.  */
54
55 void
56 repo_compile_flags (argc, argv)
57      int argc;
58      char **argv;
59 {
60 }
61
62 /* If this template has not been seen before, add a note to the repository
63    saying where the declaration was.  This may be used to find the
64    definition at link time.  */
65
66 void
67 repo_template_declared (t)
68      tree t;
69 {}
70
71 /* Note where the definition of a template lives so that instantiations can
72    be generated later.  */
73
74 void
75 repo_template_defined (t)
76      tree t;
77 {}
78
79 /* Note where the definition of a class lives to that template
80    instantiations can use it.  */
81
82 void
83 repo_class_defined (t)
84      tree t;
85 {}
86 #endif
87
88 static tree
89 repo_get_id (t)
90      tree t;
91 {
92   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
93     {
94       t = TYPE_BINFO_VTABLE (t);
95       if (t == NULL_TREE)
96         return t;
97     }
98   return DECL_ASSEMBLER_NAME (t);
99 }
100
101 /* Note that a template has been used.  If we can see the definition, offer
102    to emit it.  */
103
104 void
105 repo_template_used (t)
106      tree t;
107 {
108   tree id;
109
110   if (! flag_use_repository)
111     return;
112
113   id = repo_get_id (t);
114   if (id == NULL_TREE)
115     return;
116   
117   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
118     {
119       if (IDENTIFIER_REPO_CHOSEN (id))
120         mark_class_instantiated (t, 0);
121     }
122   else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
123     {
124       if (IDENTIFIER_REPO_CHOSEN (id))
125         mark_decl_instantiated (t, 0);
126     }
127   else
128     my_friendly_abort (1);
129
130   if (! IDENTIFIER_REPO_USED (id))
131     {
132       IDENTIFIER_REPO_USED (id) = 1;
133       pending_repo = perm_tree_cons (NULL_TREE, id, pending_repo);
134     }
135 }
136
137 #if 0
138 /* Note that the vtable for a class has been used, and offer to emit it.  */
139
140 static void
141 repo_vtable_used (t)
142      tree t;
143 {
144   if (! flag_use_repository)
145     return;
146
147   pending_repo = perm_tree_cons (NULL_TREE, t, pending_repo);
148 }
149
150 /* Note that an inline with external linkage has been used, and offer to
151    emit it.  */
152
153 void
154 repo_inline_used (fn)
155      tree fn;
156 {
157   if (! flag_use_repository)
158     return;
159
160   /* Member functions of polymorphic classes go with their vtables.  */
161   if (DECL_FUNCTION_MEMBER_P (fn) && TYPE_VIRTUAL_P (DECL_CLASS_CONTEXT (fn)))
162     {
163       repo_vtable_used (DECL_CLASS_CONTEXT (fn));
164       return;
165     }
166
167   pending_repo = perm_tree_cons (NULL_TREE, fn, pending_repo);
168 }
169
170 /* Note that a particular typeinfo node has been used, and offer to
171    emit it.  */
172
173 void
174 repo_tinfo_used (ti)
175      tree ti;
176 {
177 }
178 #endif
179
180 void
181 repo_template_instantiated (t, extern_p)
182      tree t;
183      int extern_p;
184 {
185   if (! extern_p)
186     {
187       tree id = repo_get_id (t);
188       if (id)
189         IDENTIFIER_REPO_CHOSEN (id) = 1;
190     }
191 }
192
193 static char *
194 save_string (s, len)
195      char *s;
196      int len;
197 {
198   return obstack_copy0 (&temporary_obstack, s, len);
199 }
200
201 static char *
202 get_base_filename (filename)
203      char *filename;
204 {
205   char *p = getenv ("COLLECT_GCC_OPTIONS");
206   char *output = 0;
207   int compiling = 0;
208
209   if (p)
210     while (*p)
211       {
212         char *q = p;
213         while (*q && *q != ' ') q++;
214         if (*p == '-' && p[1] == 'o')
215           {
216             p += 2;
217             if (p == q)
218               {
219                 p++; q++;
220                 if (*q)
221                   while (*q && *q != ' ') q++;
222               }
223
224             output = save_string (p, q - p);
225           }
226         else if (*p == '-' && p[1] == 'c')
227           compiling = 1;
228         if (*q) q++;
229         p = q;
230       }
231
232   if (compiling && output)
233     return output;
234
235   if (p && ! compiling)
236     {
237       warning ("-frepo must be used with -c");
238       flag_use_repository = 0;
239       return NULL;
240     }
241
242   p = rindex (filename, '/');
243   if (p)
244     return p+1;
245   else
246     return filename;
247 }        
248
249 static void
250 open_repo_file (filename)
251      char *filename;
252 {
253   register char *p;
254   char *s = get_base_filename (filename);
255
256   if (s == NULL)
257     return;
258
259   p = rindex (s, '/');
260   if (! p)
261     p = s;
262   p = rindex (p, '.');
263   if (! p)
264     p = s + strlen (s);
265
266   obstack_grow (&permanent_obstack, s, p - s);
267   repo_name = obstack_copy0 (&permanent_obstack, ".rpo", 4);
268
269   repo_file = fopen (repo_name, "r");
270 }
271
272 static char *
273 afgets (stream)
274      FILE *stream;
275 {
276   int c;
277   while ((c = getc (stream)) != EOF && c != '\n')
278     obstack_1grow (&temporary_obstack, c);
279   if (obstack_object_size (&temporary_obstack) == 0)
280     return NULL;
281   obstack_1grow (&temporary_obstack, '\0');
282   return obstack_finish (&temporary_obstack);
283 }
284
285 void
286 init_repo (filename)
287      char *filename;
288 {
289   char *buf;
290
291   if (! flag_use_repository)
292     return;
293
294   open_repo_file (filename);
295
296   if (repo_file == 0)
297     return;
298
299   while (buf = afgets (repo_file))
300     {
301       switch (buf[0])
302         {
303         case 'A':
304         case 'D':
305         case 'M':
306           break;
307         case 'C':
308         case 'O':
309           {
310             tree id = get_identifier (buf + 2);
311             tree orig;
312
313             if (buf[0] == 'C')
314               {
315                 IDENTIFIER_REPO_CHOSEN (id) = 1;
316                 orig = integer_one_node;
317               }
318             else
319               orig = NULL_TREE;
320
321             original_repo = perm_tree_cons (orig, id, original_repo);
322           }
323           break;
324         default:
325           error ("mysterious repository information in %s", repo_name);
326         }
327       obstack_free (&temporary_obstack, buf);
328     }
329 }
330
331 static void
332 reopen_repo_file_for_write ()
333 {
334   if (repo_file)
335     fclose (repo_file);
336   repo_file = fopen (repo_name, "w");
337
338   if (repo_file == 0)
339     {
340       error ("can't create repository information file `%s'", repo_name);
341       flag_use_repository = 0;
342     }
343 }
344
345 /* Emit any pending repos.  */
346
347 void
348 finish_repo ()
349 {
350   tree t;
351   char *p;
352   int repo_changed = 0;
353
354   if (! flag_use_repository)
355     return;
356
357   /* Do we have to write out a new info file?  */
358
359   /* Are there any old templates that aren't used any longer or that are
360      newly chosen?  */
361   
362   for (t = original_repo; t; t = TREE_CHAIN (t))
363     {
364       if (! IDENTIFIER_REPO_USED (TREE_VALUE (t))
365           || (! TREE_PURPOSE (t) && IDENTIFIER_REPO_CHOSEN (TREE_VALUE (t))))
366         {
367           repo_changed = 1;
368           break;
369         }
370       IDENTIFIER_REPO_USED (TREE_VALUE (t)) = 0;
371     }
372
373   /* Are there any templates that are newly used?  */
374   
375   if (! repo_changed)
376     for (t = pending_repo; t; t = TREE_CHAIN (t))
377       {
378         if (IDENTIFIER_REPO_USED (TREE_VALUE (t)))
379           {
380             repo_changed = 1;
381             break;
382           }
383       }
384
385   if (! repo_changed || errorcount || sorrycount)
386     goto out;
387
388   reopen_repo_file_for_write ();
389
390   if (repo_file == 0)
391     goto out;
392
393   fprintf (repo_file, "M %s\n", main_input_filename);
394
395   p = getpwd ();
396   fprintf (repo_file, "D %s\n", p);
397
398   p = getenv ("COLLECT_GCC_OPTIONS");
399   if (p != 0)
400     fprintf (repo_file, "A %s\n", p);
401
402   for (t = pending_repo; t; t = TREE_CHAIN (t))
403     {
404       tree val = TREE_VALUE (t);
405       char type = IDENTIFIER_REPO_CHOSEN (val) ? 'C' : 'O';
406
407       fprintf (repo_file, "%c %s\n", type, IDENTIFIER_POINTER (val));
408     }
409
410  out:
411   if (repo_file)
412     fclose (repo_file);
413 }