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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [c-pch.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Precompiled header implementation for the C languages.
2
   Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
3
 
4
This file is part of GCC.
5
 
6
GCC is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 3, or (at your option)
9
any later version.
10
 
11
GCC is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GCC; see the file COPYING3.  If not see
18
<http://www.gnu.org/licenses/>.  */
19
 
20
#include "config.h"
21
#include "system.h"
22
#include "coretypes.h"
23
#include "version.h"
24
#include "cpplib.h"
25
#include "tree.h"
26
#include "flags.h"
27
#include "c-common.h"
28
#include "output.h"
29
#include "toplev.h"
30
#include "debug.h"
31
#include "c-pragma.h"
32
#include "ggc.h"
33
#include "langhooks.h"
34
#include "hosthooks.h"
35
#include "target.h"
36
 
37
/* This is a list of flag variables that must match exactly, and their
38
   names for the error message.  The possible values for *flag_var must
39
   fit in a 'signed char'.  */
40
 
41
static const struct c_pch_matching
42
{
43
  int *flag_var;
44
  const char *flag_name;
45
} pch_matching[] = {
46
  { &flag_exceptions, "-fexceptions" },
47
  { &flag_unit_at_a_time, "-funit-at-a-time" }
48
};
49
 
50
enum {
51
  MATCH_SIZE = ARRAY_SIZE (pch_matching)
52
};
53
 
54
/* The value of the checksum in the dummy compiler that is actually
55
   checksummed.  That compiler should never be run.  */
56
static const char no_checksum[16] = { 0 };
57
 
58
/* Information about flags and suchlike that affect PCH validity.
59
 
60
   Before this structure is read, both an initial 8-character identification
61
   string, and a 16-byte checksum, have been read and validated.  */
62
 
63
struct c_pch_validity
64
{
65
  unsigned char debug_info_type;
66
  signed char match[MATCH_SIZE];
67
  void (*pch_init) (void);
68
  size_t target_data_length;
69
};
70
 
71
struct c_pch_header
72
{
73
  unsigned long asm_size;
74
};
75
 
76
#define IDENT_LENGTH 8
77
 
78
/* The file we'll be writing the PCH to.  */
79
static FILE *pch_outfile;
80
 
81
/* The position in the assembler output file when pch_init was called.  */
82
static long asm_file_startpos;
83
 
84
static const char *get_ident (void);
85
 
86
/* Compute an appropriate 8-byte magic number for the PCH file, so that
87
   utilities like file(1) can identify it, and so that GCC can quickly
88
   ignore non-PCH files and PCH files that are of a completely different
89
   format.  */
90
 
91
static const char *
92
get_ident (void)
93
{
94
  static char result[IDENT_LENGTH];
95
  static const char template[IDENT_LENGTH] = "gpch.013";
96
  static const char c_language_chars[] = "Co+O";
97
 
98
  memcpy (result, template, IDENT_LENGTH);
99
  result[4] = c_language_chars[c_language];
100
 
101
  return result;
102
}
103
 
104
/* Prepare to write a PCH file, if one is being written.  This is
105
   called at the start of compilation.
106
 
107
   Also, print out the executable checksum if -fverbose-asm is in effect.  */
108
 
109
void
110
pch_init (void)
111
{
112
  FILE *f;
113
  struct c_pch_validity v;
114
  void *target_validity;
115
  static const char partial_pch[IDENT_LENGTH] = "gpcWrite";
116
 
117
#ifdef ASM_COMMENT_START
118
  if (flag_verbose_asm)
119
    {
120
      fprintf (asm_out_file, "%s ", ASM_COMMENT_START);
121
      c_common_print_pch_checksum (asm_out_file);
122
      fputc ('\n', asm_out_file);
123
    }
124
#endif
125
 
126
  if (!pch_file)
127
    return;
128
 
129
  f = fopen (pch_file, "w+b");
130
  if (f == NULL)
131
    fatal_error ("can%'t create precompiled header %s: %m", pch_file);
132
  pch_outfile = f;
133
 
134
  gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
135
 
136
  v.debug_info_type = write_symbols;
137
  {
138
    size_t i;
139
    for (i = 0; i < MATCH_SIZE; i++)
140
      {
141
        v.match[i] = *pch_matching[i].flag_var;
142
        gcc_assert (v.match[i] == *pch_matching[i].flag_var);
143
      }
144
  }
145
  v.pch_init = &pch_init;
146
  target_validity = targetm.get_pch_validity (&v.target_data_length);
147
 
148
  if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
149
      || fwrite (executable_checksum, 16, 1, f) != 1
150
      || fwrite (&v, sizeof (v), 1, f) != 1
151
      || fwrite (target_validity, v.target_data_length, 1, f) != 1)
152
    fatal_error ("can%'t write to %s: %m", pch_file);
153
 
154
  /* We need to be able to re-read the output.  */
155
  /* The driver always provides a valid -o option.  */
156
  if (asm_file_name == NULL
157
      || strcmp (asm_file_name, "-") == 0)
158
    fatal_error ("%qs is not a valid output file", asm_file_name);
159
 
160
  asm_file_startpos = ftell (asm_out_file);
161
 
162
  /* Let the debugging format deal with the PCHness.  */
163
  (*debug_hooks->handle_pch) (0);
164
 
165
  cpp_save_state (parse_in, f);
166
}
167
 
