OSDN Git Service

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