OSDN Git Service

2004-04-08 Geoffrey Keating <geoffk@apple.com>
[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   fflush (asm_out_file);
198
199   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
200     fatal_error ("can't seek in %s: %m", asm_file_name);
201
202   for (written = asm_file_startpos; written < asm_file_end; )
203     {
204       long size = asm_file_end - written;
205       if (size > 16384)
206         size = 16384;
207       if (fread (buf, size, 1, asm_out_file) != 1)
208         fatal_error ("can't read %s: %m", asm_file_name);
209       if (fwrite (buf, size, 1, pch_outfile) != 1)
210         fatal_error ("can't write %s: %m", pch_file);
211       written += size;
212     }
213   free (buf);
214   /* asm_out_file can be written afterwards, so must be flushed first.  */
215   fflush (asm_out_file);
216
217   gt_pch_save (pch_outfile);
218   cpp_write_pch_state (parse_in, pch_outfile);
219
220   if (fseek (pch_outfile, 0, SEEK_SET) != 0
221       || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
222     fatal_error ("can't write %s: %m", pch_file);
223
224   fclose (pch_outfile);
225 }
226
227 /* Check the PCH file called NAME, open on FD, to see if it can be
228    used in this compilation.  Return 1 if valid, 0 if the file can't
229    be used now but might be if it's seen later in the compilation, and
230    2 if this file could never be used in the compilation.  */
231
232 int
233 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
234 {
235   int sizeread;
236   int result;
237   char ident[IDENT_LENGTH];
238   char short_strings[256 * 3];
239   int strings_length;
240   const char *pch_ident;
241   struct c_pch_validity v;
242
243   /* Perform a quick test of whether this is a valid
244      precompiled header for the current language.  */
245
246   sizeread = read (fd, ident, IDENT_LENGTH);
247   if (sizeread == -1)
248     fatal_error ("can't read %s: %m", name);
249   else if (sizeread != IDENT_LENGTH)
250     return 2;
251   
252   pch_ident = get_ident();
253   if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
254     {
255       if (cpp_get_options (pfile)->warn_invalid_pch)
256         {
257           if (memcmp (ident, pch_ident, 5) == 0)
258             /* It's a PCH, for the right language, but has the wrong version.
259              */
260             cpp_error (pfile, CPP_DL_WARNING, 
261                        "%s: not compatible with this GCC version", name);
262           else if (memcmp (ident, pch_ident, 4) == 0)
263             /* It's a PCH for the wrong language.  */
264             cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
265                        lang_hooks.name);
266           else 
267             /* Not any kind of PCH.  */
268             cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
269         }
270       return 2;
271     }
272
273   /* At this point, we know it's a PCH file, so it ought to be long enough
274      that we can read a c_pch_validity structure.  */
275   if (read (fd, &v, sizeof (v)) != sizeof (v))
276     fatal_error ("can't read %s: %m", name);
277
278   strings_length = (v.host_machine_length + v.target_machine_length 
279                     + v.version_length);
280   if (read (fd, short_strings, strings_length) != strings_length)
281     fatal_error ("can't read %s: %m", name);
282   if (v.host_machine_length != strlen (host_machine)
283       || memcmp (host_machine, short_strings, strlen (host_machine)) != 0)
284     {
285       if (cpp_get_options (pfile)->warn_invalid_pch)
286         cpp_error (pfile, CPP_DL_WARNING, 
287                    "%s: created on host `%.*s', but used on host `%s'", name,
288                    v.host_machine_length, short_strings, host_machine);
289       return 2;
290     }
291   if (v.target_machine_length != strlen (target_machine)
292       || memcmp (target_machine, short_strings + v.host_machine_length,
293                  strlen (target_machine)) != 0)
294     {
295       if (cpp_get_options (pfile)->warn_invalid_pch)
296         cpp_error (pfile, CPP_DL_WARNING, 
297                    "%s: created for target `%.*s', but used for target `%s'", 
298                    name, v.target_machine_length, 
299                    short_strings + v.host_machine_length, target_machine);
300       return 2;
301     }
302   if (v.version_length != strlen (version_string)
303       || memcmp (version_string, 
304                  (short_strings + v.host_machine_length 
305                   + v.target_machine_length),
306                  v.version_length) != 0)
307     {
308       if (cpp_get_options (pfile)->warn_invalid_pch)
309         cpp_error (pfile, CPP_DL_WARNING,
310                    "%s: created by version `%.*s', but this is version `%s'", 
311                    name, v.version_length, 
312                    (short_strings + v.host_machine_length 
313                     + v.target_machine_length), 
314                    version_string);
315       return 2;
316     }
317
318   /* The allowable debug info combinations are that either the PCH file
319      was built with the same as is being used now, or the PCH file was
320      built for some kind of debug info but now none is in use.  */
321   if (v.debug_info_type != write_symbols
322       && write_symbols != NO_DEBUG)
323     {
324       if (cpp_get_options (pfile)->warn_invalid_pch)
325         cpp_error (pfile, CPP_DL_WARNING, 
326                    "%s: created with -g%s, but used with -g%s", name,
327                    debug_type_names[v.debug_info_type],
328                    debug_type_names[write_symbols]);
329       return 2;
330     }
331
332   /* Check flags that must match exactly.  */
333   {
334     size_t i;
335     for (i = 0; i < MATCH_SIZE; i++)
336       if (*pch_matching[i].flag_var != v.match[i])
337         {
338           if (cpp_get_options (pfile)->warn_invalid_pch)
339             cpp_error (pfile, CPP_DL_WARNING, 
340                        "%s: settings for %s do not match", name,
341                        pch_matching[i].flag_name);
342           return 2;
343         }
344   }
345
346   /* If the text segment was not loaded at the same address as it was
347      when the PCH file was created, function pointers loaded from the
348      PCH will not be valid.  We could in theory remap all the function
349      pointers, but no support for that exists at present.  */
350   if (v.pch_init != &pch_init)
351     {
352       if (cpp_get_options (pfile)->warn_invalid_pch)
353         cpp_error (pfile, CPP_DL_WARNING, 
354                    "%s: had text segment at different address", name);
355       return 2;
356     }
357
358   /* Check the target-specific validity data.  */
359   {
360     void *this_file_data = xmalloc (v.target_data_length);
361     const char *msg;
362     
363     if ((size_t) read (fd, this_file_data, v.target_data_length)
364         != v.target_data_length)
365       fatal_error ("can't read %s: %m", name);
366     msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
367     free (this_file_data);
368     if (msg != NULL)
369       {
370         if (cpp_get_options (pfile)->warn_invalid_pch)
371           cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
372         return 2;
373       }
374   }
375
376   /* Check the preprocessor macros are the same as when the PCH was
377      generated.  */
378   
379   result = cpp_valid_state (pfile, name, fd);
380   if (result == -1)
381     return 2;
382   else
383     return result == 0;
384 }
385
386 /* Load in the PCH file NAME, open on FD.  It was originally searched for
387    by ORIG_NAME.  */
388
389 void
390 c_common_read_pch (cpp_reader *pfile, const char *name,
391                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
392 {
393   FILE *f;
394   struct c_pch_header h;
395   char *buf;
396   unsigned long written;
397   struct save_macro_data *smd;
398   
399   f = fdopen (fd, "rb");
400   if (f == NULL)
401     {
402       cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
403       return;
404     }
405
406   cpp_get_callbacks (parse_in)->valid_pch = NULL;
407
408   if (fread (&h, sizeof (h), 1, f) != 1)
409     {
410       cpp_errno (pfile, CPP_DL_ERROR, "reading");
411       return;
412     }
413
414   buf = xmalloc (16384);
415   for (written = 0; written < h.asm_size; )
416     {
417       long size = h.asm_size - written;
418       if (size > 16384)
419         size = 16384;
420       if (fread (buf, size, 1, f) != 1
421           || fwrite (buf, size, 1, asm_out_file) != 1)
422         cpp_errno (pfile, CPP_DL_ERROR, "reading");
423       written += size;
424     }
425   free (buf);
426
427   cpp_prepare_state (pfile, &smd);
428
429   gt_pch_restore (f);
430
431   if (cpp_read_state (pfile, name, f, smd) != 0)
432     return;
433
434   fclose (f);
435 }
436
437 /* Indicate that no more PCH files should be read.  */
438
439 void
440 c_common_no_more_pch (void)
441 {
442   if (cpp_get_callbacks (parse_in)->valid_pch)
443     {
444       cpp_get_callbacks (parse_in)->valid_pch = NULL;
445       host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
446     }
447 }