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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [c-pch.c] - Blame information for rev 20

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

Line No. Rev Author Line
1 12 jlechner
/* Precompiled header implementation for the C languages.
2
   Copyright (C) 2000, 2002, 2003, 2004, 2005 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 2, 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 COPYING.  If not, write to
18
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19
Boston, MA 02110-1301, USA.  */
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 "toplev.h"
31
#include "debug.h"
32
#include "c-pragma.h"
33
#include "ggc.h"
34
#include "langhooks.h"
35
#include "hosthooks.h"
36
#include "target.h"
37
 
38
/* This is a list of flag variables that must match exactly, and their
39
   names for the error message.  The possible values for *flag_var must
40
   fit in a 'signed char'.  */
41
 
42
static const struct c_pch_matching
43
{
44
  int *flag_var;
45
  const char *flag_name;
46
} pch_matching[] = {
47
  { &flag_exceptions, "-fexceptions" },
48
  { &flag_unit_at_a_time, "-funit-at-a-time" }
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 template[IDENT_LENGTH] = "gpch.013";
97
  static const char c_language_chars[] = "Co+O";
98
 
99
  memcpy (result, template, 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[IDENT_LENGTH] = "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
  v.debug_info_type = write_symbols;
138
  {
139
    size_t i;
140
    for (i = 0; i < MATCH_SIZE; i++)
141
      {
142
        v.match[i] = *pch_matching[i].flag_var;
143
        gcc_assert (v.match[i] == *pch_matching[i].flag_var);
144
      }
145
  }
146
  v.pch_init = &pch_init;
147
  target_validity = targetm.get_pch_validity (&v.target_data_length);
148
 
149
  if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
150
      || fwrite (executable_checksum, 16, 1, f) != 1
151
      || fwrite (&v, sizeof (v), 1, f) != 1
152
      || fwrite (target_validity, v.target_data_length, 1, f) != 1)
153
    fatal_error ("can%'t write to %s: %m", pch_file);
154
 
155
  /* We need to be able to re-read the output.  */
156
  /* The driver always provides a valid -o option.  */
157
  if (asm_file_name == NULL
158
      || strcmp (asm_file_name, "-") == 0)
159
    fatal_error ("%qs is not a valid output file", asm_file_name);
160
 
161
  asm_file_startpos = ftell (asm_out_file);
162
 
163
  /* Let the debugging format deal with the PCHness.  */
164
  (*debug_hooks->handle_pch) (0);
165
 
166
  cpp_save_state (parse_in, f);
167
}
168
 
169
/* Write the PCH file.  This is called at the end of a compilation which
170
   will produce a PCH file.  */
171
 
172
void
173
c_common_write_pch (void)
174
{
175
  char *buf;
176
  long asm_file_end;
177
  long written;
178
  struct c_pch_header h;
179
 
180
  (*debug_hooks->handle_pch) (1);
181
 
182
  cpp_write_pch_deps (parse_in, pch_outfile);
183
 
184
  asm_file_end = ftell (asm_out_file);
185
  h.asm_size = asm_file_end - asm_file_startpos;
186
 
187
  if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
188
    fatal_error ("can%'t write %s: %m", pch_file);
189
 
190
  buf = xmalloc (16384);
191
 
192
  if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
193
    fatal_error ("can%'t seek in %s: %m", asm_file_name);
194
 
195
  for (written = asm_file_startpos; written < asm_file_end; )
196
    {
197
      long size = asm_file_end - written;
198
      if (size > 16384)
199
        size = 16384;
200
      if (fread (buf, size, 1, asm_out_file) != 1)
201
        fatal_error ("can%'t read %s: %m", asm_file_name);
202
      if (fwrite (buf, size, 1, pch_outfile) != 1)
203
        fatal_error ("can%'t write %s: %m", pch_file);
204
      written += size;
205
    }
206
  free (buf);
207
  /* asm_out_file can be written afterwards, so fseek to clear
208
     _IOREAD flag.  */
209
  if (fseek (asm_out_file, 0, SEEK_END) != 0)
210
    fatal_error ("can%'t seek in %s: %m", asm_file_name);
211
 
212
  gt_pch_save (pch_outfile);
213
  cpp_write_pch_state (parse_in, pch_outfile);
214
 
215
  if (fseek (pch_outfile, 0, SEEK_SET) != 0
216
      || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
217
    fatal_error ("can%'t write %s: %m", pch_file);
218
 
219
  fclose (pch_outfile);
220
}
221
 
222
/* Check the PCH file called NAME, open on FD, to see if it can be
223
   used in this compilation.  Return 1 if valid, 0 if the file can't
224
   be used now but might be if it's seen later in the compilation, and
225
   2 if this file could never be used in the compilation.  */
226
 
227
int
228
c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
229
{
230
  int sizeread;
231
  int result;
232
  char ident[IDENT_LENGTH + 16];
233
  const char *pch_ident;
234
  struct c_pch_validity v;
235
 
236
  /* Perform a quick test of whether this is a valid
237
     precompiled header for the current language.  */
238
 
239
  gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
240
 
241
  sizeread = read (fd, ident, IDENT_LENGTH + 16);
242
  if (sizeread == -1)
243
    fatal_error ("can%'t read %s: %m", name);
244
  else if (sizeread != IDENT_LENGTH + 16)
245
    {
246
      cpp_error (pfile, CPP_DL_WARNING, "%s: too short to be a PCH file",
247
                 name);
248
      return 2;
249
    }
250
 
251
  pch_ident = get_ident();
252
  if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
253
    {
254
      if (cpp_get_options (pfile)->warn_invalid_pch)
255
        {
256
          if (memcmp (ident, pch_ident, 5) == 0)
257
            /* It's a PCH, for the right language, but has the wrong version.
258
             */
259
            cpp_error (pfile, CPP_DL_WARNING,
260
                       "%s: not compatible with this GCC version", name);
261
          else if (memcmp (ident, pch_ident, 4) == 0)
262
            /* It's a PCH for the wrong language.  */
263
            cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
264
                       lang_hooks.name);
265
          else
266
            /* Not any kind of PCH.  */
267
            cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
268
        }
269
      return 2;
270
    }
271
  if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0)