168
/* Write the PCH file.  This is called at the end of a compilation which
169
   will produce a PCH file.  */
170
 
171
void
172
c_common_write_pch (void)
173
{
174
  char *buf;
175
  long asm_file_end;
176
  long written;
177
  struct c_pch_header h;
178
 
179
  (*debug_hooks->handle_pch) (1);
180
 
181
  cpp_write_pch_deps (parse_in, pch_outfile);
182
 
183
  asm_file_end = ftell (asm_out_file);
184
  h.asm_size = asm_file_end - asm_file_startpos;
185
 
186
  if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
187
    fatal_error ("can%'t write %s: %m", pch_file);
188
 
189
  buf = XNEWVEC (char, 16384);
190
 
191
  if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
192
    fatal_error ("can%'t seek in %s: %m", asm_file_name);
193
 
194
  for (written = asm_file_startpos; written < asm_file_end; )
195
    {
196
      long size = asm_file_end - written;
197
      if (size > 16384)
198
        size = 16384;
199
      if (fread (buf, size, 1, asm_out_file) != 1)
200
        fatal_error ("can%'t read %s: %m", asm_file_name);
201
      if (fwrite (buf, size, 1, pch_outfile) != 1)
202
        fatal_error ("can%'t write %s: %m", pch_file);
203
      written += size;
204
    }
205
  free (buf);
206
  /* asm_out_file can be written afterwards, so fseek to clear
207
     _IOREAD flag.  */
208
  if (fseek (asm_out_file, 0, SEEK_END) != 0)
209
    fatal_error ("can%'t seek in %s: %m", asm_file_name);
210
 
211
  gt_pch_save (pch_outfile);
212
  cpp_write_pch_state (parse_in, pch_outfile);
213
 
214
  if (fseek (pch_outfile, 0, SEEK_SET) != 0
215
      || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
216
    fatal_error ("can%'t write %s: %m", pch_file);
217
 
218
  fclose (pch_outfile);
219
}
220
 
221
/* Check the PCH file called NAME, open on FD, to see if it can be
222
   used in this compilation.  Return 1 if valid, 0 if the file can't
223
   be used now but might be if it's seen later in the compilation, and
224
   2 if this file could never be used in the compilation.  */
225
 
226
int
227
c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
228
{
229
  int sizeread;
230
  int result;
231
  char ident[IDENT_LENGTH + 16];
232
  const char *pch_ident;
233
  struct c_pch_validity v;
234
 
235
  /* Perform a quick test of whether this is a valid
236
     precompiled header for the current language.  */
237
 
238
  gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
239
 
240
  sizeread = read (fd, ident, IDENT_LENGTH + 16);
241
  if (sizeread == -1)
242
    fatal_error ("can%'t read %s: %m", name);
243
  else if (sizeread != IDENT_LENGTH + 16)
244
    {
245
      cpp_error (pfile, CPP_DL_WARNING, "%s: too short to be a PCH file",
246
                 name);
247
      return 2;
248
    }
249
 
250
  pch_ident = get_ident();
251
  if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
252
    {
253
      if (cpp_get_options (pfile)->warn_invalid_pch)
254
        {
255
          if (memcmp (ident, pch_ident, 5) == 0)
256
            /* It's a PCH, for the right language, but has the wrong version.
257
             */
258
            cpp_error (pfile, CPP_DL_WARNING,
259
                       "%s: not compatible with this GCC version", name);
260
          else if (memcmp (ident, pch_ident, 4) == 0)
261
            /* It's a PCH for the wrong language.  */
262
            cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
263
                       lang_hooks.name);
264
          else
265
            /* Not any kind of PCH.  */
266
            cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
267
        }
268
      return 2;
269
    }
270
  if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0)
