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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [c-family/] [c-pch.c] - Blame information for rev 707

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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