OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [cp/] [repo.c] - Blame information for rev 12

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.