271
    {
272
      if (cpp_get_options (pfile)->warn_invalid_pch)
273
        cpp_error (pfile, CPP_DL_WARNING,
274
                   "%s: created by a different GCC executable", name);
275
      return 2;
276
    }
277
 
278
  /* At this point, we know it's a PCH file created by this
279
     executable, so it ought to be long enough that we can read a
280
     c_pch_validity structure.  */
281
  if (read (fd, &v, sizeof (v)) != sizeof (v))
282
    fatal_error ("can%'t read %s: %m", name);
283
 
284
  /* The allowable debug info combinations are that either the PCH file
285
     was built with the same as is being used now, or the PCH file was
286
     built for some kind of debug info but now none is in use.  */
287
  if (v.debug_info_type != write_symbols
288
      && write_symbols != NO_DEBUG)
289
    {
290
      if (cpp_get_options (pfile)->warn_invalid_pch)
291
        cpp_error (pfile, CPP_DL_WARNING,
292
                   "%s: created with -g%s, but used with -g%s", name,
293
                   debug_type_names[v.debug_info_type],
294
                   debug_type_names[write_symbols]);
295
      return 2;
296
    }
297
 
298
  /* Check flags that must match exactly.  */
299
  {
300
    size_t i;
301
    for (i = 0; i < MATCH_SIZE; i++)
302
      if (*pch_matching[i].flag_var != v.match[i])
303
        {
304
          if (cpp_get_options (pfile)->warn_invalid_pch)
305
            cpp_error (pfile, CPP_DL_WARNING,
306
                       "%s: settings for %s do not match", name,
307
                       pch_matching[i].flag_name);
308
          return 2;
309
        }
310
  }
311
 
312
  /* If the text segment was not loaded at the same address as it was
313
     when the PCH file was created, function pointers loaded from the
314
     PCH will not be valid.  We could in theory remap all the function
315
     pointers, but no support for that exists at present.
316
     Since we have the same executable, it should only be necessary to
317
     check one function.  */
318
  if (v.pch_init != &pch_init)
319
    {
320
      if (cpp_get_options (pfile)->warn_invalid_pch)
321
        cpp_error (pfile, CPP_DL_WARNING,
322
                   "%s: had text segment at different address", name);
323
      return 2;
324
    }
325
 
326
  /* Check the target-specific validity data.  */
327
  {
328
    void *this_file_data = xmalloc (v.target_data_length);
329
    const char *msg;
330
 
331
    if ((size_t) read (fd, this_file_data, v.target_data_length)
332
        != v.target_data_length)
333
      fatal_error ("can%'t read %s: %m", name);
334
    msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
335
    free (this_file_data);
336
    if (msg != NULL)
337
      {
338
        if (cpp_get_options (pfile)->warn_invalid_pch)
339
          cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
340
        return 2;
341
      }
342
  }
343
 
344
  /* Check the preprocessor macros are the same as when the PCH was
345
     generated.  */
346
 
347
  result = cpp_valid_state (pfile, name, fd);
348
  if (result == -1)
349
    return 2;
350
  else
351
    return result == 0;
352
}
353
 
354
/* If non-NULL, this function is called after a precompile header file
355
   is loaded.  */
