source: trunk/third/gcc/cp/repo.c @ 8834

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