OSDN Git Service

gcc/
[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 structure is read very early when validating the PCH, and
39    might be read for a PCH which is for a completely different compiler
40    for a different operating system.  Thus, it should really only contain
41    'unsigned char' entries, at least in the initial entries.  
42
43    If you add or change entries before version_length, you should increase
44    the version number in get_ident().  
45
46    There are a bunch of fields named *_length; those are lengths of data that
47    follows this structure in the same order as the fields in the structure.  */
48
49 struct c_pch_validity
50 {
51   unsigned char host_machine_length;
52   unsigned char target_machine_length;
53   unsigned char version_length;
54   unsigned char debug_info_type;
55   void (*pch_init) (void);
56   size_t target_data_length;
57 };
58
59 struct c_pch_header 
60 {
61   unsigned long asm_size;
62 };
63
64 #define IDENT_LENGTH 8
65
66 /* The file we'll be writing the PCH to.  */
67 static FILE *pch_outfile;
68
69 /* The position in the assembler output file when pch_init was called.  */
70 static long asm_file_startpos;
71
72 /* The host and target machines.  */
73 static const char host_machine[] = HOST_MACHINE;
74 static const char target_machine[] = TARGET_MACHINE;
75
76 static const char *get_ident (void);
77
78 /* Compute an appropriate 8-byte magic number for the PCH file, so that
79    utilities like file(1) can identify it, and so that GCC can quickly
80    ignore non-PCH files and PCH files that are of a completely different
81    format.  */
82
83 static const char *
84 get_ident(void)
85 {
86   static char result[IDENT_LENGTH];
87   static const char template[IDENT_LENGTH] = "gpch.012";
88   static const char c_language_chars[] = "Co+O";
89   
90   memcpy (result, template, IDENT_LENGTH);
91   result[4] = c_language_chars[c_language];
92
93   return result;
94 }
95
96 /* Prepare to write a PCH file.  This is called at the start of 
97    compilation.  */
98
99 void
100 pch_init (void)
101 {
102   FILE *f;
103   struct c_pch_validity v;
104   void *target_validity;
105   static const char partial_pch[IDENT_LENGTH] = "gpcWrite";
106   
107   if (! pch_file)
108     return;
109   
110   f = fopen (pch_file, "w+b");
111   if (f == NULL)
112     fatal_error ("can't create precompiled header %s: %m", pch_file);
113   pch_outfile = f;
114   
115   if (strlen (host_machine) > 255 || strlen (target_machine) > 255
116       || strlen (version_string) > 255)
117     abort ();
118   
119   v.host_machine_length = strlen (host_machine);
120   v.target_machine_length = strlen (target_machine);
121   v.version_length = strlen (version_string);
122   v.debug_info_type = write_symbols;
123   v.pch_init = &pch_init;
124   target_validity = targetm.get_pch_validity (&v.target_data_length);
125   
126   if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
127       || fwrite (&v, sizeof (v), 1, f) != 1
128       || fwrite (host_machine, v.host_machine_length, 1, f) != 1
129       || fwrite (target_machine, v.target_machine_length, 1, f) != 1
130       || fwrite (version_string, v.version_length, 1, f) != 1
131       || fwrite (target_validity, v.target_data_length, 1, f) != 1)
132     fatal_error ("can't write to %s: %m", pch_file);
133
134   /* We need to be able to re-read the output.  */
135   /* The driver always provides a valid -o option.  */
136   if (asm_file_name == NULL
137       || strcmp (asm_file_name, "-") == 0)
138     fatal_error ("`%s' is not a valid output file", asm_file_name);
139   
140   asm_file_startpos = ftell (asm_out_file);
141   
142   /* Let the debugging format deal with the PCHness.  */
143   (*debug_hooks->handle_pch) (0);
144   
145   cpp_save_state (parse_in, f);
146 }
147
148 /* Write the PCH file.  This is called at the end of a compilation which
149    will produce a PCH file.  */
150
151 void
152 c_common_write_pch (void)
153 {
154   char *buf;
155   long asm_file_end;
156   long written;
157   struct c_pch_header h;
158
159   (*debug_hooks->handle_pch) (1);
160
161   cpp_write_pch_deps (parse_in, pch_outfile);
162
163   asm_file_end = ftell (asm_out_file);
164   h.asm_size = asm_file_end - asm_file_startpos;
165   
166   if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
167     fatal_error ("can't write %s: %m", pch_file);
168   
169   buf = xmalloc (16384);
170   fflush (asm_out_file);
171
172   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
173     fatal_error ("can't seek in %s: %m", asm_file_name);
174
175   for (written = asm_file_startpos; written < asm_file_end; )
176     {
177       long size = asm_file_end - written;
178       if (size > 16384)
179         size = 16384;
180       if (fread (buf, size, 1, asm_out_file) != 1)
181         fatal_error ("can't read %s: %m", asm_file_name);
182       if (fwrite (buf, size, 1, pch_outfile) != 1)
183         fatal_error ("can't write %s: %m", pch_file);
184       written += size;
185     }
186   free (buf);
187   /* asm_out_file can be written afterwards, so must be flushed first.  */
188   fflush (asm_out_file);
189
190   gt_pch_save (pch_outfile);
191   cpp_write_pch_state (parse_in, pch_outfile);
192
193   if (fseek (pch_outfile, 0, SEEK_SET) != 0
194       || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
195     fatal_error ("can't write %s: %m", pch_file);
196
197   fclose (pch_outfile);
198 }
199
200 /* Check the PCH file called NAME, open on FD, to see if it can be
201    used in this compilation.  Return 1 if valid, 0 if the file can't
202    be used now but might be if it's seen later in the compilation, and
203    2 if this file could never be used in the compilation.  */
204
205 int
206 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
207 {
208   int sizeread;
209   int result;
210   char ident[IDENT_LENGTH];
211   char short_strings[256 * 3];
212   int strings_length;
213   const char *pch_ident;
214   struct c_pch_validity v;
215
216   /* Perform a quick test of whether this is a valid
217      precompiled header for the current language.  */
218
219   sizeread = read (fd, ident, IDENT_LENGTH);
220   if (sizeread == -1)
221     fatal_error ("can't read %s: %m", name);
222   else if (sizeread != IDENT_LENGTH)
223     return 2;
224   
225   pch_ident = get_ident();
226   if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
227     {
228       if (cpp_get_options (pfile)->warn_invalid_pch)
229         {
230           if (memcmp (ident, pch_ident, 5) == 0)
231             /* It's a PCH, for the right language, but has the wrong version.
232              */
233             cpp_error (pfile, CPP_DL_WARNING, 
234                        "%s: not compatible with this GCC version", name);
235           else if (memcmp (ident, pch_ident, 4) == 0)
236             /* It's a PCH for the wrong language.  */
237             cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
238                        lang_hooks.name);
239           else 
240             /* Not any kind of PCH.  */
241             cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
242         }
243       return 2;
244     }
245
246   /* At this point, we know it's a PCH file, so it ought to be long enough
247      that we can read a c_pch_validity structure.  */
248   if (read (fd, &v, sizeof (v)) != sizeof (v))
249     fatal_error ("can't read %s: %m", name);
250
251   strings_length = (v.host_machine_length + v.target_machine_length 
252                     + v.version_length);
253   if (read (fd, short_strings, strings_length) != strings_length)
254     fatal_error ("can't read %s: %m", name);
255   if (v.host_machine_length != strlen (host_machine)
256       || memcmp (host_machine, short_strings, strlen (host_machine)) != 0)
257     {
258       if (cpp_get_options (pfile)->warn_invalid_pch)
259         cpp_error (pfile, CPP_DL_WARNING, 
260                    "%s: created on host `%.*s', but used on host `%s'", name,
261                    v.host_machine_length, short_strings, host_machine);
262       return 2;
263     }
264   if (v.target_machine_length != strlen (target_machine)
265       || memcmp (target_machine, short_strings + v.host_machine_length,
266                  strlen (target_machine)) != 0)
267     {
268       if (cpp_get_options (pfile)->warn_invalid_pch)
269         cpp_error (pfile, CPP_DL_WARNING, 
270                    "%s: created for target `%.*s', but used for target `%s'", 
271                    name, v.target_machine_length, 
272                    short_strings + v.host_machine_length, target_machine);
273       return 2;
274     }
275   if (v.version_length != strlen (version_string)
276       || memcmp (version_string, 
277                  (short_strings + v.host_machine_length 
278                   + v.target_machine_length),
279                  v.version_length) != 0)
280     {
281       if (cpp_get_options (pfile)->warn_invalid_pch)
282         cpp_error (pfile, CPP_DL_WARNING,
283                    "%s: created by version `%.*s', but this is version `%s'", 
284                    name, v.version_length, 
285                    (short_strings + v.host_machine_length 
286                     + v.target_machine_length), 
287                    version_string);
288       return 2;
289     }
290
291   /* The allowable debug info combinations are that either the PCH file
292      was built with the same as is being used now, or the PCH file was
293      built for some kind of debug info but now none is in use.  */
294   if (v.debug_info_type != write_symbols
295       && write_symbols != NO_DEBUG)
296     {
297       if (cpp_get_options (pfile)->warn_invalid_pch)
298         cpp_error (pfile, CPP_DL_WARNING, 
299                    "%s: created with -g%s, but used with -g%s", name,
300                    debug_type_names[v.debug_info_type],
301                    debug_type_names[write_symbols]);
302       return 2;
303     }
304
305   /* If the text segment was not loaded at the same address as it was
306      when the PCH file was created, function pointers loaded from the
307      PCH will not be valid.  We could in theory remap all the function
308      pointers, but no support for that exists at present.  */
309   if (v.pch_init != &pch_init)
310     {
311       if (cpp_get_options (pfile)->warn_invalid_pch)
312         cpp_error (pfile, CPP_DL_WARNING, 
313                    "%s: had text segment at different address", name);
314       return 2;
315     }
316
317   /* Check the target-specific validity data.  */
318   {
319     void *this_file_data = xmalloc (v.target_data_length);
320     const char *msg;
321     
322     if ((size_t) read (fd, this_file_data, v.target_data_length)
323         != v.target_data_length)
324       fatal_error ("can't read %s: %m", name);
325     msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
326     free (this_file_data);
327     if (msg != NULL)
328       {
329         if (cpp_get_options (pfile)->warn_invalid_pch)
330           cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
331         return 2;
332       }
333   }
334
335   /* Check the preprocessor macros are the same as when the PCH was
336      generated.  */
337   
338   result = cpp_valid_state (pfile, name, fd);
339   if (result == -1)
340     return 2;
341   else
342     return result == 0;
343 }
344
345 /* Load in the PCH file NAME, open on FD.  It was originally searched for
346    by ORIG_NAME.  */
347
348 void
349 c_common_read_pch (cpp_reader *pfile, const char *name,
350                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
351 {
352   FILE *f;
353   struct c_pch_header h;
354   char *buf;
355   unsigned long written;
356   struct save_macro_data *smd;
357   
358   f = fdopen (fd, "rb");
359   if (f == NULL)
360     {
361       cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
362       return;
363     }
364
365   cpp_get_callbacks (parse_in)->valid_pch = NULL;
366
367   if (fread (&h, sizeof (h), 1, f) != 1)
368     {
369       cpp_errno (pfile, CPP_DL_ERROR, "reading");
370       return;
371     }
372
373   buf = xmalloc (16384);
374   for (written = 0; written < h.asm_size; )
375     {
376       long size = h.asm_size - written;
377       if (size > 16384)
378         size = 16384;
379       if (fread (buf, size, 1, f) != 1
380           || fwrite (buf, size, 1, asm_out_file) != 1)
381         cpp_errno (pfile, CPP_DL_ERROR, "reading");
382       written += size;
383     }
384   free (buf);
385
386   cpp_prepare_state (pfile, &smd);
387
388   gt_pch_restore (f);
389
390   if (cpp_read_state (pfile, name, f, smd) != 0)
391     return;
392
393   fclose (f);
394 }
395
396 /* Indicate that no more PCH files should be read.  */
397
398 void
399 c_common_no_more_pch (void)
400 {
401   if (cpp_get_callbacks (parse_in)->valid_pch)
402     {
403       cpp_get_callbacks (parse_in)->valid_pch = NULL;
404       host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
405     }
406 }