OSDN Git Service

03cf3bf08bcae4379cedfd1c4fb2ddb65e8e5a90
[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 /* Load in the PCH file NAME, open on FD.  It was originally searched for
388    by ORIG_NAME.  */
389
390 void
391 c_common_read_pch (cpp_reader *pfile, const char *name,
392                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
393 {
394   FILE *f;
395   struct c_pch_header h;
396   char *buf;
397   unsigned long written;
398   struct save_macro_data *smd;
399   
400   f = fdopen (fd, "rb");
401   if (f == NULL)
402     {
403       cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
404       return;
405     }
406
407   cpp_get_callbacks (parse_in)->valid_pch = NULL;
408
409   if (fread (&h, sizeof (h), 1, f) != 1)
410     {
411       cpp_errno (pfile, CPP_DL_ERROR, "reading");
412       return;
413     }
414
415   buf = xmalloc (16384);
416   for (written = 0; written < h.asm_size; )
417     {
418       long size = h.asm_size - written;
419       if (size > 16384)
420         size = 16384;
421       if (fread (buf, size, 1, f) != 1
422           || fwrite (buf, size, 1, asm_out_file) != 1)
423         cpp_errno (pfile, CPP_DL_ERROR, "reading");
424       written += size;
425     }
426   free (buf);
427
428   cpp_prepare_state (pfile, &smd);
429
430   gt_pch_restore (f);
431
432   if (cpp_read_state (pfile, name, f, smd) != 0)
433     return;
434
435   fclose (f);
436 }
437
438 /* Indicate that no more PCH files should be read.  */
439
440 void
441 c_common_no_more_pch (void)
442 {
443   if (cpp_get_callbacks (parse_in)->valid_pch)
444     {
445       cpp_get_callbacks (parse_in)->valid_pch = NULL;
446       host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
447     }
448 }