272
    {
273
      if (cpp_get_options (pfile)->warn_invalid_pch)
274
        cpp_error (pfile, CPP_DL_WARNING,
275
                   "%s: created by a different GCC executable", name);
276
      return 2;
277
    }
278
 
279
  /* At this point, we know it's a PCH file created by this
280
     executable, so it ought to be long enough that we can read a
281
     c_pch_validity structure.  */
282
  if (read (fd, &v, sizeof (v)) != sizeof (v))
283
    fatal_error ("can%'t read %s: %m", name);
284
 
285
  /* The allowable debug info combinations are that either the PCH file
286
     was built with the same as is being used now, or the PCH file was
287
     built for some kind of debug info but now none is in use.  */
288
  if (v.debug_info_type != write_symbols
289
      && write_symbols != NO_DEBUG)
290
    {
291
      if (cpp_get_options (pfile)->warn_invalid_pch)
292
        cpp_error (pfile, CPP_DL_WARNING,
293
                   "%s: created with -g%s, but used with -g%s", name,
294
                   debug_type_names[v.debug_info_type],
295
                   debug_type_names[write_symbols]);
296
      return 2;
297
    }
298
 
299
  /* Check flags that must match exactly.  */
300
  {
301
    size_t i;
302
    for (i = 0; i < MATCH_SIZE; i++)
303
      if (*pch_matching[i].flag_var != v.match[i])
304
        {
305
          if (cpp_get_options (pfile)->warn_invalid_pch)
306
            cpp_error (pfile, CPP_DL_WARNING,
307
                       "%s: settings for %s do not match", name,
308
                       pch_matching[i].flag_name);
309
          return 2;
310
        }
311
  }
312
 
313
  /* If the text segment was not loaded at the same address as it was
314
     when the PCH file was created, function pointers loaded from the
315
     PCH will not be valid.  We could in theory remap all the function
316
     pointers, but no support for that exists at present.
317
     Since we have the same executable, it should only be necessary to
318
     check one function.  */
319
  if (v.pch_init != &pch_init)
320
    {
321
      if (cpp_get_options (pfile)->warn_invalid_pch)
322
        cpp_error (pfile, CPP_DL_WARNING,
323
                   "%s: had text segment at different address", name);
324
      return 2;
325
    }
326
 
327
  /* Check the target-specific validity data.  */
328
  {
329
    void *this_file_data = xmalloc (v.target_data_length);
330
    const char *msg;
331
 
332
    if ((size_t) read (fd, this_file_data, v.target_data_length)
333
        != v.target_data_length)
334
      fatal_error ("can%'t read %s: %m", name);
335
    msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
336
    free (this_file_data);
337
    if (msg != NULL)
338
      {
339
        if (cpp_get_options (pfile)->warn_invalid_pch)
340
          cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
341
        return 2;
342
      }
343
  }
344
 
345
  /* Check the preprocessor macros are the same as when the PCH was
346
     generated.  */
347
 
348
  result = cpp_valid_state (pfile, name, fd);
