OSDN Git Service

Add Fariborz to my last change.
[pf3gnuchains/gcc-fork.git] / gcc / c-pch.c
1 /* Precompiled header implementation for the C languages.
2    Copyright (C) 2000, 2002, 2003, 2004 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, 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 /* This structure is read very early when validating the PCH, and
56    might be read for a PCH which is for a completely different compiler
57    for a different operating system.  Thus, it should really only contain
58    'unsigned char' entries, at least in the initial entries.  
59
60    If you add or change entries before version_length, you should increase
61    the version number in get_ident().  
62
63    There are a bunch of fields named *_length; those are lengths of data that
64    follows this structure in the same order as the fields in the structure.  */
65
66 struct c_pch_validity
67 {
68   unsigned char host_machine_length;
69   unsigned char target_machine_length;
70   unsigned char version_length;
71   unsigned char debug_info_type;
72   signed char match[MATCH_SIZE];
73   void (*pch_init) (void);
74   size_t target_data_length;
75 };
76
77 struct c_pch_header 
78 {
79   unsigned long asm_size;
80 };
81
82 #define IDENT_LENGTH 8
83
84 /* The file we'll be writing the PCH to.  */
85 static FILE *pch_outfile;
86
87 /* The position in the assembler output file when pch_init was called.  */
88 static long asm_file_startpos;
89
90 /* The host and target machines.  */
91 static const char host_machine[] = HOST_MACHINE;
92 static const char target_machine[] = TARGET_MACHINE;
93
94 static const char *get_ident (void);
95
96 /* Compute an appropriate 8-byte magic number for the PCH file, so that
97    utilities like file(1) can identify it, and so that GCC can quickly
98    ignore non-PCH files and PCH files that are of a completely different
99    format.  */
100
101 static const char *
102 get_ident(void)
103 {
104   static char result[IDENT_LENGTH];
105   static const char template[IDENT_LENGTH] = "gpch.012";
106   static const char c_language_chars[] = "Co+O";
107   
108   memcpy (result, template, IDENT_LENGTH);
109   result[4] = c_language_chars[c_language];
110
111   return result;
112 }
113
114 /* Prepare to write a PCH file.  This is called at the start of 
115    compilation.  */
116
117 void
118 pch_init (void)
119 {
120   FILE *f;
121   struct c_pch_validity v;
122   void *target_validity;
123   static const char partial_pch[IDENT_LENGTH] = "gpcWrite";
124   
125   if (! pch_file)
126     return;
127   
128   f = fopen (pch_file, "w+b");
129   if (f == NULL)
130     fatal_error ("can't create precompiled header %s: %m", pch_file);
131   pch_outfile = f;
132   
133   if (strlen (host_machine) > 255 || strlen (target_machine) > 255
134       || strlen (version_string) > 255)
135     abort ();
136   
137   v.host_machine_length = strlen (host_machine);
138   v.target_machine_length = strlen (target_machine);
139   v.version_length = strlen (version_string);
140   v.debug_info_type = write_symbols;
141   {
142     size_t i;
143     for (i = 0; i < MATCH_SIZE; i++)
144       {
145         v.match[i] = *pch_matching[i].flag_var;
146         if (v.match[i] != *pch_matching[i].flag_var)
147           abort ();
148       }
149   }
150   v.pch_init = &pch_init;
151   target_validity = targetm.get_pch_validity (&v.target_data_length);
152   
153   if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
154       || fwrite (&v, sizeof (v), 1, f) != 1
155       || fwrite (host_machine, v.host_machine_length, 1, f) != 1
156       || fwrite (target_machine, v.target_machine_length, 1, f) != 1
157       || fwrite (version_string, v.version_length, 1, f) != 1
158       || fwrite (target_validity, v.target_data_length, 1, f) != 1)
159     fatal_error ("can't write to %s: %m", pch_file);
160
161   /* We need to be able to re-read the output.  */
162   /* The driver always provides a valid -o option.  */
163   if (asm_file_name == NULL
164       || strcmp (asm_file_name, "-") == 0)
165     fatal_error ("`%s' is not a valid output file", asm_file_name);
166   
167   asm_file_startpos = ftell (asm_out_file);
168   
169   /* Let the debugging format deal with the PCHness.  */
170   (*debug_hooks->handle_pch) (0);
171   
172   cpp_save_state (parse_in, f);
173 }
174
175 /* Write the PCH file.  This is called at the end of a compilation which
176    will produce a PCH file.  */
177
178 void
179 c_common_write_pch (void)
180 {
181   char *buf;
182   long asm_file_end;
183   long written;
184   struct c_pch_header h;
185
186   (*debug_hooks->handle_pch) (1);
187
188   cpp_write_pch_deps (parse_in, pch_outfile);
189
190   asm_file_end = ftell (asm_out_file);
191   h.asm_size = asm_file_end - asm_file_startpos;
192   
193   if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
194     fatal_error ("can't write %s: %m", pch_file);
195   
196   buf = xmalloc (16384);
197
198   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
199     fatal_error ("can't seek in %s: %m", asm_file_name);
200
201   for (written = asm_file_startpos; written < asm_file_end; )
202     {
203       long size = asm_file_end - written;
204       if (size > 16384)
205         size = 16384;
206       if (fread (buf, size, 1, asm_out_file) != 1)
207         fatal_error ("can't read %s: %m", asm_file_name);
208       if (fwrite (buf, size, 1, pch_outfile) != 1)
209         fatal_error ("can't write %s: %m", pch_file);
210       written += size;
211     }
212   free (buf);
213   /* asm_out_file can be written afterwards, so fseek to clear
214      _IOREAD flag.  */
215   if (fseek (asm_out_file, 0, SEEK_END) != 0)
216     fatal_error ("can't seek in %s: %m", asm_file_name);
217
218   gt_pch_save (pch_outfile);
219   cpp_write_pch_state (parse_in, pch_outfile);
220
221   if (fseek (pch_outfile, 0, SEEK_SET) != 0
222       || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
223     fatal_error ("can't write %s: %m", pch_file);
224
225   fclose (pch_outfile);
226 }
227
228 /* Check the PCH file called NAME, open on FD, to see if it can be
229    used in this compilation.  Return 1 if valid, 0 if the file can't
230    be used now but might be if it's seen later in the compilation, and
231    2 if this file could never be used in the compilation.  */
232
233 int
234 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
235 {
236   int sizeread;
237   int result;
238   char ident[IDENT_LENGTH];
239   char short_strings[256 * 3];
240   int strings_length;
241   const char *pch_ident;
242   struct c_pch_validity v;
243
244   /* Perform a quick test of whether this is a valid
245      precompiled header for the current language.  */
246
247   sizeread = read (fd, ident, IDENT_LENGTH);
248   if (sizeread == -1)
249     fatal_error ("can't read %s: %m", name);
250   else if (sizeread != IDENT_LENGTH)
251     return 2;
252   
253   pch_ident = get_ident();
254   if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
255     {
256       if (cpp_get_options (pfile)->warn_invalid_pch)
257         {
258           if (memcmp (ident, pch_ident, 5) == 0)
259             /* It's a PCH, for the right language, but has the wrong version.
260              */
261             cpp_error (pfile, CPP_DL_WARNING, 
262                        "%s: not compatible with this GCC version", name);
263           else if (memcmp (ident, pch_ident, 4) == 0)
264             /* It's a PCH for the wrong language.  */
265             cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
266                        lang_hooks.name);
267           else 
268             /* Not any kind of PCH.  */
269             cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
270         }
271       return 2;
272     }
273
274   /* At this point, we know it's a PCH file, so it ought to be long enough
275      that we can read a c_pch_validity structure.  */
276   if (read (fd, &v, sizeof (v)) != sizeof (v))
277     fatal_error ("can't read %s: %m", name);
278
279   strings_length = (v.host_machine_length + v.target_machine_length 
280                     + v.version_length);
281   if (read (fd, short_strings, strings_length) != strings_length)
282     fatal_error ("can't read %s: %m", name);
283   if (v.host_machine_length != strlen (host_machine)
284       || memcmp (host_machine, short_strings, strlen (host_machine)) != 0)
285     {
286       if (cpp_get_options (pfile)->warn_invalid_pch)
287         cpp_error (pfile, CPP_DL_WARNING, 
288                    "%s: created on host `%.*s', but used on host `%s'", name,
289                    v.host_machine_length, short_strings, host_machine);
290       return 2;
291     }
292   if (v.target_machine_length != strlen (target_machine)
293       || memcmp (target_machine, short_strings + v.host_machine_length,
294                  strlen (target_machine)) != 0)
295     {
296       if (cpp_get_options (pfile)->warn_invalid_pch)
297         cpp_error (pfile, CPP_DL_WARNING, 
298                    "%s: created for target `%.*s', but used for target `%s'", 
299                    name, v.target_machine_length, 
300                    short_strings + v.host_machine_length, target_machine);
301       return 2;
302     }
303   if (v.version_length != strlen (version_string)
304       || memcmp (version_string, 
305                  (short_strings + v.host_machine_length 
306                   + v.target_machine_length),
307                  v.version_length) != 0)
308     {
309       if (cpp_get_options (pfile)->warn_invalid_pch)
310         cpp_error (pfile, CPP_DL_WARNING,
311                    "%s: created by version `%.*s', but this is version `%s'", 
312                    name, v.version_length, 
313                    (short_strings + v.host_machine_length 
314                     + v.target_machine_length), 
315                    version_string);
316       return 2;
317     }
318
319   /* The allowable debug info combinations are that either the PCH file
320      was built with the same as is being used now, or the PCH file was
321      built for some kind of debug info but now none is in use.  */
322   if (v.debug_info_type != write_symbols
323       && write_symbols != NO_DEBUG)
324     {
325       if (cpp_get_options (pfile)->warn_invalid_pch)
326         cpp_error (pfile, CPP_DL_WARNING, 
327                    "%s: created with -g%s, but used with -g%s", name,
328                    debug_type_names[v.debug_info_type],
329                    debug_type_names[write_symbols]);
330       return 2;
331     }
332
333   /* Check flags that must match exactly.  */
334   {
335     size_t i;
336     for (i = 0; i < MATCH_SIZE; i++)
337       if (*pch_matching[i].flag_var != v.match[i])
338         {
339           if (cpp_get_options (pfile)->warn_invalid_pch)
340             cpp_error (pfile, CPP_DL_WARNING, 
341                        "%s: settings for %s do not match", name,
342                        pch_matching[i].flag_name);
343           return 2;
344         }
345   }
346
347   /* If the text segment was not loaded at the same address as it was
348      when the PCH file was created, function pointers loaded from the
349      PCH will not be valid.  We could in theory remap all the function
350      pointers, but no support for that exists at present.  */
351   if (v.pch_init != &pch_init)
352     {
353       if (cpp_get_options (pfile)->warn_invalid_pch)
354         cpp_error (pfile, CPP_DL_WARNING, 
355                    "%s: had text segment at different address", name);
356       return 2;
357     }
358
359   /* Check the target-specific validity data.  */
360   {
361     void *this_file_data = xmalloc (v.target_data_length);
362     const char *msg;
363     
364     if ((size_t) read (fd, this_file_data, v.target_data_length)
365         != v.target_data_length)
366       fatal_error ("can't read %s: %m", name);
367     msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
368     free (this_file_data);
369     if (msg != NULL)
370       {
371         if (cpp_get_options (pfile)->warn_invalid_pch)
372           cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
373         return 2;
374       }
375   }
376
377   /* Check the preprocessor macros are the same as when the PCH was
378      generated.  */
379   
380   result = cpp_valid_state (pfile, name, fd);
381   if (result == -1)
382     return 2;
383   else
384     return result == 0;
385 }
386
387 /* If non-NULL, this function is called after a precompile header file
388    is loaded.  */
389 void (*lang_post_pch_load) (void);
390
391 /* Load in the PCH file NAME, open on FD.  It was originally searched for
392    by ORIG_NAME.  */
393
394 void
395 c_common_read_pch (cpp_reader *pfile, const char *name,
396                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
397 {
398   FILE *f;
399   struct c_pch_header h;
400   struct save_macro_data *smd;
401   
402   f = fdopen (fd, "rb");
403   if (f == NULL)
404     {
405       cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
406       return;
407     }
408
409   cpp_get_callbacks (parse_in)->valid_pch = NULL;
410
411   if (fread (&h, sizeof (h), 1, f) != 1)
412     {
413       cpp_errno (pfile, CPP_DL_ERROR, "reading");
414       return;
415     }
416
417   if (!flag_preprocess_only)
418     {
419       unsigned long written;
420       char * buf = xmalloc (16384);
421
422       for (written = 0; written < h.asm_size; )
423         {
424           long size = h.asm_size - written;
425           if (size > 16384)
426             size = 16384;
427           if (fread (buf, size, 1, f) != 1
428               || fwrite (buf, size, 1, asm_out_file) != 1)
429             cpp_errno (pfile, CPP_DL_ERROR, "reading");
430           written += size;
431         }
432       free (buf);
433     }
434   else
435     {
436       /* If we're preprocessing, don't write to a NULL
437          asm_out_file.  */
438       if (fseek (f, h.asm_size, SEEK_CUR) != 0)
439         cpp_errno (pfile, CPP_DL_ERROR, "seeking");
440     }
441
442   cpp_prepare_state (pfile, &smd);
443
444   gt_pch_restore (f);
445
446   if (cpp_read_state (pfile, name, f, smd) != 0)
447     return;
448
449   fclose (f);
450   
451   /* Give the front end a chance to take action after a PCH file has
452      been loadeded.  */
453   if (lang_post_pch_load)
454     (*lang_post_pch_load) ();
455 }
456
457 /* Indicate that no more PCH files should be read.  */
458
459 void
460 c_common_no_more_pch (void)
461 {
462   if (cpp_get_callbacks (parse_in)->valid_pch)
463     {
464       cpp_get_callbacks (parse_in)->valid_pch = NULL;
465       host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
466     }
467 }
468
469 /* Handle #pragma GCC pch_preprocess, to load in the PCH file.  */
470
471 #ifndef O_BINARY
472 # define O_BINARY 0
473 #endif
474
475 void
476 c_common_pch_pragma (cpp_reader *pfile)
477 {
478   tree name_t;
479   const char *name;
480   int fd;
481
482   if (c_lex (&name_t) != CPP_STRING)
483     {
484       error ("malformed #pragma GCC pch_preprocess, ignored");
485       return;
486     }
487
488   if (! cpp_get_options (pfile)->preprocessed)
489     {
490       error ("pch_preprocess pragma should only be used with -fpreprocessed");
491       inform ("use #include instead");
492       return;
493     }
494
495   name = TREE_STRING_POINTER (name_t);
496   
497   fd = open (name, O_RDONLY | O_BINARY, 0666);
498   if (fd == -1)
499     fatal_error ("%s: couldn't open PCH file: %m\n", name);
500   
501   if (c_common_valid_pch (pfile, name, fd) != 1)
502     {
503       if (!cpp_get_options (pfile)->warn_invalid_pch)
504         inform ("use -Winvalid-pch for more information");
505       fatal_error ("%s: PCH file was invalid", name);
506     }
507   
508   c_common_read_pch (pfile, name, fd, name);
509   
510   close (fd);
511 }