356
void (*lang_post_pch_load) (void);
357
 
358
/* Load in the PCH file NAME, open on FD.  It was originally searched for
359
   by ORIG_NAME.  */
360
 
361
void
362
c_common_read_pch (cpp_reader *pfile, const char *name,
363
                   int fd, const char *orig_name ATTRIBUTE_UNUSED)
364
{
365
  FILE *f;
366
  struct c_pch_header h;
367
  struct save_macro_data *smd;
368
 
369
  f = fdopen (fd, "rb");
370
  if (f == NULL)
371
    {
372
      cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
373
      return;
374
    }
375
 
376
  cpp_get_callbacks (parse_in)->valid_pch = NULL;
377
 
378
  if (fread (&h, sizeof (h), 1, f) != 1)
379
    {
380
      cpp_errno (pfile, CPP_DL_ERROR, "reading");
381
      return;
382
    }
383
 
384
  if (!flag_preprocess_only)
385
    {
386
      unsigned long written;
387
      char * buf = XNEWVEC (char, 16384);
388
 
389
      for (written = 0; written < h.asm_size; )
390
        {
391
          long size = h.asm_size - written;
392
          if (size > 16384)
393
            size = 16384;
394
          if (fread (buf, size, 1, f) != 1
395
              || fwrite (buf, size, 1, asm_out_file) != 1)
396
            cpp_errno (pfile, CPP_DL_ERROR, "reading");
397
          written += size;
398
        }
399
      free (buf);
400
    }
401
  else
402
    {
403
      /* If we're preprocessing, don't write to a NULL
404
         asm_out_file.  */
405
      if (fseek (f, h.asm_size, SEEK_CUR) != 0)
406
        cpp_errno (pfile, CPP_DL_ERROR, "seeking");
407
    }
408
 
409
  cpp_prepare_state (pfile, &smd);
410
 
411
  gt_pch_restore (f);
412
 
413
  if (cpp_read_state (pfile, name, f, smd) != 0)
414
    return;
415
 
416
  fclose (f);
417
 
418
  /* Give the front end a chance to take action after a PCH file has
419
     been loaded.  */
420
  if (lang_post_pch_load)
421
    (*lang_post_pch_load) ();
422
}
423
 
424
/* Indicate that no more PCH files should be read.  */
425
 
426
void
427
c_common_no_more_pch (void)
428
{
429
  if (cpp_get_callbacks (parse_in)->valid_pch)
430
    {
431
      cpp_get_callbacks (parse_in)->valid_pch = NULL;
432
      host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
433
    }
434
}
435
 
436
/* Handle #pragma GCC pch_preprocess, to load in the PCH file.  */
437
 
438
#ifndef O_BINARY
439
# define O_BINARY 0
440
#endif
441
 
442
void
443
c_common_pch_pragma (cpp_reader *pfile, const char *name)
444
{
445
  int fd;
446
 
447
  if (!cpp_get_options (pfile)->preprocessed)
448
    {
449
      error ("pch_preprocess pragma should only be used with -fpreprocessed");
450
      inform ("use #include instead");
451
      return;
452
    }
453
 
454
  fd = open (name, O_RDONLY | O_BINARY, 0666);
455
  if (fd == -1)
456
    fatal_error ("%s: couldn%'t open PCH file: %m", name);
457
 
458
  if (c_common_valid_pch (pfile, name, fd) != 1)
459
    {
460
      if (!cpp_get_options (pfile)->warn_invalid_pch)
461
        inform ("use -Winvalid-pch for more information");
462
      fatal_error ("%s: PCH file was invalid", name);
463
    }
464
 
465
  c_common_read_pch (pfile, name, fd, name);
466
 
467
  close (fd);
468
}
469
 
470
/* Print out executable_checksum[].  */
471
 
472
void
473
c_common_print_pch_checksum (FILE *f)
474
{
475
  int i;
476
  fputs ("Compiler executable checksum: ", f);
477
  for (i = 0; i < 16; i++)
478
    fprintf (f, "%02x", executable_checksum[i]);
479
  putc ('\n', f);
480
}

powered by: WebSVN 2.1.0

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