349
  if (result == -1)
350
    return 2;
351
  else
352
    return result == 0;
353
}
354
 
355
/* If non-NULL, this function is called after a precompile header file
356
   is loaded.  */
357
void (*lang_post_pch_load) (void);
358
 
359
/* Load in the PCH file NAME, open on FD.  It was originally searched for
360
   by ORIG_NAME.  */
361
 
362
void
363
c_common_read_pch (cpp_reader *pfile, const char *name,
364
                   int fd, const char *orig_name ATTRIBUTE_UNUSED)
365
{
366
  FILE *f;
367
  struct c_pch_header h;
368
  struct save_macro_data *smd;
369
 
370
  f = fdopen (fd, "rb");
371
  if (f == NULL)
372
    {
373
      cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
374
      return;
375
    }
376
 
377
  cpp_get_callbacks (parse_in)->valid_pch = NULL;
378
 
379
  if (fread (&h, sizeof (h), 1, f) != 1)
380
    {
381
      cpp_errno (pfile, CPP_DL_ERROR, "reading");
382
      return;
383
    }
384
 
385
  if (!flag_preprocess_only)
386
    {
387
      unsigned long written;
388
      char * buf = xmalloc (16384);
389
 
390
      for (written = 0; written < h.asm_size; )
391
        {
392
          long size = h.asm_size - written;
393
          if (size > 16384)
394
            size = 16384;
395
          if (fread (buf, size, 1, f) != 1
396
              || fwrite (buf, size, 1, asm_out_file) != 1)
397
            cpp_errno (pfile, CPP_DL_ERROR, "reading");
398
          written += size;
399
        }
400
      free (buf);
401
    }
402
  else
403
    {
404
      /* If we're preprocessing, don't write to a NULL
405
         asm_out_file.  */
406
      if (fseek (f, h.asm_size, SEEK_CUR) != 0)
407
        cpp_errno (pfile, CPP_DL_ERROR, "seeking");
408
    }
409
 
410
  cpp_prepare_state (pfile, &smd);
411
 
412
  gt_pch_restore (f);
413
 
414
  if (cpp_read_state (pfile, name, f, smd) != 0)
415
    return;
416
 
417
  fclose (f);
418
 
419
  /* Give the front end a chance to take action after a PCH file has
420
     been loaded.  */
421
  if (lang_post_pch_load)
422
    (*lang_post_pch_load) ();
423
}
424
 
425
/* Indicate that no more PCH files should be read.  */
426
 
427
void
428
c_common_no_more_pch (void)
429
{
430
  if (cpp_get_callbacks (parse_in)->valid_pch)
431
    {
432
      cpp_get_callbacks (parse_in)->valid_pch = NULL;
433
      host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
434
    }
435
}
436
 
437
/* Handle #pragma GCC pch_preprocess, to load in the PCH file.  */
438
 
439
#ifndef O_BINARY
440
# define O_BINARY 0
441
#endif
442
 
443
void
444
c_common_pch_pragma (cpp_reader *pfile)
445
{
446
  tree name_t;
447
  const char *name;
448
  int fd;
449
 
450
  if (c_lex (&name_t) != CPP_STRING)
451
    {
452
      error ("malformed #pragma GCC pch_preprocess, ignored");
453
      return;
454
    }
455
 
456
  if (!cpp_get_options (pfile)->preprocessed)
457
    {
458
      error ("pch_preprocess pragma should only be used with -fpreprocessed");
459
      inform ("use #include instead");
460
      return;
461
    }
462
 
463
  name = TREE_STRING_POINTER (name_t);
464
 
465
  fd = open (name, O_RDONLY | O_BINARY, 0666);
466
  if (fd == -1)
467
    fatal_error ("%s: couldn%'t open PCH file: %m", name);
468
 
469
  if (c_common_valid_pch (pfile, name, fd) != 1)
470
    {
471
      if (!cpp_get_options (pfile)->warn_invalid_pch)
472
        inform ("use -Winvalid-pch for more information");
473
      fatal_error ("%s: PCH file was invalid", name);
474
    }
475
 
476
  c_common_read_pch (pfile, name, fd, name);
477
 
478
  close (fd);
479
}
480
 
481
/* Print out executable_checksum[].  */
482
 
483
void
484
c_common_print_pch_checksum (FILE *f)
485
{
486
  int i;
487
  fputs ("Compiler executable checksum: ", f);
488
  for (i = 0; i < 16; i++)
489
    fprintf (f, "%02x", executable_checksum[i]);
490
  putc ('\n', f);
491
}

powered by: WebSVN 2.1.0

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